//===================================================================================== // FreePortal //===================================================================================== geBoolean FreePortal(GBSP_Portal *Portal) { if (!Portal->Poly) { GHook.Error("FreePortal: Portal with NULL Poly.\n"); return GE_FALSE; } FreePoly(Portal->Poly); geRam_Free(Portal); return GE_TRUE; }
//================================================================================ // FreeAllVisData //================================================================================ void FreeAllVisData(void) { int32 i; if (LeafVisBits) geRam_Free(LeafVisBits); LeafVisBits = NULL; GFXVisData = NULL; NumGFXVisData = 0; if (VisPortals) { for (i=0; i< NumVisPortals; i++) { FreePoly(VisPortals[i].Poly); if (VisPortals[i].FinalVisBits) geRam_Free(VisPortals[i].FinalVisBits); if (VisPortals[i].VisBits) geRam_Free(VisPortals[i].VisBits); } geRam_Free(VisPortals); } if (VisSortedPortals) geRam_Free(VisSortedPortals); if (PortalSeen) geRam_Free(PortalSeen); if (VisLeafs) geRam_Free(VisLeafs); VisPortals = NULL; VisSortedPortals = NULL; PortalSeen = NULL; VisLeafs = NULL; FreeGBSPFile(); // Free rest of GBSP GFX data }
//===================================================================================== // PartitionPortals_r //===================================================================================== geBoolean PartitionPortals_r(GBSP_Node *Node) { GBSP_Poly *NewPoly, *FPoly, *BPoly; GBSP_Plane *pPlane, *pPlane2; GBSP_Portal *Portal, *NewPortal, *Next; GBSP_Node *Front, *Back, *OtherNode; int32 Side; CalcNodeBoundsFromPortals(Node); if (Node->PlaneNum == PLANENUM_LEAF) return GE_TRUE; if (VisPortals && Node->Detail) // We can stop at detail seperators for the vis tree return GE_TRUE; //if (!InitializeNodePortal(Node)) // return GE_FALSE; //if (!DistributeNodePortalsToChildren(Node)) // return GE_FALSE; Front = Node->Children[0]; Back = Node->Children[1]; pPlane = &Planes[Node->PlaneNum]; // Create a new portal if (!CreatePolyOnNode (Node, &NewPoly)) { GHook.Error("PartitionPortals_r: CreatePolyOnNode failed.\n"); return GE_FALSE; } // Clip it against all other portals attached to this node for (Portal = Node->Portals; Portal && NewPoly; Portal = Portal->Next[Side]) { if (Portal->Nodes[0] == Node) Side = 0; else if (Portal->Nodes[1] == Node) Side = 1; else { GHook.Error("PartitionPortals_r: Portal does not look at either node.\n"); return GE_FALSE; } pPlane2 = &Planes[Portal->PlaneNum]; if (!ClipPolyEpsilon(NewPoly, 0.001f, pPlane2, Side, &NewPoly)) { GHook.Error("PartitionPortals_r: There was an error clipping the poly.\n"); return GE_FALSE; } if (!NewPoly) { GHook.Printf("PartitionPortals_r: Portal was cut away.\n"); break; } } if (NewPoly && PolyIsTiny (NewPoly)) { FreePoly(NewPoly); NewPoly = NULL; } if (NewPoly) { NewPortal = AllocPortal(); if (!NewPortal) { GHook.Error("PartitionPortals_r: Out of memory for portal.\n"); return GE_FALSE; } NewPortal->Poly = NewPoly; NewPortal->PlaneNum = Node->PlaneNum; NewPortal->OnNode = Node; if (!CheckPortal(NewPortal)) { GHook.Error("PartiionPortals_r: Check Portal failed.\n"); return GE_FALSE; } else AddPortalToNodes(NewPortal, Front, Back); } // Partition all portals by this node for (Portal = Node->Portals; Portal; Portal = Next) { if (Portal->Nodes[0] == Node) Side = 0; else if (Portal->Nodes[1] == Node) Side = 1; else { GHook.Error("PartitionPortals_r: Portal does not look at either node.\n"); return GE_FALSE; } Next = Portal->Next[Side]; // Remember the node on the back side OtherNode = Portal->Nodes[!Side]; RemovePortalFromNode(Portal, Portal->Nodes[0]); RemovePortalFromNode(Portal, Portal->Nodes[1]); if (!SplitPolyEpsilon(Portal->Poly, 0.001f, pPlane, &FPoly, &BPoly, GE_FALSE)) { GHook.Error("PartitionPortals_r: Could not split portal.\n"); return GE_FALSE; } if (FPoly && PolyIsTiny(FPoly)) { FreePoly(FPoly); FPoly = NULL; } if (BPoly && PolyIsTiny(BPoly)) { FreePoly(BPoly); BPoly = NULL; } if (!FPoly && !BPoly) continue; if (!FPoly) { Portal->Poly = BPoly; if (Side) AddPortalToNodes(Portal, OtherNode, Back); else AddPortalToNodes(Portal, Back, OtherNode); continue; } if (!BPoly) { Portal->Poly = FPoly; if (Side) AddPortalToNodes(Portal, OtherNode, Front); else AddPortalToNodes(Portal, Front, OtherNode); continue; } // Portal was split NewPortal = AllocPortal(); if (!NewPortal) { GHook.Error("PartitionPortals_r: Out of memory for portal.\n"); return GE_FALSE; } Portal->Poly = FPoly; *NewPortal = *Portal; NewPortal->Poly = BPoly; if (Side) { AddPortalToNodes(Portal, OtherNode, Front); AddPortalToNodes(NewPortal, OtherNode, Back); } else { AddPortalToNodes(Portal, Front, OtherNode); AddPortalToNodes(NewPortal, Back, OtherNode); } } if (Node->Portals != NULL) { GHook.Printf("*WARNING* PartitionPortals_r: Portals still on node after distribution...\n"); } if (!PartitionPortals_r(Front)) return GE_FALSE; if (!PartitionPortals_r(Back)) return GE_FALSE; return GE_TRUE; }
//======================================================================================= // LoadPortalFile //======================================================================================= geBoolean LoadPortalFile(char *FileName) { int32 LeafFrom, LeafTo; VIS_Portal *pPortal; VIS_Leaf *pLeaf; GBSP_Poly *pPoly; int32 i, NumVerts; char TAG[13]; geVFile *f; pPoly = NULL; // open the file f = geVFile_OpenNewSystem(NULL, GE_VFILE_TYPE_DOS, FileName, NULL, GE_VFILE_OPEN_READONLY); if (!f) // opps { GHook.Error("LoadPortalFile: Could not open %s for reading.\n", FileName); goto ExitWithError; } // // Check the TAG // if (geVFile_Read(f, TAG, sizeof(char) * 12) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading portal file TAG.\n"); goto ExitWithError; } if (strncmp(TAG, "GBSP_PRTFILE", 12)) { GHook.Error("LoadPortalFile: %s is not a GBSP Portal file.\n", FileName); goto ExitWithError; } // // Get the number of portals // if (geVFile_Read(f, &NumVisPortals, sizeof(int32)) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading NumVisPortals.\n"); goto ExitWithError; } if (NumVisPortals >= MAX_TEMP_PORTALS) { GHook.Error("LoadPortalFile: Max portals for temp buffers.\n"); goto ExitWithError; } VisPortals = GE_RAM_ALLOCATE_ARRAY(VIS_Portal,NumVisPortals); if (!VisPortals) { GHook.Error("LoadPortalFile: Out of memory for VisPortals.\n"); goto ExitWithError; } memset(VisPortals, 0, sizeof(VIS_Portal)*NumVisPortals); VisSortedPortals = GE_RAM_ALLOCATE_ARRAY(pVIS_Portal,NumVisPortals); if (!VisSortedPortals) { GHook.Error("LoadPortalFile: Out of memory for VisSortedPortals.\n"); goto ExitWithError; } // // Get the number of leafs // if (geVFile_Read(f, &NumVisLeafs, sizeof(int32)) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading NumVisLeafs.\n"); goto ExitWithError; } if (NumVisLeafs > NumGFXLeafs) goto ExitWithError; VisLeafs = GE_RAM_ALLOCATE_ARRAY(VIS_Leaf,NumVisLeafs); if (!VisLeafs) { GHook.Error("LoadPortalFile: Out of memory for VisLeafs.\n"); goto ExitWithError; } memset(VisLeafs, 0, sizeof(VIS_Leaf)*NumVisLeafs); // // Load in the portals // for (i=0; i< NumVisPortals; i++) { if (geVFile_Read(f, &NumVerts, sizeof(int32)) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading NumVerts.\n"); goto ExitWithError; } pPoly = AllocPoly(NumVerts); if (!pPoly) goto ExitWithError; if (geVFile_Read(f, pPoly->Verts, sizeof(geVec3d) * NumVerts) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading portal vertices.\n"); goto ExitWithError; } if (geVFile_Read(f, &LeafFrom, sizeof(int32)) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading portal LeafFrom.\n"); goto ExitWithError; } if (geVFile_Read(f, &LeafTo, sizeof(int32)) != GE_TRUE) { GHook.Error("LoadPortalFile: Error reading portal LeafTo.\n"); goto ExitWithError; } if (LeafFrom >= NumVisLeafs || LeafFrom < 0) { GHook.Error("LoadPortalFile: Invalid LeafFrom: %i.\n", LeafFrom); goto ExitWithError; } if (LeafTo >= NumVisLeafs || LeafTo < 0) { GHook.Error("LoadPortalFile: Invalid LeafTo: %i.\n", LeafTo); goto ExitWithError; } pLeaf = &VisLeafs[LeafFrom]; pPortal = &VisPortals[i]; pPortal->Poly = pPoly; pPortal->Leaf = LeafTo; PlaneFromVerts(pPoly->Verts, &pPortal->Plane); pPortal->Next = pLeaf->Portals; pLeaf->Portals = pPortal; CalcPortalInfo(pPortal); } NumVisLeafBytes = ((NumVisLeafs+63)&~63) >> 3; NumVisPortalBytes = ((NumVisPortals+63)&~63) >> 3; NumVisPortalLongs = NumVisPortalBytes/sizeof(uint32); NumVisLeafLongs = NumVisLeafBytes/sizeof(uint32); geVFile_Close(f); return GE_TRUE; // ==== ERROR === ExitWithError: { if (f) geVFile_Close(f); if (VisPortals) geRam_Free(VisPortals); if (VisSortedPortals) geRam_Free(VisSortedPortals); if (VisLeafs) geRam_Free(VisLeafs); if (pPoly) FreePoly(pPoly); VisPortals = NULL; VisSortedPortals = NULL; VisLeafs = NULL; pPoly = NULL; return GE_FALSE; } }