/* ============ idAASBuild::GravitationalSubdivision ============ */ void idAASBuild::GravitationalSubdivision( idBrushBSP &bsp ) { numGravitationalSubdivisions = 0; common->Printf( "[Gravitational Subdivision]\n" ); SetPortalFlags_r( bsp.GetRootNode() ); GravSubdiv_r( bsp.GetRootNode() ); common->Printf( "\r%6d subdivisions\n", numGravitationalSubdivisions ); }
/* ============ idAASBuild::MergeLeafNodes ============ */ void idAASBuild::MergeLeafNodes( idBrushBSP &bsp ) { numMergedLeafNodes = 0; common->Printf( "[Merge Leaf Nodes]\n" ); MergeLeafNodes_r( bsp, bsp.GetRootNode() ); bsp.GetRootNode()->RemoveFlagRecurse( NODE_DONE ); bsp.PruneMergedTree_r( bsp.GetRootNode() ); common->Printf( "\r%6d leaf nodes merged\n", numMergedLeafNodes ); }
/* ============ idAASBuild::LedgeSubdivision NOTE: this assumes the bounding box is higher than the maximum step height only ledges with vertical sides are considered ============ */ void idAASBuild::LedgeSubdivision( idBrushBSP &bsp ) { numLedgeSubdivisions = 0; ledgeList.Clear(); common->Printf( "[Ledge Subdivision]\n" ); bsp.GetRootNode()->RemoveFlagRecurse( NODE_VISITED ); FindLedges_r( bsp.GetRootNode(), bsp.GetRootNode() ); bsp.GetRootNode()->RemoveFlagRecurse( NODE_VISITED ); common->Printf( "\r%6d ledges\n", ledgeList.Num() ); LedgeSubdiv( bsp.GetRootNode() ); common->Printf( "\r%6d subdivisions\n", numLedgeSubdivisions ); }
/* ================ idAASBuild::StoreFile ================ */ bool idAASBuild::StoreFile( const idBrushBSP& bsp ) { aasEdge_t edge; aasFace_t face; aasArea_t area; aasNode_t node; common->Printf( "[Store AAS]\n" ); SetupHash(); ClearHash( bsp.GetTreeBounds() ); file = new idAASFileLocal(); file->Clear(); SetSizeEstimate( bsp, file ); // the first edge is a dummy memset( &edge, 0, sizeof( edge ) ); file->edges.Append( edge ); // the first face is a dummy memset( &face, 0, sizeof( face ) ); file->faces.Append( face ); // the first area is a dummy memset( &area, 0, sizeof( area ) ); file->areas.Append( area ); // the first node is a dummy memset( &node, 0, sizeof( node ) ); file->nodes.Append( node ); // store the tree StoreTree_r( bsp.GetRootNode() ); // calculate area bounds and a reachable point in the area file->FinishAreas(); ShutdownHash(); common->Printf( "\r%6d areas\n", file->areas.Num() ); return true; }
/* ============ idAASBuild::MergeWithAdjacentLeafNodes ============ */ bool idAASBuild::MergeWithAdjacentLeafNodes( idBrushBSP &bsp, idBrushBSPNode *node ) { int s, numMerges = 0, otherNodeFlags; idBrushBSPPortal *p; do { for ( p = node->GetPortals(); p; p = p->Next(s) ) { s = (p->GetNode(1) == node); // both leaf nodes must have the same contents if ( node->GetContents() != p->GetNode(!s)->GetContents() ) { continue; } // cannot merge leaf nodes if one is near a ledge and the other is not if ( (node->GetFlags() & AREA_LEDGE) != (p->GetNode(!s)->GetFlags() & AREA_LEDGE) ) { continue; } // cannot merge leaf nodes if one has a floor portal and the other a gap portal if ( node->GetFlags() & AREA_FLOOR ) { if ( p->GetNode(!s)->GetFlags() & AREA_GAP ) { if ( !AllGapsLeadToOtherNode( p->GetNode(!s), node ) ) { continue; } } } else if ( node->GetFlags() & AREA_GAP ) { if ( p->GetNode(!s)->GetFlags() & AREA_FLOOR ) { if ( !AllGapsLeadToOtherNode( node, p->GetNode(!s) ) ) { continue; } } } otherNodeFlags = p->GetNode(!s)->GetFlags(); // try to merge the leaf nodes if ( bsp.TryMergeLeafNodes( p, s ) ) { node->SetFlag( otherNodeFlags ); if ( node->GetFlags() & AREA_FLOOR ) { node->RemoveFlag( AREA_GAP ); } numMerges++; DisplayRealTimeString( "\r%6d", ++numMergedLeafNodes ); break; } } } while( p ); if ( numMerges ) { return true; } return false; }
/* ================ idAASBuild::SetSizeEstimate ================ */ void idAASBuild::SetSizeEstimate( const idBrushBSP &bsp, idAASFileLocal *file ) { sizeEstimate_t size; size.numEdgeIndexes = 1; size.numFaceIndexes = 1; size.numAreas = 1; size.numNodes = 1; GetSizeEstimate_r( NULL, bsp.GetRootNode(), size ); file->planeList.Resize( size.numNodes / 2, 1024 ); file->vertices.Resize( size.numEdgeIndexes / 3, 1024 ); file->edges.Resize( size.numEdgeIndexes / 2, 1024 ); file->edgeIndex.Resize( size.numEdgeIndexes, 4096 ); file->faces.Resize( size.numFaceIndexes, 1024 ); file->faceIndex.Resize( size.numFaceIndexes, 4096 ); file->areas.Resize( size.numAreas, 1024 ); file->nodes.Resize( size.numNodes, 1024 ); }