From defdc1c81326656bb88bc491eeb4e718a1940b19 Mon Sep 17 00:00:00 2001 From: LJW-Dev <48092720+LJW-Dev@users.noreply.github.com> Date: Mon, 13 Apr 2026 13:07:43 +0800 Subject: [PATCH] refactor: better implementation of static and script surfaces --- src/ObjLoading/Game/T6/BSP/BSP.h | 8 +- src/ObjLoading/Game/T6/BSP/BSPCreator.cpp | 13 +-- .../Game/T6/BSP/Linker/ClipMapLinker.cpp | 18 +++- .../Game/T6/BSP/Linker/GfxWorldLinker.cpp | 92 +++++++++++-------- 4 files changed, 76 insertions(+), 55 deletions(-) diff --git a/src/ObjLoading/Game/T6/BSP/BSP.h b/src/ObjLoading/Game/T6/BSP/BSP.h index 95e94ebc..670df6a7 100644 --- a/src/ObjLoading/Game/T6/BSP/BSP.h +++ b/src/ObjLoading/Game/T6/BSP/BSP.h @@ -64,14 +64,14 @@ namespace BSP struct BSPWorld { - std::vector surfaces; + + std::vector staticSurfaces; + std::vector scriptSurfaces; + std::vector vertices; std::vector indices; std::vector materials; std::vector xmodels; - - size_t staticSurfaceCount; - std::vector internal_scriptSurfaces; }; enum BSPLightType diff --git a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp index d8129f42..e14bcb90 100644 --- a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp +++ b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp @@ -461,7 +461,7 @@ namespace vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour; CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour); - m_curr_bsp_world->surfaces.emplace_back(surface); + m_curr_bsp_world->staticSurfaces.emplace_back(surface); } return true; @@ -678,7 +678,7 @@ namespace BSPModel model; model.isGfxModel = m_is_world_gfx; - model.surfaceIndex = m_curr_bsp_world->internal_scriptSurfaces.size(); + model.surfaceIndex = m_curr_bsp_world->scriptSurfaces.size(); model.surfaceCount = mesh.primitives.size(); m_bsp->models.emplace_back(model); @@ -709,7 +709,7 @@ namespace vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour; CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour); - m_curr_bsp_world->internal_scriptSurfaces.emplace_back(surface); + m_curr_bsp_world->scriptSurfaces.emplace_back(surface); } return m_bsp->models.size(); // script model index starts at 1 @@ -1154,13 +1154,6 @@ namespace LoadMaterials(jRoot); TraverseNodes(jRoot); // requires materials and lights - - size_t staticSurfaceCount = m_curr_bsp_world->surfaces.size(); - for (auto& model : m_bsp->models) - model.surfaceIndex += staticSurfaceCount; - m_curr_bsp_world->staticSurfaceCount = staticSurfaceCount; - m_curr_bsp_world->surfaces.insert( - m_curr_bsp_world->surfaces.end(), m_curr_bsp_world->internal_scriptSurfaces.begin(), m_curr_bsp_world->internal_scriptSurfaces.end()); } catch (const GltfLoadException& e) { diff --git a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp index 43390e00..ff348e19 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp @@ -270,7 +270,7 @@ namespace BSP std::vector partitionIndexes; for (size_t surfIdx = 0; surfIdx < bspMpdel.surfaceCount; surfIdx++) { - ColSurface& surf = collisionSurfaceVec.at(bspMpdel.surfaceIndex + surfIdx); + ColSurface& surf = collisionSurfaceVec.at(bsp->colWorld.staticSurfaces.size() + bspMpdel.surfaceIndex + surfIdx); for (size_t partitionIdx = 0; partitionIdx < surf.partitionCount; partitionIdx++) { size_t clipMapPartitionIndex = surf.partitionStartIndex + partitionIdx; @@ -712,7 +712,7 @@ namespace BSP } std::unique_ptr tree = std::make_unique(worldMins.x, worldMins.y, worldMins.z, worldMaxs.x, worldMaxs.y, worldMaxs.z, 0); - for (size_t surfIdx = 0; surfIdx < bsp->colWorld.staticSurfaceCount; surfIdx++) // only add the surfaces the player will collide with + for (size_t surfIdx = 0; surfIdx < bsp->colWorld.staticSurfaces.size(); surfIdx++) // only add static surfaces { ColSurface& colSurface = collisionSurfaceVec.at(surfIdx); for (size_t partitionIdx = 0; partitionIdx < colSurface.partitionCount; partitionIdx++) @@ -768,11 +768,23 @@ namespace BSP for (unsigned int vertIdx = 0; vertIdx < clipMap->vertCount; vertIdx++) clipMap->verts[vertIdx] = bsp->colWorld.vertices[vertIdx].pos; + size_t staticSurfaceCount = bsp->colWorld.staticSurfaces.size(); + size_t scriptSurfaceCount = bsp->colWorld.scriptSurfaces.size(); + size_t totalSurfaceCount = staticSurfaceCount + scriptSurfaceCount; + + // TODO: figure out SV_EntityContact and see how it interacts with partitions + std::vector triIndexVec; std::vector partitionVec; std::vector uniqueIndicesVec; - for (BSPSurface& surface : bsp->colWorld.surfaces) + for (size_t surfIdx = 0; surfIdx < totalSurfaceCount; surfIdx++) { + BSPSurface surface; + if (surfIdx < staticSurfaceCount) + surface = bsp->colWorld.staticSurfaces.at(surfIdx); + else + surface = bsp->colWorld.scriptSurfaces.at(surfIdx - staticSurfaceCount); + int indexOfFirstIndex = surface.indexOfFirstIndex; int indexOfFirstTri = surface.indexOfFirstIndex / 3; int indexOfFirstVertex = surface.indexOfFirstVertex; diff --git a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp index 83320f52..43ff731f 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp @@ -53,13 +53,21 @@ namespace BSP { loadDrawData(bsp, gfxWorld); - size_t surfaceCount = bsp->gfxWorld.surfaces.size(); - gfxWorld->surfaceCount = static_cast(surfaceCount); - gfxWorld->dpvs.staticSurfaceCount = static_cast(surfaceCount); - gfxWorld->dpvs.surfaces = m_memory.Alloc(surfaceCount); - for (size_t surfIdx = 0; surfIdx < surfaceCount; surfIdx++) + size_t staticSurfaceCount = bsp->gfxWorld.staticSurfaces.size(); + size_t scriptSurfaceCount = bsp->gfxWorld.scriptSurfaces.size(); + size_t totalSurfaceCount = staticSurfaceCount + scriptSurfaceCount; + + // Static surfaces go first in the array then script surfaces after + gfxWorld->surfaceCount = static_cast(totalSurfaceCount); + gfxWorld->dpvs.staticSurfaceCount = static_cast(staticSurfaceCount); + gfxWorld->dpvs.surfaces = m_memory.Alloc(totalSurfaceCount); + for (size_t surfIdx = 0; surfIdx < totalSurfaceCount; surfIdx++) { - BSPSurface& bspSurface = bsp->gfxWorld.surfaces.at(surfIdx); + BSPSurface bspSurface; + if (surfIdx < staticSurfaceCount) + bspSurface = bsp->gfxWorld.staticSurfaces.at(surfIdx); + else + bspSurface = bsp->gfxWorld.scriptSurfaces.at(surfIdx - staticSurfaceCount); GfxSurface* gfxSurface = &gfxWorld->dpvs.surfaces[surfIdx]; gfxSurface->tris.triCount = bspSurface.triCount; @@ -124,26 +132,26 @@ namespace BSP } // Some code uses Sorted surfs to index surfaces, so for simplicity keep the indexes sequential and from 0 - gfxWorld->dpvs.sortedSurfIndex = m_memory.Alloc(surfaceCount); - for (size_t surfIdx = 0; surfIdx < surfaceCount; surfIdx++) + gfxWorld->dpvs.sortedSurfIndex = m_memory.Alloc(staticSurfaceCount); + for (size_t surfIdx = 0; surfIdx < staticSurfaceCount; surfIdx++) gfxWorld->dpvs.sortedSurfIndex[surfIdx] = static_cast(surfIdx); // surface materials are written to by the game - gfxWorld->dpvs.surfaceMaterials = m_memory.Alloc(surfaceCount); + gfxWorld->dpvs.surfaceMaterials = m_memory.Alloc(staticSurfaceCount); // set all surface types to lit opaque gfxWorld->dpvs.litSurfsBegin = 0; - gfxWorld->dpvs.litSurfsEnd = static_cast(surfaceCount); - gfxWorld->dpvs.emissiveOpaqueSurfsBegin = static_cast(surfaceCount); - gfxWorld->dpvs.emissiveOpaqueSurfsEnd = static_cast(surfaceCount); - gfxWorld->dpvs.emissiveTransSurfsBegin = static_cast(surfaceCount); - gfxWorld->dpvs.emissiveTransSurfsEnd = static_cast(surfaceCount); - gfxWorld->dpvs.litTransSurfsBegin = static_cast(surfaceCount); - gfxWorld->dpvs.litTransSurfsEnd = static_cast(surfaceCount); + gfxWorld->dpvs.litSurfsEnd = static_cast(staticSurfaceCount); + gfxWorld->dpvs.emissiveOpaqueSurfsBegin = static_cast(staticSurfaceCount); + gfxWorld->dpvs.emissiveOpaqueSurfsEnd = static_cast(staticSurfaceCount); + gfxWorld->dpvs.emissiveTransSurfsBegin = static_cast(staticSurfaceCount); + gfxWorld->dpvs.emissiveTransSurfsEnd = static_cast(staticSurfaceCount); + gfxWorld->dpvs.litTransSurfsBegin = static_cast(staticSurfaceCount); + gfxWorld->dpvs.litTransSurfsEnd = static_cast(staticSurfaceCount); // visdata is written to by the game // all visdata is alligned by 128 - size_t allignedSurfaceCount = BSPUtil::allignBy128(surfaceCount); + size_t allignedSurfaceCount = BSPUtil::allignBy128(staticSurfaceCount); gfxWorld->dpvs.surfaceVisDataCount = static_cast(allignedSurfaceCount); gfxWorld->dpvs.surfaceVisData[0] = m_memory.Alloc(allignedSurfaceCount); gfxWorld->dpvs.surfaceVisData[1] = m_memory.Alloc(allignedSurfaceCount); @@ -507,7 +515,7 @@ namespace BSP gfxWorld->cells[0].aabbTree[0].childCount = 0; gfxWorld->cells[0].aabbTree[0].childrenOffset = 0; gfxWorld->cells[0].aabbTree[0].startSurfIndex = 0; - gfxWorld->cells[0].aabbTree[0].surfaceCount = static_cast(gfxWorld->surfaceCount); + gfxWorld->cells[0].aabbTree[0].surfaceCount = static_cast(gfxWorld->dpvs.staticSurfaceCount); gfxWorld->cells[0].aabbTree[0].smodelIndexCount = static_cast(gfxWorld->dpvs.smodelCount); gfxWorld->cells[0].aabbTree[0].smodelIndexes = m_memory.Alloc(gfxWorld->dpvs.smodelCount); for (unsigned short smodelIdx = 0; smodelIdx < gfxWorld->dpvs.smodelCount; smodelIdx++) @@ -537,16 +545,17 @@ namespace BSP void GfxWorldLinker::loadWorldBounds(GfxWorld* gfxWorld) { - gfxWorld->mins.x = gfxWorld->dpvs.surfaces[0].bounds[0].x; - gfxWorld->mins.y = gfxWorld->dpvs.surfaces[0].bounds[0].y; - gfxWorld->mins.z = gfxWorld->dpvs.surfaces[0].bounds[0].z; - gfxWorld->maxs.x = gfxWorld->dpvs.surfaces[0].bounds[1].x; - gfxWorld->maxs.y = gfxWorld->dpvs.surfaces[0].bounds[1].y; - gfxWorld->maxs.z = gfxWorld->dpvs.surfaces[0].bounds[1].z; + gfxWorld->mins = gfxWorld->dpvs.surfaces[0].bounds[0]; + gfxWorld->maxs = gfxWorld->dpvs.surfaces[0].bounds[1]; for (int surfIdx = 0; surfIdx < gfxWorld->surfaceCount; surfIdx++) { BSPUtil::updateAABB(gfxWorld->dpvs.surfaces[surfIdx].bounds[0], gfxWorld->dpvs.surfaces[surfIdx].bounds[1], gfxWorld->mins, gfxWorld->maxs); } + + for (unsigned int smodeldx = 0; smodeldx < gfxWorld->dpvs.smodelCount; smodeldx++) + { + BSPUtil::updateAABB(gfxWorld->dpvs.smodelInsts[smodeldx].mins, gfxWorld->dpvs.smodelInsts[smodeldx].maxs, gfxWorld->mins, gfxWorld->maxs); + } } void GfxWorldLinker::loadModels(BSPData* bsp, GfxWorld* gfxWorld) @@ -557,27 +566,34 @@ namespace BSP // first model is always the world model gfxWorld->models[0].startSurfIndex = 0; - gfxWorld->models[0].surfaceCount = static_cast(gfxWorld->surfaceCount); - gfxWorld->models[0].bounds[0].x = gfxWorld->mins.x; - gfxWorld->models[0].bounds[0].y = gfxWorld->mins.y; - gfxWorld->models[0].bounds[0].z = gfxWorld->mins.z; - gfxWorld->models[0].bounds[1].x = gfxWorld->maxs.x; - gfxWorld->models[0].bounds[1].y = gfxWorld->maxs.y; - gfxWorld->models[0].bounds[1].z = gfxWorld->maxs.z; + gfxWorld->models[0].surfaceCount = static_cast(gfxWorld->dpvs.staticSurfaceCount); + for (unsigned int surfIdx = 0; surfIdx < gfxWorld->dpvs.staticSurfaceCount; surfIdx++) + { + if (surfIdx == 0) + { + gfxWorld->models[0].bounds[0] = gfxWorld->dpvs.surfaces[surfIdx].bounds[0]; + gfxWorld->models[0].bounds[1] = gfxWorld->dpvs.surfaces[surfIdx].bounds[1]; + } + else + BSPUtil::updateAABB(gfxWorld->dpvs.surfaces[surfIdx].bounds[0], + gfxWorld->dpvs.surfaces[surfIdx].bounds[1], + gfxWorld->models[0].bounds[0], + gfxWorld->models[0].bounds[1]); + } memset(&gfxWorld->models[0].writable, 0, sizeof(GfxBrushModelWritable)); for (size_t modelIdx = 0; modelIdx < bsp->models.size(); modelIdx++) { auto currEntModel = &gfxWorld->models[modelIdx + 1]; - auto& bspMpdel = bsp->models.at(modelIdx); + auto& bspModel = bsp->models.at(modelIdx); - if (bspMpdel.isGfxModel) + if (bspModel.isGfxModel) { - currEntModel->startSurfIndex = bspMpdel.surfaceIndex; - currEntModel->surfaceCount = bspMpdel.surfaceCount; - for (size_t surfIdx = 0; surfIdx < bspMpdel.surfaceCount; surfIdx++) + currEntModel->startSurfIndex = bsp->gfxWorld.staticSurfaces.size() + bspModel.surfaceIndex; + currEntModel->surfaceCount = bspModel.surfaceCount; + for (size_t surfIdx = 0; surfIdx < bspModel.surfaceCount; surfIdx++) { - GfxSurface* surf = &gfxWorld->dpvs.surfaces[bspMpdel.surfaceIndex + surfIdx]; + GfxSurface* surf = &gfxWorld->dpvs.surfaces[currEntModel->startSurfIndex + surfIdx]; if (surfIdx == 0) { currEntModel->bounds[0] = surf->bounds[0]; @@ -817,7 +833,7 @@ namespace BSP if (!loadReflectionProbeData(gfxWorld)) return nullptr; - // world bounds are based on loaded surface mins/maxs + // world bounds are based on loaded surface mins/maxs and xmodels loadWorldBounds(gfxWorld); if (!loadOutdoors(gfxWorld))