29 #include "../../../idlib/precompiled.h"
36 #define BSP_GRID_SIZE 512.0f
37 #define SPLITTER_EPSILON 0.1f
38 #define VERTEX_MELT_EPSILON 0.1f
39 #define VERTEX_MELT_HASH_SIZE 32
41 #define PORTAL_PLANE_NORMAL_EPSILON 0.00001f
42 #define PORTAL_PLANE_DIST_EPSILON 0.01f
113 common->
Error(
"idBrushBSPPortal::RemoveFromNode: portal not in node" );
120 if ( t->
nodes[0] == l ) {
123 else if ( t->
nodes[1] == l ) {
127 common->
Error(
"idBrushBSPPortal::RemoveFromNode: portal not bounding node" );
131 if (
nodes[0] == l ) {
135 else if (
nodes[1] == l ) {
140 common->
Error(
"idBrushBSPPortal::RemoveFromNode: mislinked portal" );
152 frontNode =
nodes[0];
176 (*front) = (*back) =
NULL;
177 winding->
Split( splitPlane, 0.1
f, &frontWinding, &backWinding );
178 if ( frontWinding ) {
180 (*front)->plane =
plane;
182 (*front)->flags =
flags;
183 (*front)->winding = frontWinding;
187 (*back)->plane =
plane;
189 (*back)->flags =
flags;
190 (*back)->winding = backWinding;
193 if ( frontWinding && backWinding ) {
196 else if ( frontWinding ) {
278 s = (p->
nodes[1] ==
this);
302 s = (p->
nodes[1] ==
this);
310 s = (p->
nodes[1] ==
this);
339 s = (p->
nodes[1] ==
this);
341 mid = mid->
Clip( -p->
plane, 0.1f,
false );
344 mid = mid->
Clip( p->
plane, 0.1f,
false );
353 for ( i = 0; i < 2; i++ ) {
362 s = (p->
nodes[1] ==
this);
363 p->
Split( splitPlane, &newPortals[0], &newPortals[1] );
364 for ( i = 0; i < 2; i++ ) {
365 if ( newPortals[i] ) {
381 midPortal->
plane = splitPlane;
382 midPortal->
planeNum = splitPlaneNum;
384 midPortal->
AddToNodes( newNodes[0], newNodes[1] );
404 front = back =
false;
406 s = (p->
nodes[1] ==
this);
590 int i,
j,
num,
s, lastNumSplits;
593 float d, d_front, d_back, brush_front, brush_back;
595 plane = &planeList[planeNum];
612 if ( !(( num ^ planeNum ) >> 1) ) {
613 if ( num == planeNum ) {
618 if ( num == ( planeNum ^ 1 ) ) {
627 brush_front = brush_back = 0.0f;
635 if ( testedPlanes[j] || testedPlanes[j^1] ) {
643 d_front = d_back = 0.0f;
645 d = plane->
Distance( (*w)[j].ToVec3() );
649 else if ( d < d_back ) {
656 if ( d_front > brush_front ) {
657 brush_front = d_front;
659 else if ( d_back < brush_back ) {
665 if ( stats.
numSplits > lastNumSplits && (brush_front < 1.0f || brush_back > -1.0f) ) {
678 int i, planeNum, bestSplitter,
value, bestValue,
f, numBrushSides;
682 memset( testedPlanes, 0, planeList.
Num() *
sizeof(
bool ) );
685 bestValue = -99999999;
700 if ( testedPlanes[planeNum] || testedPlanes[planeNum^1] ) {
704 testedPlanes[planeNum] = testedPlanes[planeNum^1] =
true;
710 memset( &stats, 0,
sizeof( stats ) );
729 if ( value < bestValue ) {
740 if ( value > bestValue ) {
742 bestSplitter = planeNum;
761 int i, numValidBrushSplitters;
768 numValidBrushSplitters = 0;
775 numValidBrushSplitters++;
778 if ( numValidBrushSplitters == 0 ) {
793 planeNum =
FindSplitter( node, planeList, testedPlanes, bestStats );
796 if ( planeNum == -1 ) {
820 node->
plane = planeList[planeNum];
862 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
878 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
882 testedPlanes =
new bool[planeList.
Num()];
888 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
914 halfSize = (bounds[1] - bounds[0]) * 0.5
f;
915 for ( axis = 0; axis < 3; axis++ ) {
922 if ( dist > bounds[0][axis] + 1.0
f && dist < bounds[1][axis] - 1.0
f ) {
989 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
990 for ( i = 0; i < gridCells.
Num(); i++ ) {
995 for ( i = 0; i < gridCells.
Num(); i++ ) {
1040 for ( i = 0; i < 2; i++ ) {
1048 if ( nodes[!s] == node->
children[!i] ) {
1083 #define BASE_WINDING_EPSILON 0.001f
1124 for ( p = node->
portals; p && w; p = p->
next[side] ) {
1125 if ( p->
nodes[0] == node ) {
1129 else if ( p->
nodes[1] == node ) {
1134 common->
Error(
"MakeNodePortal: mislinked portal" );
1160 #define SPLIT_WINDING_EPSILON 0.001f
1169 plane = &node->
plane;
1173 for ( p = node->
portals; p; p = nextPortal ) {
1174 if (p->
nodes[0] == node) {
1177 else if (p->
nodes[1] == node) {
1181 common->
Error(
"idBrushBSP::SplitNodePortals: mislinked portal" );
1183 nextPortal = p->
next[side];
1185 otherNode = p->
nodes[!side];
1192 if ( frontWinding && frontWinding->
IsTiny() ) {
1193 delete frontWinding;
1194 frontWinding =
NULL;
1198 if ( backWinding && backWinding->
IsTiny() ) {
1204 if ( !frontWinding && !backWinding ) {
1209 if ( !frontWinding ) {
1219 if ( !backWinding ) {
1220 delete frontWinding;
1233 newPortal->
winding = backWinding;
1264 if ( bounds[0][0] >= bounds[1][0] ) {
1268 for ( i = 0; i < 3; i++ ) {
1301 for ( i = 0; i < 3; i++ ) {
1302 if ( bounds[0][i] > bounds[1][i] ) {
1314 for ( i = 0; i < 3; i++ ) {
1315 for ( j = 0; j < 2; j++ ) {
1319 normal[
i] = j ? -1 : 1;
1331 for ( i = 0; i < 6; i++ ) {
1332 for ( j = 0; j < 6; j++ ) {
1393 s = (p->
nodes[0] == node);
1402 lineFile->
Printf(
"%f %f %f\n", mid[0], mid[1], mid[2] );
1422 common->
Error(
"FloodThroughPortals_r: node already occupied\n" );
1425 common->
Error(
"FloodThroughPortals_r: NULL node\n" );
1431 s = (p->
nodes[1] == node);
1434 if ( !p->
nodes[!s] ) {
1522 for ( j = 0; j < classNames.
Num(); j++ ) {
1523 if ( classname.
Icmp( classNames[j] ) == 0 ) {
1528 if ( j >= classNames.
Num() ) {
1573 if ( !( node->
contents & contents ) ) {
1625 s = (p->
nodes[1] == node);
1657 for ( p1 = node->
GetPortals(); p1; p1 = nextp1 ) {
1658 s1 = (p1->
GetNode(1) == node);
1659 nextp1 = p1->
Next(s1);
1661 for ( p2 = nextp1; p2; p2 = nextp2 ) {
1662 s2 = (p2->
GetNode(1) == node);
1663 nextp2 = p2->
Next(s2);
1685 for ( p1 = node->
GetPortals(); p1; p1 = nextp1 ) {
1686 s1 = (p1->
GetNode(1) == node);
1687 nextp1 = p1->
Next(s1);
1694 foundPortal =
false;
1695 for ( p2 = node->
GetPortals(); p2; p2 = nextp2 ) {
1696 s2 = (p2->
GetNode(1) == node);
1697 nextp2 = p2->
Next(s2);
1709 if ( !p2 && foundPortal ) {
1710 for ( p2 = node->
GetPortals(); p2; p2 = nextp2 ) {
1711 s2 = (p2->
GetNode(1) == node);
1712 nextp2 = p2->
Next(s2);
1733 for ( p1 = node->
GetPortals(); p1; p1 = nextp1 ) {
1734 s1 = (p1->
GetNode(1) == node);
1735 nextp1 = p1->
Next(s1);
1741 for ( p2 = nextp1; p2; p2 = nextp2 ) {
1742 s2 = (p2->
GetNode(1) == node);
1743 nextp2 = p2->
Next(s2);
1795 if ( node->
contents & skipContents ) {
1837 for ( i = 0; i < 2; i++ ) {
1866 if ( node->
children[0] == oldNode ) {
1869 if ( node->
children[1] == oldNode ) {
1895 int i,
j, k, s1, s2,
s;
1902 nodes[0] = node1 = portal->
nodes[side];
1903 nodes[1] = node2 = portal->
nodes[!side];
1906 for ( i = 0; i < 2; i++ ) {
1910 for ( p1 = nodes[i]->portals; p1; p1 = p1->
next[s1] ) {
1911 s1 = (p1->
nodes[1] == nodes[
i]);
1913 if ( p1->
nodes[!s1] == nodes[j] ) {
1925 for ( p2 = nodes[j]->portals; p2; p2 = p2->
next[s2] ) {
1926 s2 = (p2->
nodes[1] == nodes[
j]);
1928 if ( p2->
nodes[!s2] == nodes[i] ) {
1934 if ( plane.
Distance( (*w)[k].ToVec3() ) < -0.1
f ) {
1943 for ( p = node1->
portals; p; p = nextp ) {
1944 s = (p->
nodes[1] == node1);
1947 if ( p->
nodes[!s] == node2 ) {
1956 s = (p->
nodes[1] == node2);
1968 s = (p->
nodes[1] == node1);
1997 s1 = (p1->
GetNode(1) == node);
2013 s1 = (p1->
GetNode(1) == node);
2052 s1 = (p1->
GetNode(1) == node);
2063 MeltFlood_r( node, skipContents, bounds, vertexList );
2066 for ( i = 0; i < vertexList.
Num(); i++ ) {
2085 if ( node->
contents & skipContents ) {
2109 s1 = (p1->
GetNode(1) == node);
2124 if ( node->
contents & skipContents ) {
bool(* BrushChopAllowed)(idBrush *b1, idBrush *b2)
void GetBounds(idBounds &bounds) const
void Init(const type &mins, const type &maxs, const int boxHashSize, const int initialSize)
void MergePortals(int skipContents)
#define VERTEX_MELT_HASH_SIZE
#define BRUSH_PLANESIDE_BOTH
idMapEntity * GetEntity(int i) const
GLsizei const GLfloat * value
idStr & SetFileExtension(const char *extension)
assert(prefInfo.fullscreenBtn)
const idVec3 & Normal(void) const
bool(* BrushMergeAllowed)(idBrush *b1, idBrush *b2)
int GetContents(void) const
void MeltPortals(int skipContents)
void AddToConvexHull(const idWinding *winding, const idVec3 &normal, const float epsilon=ON_EPSILON)
bool RemoveOutside(const idMapFile *mapFile, int contents, const idStrList &classNames)
float Distance(const idVec3 &v) const
void FloodThroughPortals_r(idBrushBSPNode *node, int contents, int depth)
void CreatePlaneList(idPlaneSet &planeList) const
int GetSavedPlaneSide(void) const
const idWinding * GetWinding(void) const
idWinding * TryMerge(const idWinding &w, const idVec3 &normal, int keep=false) const
int FindSplitter(idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &bestStats)
void MergePortals_r(idBrushBSPNode *node, int skipContents)
const idPlane & GetPlane(void) const
idFileSystem * fileSystem
#define BRUSH_PLANESIDE_BACK
void MakeTreePortals_r(idBrushBSPNode *node)
void SetSplitterUsed(idBrushBSPNode *node, int planeNum)
void Split(const idPlane &plane, int planeNum, idBrushList &frontList, idBrushList &backList, bool useBrushSavedPlaneSide=false)
int BrushSplitterStats(const idBrush *brush, int planeNum, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &stats)
GLint GLint GLsizei GLsizei GLsizei depth
#define VERTEX_MELT_EPSILON
int PlaneSide(const idPlane &plane, float epsilon=ON_EPSILON) const
void Chop(bool(*ChopAllowed)(idBrush *b1, idBrush *b2))
bool TryMergeLeafNodes(idBrushBSPPortal *portal, int side)
idBrushBSPPortal * next[2]
idBrushSide * GetSide(int i) const
idWinding * Reverse(void) const
void SetNormal(const idVec3 &normal)
idWinding * Clip(const idPlane &plane, const float epsilon=ON_EPSILON, const bool keepOn=false)
void WriteBrushMap(const idStr &fileName, const idStr &ext, int contents)
void SplitNodePortals(idBrushBSPNode *node)
void SetPortalPlanes(void)
friend class idBrushBSPPortal
void RemoveFlagRecurse(int flag)
bool InsertPointIfOnEdge(const idVec3 &point, const idPlane &plane, const float epsilon=ON_EPSILON)
int Icmp(const char *text) const
int FindPlane(const idPlane &plane, const float normalEps, const float distEps)
idBrushBSPNode * nodes[2]
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
idBrushBSPPortal * portals
void MergeLeafNodePortals(idBrushBSPNode *node, int skipContents)
#define PORTAL_PLANE_DIST_EPSILON
bool AddPoint(const idVec3 &v)
bool FloodFromEntities(const idMapFile *mapFile, int contents, const idStrList &classNames)
idBrush * Head(void) const
GLuint GLuint GLsizei count
#define BRUSH_PLANESIDE_FACING
int GetNumPoints(void) const
const char * GetString(const char *key, const char *defaultString="") const
GLubyte GLubyte GLubyte GLubyte w
void SetDist(const float dist)
idBrushBSPNode * GetNode(int side) const
int GetNumEntities(void) const
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
bool IsValidSplitter(const idBrushSide *side)
void RemoveColinearPoints_r(idBrushBSPNode *node, int skipContents)
#define SFL_USED_SPLITTER
void MeltFlood_r(idBrushBSPNode *node, int skipContents, idBounds &bounds, idVectorSet< idVec3, 3 > &vertexList)
const idBounds & GetBounds(void) const
int FindVector(const type &v, const float epsilon)
idVec3 GetVector(const char *key, const char *defaultString=NULL) const
virtual idFile * OpenFileWrite(const char *relativePath, const char *basePath="fs_savepath")=0
#define BASE_WINDING_EPSILON
void UpdateTreeAfterMerge_r(idBrushBSPNode *node, const idBounds &bounds, idBrushBSPNode *oldNode, idBrushBSPNode *newNode)
virtual void Printf(const char *fmt,...) id_attribute((format(printf
void RemoveOutside_r(idBrushBSPNode *node, int contents)
int GetContents(void) const
idBounds Expand(const float d) const
void SetPortalPlanes_r(idBrushBSPNode *node, idPlaneSet &planeList)
int Side(const idVec3 &v, const float epsilon=0.0f) const
#define BFL_NO_VALID_SPLITTERS
void RemoveFlagFlood(int flag)
idBrush * Next(void) const
void LeakFile(const idStr &fileName)
idBrushBSPNode * children[2]
int Split(const idPlane &plane, const float epsilon, idWinding **front, idWinding **back) const
int Append(const type &obj)
void MakeNodePortal(idBrushBSPNode *node)
void RemoveLeafNodeColinearPoints(idBrushBSPNode *node)
bool FloodFromOrigin(const idVec3 &origin, int contents)
void BuildGrid_r(idList< idBrushBSPNode * > &gridCells, idBrushBSPNode *node)
struct splitterStats_s splitterStats_t
bool IntersectsBounds(const idBounds &a) const
idWinding * BaseWindingForNode(idBrushBSPNode *node)
idVec3 GetCenter(void) const
#define PORTAL_PLANE_NORMAL_EPSILON
idBrushBSPPortal * GetPortals(void) const
idBounds GetPortalBounds(void)
const idPlane & GetPlane(void) const
#define SPLIT_WINDING_EPSILON
idBrushBSPNode * ProcessGridCell(idBrushBSPNode *node, int skipContents)
#define PLANETYPE_TRUEAXIAL
const char * c_str(void) const
idWinding * GetWinding(void) const
void Build(idBrushList brushList, int skipContents, bool(*ChopAllowed)(idBrush *b1, idBrush *b2), bool(*MergeAllowed)(idBrush *b1, idBrush *b2))
void SetFlagOnFacingBrushSides(const idPlane &plane, int flag)
idBrushBSPPortal * Next(int side) const
void DisplayRealTimeString(char *string,...)
void RemoveFlagRecurseFlood(int flag)
idBounds & ExpandSelf(const float d)
void SetContentsFromBrushes(void)
int Split(const idPlane &splitPlane, idBrushBSPPortal **front, idBrushBSPPortal **back)
if(!ValidDisplayID(prefInfo.prefDisplayID)) prefInfo.prefDisplayID
void RemoveMultipleLeafNodeReferences_r(idBrushBSPNode *node)
bool FromBounds(const idBounds &bounds)
int GetNumSides(void) const
void MeltPortals_r(idBrushBSPNode *node, int skipContents, idVectorSet< idVec3, 3 > &vertexList)
virtual void CloseFile(idFile *f)=0
idBrushBSPNode * BuildBrushBSP_r(idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, int skipContents)
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
bool MergeAllowed(idBrush *b1, idBrush *b2)
void RemoveFromNode(idBrushBSPNode *l)
virtual void Error(const char *fmt,...) id_attribute((format(printf
void WriteBrush(const idBrush *brush)
idBounds GetBounds(void) const
void MakeOutsidePortals(void)
bool ContainsPoint(const idVec3 &p) const
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
void AddToNodes(idBrushBSPNode *front, idBrushBSPNode *back)
void PruneTree(int contents)
void RemoveFlag(int flag)
virtual int Printf(const char *fmt,...) id_attribute((format(printf
void RemoveColinearPoints(const idVec3 &normal, const float epsilon=ON_EPSILON)
#define BRUSH_PLANESIDE_FRONT
void Free_r(idBrushBSPNode *node)
void MeltLeafNodePortals(idBrushBSPNode *node, int skipContents, idVectorSet< idVec3, 3 > &vertexList)
bool Split(const idPlane &splitPlane, int splitPlaneNum)
void PruneTree_r(idBrushBSPNode *node, int contents)
int Split(const idPlane &plane, int planeNum, idBrush **front, idBrush **back) const
void PruneMergedTree_r(idBrushBSPNode *node)