qbsp: parallelize CSGFaces
This commit is contained in:
parent
e2a5f62f32
commit
1f565d7e7a
|
|
@ -122,6 +122,8 @@ endif (MSVC)
|
|||
#minimum version that supports unordered_map
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
||||
|
||||
find_package(TBB REQUIRED)
|
||||
|
||||
add_subdirectory(bspinfo)
|
||||
add_subdirectory(bsputil)
|
||||
add_subdirectory(light)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ project (qbsp CXX)
|
|||
add_definitions(-DDOUBLEVEC_T)
|
||||
|
||||
add_executable(qbsp ${QBSP_SOURCES} main.cc)
|
||||
target_link_libraries(qbsp ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(qbsp ${CMAKE_THREAD_LIBS_INIT} TBB::tbb)
|
||||
install(TARGETS qbsp RUNTIME DESTINATION bin)
|
||||
|
||||
# test (copied from light/CMakeLists.txt)
|
||||
|
|
@ -22,4 +22,4 @@ set(QBSP_TEST_SOURCE
|
|||
add_executable(testqbsp EXCLUDE_FROM_ALL ${QBSP_TEST_SOURCE})
|
||||
add_test(testqbsp testqbsp)
|
||||
|
||||
target_link_libraries (testqbsp ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries (testqbsp ${CMAKE_THREAD_LIBS_INIT} TBB::tbb)
|
||||
|
|
|
|||
62
qbsp/csg4.cc
62
qbsp/csg4.cc
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#include <qbsp/qbsp.hh>
|
||||
|
||||
#include "tbb/mutex.h"
|
||||
#include "tbb/parallel_do.h"
|
||||
#include "tbb/parallel_for.h"
|
||||
|
||||
/*
|
||||
|
||||
NOTES
|
||||
|
|
@ -564,17 +568,8 @@ Returns a list of surfaces containing all of the faces
|
|||
surface_t *
|
||||
CSGFaces(const mapentity_t *entity)
|
||||
{
|
||||
int i;
|
||||
const brush_t *brush, *clipbrush;
|
||||
const face_t *clipface;
|
||||
face_t *inside, *outside;
|
||||
bool overwrite, mirror;
|
||||
surface_t *surfaces;
|
||||
int progress = 0;
|
||||
|
||||
Message(msgProgress, "CSGFaces");
|
||||
|
||||
std::map<int, face_t *> planefaces;
|
||||
csgfaces = brushfaces = csgmergefaces = 0;
|
||||
|
||||
#if 0
|
||||
|
|
@ -583,17 +578,33 @@ CSGFaces(const mapentity_t *entity)
|
|||
logprint(" %s (%s)\n", map.texinfoTextureName(brush->faces->texinfo).c_str(), GetContentsName(brush->contents));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// copy to vector
|
||||
// TODO: change brush list in mapentity_t to a vector so we can skip this
|
||||
std::vector<const brush_t*> brushvec;
|
||||
for (const brush_t* brush = entity->brushes; brush; brush = brush->next) {
|
||||
brushvec.push_back(brush);
|
||||
}
|
||||
|
||||
// output vector for the parallel_for
|
||||
std::vector<face_t*> brushvec_outsides;
|
||||
brushvec_outsides.resize(brushvec.size());
|
||||
|
||||
/*
|
||||
* For each brush, clip away the parts that are inside other brushes.
|
||||
* Solid brushes override non-solid brushes.
|
||||
* brush => the brush to be clipped
|
||||
* clipbrush => the brush we are clipping against
|
||||
*
|
||||
* The output of this is a face list for each brush called "outside"
|
||||
*/
|
||||
for (brush = entity->brushes; brush; brush = brush->next) {
|
||||
outside = CopyBrushFaces(brush);
|
||||
overwrite = false;
|
||||
clipbrush = entity->brushes;
|
||||
tbb::parallel_for(static_cast<size_t>(0), brushvec.size(),
|
||||
[entity, &brushvec, &brushvec_outsides](const size_t i) {
|
||||
const brush_t* brush = brushvec[i];
|
||||
face_t *outside = CopyBrushFaces(brush);
|
||||
bool overwrite = false;
|
||||
const brush_t *clipbrush = entity->brushes;
|
||||
|
||||
for (; clipbrush; clipbrush = clipbrush->next) {
|
||||
if (brush == clipbrush) {
|
||||
/* Brushes further down the list overried earlier ones */
|
||||
|
|
@ -632,6 +643,7 @@ CSGFaces(const mapentity_t *entity)
|
|||
}
|
||||
|
||||
/* check bounding box first */
|
||||
int i;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (brush->mins[i] > clipbrush->maxs[i])
|
||||
break;
|
||||
|
|
@ -647,11 +659,11 @@ CSGFaces(const mapentity_t *entity)
|
|||
*/
|
||||
|
||||
// divide faces by the planes of the new brush
|
||||
inside = outside;
|
||||
face_t *inside = outside;
|
||||
outside = NULL;
|
||||
|
||||
RemoveOutsideFaces(clipbrush, &inside, &outside);
|
||||
clipface = clipbrush->faces;
|
||||
const face_t *clipface = clipbrush->faces;
|
||||
for (; clipface; clipface = clipface->next)
|
||||
ClipInside(clipface, overwrite, &inside, &outside);
|
||||
|
||||
|
|
@ -680,18 +692,24 @@ CSGFaces(const mapentity_t *entity)
|
|||
}
|
||||
}
|
||||
|
||||
// save the result
|
||||
brushvec_outsides[i] = outside;
|
||||
});
|
||||
|
||||
// Non parallel part:
|
||||
std::map<int, face_t *> planefaces;
|
||||
for (size_t i = 0; i < brushvec.size(); ++i) {
|
||||
const brush_t* brush = brushvec[i];
|
||||
face_t* outside = brushvec_outsides[i];
|
||||
|
||||
/*
|
||||
* All of the faces left on the outside list are real surface faces
|
||||
* If the brush is non-solid, mirror faces for the inside view
|
||||
*/
|
||||
mirror = options.fContentHack ? true : (brush->contents != CONTENTS_SOLID);
|
||||
const bool mirror = options.fContentHack ? true : (brush->contents != CONTENTS_SOLID);
|
||||
SaveFacesToPlaneList(outside, mirror, planefaces);
|
||||
|
||||
progress++;
|
||||
Message(msgPercent, progress, entity->numbrushes);
|
||||
}
|
||||
|
||||
surfaces = BuildSurfaces(planefaces);
|
||||
surface_t *surfaces = BuildSurfaces(planefaces);
|
||||
|
||||
Message(msgStat, "%8d brushfaces", brushfaces);
|
||||
Message(msgStat, "%8d csgfaces", csgfaces);
|
||||
|
|
|
|||
Loading…
Reference in New Issue