commit
b56afb5988
|
|
@ -122,6 +122,8 @@ endif (MSVC)
|
||||||
#minimum version that supports unordered_map
|
#minimum version that supports unordered_map
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
||||||
|
|
||||||
|
find_package(TBB REQUIRED)
|
||||||
|
|
||||||
add_subdirectory(bspinfo)
|
add_subdirectory(bspinfo)
|
||||||
add_subdirectory(bsputil)
|
add_subdirectory(bsputil)
|
||||||
add_subdirectory(light)
|
add_subdirectory(light)
|
||||||
|
|
|
||||||
17
appveyor.yml
17
appveyor.yml
|
|
@ -1,13 +1,12 @@
|
||||||
platform:
|
platform:
|
||||||
- x86
|
|
||||||
- x64
|
- x64
|
||||||
|
|
||||||
version: 1.0.{build}
|
version: 1.0.{build}
|
||||||
install:
|
install:
|
||||||
- ps: Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v2.15.0/embree-2.15.0.x64.windows.zip' -OutFile 'embree64.zip'
|
- ps: Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v2.17.7/embree-2.17.7.x64.windows.zip' -OutFile 'embree64.zip'
|
||||||
- ps: 7z x embree64.zip -oc:\
|
- ps: 7z x embree64.zip -oc:\
|
||||||
- ps: Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v2.15.0/embree-2.15.0.win32.windows.zip' -OutFile 'embree.zip'
|
- ps: Invoke-WebRequest 'https://github.com/intel/tbb/releases/download/2017_U7/tbb2017_20170604oss_win.zip' -OutFile 'tbb.zip'
|
||||||
- ps: 7z x embree.zip -oc:\
|
- ps: 7z x tbb.zip -oc:\
|
||||||
build_script:
|
build_script:
|
||||||
- ps: >-
|
- ps: >-
|
||||||
$env:Path += ";C:\cygwin64\bin"
|
$env:Path += ";C:\cygwin64\bin"
|
||||||
|
|
@ -16,15 +15,9 @@ build_script:
|
||||||
|
|
||||||
cd cmakebuild
|
cd cmakebuild
|
||||||
|
|
||||||
If ($env:Platform -Match "x64") {
|
cmake .. -T v120_xp -Dembree_DIR="c:/embree-2.17.7.x64.windows" -DTBB_DIR="C:/tbb2017_20170604oss/cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets"
|
||||||
cmake .. -T v120_xp -Dembree_DIR="c:/embree-2.15.0.x64.windows" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets"
|
|
||||||
|
|
||||||
$cmakePlatform = "x64"
|
$cmakePlatform = "x64"
|
||||||
} Else {
|
|
||||||
cmake .. -T v120_xp -Dembree_DIR="c:/embree-2.15.0.win32.windows" -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013\lib\cmake\Qt5Widgets"
|
|
||||||
|
|
||||||
$cmakePlatform = "win32"
|
|
||||||
}
|
|
||||||
|
|
||||||
msbuild /target:testlight /p:Configuration=Release /p:Platform=$cmakePlatform /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ericw-tools.sln
|
msbuild /target:testlight /p:Configuration=Release /p:Platform=$cmakePlatform /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" ericw-tools.sln
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ cmake --version
|
||||||
|
|
||||||
mkdir "$BUILD_DIR"
|
mkdir "$BUILD_DIR"
|
||||||
cd "$BUILD_DIR"
|
cd "$BUILD_DIR"
|
||||||
wget https://github.com/embree/embree/releases/download/v2.15.0/embree-2.15.0.x86_64.linux.tar.gz -O embree.tgz
|
wget https://github.com/embree/embree/releases/download/v2.17.7/embree-2.17.7.x86_64.linux.tar.gz -O embree.tgz
|
||||||
|
wget https://github.com/intel/tbb/releases/download/2017_U7/tbb2017_20170604oss_lin.tgz -O tbb.tgz
|
||||||
tar xf embree.tgz
|
tar xf embree.tgz
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -Dembree_DIR="$(pwd)/embree-2.15.0.x86_64.linux"
|
tar xf tbb.tgz
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -Dembree_DIR="$(pwd)/embree-2.17.7.x86_64.linux" -DTBB_DIR="$(pwd)/tbb2017_20170604oss/cmake"
|
||||||
make -j8 VERBOSE=1
|
make -j8 VERBOSE=1
|
||||||
make -j8 VERBOSE=1 testlight
|
make -j8 VERBOSE=1 testlight
|
||||||
make -j8 VERBOSE=1 testqbsp
|
make -j8 VERBOSE=1 testqbsp
|
||||||
|
|
|
||||||
12
build-osx.sh
12
build-osx.sh
|
|
@ -1,11 +1,15 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
BUILD_DIR=build-osx
|
BUILD_DIR=build-osx
|
||||||
EMBREE_TGZ="https://github.com/embree/embree/releases/download/v2.15.0/embree-2.15.0.x86_64.macosx.tar.gz"
|
EMBREE_TGZ="https://github.com/embree/embree/releases/download/v2.17.7/embree-2.17.7.x86_64.macosx.tar.gz"
|
||||||
EMBREE_TGZ_NAME=$(basename "$EMBREE_TGZ")
|
EMBREE_TGZ_NAME=$(basename "$EMBREE_TGZ")
|
||||||
EMBREE_DIR_NAME=$(basename "$EMBREE_TGZ" ".tar.gz")
|
EMBREE_DIR_NAME=$(basename "$EMBREE_TGZ" ".tar.gz")
|
||||||
EMBREE_WITH_VERSION=$(basename "$EMBREE_TGZ" ".x86_64.macosx.tar.gz")
|
EMBREE_WITH_VERSION=$(basename "$EMBREE_TGZ" ".x86_64.macosx.tar.gz")
|
||||||
|
|
||||||
|
TBB_TGZ="https://github.com/intel/tbb/releases/download/2017_U7/tbb2017_20170604oss_mac.tgz"
|
||||||
|
TBB_TGZ_NAME=$(basename "$TBB_TGZ")
|
||||||
|
TBB_DIR_NAME="tbb2017_20170604oss"
|
||||||
|
|
||||||
if [ -d "$BUILD_DIR" ]; then
|
if [ -d "$BUILD_DIR" ]; then
|
||||||
echo "$BUILD_DIR already exists, remove it first"
|
echo "$BUILD_DIR already exists, remove it first"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -14,9 +18,13 @@ fi
|
||||||
mkdir "$BUILD_DIR"
|
mkdir "$BUILD_DIR"
|
||||||
cd "$BUILD_DIR"
|
cd "$BUILD_DIR"
|
||||||
wget "$EMBREE_TGZ"
|
wget "$EMBREE_TGZ"
|
||||||
|
wget "$TBB_TGZ"
|
||||||
tar xf "$EMBREE_TGZ_NAME"
|
tar xf "$EMBREE_TGZ_NAME"
|
||||||
|
tar xf "$TBB_TGZ_NAME"
|
||||||
|
|
||||||
EMBREE_CMAKE_DIR="$(pwd)/$EMBREE_DIR_NAME"
|
EMBREE_CMAKE_DIR="$(pwd)/$EMBREE_DIR_NAME"
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release -Dembree_DIR="$EMBREE_CMAKE_DIR"
|
TBB_CMAKE_DIR="$(pwd)/${TBB_DIR_NAME}/cmake"
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -Dembree_DIR="$EMBREE_CMAKE_DIR" -DTBB_DIR="$TBB_CMAKE_DIR"
|
||||||
make -j8
|
make -j8
|
||||||
make -j8 testlight
|
make -j8 testlight
|
||||||
make -j8 testqbsp
|
make -j8 testqbsp
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ set(LIGHT_SOURCES
|
||||||
${LIGHT_INCLUDES})
|
${LIGHT_INCLUDES})
|
||||||
|
|
||||||
|
|
||||||
FIND_PACKAGE(embree 2.0)
|
FIND_PACKAGE(embree 2.0 REQUIRED)
|
||||||
|
|
||||||
if (embree_FOUND)
|
if (embree_FOUND)
|
||||||
MESSAGE(STATUS "Embree library found: ${EMBREE_LIBRARY}")
|
MESSAGE(STATUS "Embree library found: ${EMBREE_LIBRARY}")
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ project (qbsp CXX)
|
||||||
add_definitions(-DDOUBLEVEC_T)
|
add_definitions(-DDOUBLEVEC_T)
|
||||||
|
|
||||||
add_executable(qbsp ${QBSP_SOURCES} main.cc)
|
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)
|
install(TARGETS qbsp RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
# test (copied from light/CMakeLists.txt)
|
# test (copied from light/CMakeLists.txt)
|
||||||
|
|
@ -22,4 +22,4 @@ set(QBSP_TEST_SOURCE
|
||||||
add_executable(testqbsp EXCLUDE_FROM_ALL ${QBSP_TEST_SOURCE})
|
add_executable(testqbsp EXCLUDE_FROM_ALL ${QBSP_TEST_SOURCE})
|
||||||
add_test(testqbsp testqbsp)
|
add_test(testqbsp testqbsp)
|
||||||
|
|
||||||
target_link_libraries (testqbsp ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries (testqbsp ${CMAKE_THREAD_LIBS_INIT} TBB::tbb)
|
||||||
|
|
|
||||||
76
qbsp/csg4.cc
76
qbsp/csg4.cc
|
|
@ -22,6 +22,10 @@
|
||||||
|
|
||||||
#include <qbsp/qbsp.hh>
|
#include <qbsp/qbsp.hh>
|
||||||
|
|
||||||
|
#include "tbb/mutex.h"
|
||||||
|
#include "tbb/parallel_do.h"
|
||||||
|
#include "tbb/parallel_for.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
|
|
@ -218,18 +222,14 @@ time in mergefaces later on (and sometimes a lot of memory)
|
||||||
static void
|
static void
|
||||||
RemoveOutsideFaces(const brush_t *brush, face_t **inside, face_t **outside)
|
RemoveOutsideFaces(const brush_t *brush, face_t **inside, face_t **outside)
|
||||||
{
|
{
|
||||||
qbsp_plane_t clipplane;
|
face_t *face = *inside;
|
||||||
const face_t *clipface;
|
face_t *next = nullptr;
|
||||||
face_t *face, *next;
|
|
||||||
winding_t *w;
|
|
||||||
|
|
||||||
face = *inside;
|
|
||||||
*inside = NULL;
|
*inside = NULL;
|
||||||
while (face) {
|
while (face) {
|
||||||
next = face->next;
|
next = face->next;
|
||||||
w = CopyWinding(&face->w);
|
winding_t *w = CopyWinding(&face->w);
|
||||||
for (clipface = brush->faces; clipface; clipface = clipface->next) {
|
for (const face_t *clipface = brush->faces; clipface; clipface = clipface->next) {
|
||||||
clipplane = map.planes[clipface->planenum];
|
qbsp_plane_t clipplane = map.planes[clipface->planenum];
|
||||||
if (!clipface->planeside) {
|
if (!clipface->planeside) {
|
||||||
VectorSubtract(vec3_origin, clipplane.normal, clipplane.normal);
|
VectorSubtract(vec3_origin, clipplane.normal, clipplane.normal);
|
||||||
clipplane.dist = -clipplane.dist;
|
clipplane.dist = -clipplane.dist;
|
||||||
|
|
@ -564,17 +564,8 @@ Returns a list of surfaces containing all of the faces
|
||||||
surface_t *
|
surface_t *
|
||||||
CSGFaces(const mapentity_t *entity)
|
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");
|
Message(msgProgress, "CSGFaces");
|
||||||
|
|
||||||
std::map<int, face_t *> planefaces;
|
|
||||||
csgfaces = brushfaces = csgmergefaces = 0;
|
csgfaces = brushfaces = csgmergefaces = 0;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
@ -583,17 +574,33 @@ CSGFaces(const mapentity_t *entity)
|
||||||
logprint(" %s (%s)\n", map.texinfoTextureName(brush->faces->texinfo).c_str(), GetContentsName(brush->contents));
|
logprint(" %s (%s)\n", map.texinfoTextureName(brush->faces->texinfo).c_str(), GetContentsName(brush->contents));
|
||||||
}
|
}
|
||||||
#endif
|
#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.
|
* For each brush, clip away the parts that are inside other brushes.
|
||||||
* Solid brushes override non-solid brushes.
|
* Solid brushes override non-solid brushes.
|
||||||
* brush => the brush to be clipped
|
* brush => the brush to be clipped
|
||||||
* clipbrush => the brush we are clipping against
|
* 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) {
|
tbb::parallel_for(static_cast<size_t>(0), brushvec.size(),
|
||||||
outside = CopyBrushFaces(brush);
|
[entity, &brushvec, &brushvec_outsides](const size_t i) {
|
||||||
overwrite = false;
|
const brush_t* brush = brushvec[i];
|
||||||
clipbrush = entity->brushes;
|
face_t *outside = CopyBrushFaces(brush);
|
||||||
|
bool overwrite = false;
|
||||||
|
const brush_t *clipbrush = entity->brushes;
|
||||||
|
|
||||||
for (; clipbrush; clipbrush = clipbrush->next) {
|
for (; clipbrush; clipbrush = clipbrush->next) {
|
||||||
if (brush == clipbrush) {
|
if (brush == clipbrush) {
|
||||||
/* Brushes further down the list overried earlier ones */
|
/* Brushes further down the list overried earlier ones */
|
||||||
|
|
@ -632,6 +639,7 @@ CSGFaces(const mapentity_t *entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check bounding box first */
|
/* check bounding box first */
|
||||||
|
int i;
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
if (brush->mins[i] > clipbrush->maxs[i])
|
if (brush->mins[i] > clipbrush->maxs[i])
|
||||||
break;
|
break;
|
||||||
|
|
@ -647,11 +655,11 @@ CSGFaces(const mapentity_t *entity)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// divide faces by the planes of the new brush
|
// divide faces by the planes of the new brush
|
||||||
inside = outside;
|
face_t *inside = outside;
|
||||||
outside = NULL;
|
outside = NULL;
|
||||||
|
|
||||||
RemoveOutsideFaces(clipbrush, &inside, &outside);
|
RemoveOutsideFaces(clipbrush, &inside, &outside);
|
||||||
clipface = clipbrush->faces;
|
const face_t *clipface = clipbrush->faces;
|
||||||
for (; clipface; clipface = clipface->next)
|
for (; clipface; clipface = clipface->next)
|
||||||
ClipInside(clipface, overwrite, &inside, &outside);
|
ClipInside(clipface, overwrite, &inside, &outside);
|
||||||
|
|
||||||
|
|
@ -680,18 +688,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
|
* 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
|
* 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);
|
SaveFacesToPlaneList(outside, mirror, planefaces);
|
||||||
|
|
||||||
progress++;
|
|
||||||
Message(msgPercent, progress, entity->numbrushes);
|
|
||||||
}
|
}
|
||||||
|
surface_t *surfaces = BuildSurfaces(planefaces);
|
||||||
surfaces = BuildSurfaces(planefaces);
|
|
||||||
|
|
||||||
Message(msgStat, "%8d brushfaces", brushfaces);
|
Message(msgStat, "%8d brushfaces", brushfaces);
|
||||||
Message(msgStat, "%8d csgfaces", csgfaces);
|
Message(msgStat, "%8d csgfaces", csgfaces);
|
||||||
|
|
|
||||||
201
qbsp/solidbsp.cc
201
qbsp/solidbsp.cc
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include <qbsp/qbsp.hh>
|
#include <qbsp/qbsp.hh>
|
||||||
|
|
||||||
|
#include "tbb/task_group.h"
|
||||||
|
|
||||||
int splitnodes;
|
int splitnodes;
|
||||||
|
|
||||||
static int leaffaces;
|
static int leaffaces;
|
||||||
|
|
@ -232,15 +234,12 @@ DivideBounds(const vec3_t mins, const vec3_t maxs, const qbsp_plane_t *split,
|
||||||
* Calculate the split plane metric for axial planes
|
* Calculate the split plane metric for axial planes
|
||||||
*/
|
*/
|
||||||
static vec_t
|
static vec_t
|
||||||
SplitPlaneMetric_Axial(const qbsp_plane_t *p, vec3_t mins, vec3_t maxs)
|
SplitPlaneMetric_Axial(const qbsp_plane_t *p, const vec3_t mins, const vec3_t maxs)
|
||||||
{
|
{
|
||||||
vec_t value, dist;
|
vec_t value = 0;
|
||||||
int i;
|
for (int i = 0; i < 3; i++) {
|
||||||
|
|
||||||
value = 0;
|
|
||||||
for (i = 0; i < 3; i++) {
|
|
||||||
if (i == p->type) {
|
if (i == p->type) {
|
||||||
dist = p->dist * p->normal[i];
|
const vec_t dist = p->dist * p->normal[i];
|
||||||
value += (maxs[i] - dist) * (maxs[i] - dist);
|
value += (maxs[i] - dist) * (maxs[i] - dist);
|
||||||
value += (dist - mins[i]) * (dist - mins[i]);
|
value += (dist - mins[i]) * (dist - mins[i]);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -255,14 +254,13 @@ SplitPlaneMetric_Axial(const qbsp_plane_t *p, vec3_t mins, vec3_t maxs)
|
||||||
* Calculate the split plane metric for non-axial planes
|
* Calculate the split plane metric for non-axial planes
|
||||||
*/
|
*/
|
||||||
static vec_t
|
static vec_t
|
||||||
SplitPlaneMetric_NonAxial(const qbsp_plane_t *p, vec3_t mins, vec3_t maxs)
|
SplitPlaneMetric_NonAxial(const qbsp_plane_t *p, const vec3_t mins, const vec3_t maxs)
|
||||||
{
|
{
|
||||||
vec3_t fmins, fmaxs, bmins, bmaxs;
|
vec3_t fmins, fmaxs, bmins, bmaxs;
|
||||||
vec_t value = 0.0;
|
vec_t value = 0.0;
|
||||||
int i;
|
|
||||||
|
|
||||||
DivideBounds(mins, maxs, p, fmins, fmaxs, bmins, bmaxs);
|
DivideBounds(mins, maxs, p, fmins, fmaxs, bmins, bmaxs);
|
||||||
for (i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
value += (fmaxs[i] - fmins[i]) * (fmaxs[i] - fmins[i]);
|
value += (fmaxs[i] - fmins[i]) * (fmaxs[i] - fmins[i]);
|
||||||
value += (bmaxs[i] - bmins[i]) * (bmaxs[i] - bmins[i]);
|
value += (bmaxs[i] - bmins[i]) * (bmaxs[i] - bmins[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +269,7 @@ SplitPlaneMetric_NonAxial(const qbsp_plane_t *p, vec3_t mins, vec3_t maxs)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline vec_t
|
static inline vec_t
|
||||||
SplitPlaneMetric(const qbsp_plane_t *p, vec3_t mins, vec3_t maxs)
|
SplitPlaneMetric(const qbsp_plane_t *p, const vec3_t mins, const vec3_t maxs)
|
||||||
{
|
{
|
||||||
vec_t value;
|
vec_t value;
|
||||||
|
|
||||||
|
|
@ -291,19 +289,14 @@ The clipping hull BSP doesn't worry about avoiding splits
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
static surface_t *
|
static surface_t *
|
||||||
ChooseMidPlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
ChooseMidPlaneFromList(surface_t *surfaces, const vec3_t mins, const vec3_t maxs)
|
||||||
{
|
{
|
||||||
surface_t *surf, *bestsurface;
|
|
||||||
vec_t metric, bestmetric;
|
|
||||||
qbsp_plane_t *plane;
|
|
||||||
int pass;
|
|
||||||
|
|
||||||
/* pick the plane that splits the least */
|
/* pick the plane that splits the least */
|
||||||
bestmetric = VECT_MAX;
|
vec_t bestmetric = VECT_MAX;
|
||||||
bestsurface = NULL;
|
surface_t *bestsurface = nullptr;
|
||||||
|
|
||||||
for (pass = 0; pass < 2; pass++) {
|
for (int pass = 0; pass < 2; pass++) {
|
||||||
for (surf = surfaces; surf; surf = surf->next) {
|
for (surface_t *surf = surfaces; surf; surf = surf->next) {
|
||||||
if (surf->onnode)
|
if (surf->onnode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -313,12 +306,12 @@ ChooseMidPlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* check for axis aligned surfaces */
|
/* check for axis aligned surfaces */
|
||||||
plane = &map.planes[surf->planenum];
|
const qbsp_plane_t *plane = &map.planes[surf->planenum];
|
||||||
if (!(plane->type < 3))
|
if (!(plane->type < 3))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* calculate the split metric, smaller values are better */
|
/* calculate the split metric, smaller values are better */
|
||||||
metric = SplitPlaneMetric(plane, mins, maxs);
|
const vec_t metric = SplitPlaneMetric(plane, mins, maxs);
|
||||||
if (metric < bestmetric) {
|
if (metric < bestmetric) {
|
||||||
bestmetric = metric;
|
bestmetric = metric;
|
||||||
bestsurface = surf;
|
bestsurface = surf;
|
||||||
|
|
@ -327,7 +320,7 @@ ChooseMidPlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
|
|
||||||
if (!bestsurface) {
|
if (!bestsurface) {
|
||||||
/* Choose based on spatial subdivision only */
|
/* Choose based on spatial subdivision only */
|
||||||
for (surf = surfaces; surf; surf = surf->next) {
|
for (surface_t *surf = surfaces; surf; surf = surf->next) {
|
||||||
if (surf->onnode)
|
if (surf->onnode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -336,8 +329,8 @@ ChooseMidPlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
if( !surf->has_struct && !pass )
|
if( !surf->has_struct && !pass )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
plane = &map.planes[surf->planenum];
|
const qbsp_plane_t *plane = &map.planes[surf->planenum];
|
||||||
metric = SplitPlaneMetric(plane, mins, maxs);
|
const vec_t metric = SplitPlaneMetric(plane, mins, maxs);
|
||||||
if (metric < bestmetric) {
|
if (metric < bestmetric) {
|
||||||
bestmetric = metric;
|
bestmetric = metric;
|
||||||
bestsurface = surf;
|
bestsurface = surf;
|
||||||
|
|
@ -377,21 +370,14 @@ The real BSP hueristic
|
||||||
static surface_t *
|
static surface_t *
|
||||||
ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
{
|
{
|
||||||
int pass, splits, minsplits;
|
|
||||||
bool hintsplit;
|
|
||||||
surface_t *surf, *surf2, *bestsurface;
|
|
||||||
vec_t distribution, bestdistribution;
|
|
||||||
const qbsp_plane_t *plane, *plane2;
|
|
||||||
const face_t *face;
|
|
||||||
|
|
||||||
/* pick the plane that splits the least */
|
/* pick the plane that splits the least */
|
||||||
minsplits = INT_MAX - 1;
|
int minsplits = INT_MAX - 1;
|
||||||
bestdistribution = VECT_MAX;
|
vec_t bestdistribution = VECT_MAX;
|
||||||
bestsurface = NULL;
|
surface_t *bestsurface = nullptr;
|
||||||
|
|
||||||
/* Two passes - exhaust all non-detail faces before details */
|
/* Two passes - exhaust all non-detail faces before details */
|
||||||
for (pass = 0; pass < 2; pass++) {
|
for (int pass = 0; pass < 2; pass++) {
|
||||||
for (surf = surfaces; surf; surf = surf->next) {
|
for (surface_t *surf = surfaces; surf; surf = surf->next) {
|
||||||
if (surf->onnode)
|
if (surf->onnode)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -399,8 +385,8 @@ ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
* Check that the surface has a suitable face for the current pass
|
* Check that the surface has a suitable face for the current pass
|
||||||
* and check whether this is a hint split.
|
* and check whether this is a hint split.
|
||||||
*/
|
*/
|
||||||
hintsplit = false;
|
bool hintsplit = false;
|
||||||
for (face = surf->faces; face; face = face->next) {
|
for (const face_t *face = surf->faces; face; face = face->next) {
|
||||||
if (map.mtexinfos.at(face->texinfo).flags & TEX_HINT)
|
if (map.mtexinfos.at(face->texinfo).flags & TEX_HINT)
|
||||||
hintsplit = true;
|
hintsplit = true;
|
||||||
}
|
}
|
||||||
|
|
@ -411,16 +397,16 @@ ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
plane = &map.planes[surf->planenum];
|
const qbsp_plane_t *plane = &map.planes[surf->planenum];
|
||||||
splits = 0;
|
int splits = 0;
|
||||||
|
|
||||||
for (surf2 = surfaces; surf2; surf2 = surf2->next) {
|
for (surface_t *surf2 = surfaces; surf2; surf2 = surf2->next) {
|
||||||
if (surf2 == surf || surf2->onnode)
|
if (surf2 == surf || surf2->onnode)
|
||||||
continue;
|
continue;
|
||||||
plane2 = &map.planes[surf2->planenum];
|
const qbsp_plane_t *plane2 = &map.planes[surf2->planenum];
|
||||||
if (plane->type < 3 && plane->type == plane2->type)
|
if (plane->type < 3 && plane->type == plane2->type)
|
||||||
continue;
|
continue;
|
||||||
for (face = surf2->faces; face; face = face->next) {
|
for (const face_t *face = surf2->faces; face; face = face->next) {
|
||||||
const uint64_t flags = map.mtexinfos.at(face->texinfo).flags;
|
const uint64_t flags = map.mtexinfos.at(face->texinfo).flags;
|
||||||
/* Don't penalize for splitting skip faces */
|
/* Don't penalize for splitting skip faces */
|
||||||
if (flags & TEX_SKIP)
|
if (flags & TEX_SKIP)
|
||||||
|
|
@ -448,7 +434,7 @@ ChoosePlaneFromList(surface_t *surfaces, vec3_t mins, vec3_t maxs)
|
||||||
*/
|
*/
|
||||||
if (splits < minsplits || (splits == minsplits && plane->type < 3)) {
|
if (splits < minsplits || (splits == minsplits && plane->type < 3)) {
|
||||||
if (plane->type < 3) {
|
if (plane->type < 3) {
|
||||||
distribution = SplitPlaneMetric(plane, mins, maxs);
|
const vec_t distribution = SplitPlaneMetric(plane, mins, maxs);
|
||||||
if (distribution > bestdistribution && splits == minsplits)
|
if (distribution > bestdistribution && splits == minsplits)
|
||||||
continue;
|
continue;
|
||||||
bestdistribution = distribution;
|
bestdistribution = distribution;
|
||||||
|
|
@ -481,14 +467,10 @@ returns NULL if the surface list can not be divided any more (a leaf)
|
||||||
static surface_t *
|
static surface_t *
|
||||||
SelectPartition(surface_t *surfaces)
|
SelectPartition(surface_t *surfaces)
|
||||||
{
|
{
|
||||||
int i, surfcount;
|
|
||||||
vec3_t mins, maxs;
|
|
||||||
surface_t *surf, *bestsurface;
|
|
||||||
|
|
||||||
// count onnode surfaces
|
// count onnode surfaces
|
||||||
surfcount = 0;
|
int surfcount = 0;
|
||||||
bestsurface = NULL;
|
surface_t *bestsurface = nullptr;
|
||||||
for (surf = surfaces; surf; surf = surf->next)
|
for (surface_t *surf = surfaces; surf; surf = surf->next)
|
||||||
if (!surf->onnode) {
|
if (!surf->onnode) {
|
||||||
surfcount++;
|
surfcount++;
|
||||||
bestsurface = surf;
|
bestsurface = surf;
|
||||||
|
|
@ -501,12 +483,13 @@ SelectPartition(surface_t *surfaces)
|
||||||
return bestsurface; // this is a final split
|
return bestsurface; // this is a final split
|
||||||
|
|
||||||
// calculate a bounding box of the entire surfaceset
|
// calculate a bounding box of the entire surfaceset
|
||||||
for (i = 0; i < 3; i++) {
|
vec3_t mins, maxs;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
mins[i] = VECT_MAX;
|
mins[i] = VECT_MAX;
|
||||||
maxs[i] = -VECT_MAX;
|
maxs[i] = -VECT_MAX;
|
||||||
}
|
}
|
||||||
for (surf = surfaces; surf; surf = surf->next)
|
for (surface_t *surf = surfaces; surf; surf = surf->next)
|
||||||
for (i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (surf->mins[i] < mins[i])
|
if (surf->mins[i] < mins[i])
|
||||||
mins[i] = surf->mins[i];
|
mins[i] = surf->mins[i];
|
||||||
if (surf->maxs[i] > maxs[i])
|
if (surf->maxs[i] > maxs[i])
|
||||||
|
|
@ -552,11 +535,8 @@ Calculates the bounding box
|
||||||
void
|
void
|
||||||
CalcSurfaceInfo(surface_t *surf)
|
CalcSurfaceInfo(surface_t *surf)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
const face_t *f;
|
|
||||||
|
|
||||||
// calculate a bounding box
|
// calculate a bounding box
|
||||||
for (i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
surf->mins[i] = VECT_MAX;
|
surf->mins[i] = VECT_MAX;
|
||||||
surf->maxs[i] = -VECT_MAX;
|
surf->maxs[i] = -VECT_MAX;
|
||||||
}
|
}
|
||||||
|
|
@ -564,7 +544,7 @@ CalcSurfaceInfo(surface_t *surf)
|
||||||
surf->has_detail = false;
|
surf->has_detail = false;
|
||||||
surf->has_struct = false;
|
surf->has_struct = false;
|
||||||
|
|
||||||
for (f = surf->faces; f; f = f->next) {
|
for (const face_t *f = surf->faces; f; f = f->next) {
|
||||||
if (f->contents[0] >= 0 || f->contents[1] >= 0)
|
if (f->contents[0] >= 0 || f->contents[1] >= 0)
|
||||||
Error("Bad contents in face (%s)", __func__);
|
Error("Bad contents in face (%s)", __func__);
|
||||||
|
|
||||||
|
|
@ -592,8 +572,8 @@ CalcSurfaceInfo(surface_t *surf)
|
||||||
else
|
else
|
||||||
surf->has_struct = true;
|
surf->has_struct = true;
|
||||||
|
|
||||||
for (i = 0; i < f->w.numpoints; i++)
|
for (int i = 0; i < f->w.numpoints; i++)
|
||||||
for (j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
if (f->w.points[i][j] < surf->mins[j])
|
if (f->w.points[i][j] < surf->mins[j])
|
||||||
surf->mins[j] = f->w.points[i][j];
|
surf->mins[j] = f->w.points[i][j];
|
||||||
if (f->w.points[i][j] > surf->maxs[j])
|
if (f->w.points[i][j] > surf->maxs[j])
|
||||||
|
|
@ -610,31 +590,26 @@ DividePlane
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
DividePlane(surface_t *in, qbsp_plane_t *split, surface_t **front,
|
DividePlane(surface_t *in, const qbsp_plane_t *split, surface_t **front,
|
||||||
surface_t **back)
|
surface_t **back)
|
||||||
{
|
{
|
||||||
face_t *facet, *next;
|
const qbsp_plane_t *inplane = &map.planes[in->planenum];
|
||||||
face_t *frontlist, *backlist;
|
|
||||||
face_t *frontfrag, *backfrag;
|
|
||||||
surface_t *newsurf;
|
|
||||||
qbsp_plane_t *inplane;
|
|
||||||
|
|
||||||
inplane = &map.planes[in->planenum];
|
|
||||||
*front = *back = NULL;
|
*front = *back = NULL;
|
||||||
|
|
||||||
// parallel case is easy
|
// parallel case is easy
|
||||||
if (VectorCompare(inplane->normal, split->normal, EQUAL_EPSILON)) {
|
if (VectorCompare(inplane->normal, split->normal, EQUAL_EPSILON)) {
|
||||||
// check for exactly on node
|
// check for exactly on node
|
||||||
if (inplane->dist == split->dist) {
|
if (inplane->dist == split->dist) {
|
||||||
facet = in->faces;
|
face_t *facet = in->faces;
|
||||||
in->faces = NULL;
|
in->faces = NULL;
|
||||||
in->onnode = true;
|
in->onnode = true;
|
||||||
|
|
||||||
// divide the facets to the front and back sides
|
// divide the facets to the front and back sides
|
||||||
newsurf = (surface_t *)AllocMem(SURFACE, 1, true);
|
surface_t *newsurf = (surface_t *)AllocMem(SURFACE, 1, true);
|
||||||
*newsurf = *in;
|
*newsurf = *in;
|
||||||
|
|
||||||
// Prepend each face in facet list to either in or newsurf lists
|
// Prepend each face in facet list to either in or newsurf lists
|
||||||
|
face_t* next;
|
||||||
for (; facet; facet = next) {
|
for (; facet; facet = next) {
|
||||||
next = facet->next;
|
next = facet->next;
|
||||||
if (facet->planeside == 1) {
|
if (facet->planeside == 1) {
|
||||||
|
|
@ -672,11 +647,15 @@ DividePlane(surface_t *in, qbsp_plane_t *split, surface_t **front,
|
||||||
}
|
}
|
||||||
// do a real split. may still end up entirely on one side
|
// do a real split. may still end up entirely on one side
|
||||||
// OPTIMIZE: use bounding box for fast test
|
// OPTIMIZE: use bounding box for fast test
|
||||||
frontlist = NULL;
|
face_t *frontlist = NULL;
|
||||||
backlist = NULL;
|
face_t *backlist = NULL;
|
||||||
|
|
||||||
for (facet = in->faces; facet; facet = next) {
|
face_t *next;
|
||||||
|
for (face_t *facet = in->faces; facet; facet = next) {
|
||||||
next = facet->next;
|
next = facet->next;
|
||||||
|
|
||||||
|
face_t *frontfrag = NULL;
|
||||||
|
face_t *backfrag = NULL;
|
||||||
SplitFace(facet, split, &frontfrag, &backfrag);
|
SplitFace(facet, split, &frontfrag, &backfrag);
|
||||||
if (frontfrag) {
|
if (frontfrag) {
|
||||||
frontfrag->next = frontlist;
|
frontfrag->next = frontlist;
|
||||||
|
|
@ -702,7 +681,7 @@ DividePlane(surface_t *in, qbsp_plane_t *split, surface_t **front,
|
||||||
}
|
}
|
||||||
|
|
||||||
// stuff got split, so allocate one new plane and reuse in
|
// stuff got split, so allocate one new plane and reuse in
|
||||||
newsurf = (surface_t *)AllocMem(SURFACE, 1, true);
|
surface_t *newsurf = (surface_t *)AllocMem(SURFACE, 1, true);
|
||||||
*newsurf = *in;
|
*newsurf = *in;
|
||||||
newsurf->faces = backlist;
|
newsurf->faces = backlist;
|
||||||
*back = newsurf;
|
*back = newsurf;
|
||||||
|
|
@ -721,7 +700,7 @@ DivideNodeBounds
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
DivideNodeBounds(node_t *node, qbsp_plane_t *split)
|
DivideNodeBounds(node_t *node, const qbsp_plane_t *split)
|
||||||
{
|
{
|
||||||
DivideBounds(node->mins, node->maxs, split,
|
DivideBounds(node->mins, node->maxs, split,
|
||||||
node->children[0]->mins, node->children[0]->maxs,
|
node->children[0]->mins, node->children[0]->maxs,
|
||||||
|
|
@ -809,21 +788,17 @@ original faces that have some fragment inside this leaf
|
||||||
static void
|
static void
|
||||||
LinkConvexFaces(surface_t *planelist, node_t *leafnode)
|
LinkConvexFaces(surface_t *planelist, node_t *leafnode)
|
||||||
{
|
{
|
||||||
face_t *f, *next;
|
|
||||||
surface_t *surf, *pnext;
|
|
||||||
int i, count;
|
|
||||||
|
|
||||||
leafnode->faces = NULL;
|
leafnode->faces = NULL;
|
||||||
leafnode->contents = 0;
|
leafnode->contents = 0;
|
||||||
leafnode->planenum = PLANENUM_LEAF;
|
leafnode->planenum = PLANENUM_LEAF;
|
||||||
|
|
||||||
count = 0;
|
int count = 0;
|
||||||
for (surf = planelist; surf; surf = surf->next) {
|
for (surface_t *surf = planelist; surf; surf = surf->next) {
|
||||||
for (f = surf->faces; f; f = f->next) {
|
for (face_t *f = surf->faces; f; f = f->next) {
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
int currentpri = Contents_Priority(leafnode->contents);
|
const int currentpri = Contents_Priority(leafnode->contents);
|
||||||
int fpri = Contents_Priority(f->contents[0]);
|
const int fpri = Contents_Priority(f->contents[0]);
|
||||||
if (fpri > currentpri) {
|
if (fpri > currentpri) {
|
||||||
leafnode->contents = f->contents[0];
|
leafnode->contents = f->contents[0];
|
||||||
}
|
}
|
||||||
|
|
@ -879,10 +854,12 @@ LinkConvexFaces(surface_t *planelist, node_t *leafnode)
|
||||||
leaffaces += count;
|
leaffaces += count;
|
||||||
leafnode->markfaces = (face_t **)AllocMem(OTHER, sizeof(face_t *) * (count + 1), true);
|
leafnode->markfaces = (face_t **)AllocMem(OTHER, sizeof(face_t *) * (count + 1), true);
|
||||||
|
|
||||||
i = 0;
|
int i = 0;
|
||||||
for (surf = planelist; surf; surf = pnext) {
|
surface_t *pnext;
|
||||||
|
for (surface_t *surf = planelist; surf; surf = pnext) {
|
||||||
pnext = surf->next;
|
pnext = surf->next;
|
||||||
for (f = surf->faces; f; f = next) {
|
face_t* next;
|
||||||
|
for (face_t *f = surf->faces; f; f = next) {
|
||||||
next = f->next;
|
next = f->next;
|
||||||
leafnode->markfaces[i] = f->original;
|
leafnode->markfaces[i] = f->original;
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -908,12 +885,11 @@ is returned here (why?)
|
||||||
static face_t *
|
static face_t *
|
||||||
LinkNodeFaces(surface_t *surface)
|
LinkNodeFaces(surface_t *surface)
|
||||||
{
|
{
|
||||||
face_t *f, *newf, **prevptr;
|
|
||||||
face_t *list = NULL;
|
face_t *list = NULL;
|
||||||
|
|
||||||
// subdivide large faces
|
// subdivide large faces
|
||||||
prevptr = &surface->faces;
|
face_t** prevptr = &surface->faces;
|
||||||
f = *prevptr;
|
face_t *f = *prevptr;
|
||||||
while (f) {
|
while (f) {
|
||||||
SubdivideFace(f, prevptr);
|
SubdivideFace(f, prevptr);
|
||||||
prevptr = &(*prevptr)->next;
|
prevptr = &(*prevptr)->next;
|
||||||
|
|
@ -921,9 +897,9 @@ LinkNodeFaces(surface_t *surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy
|
// copy
|
||||||
for (f = surface->faces; f; f = f->next) {
|
for (face_t *f = surface->faces; f; f = f->next) {
|
||||||
nodefaces++;
|
nodefaces++;
|
||||||
newf = (face_t *)AllocMem(FACE, 1, true);
|
face_t *newf = (face_t *)AllocMem(FACE, 1, true);
|
||||||
*newf = *f;
|
*newf = *f;
|
||||||
f->original = newf;
|
f->original = newf;
|
||||||
newf->next = list;
|
newf->next = list;
|
||||||
|
|
@ -942,12 +918,7 @@ PartitionSurfaces
|
||||||
static void
|
static void
|
||||||
PartitionSurfaces(surface_t *surfaces, node_t *node)
|
PartitionSurfaces(surface_t *surfaces, node_t *node)
|
||||||
{
|
{
|
||||||
surface_t *split, *surf, *next;
|
surface_t *split = SelectPartition(surfaces);
|
||||||
surface_t *frontlist, *backlist;
|
|
||||||
surface_t *frontfrag, *backfrag;
|
|
||||||
qbsp_plane_t *splitplane;
|
|
||||||
|
|
||||||
split = SelectPartition(surfaces);
|
|
||||||
if (!split) { // this is a leaf node
|
if (!split) { // this is a leaf node
|
||||||
node->planenum = PLANENUM_LEAF;
|
node->planenum = PLANENUM_LEAF;
|
||||||
|
|
||||||
|
|
@ -966,16 +937,19 @@ PartitionSurfaces(surface_t *surfaces, node_t *node)
|
||||||
node->planenum = split->planenum;
|
node->planenum = split->planenum;
|
||||||
node->detail_separator = split->detail_separator;
|
node->detail_separator = split->detail_separator;
|
||||||
|
|
||||||
splitplane = &map.planes[split->planenum];
|
const qbsp_plane_t *splitplane = &map.planes[split->planenum];
|
||||||
|
|
||||||
DivideNodeBounds(node, splitplane);
|
DivideNodeBounds(node, splitplane);
|
||||||
|
|
||||||
// multiple surfaces, so split all the polysurfaces into front and back lists
|
// multiple surfaces, so split all the polysurfaces into front and back lists
|
||||||
frontlist = NULL;
|
surface_t *frontlist = NULL;
|
||||||
backlist = NULL;
|
surface_t *backlist = NULL;
|
||||||
|
|
||||||
for (surf = surfaces; surf; surf = next) {
|
surface_t *next;
|
||||||
|
for (surface_t *surf = surfaces; surf; surf = next) {
|
||||||
next = surf->next;
|
next = surf->next;
|
||||||
|
|
||||||
|
surface_t *frontfrag, *backfrag;
|
||||||
DividePlane(surf, splitplane, &frontfrag, &backfrag);
|
DividePlane(surf, splitplane, &frontfrag, &backfrag);
|
||||||
if (frontfrag && backfrag) {
|
if (frontfrag && backfrag) {
|
||||||
// the plane was split, which may expose oportunities to merge
|
// the plane was split, which may expose oportunities to merge
|
||||||
|
|
@ -998,8 +972,10 @@ PartitionSurfaces(surface_t *surfaces, node_t *node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PartitionSurfaces(frontlist, node->children[0]);
|
tbb::task_group g;
|
||||||
PartitionSurfaces(backlist, node->children[1]);
|
g.run([&](){ PartitionSurfaces(frontlist, node->children[0]); });
|
||||||
|
g.run([&](){ PartitionSurfaces(backlist, node->children[1]); });
|
||||||
|
g.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1011,9 +987,6 @@ SolidBSP
|
||||||
node_t *
|
node_t *
|
||||||
SolidBSP(const mapentity_t *entity, surface_t *surfhead, bool midsplit)
|
SolidBSP(const mapentity_t *entity, surface_t *surfhead, bool midsplit)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
node_t *headnode;
|
|
||||||
|
|
||||||
if (!surfhead) {
|
if (!surfhead) {
|
||||||
/*
|
/*
|
||||||
* We allow an entity to be constructed with no visible brushes
|
* We allow an entity to be constructed with no visible brushes
|
||||||
|
|
@ -1021,8 +994,8 @@ SolidBSP(const mapentity_t *entity, surface_t *surfhead, bool midsplit)
|
||||||
* collision hull for the engine. Probably could be done a little
|
* collision hull for the engine. Probably could be done a little
|
||||||
* smarter, but this works.
|
* smarter, but this works.
|
||||||
*/
|
*/
|
||||||
headnode = (node_t *)AllocMem(NODE, 1, true);
|
node_t *headnode = (node_t *)AllocMem(NODE, 1, true);
|
||||||
for (i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
headnode->mins[i] = entity->mins[i] - SIDESPACE;
|
headnode->mins[i] = entity->mins[i] - SIDESPACE;
|
||||||
headnode->maxs[i] = entity->maxs[i] + SIDESPACE;
|
headnode->maxs[i] = entity->maxs[i] + SIDESPACE;
|
||||||
}
|
}
|
||||||
|
|
@ -1040,11 +1013,11 @@ SolidBSP(const mapentity_t *entity, surface_t *surfhead, bool midsplit)
|
||||||
|
|
||||||
Message(msgProgress, "SolidBSP");
|
Message(msgProgress, "SolidBSP");
|
||||||
|
|
||||||
headnode = (node_t *)AllocMem(NODE, 1, true);
|
node_t *headnode = (node_t *)AllocMem(NODE, 1, true);
|
||||||
usemidsplit = midsplit;
|
usemidsplit = midsplit;
|
||||||
|
|
||||||
// calculate a bounding box for the entire model
|
// calculate a bounding box for the entire model
|
||||||
for (i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
headnode->mins[i] = entity->mins[i] - SIDESPACE;
|
headnode->mins[i] = entity->mins[i] - SIDESPACE;
|
||||||
headnode->maxs[i] = entity->maxs[i] + SIDESPACE;
|
headnode->maxs[i] = entity->maxs[i] + SIDESPACE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
qbsp/util.cc
16
qbsp/util.cc
|
|
@ -70,11 +70,6 @@ AllocMem(int Type, int cElements, bool fZero)
|
||||||
// Special stuff for face_t
|
// Special stuff for face_t
|
||||||
if (Type == FACE && cElements == 1)
|
if (Type == FACE && cElements == 1)
|
||||||
((face_t *)pTemp)->planenum = -1;
|
((face_t *)pTemp)->planenum = -1;
|
||||||
if (Type == WINDING) {
|
|
||||||
// FIXME: Remove this! Causing UBSan warnings
|
|
||||||
*(int *)pTemp = cSize;
|
|
||||||
pTemp = (char *)pTemp + sizeof(int);
|
|
||||||
}
|
|
||||||
|
|
||||||
rgMemTotal[Type] += cElements;
|
rgMemTotal[Type] += cElements;
|
||||||
rgMemActive[Type] += cElements;
|
rgMemActive[Type] += cElements;
|
||||||
|
|
@ -103,14 +98,9 @@ void
|
||||||
FreeMem(void *pMem, int Type, int cElements)
|
FreeMem(void *pMem, int Type, int cElements)
|
||||||
{
|
{
|
||||||
rgMemActive[Type] -= cElements;
|
rgMemActive[Type] -= cElements;
|
||||||
if (Type == WINDING) {
|
|
||||||
pMem = (char *)pMem - sizeof(int);
|
rgMemActiveBytes[Type] -= cElements * MemSize[Type];
|
||||||
rgMemActiveBytes[Type] -= *(int *)pMem;
|
rgMemActive[GLOBAL] -= cElements * MemSize[Type];
|
||||||
rgMemActive[GLOBAL] -= *(int *)pMem;
|
|
||||||
} else {
|
|
||||||
rgMemActiveBytes[Type] -= cElements * MemSize[Type];
|
|
||||||
rgMemActive[GLOBAL] -= cElements * MemSize[Type];
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pMem);
|
free(pMem);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue