2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 08:42:35 +00:00

refactor: better implementation of static and script surfaces

This commit is contained in:
LJW-Dev
2026-04-13 13:07:43 +08:00
committed by Jan Laupetin
parent 026109dda7
commit defdc1c813
4 changed files with 76 additions and 55 deletions
+4 -4
View File
@@ -64,14 +64,14 @@ namespace BSP
struct BSPWorld struct BSPWorld
{ {
std::vector<BSPSurface> surfaces;
std::vector<BSPSurface> staticSurfaces;
std::vector<BSPSurface> scriptSurfaces;
std::vector<BSPVertex> vertices; std::vector<BSPVertex> vertices;
std::vector<uint16_t> indices; std::vector<uint16_t> indices;
std::vector<BSPMaterial> materials; std::vector<BSPMaterial> materials;
std::vector<BSPXModel> xmodels; std::vector<BSPXModel> xmodels;
size_t staticSurfaceCount;
std::vector<BSPSurface> internal_scriptSurfaces;
}; };
enum BSPLightType enum BSPLightType
+3 -10
View File
@@ -461,7 +461,7 @@ namespace
vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour; vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour;
CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour); CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour);
m_curr_bsp_world->surfaces.emplace_back(surface); m_curr_bsp_world->staticSurfaces.emplace_back(surface);
} }
return true; return true;
@@ -678,7 +678,7 @@ namespace
BSPModel model; BSPModel model;
model.isGfxModel = m_is_world_gfx; 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(); model.surfaceCount = mesh.primitives.size();
m_bsp->models.emplace_back(model); m_bsp->models.emplace_back(model);
@@ -709,7 +709,7 @@ namespace
vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour; vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour;
CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour); 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 return m_bsp->models.size(); // script model index starts at 1
@@ -1154,13 +1154,6 @@ namespace
LoadMaterials(jRoot); LoadMaterials(jRoot);
TraverseNodes(jRoot); // requires materials and lights 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) catch (const GltfLoadException& e)
{ {
@@ -270,7 +270,7 @@ namespace BSP
std::vector<int> partitionIndexes; std::vector<int> partitionIndexes;
for (size_t surfIdx = 0; surfIdx < bspMpdel.surfaceCount; surfIdx++) 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++) for (size_t partitionIdx = 0; partitionIdx < surf.partitionCount; partitionIdx++)
{ {
size_t clipMapPartitionIndex = surf.partitionStartIndex + partitionIdx; size_t clipMapPartitionIndex = surf.partitionStartIndex + partitionIdx;
@@ -712,7 +712,7 @@ namespace BSP
} }
std::unique_ptr<BSPTree> tree = std::make_unique<BSPTree>(worldMins.x, worldMins.y, worldMins.z, worldMaxs.x, worldMaxs.y, worldMaxs.z, 0); std::unique_ptr<BSPTree> tree = std::make_unique<BSPTree>(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); ColSurface& colSurface = collisionSurfaceVec.at(surfIdx);
for (size_t partitionIdx = 0; partitionIdx < colSurface.partitionCount; partitionIdx++) for (size_t partitionIdx = 0; partitionIdx < colSurface.partitionCount; partitionIdx++)
@@ -768,11 +768,23 @@ namespace BSP
for (unsigned int vertIdx = 0; vertIdx < clipMap->vertCount; vertIdx++) for (unsigned int vertIdx = 0; vertIdx < clipMap->vertCount; vertIdx++)
clipMap->verts[vertIdx] = bsp->colWorld.vertices[vertIdx].pos; 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<uint16_t> triIndexVec; std::vector<uint16_t> triIndexVec;
std::vector<CollisionPartition> partitionVec; std::vector<CollisionPartition> partitionVec;
std::vector<uint16_t> uniqueIndicesVec; std::vector<uint16_t> 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 indexOfFirstIndex = surface.indexOfFirstIndex;
int indexOfFirstTri = surface.indexOfFirstIndex / 3; int indexOfFirstTri = surface.indexOfFirstIndex / 3;
int indexOfFirstVertex = surface.indexOfFirstVertex; int indexOfFirstVertex = surface.indexOfFirstVertex;
@@ -53,13 +53,21 @@ namespace BSP
{ {
loadDrawData(bsp, gfxWorld); loadDrawData(bsp, gfxWorld);
size_t surfaceCount = bsp->gfxWorld.surfaces.size(); size_t staticSurfaceCount = bsp->gfxWorld.staticSurfaces.size();
gfxWorld->surfaceCount = static_cast<int>(surfaceCount); size_t scriptSurfaceCount = bsp->gfxWorld.scriptSurfaces.size();
gfxWorld->dpvs.staticSurfaceCount = static_cast<unsigned int>(surfaceCount); size_t totalSurfaceCount = staticSurfaceCount + scriptSurfaceCount;
gfxWorld->dpvs.surfaces = m_memory.Alloc<GfxSurface>(surfaceCount);
for (size_t surfIdx = 0; surfIdx < surfaceCount; surfIdx++) // Static surfaces go first in the array then script surfaces after
gfxWorld->surfaceCount = static_cast<int>(totalSurfaceCount);
gfxWorld->dpvs.staticSurfaceCount = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.surfaces = m_memory.Alloc<GfxSurface>(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* gfxSurface = &gfxWorld->dpvs.surfaces[surfIdx];
gfxSurface->tris.triCount = bspSurface.triCount; 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 // Some code uses Sorted surfs to index surfaces, so for simplicity keep the indexes sequential and from 0
gfxWorld->dpvs.sortedSurfIndex = m_memory.Alloc<uint16_t>(surfaceCount); gfxWorld->dpvs.sortedSurfIndex = m_memory.Alloc<uint16_t>(staticSurfaceCount);
for (size_t surfIdx = 0; surfIdx < surfaceCount; surfIdx++) for (size_t surfIdx = 0; surfIdx < staticSurfaceCount; surfIdx++)
gfxWorld->dpvs.sortedSurfIndex[surfIdx] = static_cast<uint16_t>(surfIdx); gfxWorld->dpvs.sortedSurfIndex[surfIdx] = static_cast<uint16_t>(surfIdx);
// surface materials are written to by the game // surface materials are written to by the game
gfxWorld->dpvs.surfaceMaterials = m_memory.Alloc<GfxDrawSurf_align4>(surfaceCount); gfxWorld->dpvs.surfaceMaterials = m_memory.Alloc<GfxDrawSurf_align4>(staticSurfaceCount);
// set all surface types to lit opaque // set all surface types to lit opaque
gfxWorld->dpvs.litSurfsBegin = 0; gfxWorld->dpvs.litSurfsBegin = 0;
gfxWorld->dpvs.litSurfsEnd = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.litSurfsEnd = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.emissiveOpaqueSurfsBegin = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.emissiveOpaqueSurfsBegin = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.emissiveOpaqueSurfsEnd = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.emissiveOpaqueSurfsEnd = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.emissiveTransSurfsBegin = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.emissiveTransSurfsBegin = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.emissiveTransSurfsEnd = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.emissiveTransSurfsEnd = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.litTransSurfsBegin = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.litTransSurfsBegin = static_cast<unsigned int>(staticSurfaceCount);
gfxWorld->dpvs.litTransSurfsEnd = static_cast<unsigned int>(surfaceCount); gfxWorld->dpvs.litTransSurfsEnd = static_cast<unsigned int>(staticSurfaceCount);
// visdata is written to by the game // visdata is written to by the game
// all visdata is alligned by 128 // all visdata is alligned by 128
size_t allignedSurfaceCount = BSPUtil::allignBy128(surfaceCount); size_t allignedSurfaceCount = BSPUtil::allignBy128(staticSurfaceCount);
gfxWorld->dpvs.surfaceVisDataCount = static_cast<unsigned int>(allignedSurfaceCount); gfxWorld->dpvs.surfaceVisDataCount = static_cast<unsigned int>(allignedSurfaceCount);
gfxWorld->dpvs.surfaceVisData[0] = m_memory.Alloc<char>(allignedSurfaceCount); gfxWorld->dpvs.surfaceVisData[0] = m_memory.Alloc<char>(allignedSurfaceCount);
gfxWorld->dpvs.surfaceVisData[1] = m_memory.Alloc<char>(allignedSurfaceCount); gfxWorld->dpvs.surfaceVisData[1] = m_memory.Alloc<char>(allignedSurfaceCount);
@@ -507,7 +515,7 @@ namespace BSP
gfxWorld->cells[0].aabbTree[0].childCount = 0; gfxWorld->cells[0].aabbTree[0].childCount = 0;
gfxWorld->cells[0].aabbTree[0].childrenOffset = 0; gfxWorld->cells[0].aabbTree[0].childrenOffset = 0;
gfxWorld->cells[0].aabbTree[0].startSurfIndex = 0; gfxWorld->cells[0].aabbTree[0].startSurfIndex = 0;
gfxWorld->cells[0].aabbTree[0].surfaceCount = static_cast<uint16_t>(gfxWorld->surfaceCount); gfxWorld->cells[0].aabbTree[0].surfaceCount = static_cast<uint16_t>(gfxWorld->dpvs.staticSurfaceCount);
gfxWorld->cells[0].aabbTree[0].smodelIndexCount = static_cast<uint16_t>(gfxWorld->dpvs.smodelCount); gfxWorld->cells[0].aabbTree[0].smodelIndexCount = static_cast<uint16_t>(gfxWorld->dpvs.smodelCount);
gfxWorld->cells[0].aabbTree[0].smodelIndexes = m_memory.Alloc<unsigned short>(gfxWorld->dpvs.smodelCount); gfxWorld->cells[0].aabbTree[0].smodelIndexes = m_memory.Alloc<unsigned short>(gfxWorld->dpvs.smodelCount);
for (unsigned short smodelIdx = 0; smodelIdx < gfxWorld->dpvs.smodelCount; smodelIdx++) for (unsigned short smodelIdx = 0; smodelIdx < gfxWorld->dpvs.smodelCount; smodelIdx++)
@@ -537,16 +545,17 @@ namespace BSP
void GfxWorldLinker::loadWorldBounds(GfxWorld* gfxWorld) void GfxWorldLinker::loadWorldBounds(GfxWorld* gfxWorld)
{ {
gfxWorld->mins.x = gfxWorld->dpvs.surfaces[0].bounds[0].x; gfxWorld->mins = gfxWorld->dpvs.surfaces[0].bounds[0];
gfxWorld->mins.y = gfxWorld->dpvs.surfaces[0].bounds[0].y; gfxWorld->maxs = gfxWorld->dpvs.surfaces[0].bounds[1];
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;
for (int surfIdx = 0; surfIdx < gfxWorld->surfaceCount; surfIdx++) 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); 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) void GfxWorldLinker::loadModels(BSPData* bsp, GfxWorld* gfxWorld)
@@ -557,27 +566,34 @@ namespace BSP
// first model is always the world model // first model is always the world model
gfxWorld->models[0].startSurfIndex = 0; gfxWorld->models[0].startSurfIndex = 0;
gfxWorld->models[0].surfaceCount = static_cast<unsigned int>(gfxWorld->surfaceCount); gfxWorld->models[0].surfaceCount = static_cast<unsigned int>(gfxWorld->dpvs.staticSurfaceCount);
gfxWorld->models[0].bounds[0].x = gfxWorld->mins.x; for (unsigned int surfIdx = 0; surfIdx < gfxWorld->dpvs.staticSurfaceCount; surfIdx++)
gfxWorld->models[0].bounds[0].y = gfxWorld->mins.y; {
gfxWorld->models[0].bounds[0].z = gfxWorld->mins.z; if (surfIdx == 0)
gfxWorld->models[0].bounds[1].x = gfxWorld->maxs.x; {
gfxWorld->models[0].bounds[1].y = gfxWorld->maxs.y; gfxWorld->models[0].bounds[0] = gfxWorld->dpvs.surfaces[surfIdx].bounds[0];
gfxWorld->models[0].bounds[1].z = gfxWorld->maxs.z; 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)); memset(&gfxWorld->models[0].writable, 0, sizeof(GfxBrushModelWritable));
for (size_t modelIdx = 0; modelIdx < bsp->models.size(); modelIdx++) for (size_t modelIdx = 0; modelIdx < bsp->models.size(); modelIdx++)
{ {
auto currEntModel = &gfxWorld->models[modelIdx + 1]; 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->startSurfIndex = bsp->gfxWorld.staticSurfaces.size() + bspModel.surfaceIndex;
currEntModel->surfaceCount = bspMpdel.surfaceCount; currEntModel->surfaceCount = bspModel.surfaceCount;
for (size_t surfIdx = 0; surfIdx < bspMpdel.surfaceCount; surfIdx++) 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) if (surfIdx == 0)
{ {
currEntModel->bounds[0] = surf->bounds[0]; currEntModel->bounds[0] = surf->bounds[0];
@@ -817,7 +833,7 @@ namespace BSP
if (!loadReflectionProbeData(gfxWorld)) if (!loadReflectionProbeData(gfxWorld))
return nullptr; return nullptr;
// world bounds are based on loaded surface mins/maxs // world bounds are based on loaded surface mins/maxs and xmodels
loadWorldBounds(gfxWorld); loadWorldBounds(gfxWorld);
if (!loadOutdoors(gfxWorld)) if (!loadOutdoors(gfxWorld))