/* =========================================================================== Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). Doom 3 Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Doom 3 Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Doom 3 Source Code. If not, see . In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ #ifndef __BRUSHBSP_H__ #define __BRUSHBSP_H__ #include "idlib/containers/VectorSet.h" #include "idlib/containers/StrList.h" #include "idlib/geometry/Winding.h" #include "idlib/MapFile.h" #include "tools/compilers/aas/Brush.h" /* =============================================================================== BrushBSP =============================================================================== */ class idBrushBSP; class idBrushBSPNode; class idBrushBSPPortal; //=============================================================== // // idBrushBSPPortal // //=============================================================== class idBrushBSPPortal { friend class idBrushBSP; friend class idBrushBSPNode; public: idBrushBSPPortal( void ); ~idBrushBSPPortal( void ); void AddToNodes( idBrushBSPNode *front, idBrushBSPNode *back ); void RemoveFromNode( idBrushBSPNode *l ); void Flip( void ); int Split( const idPlane &splitPlane, idBrushBSPPortal **front, idBrushBSPPortal **back ); idWinding * GetWinding( void ) const { return winding; } const idPlane & GetPlane( void ) const { return plane; } void SetFaceNum( int num ) { faceNum = num; } int GetFaceNum( void ) const { return faceNum; } int GetFlags( void ) const { return flags; } void SetFlag( int flag ) { flags |= flag; } void RemoveFlag( int flag ) { flags &= ~flag; } idBrushBSPPortal * Next( int side ) const { return next[side]; } idBrushBSPNode * GetNode( int side ) const { return nodes[side]; } private: idPlane plane; // portal plane int planeNum; // number of plane this portal is on idWinding * winding; // portal winding idBrushBSPNode * nodes[2]; // nodes this portal seperates idBrushBSPPortal * next[2]; // next portal in list for both nodes int flags; // portal flags int faceNum; // number of the face created for this portal }; //=============================================================== // // idBrushBSPNode // //=============================================================== #define NODE_VISITED BIT(30) #define NODE_DONE BIT(31) class idBrushBSPNode { friend class idBrushBSP; friend class idBrushBSPPortal; public: idBrushBSPNode( void ); ~idBrushBSPNode( void ); void SetContentsFromBrushes( void ); idBounds GetPortalBounds( void ); idBrushBSPNode * GetChild( int index ) const { return children[index]; } idBrushBSPNode * GetParent( void ) const { return parent; } void SetContents( int contents ) { this->contents = contents; } int GetContents( void ) const { return contents; } const idPlane & GetPlane( void ) const { return plane; } idBrushBSPPortal * GetPortals( void ) const { return portals; } void SetAreaNum( int num ) { areaNum = num; } int GetAreaNum( void ) const { return areaNum; } int GetFlags( void ) const { return flags; } void SetFlag( int flag ) { flags |= flag; } void RemoveFlag( int flag ) { flags &= ~flag; } bool TestLeafNode( void ); // remove the flag from nodes found by flooding through portals to nodes with the flag set void RemoveFlagFlood( int flag ); // recurse down the tree and remove the flag from all visited nodes void RemoveFlagRecurse( int flag ); // first recurse down the tree and flood from there void RemoveFlagRecurseFlood( int flag ); // returns side of the plane the node is on int PlaneSide( const idPlane &plane, float epsilon = ON_EPSILON ) const; // split the leaf node with a plane bool Split( const idPlane &splitPlane, int splitPlaneNum ); private: idPlane plane; // split plane if this is not a leaf node idBrush * volume; // node volume int contents; // node contents idBrushList brushList; // list with brushes for this node idBrushBSPNode * parent; // parent of this node idBrushBSPNode * children[2]; // both are NULL if this is a leaf node idBrushBSPPortal * portals; // portals of this node int flags; // node flags int areaNum; // number of the area created for this node int occupied; // true when portal is occupied }; //=============================================================== // // idBrushBSP // //=============================================================== class idBrushBSP { public: idBrushBSP( void ); ~idBrushBSP( void ); // build a bsp tree from a set of brushes void Build( idBrushList brushList, int skipContents, bool (*ChopAllowed)( idBrush *b1, idBrush *b2 ), bool (*MergeAllowed)( idBrush *b1, idBrush *b2 ) ); // remove splits in subspaces with the given contents void PruneTree( int contents ); // portalize the bsp tree void Portalize( void ); // remove subspaces outside the map not reachable by entities bool RemoveOutside( const idMapFile *mapFile, int contents, const idStrList &classNames ); // write file with a trace going through a leak void LeakFile( const idStr &fileName ); // try to merge portals void MergePortals( int skipContents ); // try to merge the two leaf nodes at either side of the portal bool TryMergeLeafNodes( idBrushBSPPortal *portal, int side ); void PruneMergedTree_r( idBrushBSPNode *node ); // melt portal windings void MeltPortals( int skipContents ); // write a map file with a brush for every leaf node that has the given contents void WriteBrushMap( const idStr &fileName, const idStr &ext, int contents ); // bounds for the whole tree const idBounds & GetTreeBounds( void ) const { return treeBounds; } // root node of the tree idBrushBSPNode * GetRootNode( void ) const { return root; } private: idBrushBSPNode * root; idBrushBSPNode * outside; idBounds treeBounds; idPlaneSet portalPlanes; int numGridCells; int numSplits; int numGridCellSplits; int numPrunedSplits; int numPortals; int solidLeafNodes; int outsideLeafNodes; int insideLeafNodes; int numMergedPortals; int numInsertedPoints; idVec3 leakOrigin; int brushMapContents; idBrushMap * brushMap; bool (*BrushChopAllowed)( idBrush *b1, idBrush *b2 ); bool (*BrushMergeAllowed)( idBrush *b1, idBrush *b2 ); private: void RemoveMultipleLeafNodeReferences_r( idBrushBSPNode *node ); void Free_r( idBrushBSPNode *node ); void IncreaseNumSplits( void ); bool IsValidSplitter( const idBrushSide *side ); int BrushSplitterStats( const idBrush *brush, int planeNum, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &stats ); int FindSplitter( idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &bestStats ); void SetSplitterUsed( idBrushBSPNode *node, int planeNum ); idBrushBSPNode * BuildBrushBSP_r( idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, int skipContents ); idBrushBSPNode * ProcessGridCell( idBrushBSPNode *node, int skipContents ); void BuildGrid_r( idList &gridCells, idBrushBSPNode *node ); void PruneTree_r( idBrushBSPNode *node, int contents ); void MakeOutsidePortals( void ); idWinding * BaseWindingForNode( idBrushBSPNode *node ); void MakeNodePortal( idBrushBSPNode *node ); void SplitNodePortals( idBrushBSPNode *node ); void MakeTreePortals_r( idBrushBSPNode *node ); void FloodThroughPortals_r( idBrushBSPNode *node, int contents, int depth ); bool FloodFromOrigin( const idVec3 &origin, int contents ); bool FloodFromEntities( const idMapFile *mapFile, int contents, const idStrList &classNames ); void RemoveOutside_r( idBrushBSPNode *node, int contents ); void SetPortalPlanes_r( idBrushBSPNode *node, idPlaneSet &planeList ); void SetPortalPlanes( void ); void MergePortals_r( idBrushBSPNode *node, int skipContents ); void MergeLeafNodePortals( idBrushBSPNode *node, int skipContents ); void UpdateTreeAfterMerge_r( idBrushBSPNode *node, const idBounds &bounds, idBrushBSPNode *oldNode, idBrushBSPNode *newNode ); void RemoveLeafNodeColinearPoints( idBrushBSPNode *node ); void RemoveColinearPoints_r( idBrushBSPNode *node, int skipContents ); void MeltFlood_r( idBrushBSPNode *node, int skipContents, idBounds &bounds, idVectorSet &vertexList ); void MeltLeafNodePortals( idBrushBSPNode *node, int skipContents, idVectorSet &vertexList ); void MeltPortals_r( idBrushBSPNode *node, int skipContents, idVectorSet &vertexList ); }; #endif /* !__BRUSHBSP_H__ */