2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-11-23 13:12:06 +00:00

Refactor to improve C++ and safe code use

This commit is contained in:
LJW-Dev
2025-10-26 18:20:04 +08:00
parent 173565c7b3
commit 9d4c32b6b4
10 changed files with 285 additions and 261 deletions

View File

@@ -7096,6 +7096,23 @@ namespace T6
char* stringValue; char* stringValue;
}; };
enum GfxLightType
{
GFX_LIGHT_TYPE_NONE = 0x0,
GFX_LIGHT_TYPE_DIR = 0x1,
GFX_LIGHT_TYPE_SPOT = 0x2,
GFX_LIGHT_TYPE_SPOT_SQUARE = 0x3,
GFX_LIGHT_TYPE_SPOT_ROUND = 0x4,
GFX_LIGHT_TYPE_OMNI = 0x5,
GFX_LIGHT_TYPE_COUNT = 0x6,
GFX_LIGHT_TYPE_DIR_SHADOWMAP = 0x6,
GFX_LIGHT_TYPE_SPOT_SHADOWMAP = 0x7,
GFX_LIGHT_TYPE_SPOT_SQUARE_SHADOWMAP = 0x8,
GFX_LIGHT_TYPE_SPOT_ROUND_SHADOWMAP = 0x9,
GFX_LIGHT_TYPE_OMNI_SHADOWMAP = 0xA,
GFX_LIGHT_TYPE_COUNT_WITH_SHADOWMAP_VERSIONS = 0xB,
};
#ifndef __zonecodegenerator #ifndef __zonecodegenerator
} // namespace T6 } // namespace T6
#endif #endif

View File

@@ -64,8 +64,12 @@ namespace BSP
{ {
constexpr int MAX_COLLISION_VERTS = UINT16_MAX; constexpr int MAX_COLLISION_VERTS = UINT16_MAX;
constexpr int STATIC_LIGHT_INDEX = 0; enum BSPDefaultLights
constexpr int SUN_LIGHT_INDEX = 1; {
STATIC_LIGHT_INDEX = 0,
SUN_LIGHT_INDEX = 1,
BSP_DEFAULT_LIGHT_COUNT = 2
};
inline const char* DEFENDER_SPAWN_POINT_NAMES[] = { inline const char* DEFENDER_SPAWN_POINT_NAMES[] = {
"mp_ctf_spawn_allies", "mp_ctf_spawn_allies",
@@ -182,5 +186,9 @@ namespace BSP
// lightgrid (global) lighting colour // lightgrid (global) lighting colour
// since lightgrids are not well understood, this colour is used for the R, G and B values right now // since lightgrids are not well understood, this colour is used for the R, G and B values right now
constexpr unsigned char LIGHTGRID_COLOUR = 128; constexpr unsigned char LIGHTGRID_COLOUR = 128;
// Sunlight values
constexpr vec4_t SUNLIGHT_COLOR = { 0.75f, 0.75f, 0.75f, 1.0f };
constexpr vec3_t SUNLIGHT_DIRECTION = { 0.0f, 0.0f, 0.0f };
}; };
} }

View File

@@ -59,87 +59,85 @@ namespace
if (meshPart.num_faces == 0) if (meshPart.num_faces == 0)
continue; continue;
surfaceVec.emplace_back(); BSPSurface surface;
BSPSurface* surface = &surfaceVec[surfaceVec.size() - 1];
size_t partTriangleNum = meshPart.num_triangles; size_t partTriangleNum = meshPart.num_triangles;
surface->triCount = static_cast<int>(partTriangleNum); surface.triCount = static_cast<int>(partTriangleNum);
surface->indexOfFirstVertex = vertexVec.size(); surface.indexOfFirstVertex = static_cast<int>(vertexVec.size());
surface->indexOfFirstIndex = indexVec.size(); surface.indexOfFirstIndex = static_cast<int>(indexVec.size());
if (mesh->materials.count == 0) if (mesh->materials.count == 0)
{ {
surface->material.materialType = MATERIAL_TYPE_EMPTY; surface.material.materialType = MATERIAL_TYPE_EMPTY;
surface->material.materialName = ""; surface.material.materialName = "";
} }
else else
{ {
surface->material.materialType = MATERIAL_TYPE_TEXTURE; surface.material.materialType = MATERIAL_TYPE_TEXTURE;
surface->material.materialName = mesh->materials.data[meshPart.index]->name.data; surface.material.materialName = mesh->materials.data[meshPart.index]->name.data;
} }
std::vector<BSPVertex> vertices; std::vector<BSPVertex> tempVertices;
std::vector<uint32_t> indices; std::vector<uint32_t> tempIndices;
indices.resize(mesh->max_face_triangles * 3); tempIndices.resize(mesh->max_face_triangles * 3);
for (uint32_t faceIndex : meshPart.face_indices) for (uint32_t faceIndex : meshPart.face_indices)
{ {
ufbx_face* face = &mesh->faces.data[faceIndex]; ufbx_face* face = &mesh->faces.data[faceIndex];
// Triangulate the face into the indices vector // Triangulate the face into the indices vector
uint32_t triangluatedTriCount = ufbx_triangulate_face(indices.data(), indices.size(), mesh, *face); uint32_t triangluatedTriCount = ufbx_triangulate_face(tempIndices.data(), tempIndices.size(), mesh, *face);
// Iterate over each triangle corner contiguously.
for (uint32_t idxOfIndex = 0; idxOfIndex < triangluatedTriCount * 3; idxOfIndex++) for (uint32_t idxOfIndex = 0; idxOfIndex < triangluatedTriCount * 3; idxOfIndex++)
{ {
vertices.emplace_back(); BSPVertex vertex;
BSPVertex* vertex = &vertices[vertices.size() - 1]; uint32_t index = tempIndices[idxOfIndex];
uint32_t index = indices[idxOfIndex];
ufbx_vec3 transformedPos = ufbx_transform_position(&meshMatrix, ufbx_get_vertex_vec3(&mesh->vertex_position, index)); ufbx_vec3 transformedPos = ufbx_transform_position(&meshMatrix, ufbx_get_vertex_vec3(&mesh->vertex_position, index));
vertex->pos.x = static_cast<float>(transformedPos.x); vertex.pos.x = static_cast<float>(transformedPos.x);
vertex->pos.y = static_cast<float>(transformedPos.y); vertex.pos.y = static_cast<float>(transformedPos.y);
vertex->pos.z = static_cast<float>(transformedPos.z); vertex.pos.z = static_cast<float>(transformedPos.z);
if (surface->material.materialType == MATERIAL_TYPE_TEXTURE || surface->material.materialType == MATERIAL_TYPE_EMPTY) if (surface.material.materialType == MATERIAL_TYPE_TEXTURE || surface.material.materialType == MATERIAL_TYPE_EMPTY)
{ {
vertex->color.x = 1.0f; vertex.color.x = 1.0f;
vertex->color.y = 1.0f; vertex.color.y = 1.0f;
vertex->color.z = 1.0f; vertex.color.z = 1.0f;
vertex->color.w = 1.0f; vertex.color.w = 1.0f;
} }
else // surface->material.materialType == MATERIAL_TYPE_COLOUR else // surface->material.materialType == MATERIAL_TYPE_COLOUR
{ {
float factor = static_cast<float>(mesh->materials.data[meshPart.index]->fbx.diffuse_factor.value_real); float factor = static_cast<float>(mesh->materials.data[meshPart.index]->fbx.diffuse_factor.value_real);
ufbx_vec4 diffuse = mesh->materials.data[meshPart.index]->fbx.diffuse_color.value_vec4; ufbx_vec4 diffuse = mesh->materials.data[meshPart.index]->fbx.diffuse_color.value_vec4;
vertex->color.x = static_cast<float>(diffuse.x * factor); vertex.color.x = static_cast<float>(diffuse.x * factor);
vertex->color.y = static_cast<float>(diffuse.y * factor); vertex.color.y = static_cast<float>(diffuse.y * factor);
vertex->color.z = static_cast<float>(diffuse.z * factor); vertex.color.z = static_cast<float>(diffuse.z * factor);
vertex->color.w = static_cast<float>(diffuse.w * factor); vertex.color.w = static_cast<float>(diffuse.w * factor);
} }
// 1.0f - uv.y reason: https://gamedev.stackexchange.com/questions/92886/fbx-uv-coordinates-is-strange // 1.0f - uv.y reason: https://gamedev.stackexchange.com/questions/92886/fbx-uv-coordinates-is-strange
ufbx_vec2 uv = ufbx_get_vertex_vec2(&mesh->vertex_uv, index); ufbx_vec2 uv = ufbx_get_vertex_vec2(&mesh->vertex_uv, index);
vertex->texCoord.x = static_cast<float>(uv.x); vertex.texCoord.x = static_cast<float>(uv.x);
vertex->texCoord.y = static_cast<float>(1.0f - uv.y); vertex.texCoord.y = static_cast<float>(1.0f - uv.y);
ufbx_vec3 normal = ufbx_get_vertex_vec3(&mesh->vertex_normal, index); ufbx_vec3 normal = ufbx_get_vertex_vec3(&mesh->vertex_normal, index);
vertex->normal.x = static_cast<float>(normal.x); vertex.normal.x = static_cast<float>(normal.x);
vertex->normal.y = static_cast<float>(normal.y); vertex.normal.y = static_cast<float>(normal.y);
vertex->normal.z = static_cast<float>(normal.z); vertex.normal.z = static_cast<float>(normal.z);
if (mesh->vertex_tangent.exists) if (mesh->vertex_tangent.exists)
{ {
ufbx_vec3 tangent = ufbx_get_vertex_vec3(&mesh->vertex_tangent, index); ufbx_vec3 tangent = ufbx_get_vertex_vec3(&mesh->vertex_tangent, index);
vertex->tangent.x = static_cast<float>(tangent.x); vertex.tangent.x = static_cast<float>(tangent.x);
vertex->tangent.y = static_cast<float>(tangent.y); vertex.tangent.y = static_cast<float>(tangent.y);
vertex->tangent.z = static_cast<float>(tangent.z); vertex.tangent.z = static_cast<float>(tangent.z);
} }
else else
{ {
vertex->tangent.x = 0.0f; vertex.tangent.x = 0.0f;
vertex->tangent.y = 0.0f; vertex.tangent.y = 0.0f;
vertex->tangent.z = 0.0f; vertex.tangent.z = 0.0f;
} }
tempVertices.emplace_back(vertex);
} }
} }
@@ -147,7 +145,7 @@ namespace
// ufbx_generate_indices will deduplicate vertices, modifying the arrays passed in streams, // ufbx_generate_indices will deduplicate vertices, modifying the arrays passed in streams,
// indices are written to outIndices and the number of unique vertices is returned. // indices are written to outIndices and the number of unique vertices is returned.
ufbx_vertex_stream streams[1] = { ufbx_vertex_stream streams[1] = {
{vertices.data(), vertices.size(), sizeof(BSPVertex)}, {tempVertices.data(), tempVertices.size(), sizeof(BSPVertex)},
}; };
std::vector<uint32_t> outIndices; std::vector<uint32_t> outIndices;
outIndices.resize(partTriangleNum * 3); outIndices.resize(partTriangleNum * 3);
@@ -155,14 +153,16 @@ namespace
assert(numGeneratedVertices != 0); assert(numGeneratedVertices != 0);
// trim non-unique vertexes and add to the world vertex vector // trim non-unique vertexes and add to the world vertex vector
vertices.resize(numGeneratedVertices); tempVertices.resize(numGeneratedVertices);
vertexVec.insert(vertexVec.end(), vertices.begin(), vertices.end()); vertexVec.insert(vertexVec.end(), tempVertices.begin(), tempVertices.end());
// T6 uses unsigned shorts as their index type so we have to loop and convert them from an unsigned int // T6 uses unsigned shorts as their index type so we have to loop and convert them from an unsigned int
for (size_t idx = 0; idx < outIndices.size(); idx++) for (size_t idx = 0; idx < outIndices.size(); idx++)
{ {
indexVec.emplace_back(static_cast<uint16_t>(outIndices[idx])); indexVec.emplace_back(static_cast<uint16_t>(outIndices[idx]));
} }
surfaceVec.emplace_back(surface);
} }
} }

View File

@@ -10,79 +10,73 @@ std::string BSPUtil::getFileNameForBSPAsset(std::string assetName)
return std::format("BSP/{}", assetName); return std::format("BSP/{}", assetName);
} }
// BO2 uses a different coordinate system, so this converts it back from OpenGLs default vec3_t BSPUtil::convertToBO2Coords(vec3_t coordinate)
vec3_t BSPUtil::convertToBO2Coords(vec3_t OGL_coordinate)
{ {
vec3_t result; vec3_t result;
result.x = OGL_coordinate.x; result.x = coordinate.x;
result.y = -OGL_coordinate.z; result.y = -coordinate.z;
result.z = OGL_coordinate.y; result.z = coordinate.y;
return result; return result;
} }
// BO2 uses a weird coordinate system, so this converts it to OpenGLs default vec3_t BSPUtil::convertFromBO2Coords(vec3_t coordinate)
vec3_t BSPUtil::convertFromBO2Coords(vec3_t bo2_coordinate)
{ {
vec3_t result; vec3_t result;
result.x = bo2_coordinate.x; result.x = coordinate.x;
result.y = bo2_coordinate.z; result.y = coordinate.z;
result.z = -bo2_coordinate.y; result.z = -coordinate.y;
return result; return result;
} }
void BSPUtil::calcNewBounds(vec3_t* newmins, vec3_t* newmaxs, vec3_t* currmins, vec3_t* currmaxs) void BSPUtil::updateAABB(vec3_t* newAABBMins, vec3_t* newAABBMaxs, vec3_t* AABBMins, vec3_t* AABBMaxs)
{ {
if (currmins->x > newmins->x) if (AABBMins->x > newAABBMins->x)
currmins->x = newmins->x; AABBMins->x = newAABBMins->x;
if (newmaxs->x > currmaxs->x) if (newAABBMaxs->x > AABBMaxs->x)
currmaxs->x = newmaxs->x; AABBMaxs->x = newAABBMaxs->x;
if (currmins->y > newmins->y) if (AABBMins->y > newAABBMins->y)
currmins->y = newmins->y; AABBMins->y = newAABBMins->y;
if (newmaxs->y > currmaxs->y) if (newAABBMaxs->y > AABBMaxs->y)
currmaxs->y = newmaxs->y; AABBMaxs->y = newAABBMaxs->y;
if (currmins->z > newmins->z) if (AABBMins->z > newAABBMins->z)
currmins->z = newmins->z; AABBMins->z = newAABBMins->z;
if (newmaxs->z > currmaxs->z) if (newAABBMaxs->z > AABBMaxs->z)
currmaxs->z = newmaxs->z; AABBMaxs->z = newAABBMaxs->z;
} }
void BSPUtil::calcNewBoundsWithPoint(vec3_t* point, vec3_t* currmins, vec3_t* currmaxs) void BSPUtil::updateAABBWithpoint(vec3_t* point, vec3_t* AABBMins, vec3_t* AABBMaxs)
{ {
if (currmins->x > point->x) if (AABBMins->x > point->x)
currmins->x = point->x; AABBMins->x = point->x;
if (point->x > currmaxs->x) if (point->x > AABBMaxs->x)
currmaxs->x = point->x; AABBMaxs->x = point->x;
if (currmins->y > point->y) if (AABBMins->y > point->y)
currmins->y = point->y; AABBMins->y = point->y;
if (point->y > currmaxs->y) if (point->y > AABBMaxs->y)
currmaxs->y = point->y; AABBMaxs->y = point->y;
if (currmins->z > point->z) if (AABBMins->z > point->z)
currmins->z = point->z; AABBMins->z = point->z;
if (point->z > currmaxs->z) if (point->z > AABBMaxs->z)
currmaxs->z = point->z; AABBMaxs->z = point->z;
} }
vec3_t BSPUtil::calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs) vec3_t BSPUtil::calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs)
{ {
// Origin is the midpoint: (min + max) / 2 vec3_t result;
vec3_t temp; result.x = (mins->x + maxs->x) * 0.5f;
temp.x = mins->x + maxs->x; result.y = (mins->y + maxs->y) * 0.5f;
temp.y = mins->y + maxs->y; result.z = (mins->z + maxs->z) * 0.5f;
temp.z = mins->z + maxs->z; return result;
temp.x *= 0.5f;
temp.y *= 0.5f;
temp.z *= 0.5f;
return temp;
} }
int BSPUtil::allignBy128(int size) int BSPUtil::allignBy128(int size)

View File

@@ -9,8 +9,8 @@ public:
static std::string getFileNameForBSPAsset(std::string assetName); static std::string getFileNameForBSPAsset(std::string assetName);
static vec3_t convertToBO2Coords(vec3_t OGL_coordinate); static vec3_t convertToBO2Coords(vec3_t OGL_coordinate);
static vec3_t convertFromBO2Coords(vec3_t bo2_coordinate); static vec3_t convertFromBO2Coords(vec3_t bo2_coordinate);
static void calcNewBounds(vec3_t* newmins, vec3_t* newmaxs, vec3_t* currmins, vec3_t* currmaxs); static void updateAABB(vec3_t* newAABBMins, vec3_t* newAABBMaxs, vec3_t* AABBMins, vec3_t* AABBMaxs);
static void calcNewBoundsWithPoint(vec3_t* point, vec3_t* currmins, vec3_t* currmaxs); static void updateAABBWithpoint(vec3_t* point, vec3_t* AABBMins, vec3_t* AABBMaxs);
static vec3_t calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs); static vec3_t calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs);
static int allignBy128(int size); static int allignBy128(int size);
static float distBetweenPoints(vec3_t p1, vec3_t p2); static float distBetweenPoints(vec3_t p1, vec3_t p2);

View File

@@ -27,7 +27,6 @@ namespace BSP
clipMap->dynEntClientList[0] = m_memory.Alloc<DynEntityClient>(clipMap->dynEntCount[0]); clipMap->dynEntClientList[0] = m_memory.Alloc<DynEntityClient>(clipMap->dynEntCount[0]);
clipMap->dynEntClientList[1] = nullptr; clipMap->dynEntClientList[1] = nullptr;
memset(clipMap->dynEntClientList[0], 0, sizeof(DynEntityClient) * clipMap->dynEntCount[0]);
clipMap->dynEntServerList[0] = nullptr; clipMap->dynEntServerList[0] = nullptr;
clipMap->dynEntServerList[1] = nullptr; clipMap->dynEntServerList[1] = nullptr;
@@ -36,15 +35,12 @@ namespace BSP
clipMap->dynEntCollList[1] = nullptr; clipMap->dynEntCollList[1] = nullptr;
clipMap->dynEntCollList[2] = nullptr; clipMap->dynEntCollList[2] = nullptr;
clipMap->dynEntCollList[3] = nullptr; clipMap->dynEntCollList[3] = nullptr;
memset(clipMap->dynEntCollList[0], 0, sizeof(DynEntityColl) * clipMap->dynEntCount[0]);
clipMap->dynEntPoseList[0] = m_memory.Alloc<DynEntityPose>(clipMap->dynEntCount[0]); clipMap->dynEntPoseList[0] = m_memory.Alloc<DynEntityPose>(clipMap->dynEntCount[0]);
clipMap->dynEntPoseList[1] = nullptr; clipMap->dynEntPoseList[1] = nullptr;
memset(clipMap->dynEntPoseList[0], 0, sizeof(DynEntityPose) * clipMap->dynEntCount[0]);
clipMap->dynEntDefList[0] = m_memory.Alloc<DynEntityDef>(clipMap->dynEntCount[0]); clipMap->dynEntDefList[0] = m_memory.Alloc<DynEntityDef>(clipMap->dynEntCount[0]);
clipMap->dynEntDefList[1] = nullptr; clipMap->dynEntDefList[1] = nullptr;
memset(clipMap->dynEntDefList[0], 0, sizeof(DynEntityDef) * clipMap->dynEntCount[0]);
} }
void ClipMapLinker::loadVisibility(clipMap_t* clipMap) void ClipMapLinker::loadVisibility(clipMap_t* clipMap)
@@ -122,19 +118,18 @@ namespace BSP
void ClipMapLinker::loadRopesAndConstraints(clipMap_t* clipMap) void ClipMapLinker::loadRopesAndConstraints(clipMap_t* clipMap)
{ {
clipMap->num_constraints = 0; // max 511 clipMap->num_constraints = 0; // max 511
clipMap->constraints = NULL; clipMap->constraints = nullptr;
// The game allocates 32 empty ropes // The game allocates 32 empty ropes
clipMap->max_ropes = 32; // max 300 clipMap->max_ropes = 32; // max 300
clipMap->ropes = m_memory.Alloc <rope_t> (clipMap->max_ropes); clipMap->ropes = m_memory.Alloc <rope_t> (clipMap->max_ropes);
memset(clipMap->ropes, 0, sizeof(rope_t) * clipMap->max_ropes);
} }
void ClipMapLinker::loadSubModelCollision(clipMap_t* clipMap, BSPData* bsp) void ClipMapLinker::loadSubModelCollision(clipMap_t* clipMap, BSPData* bsp)
{ {
// Submodels are used for the world and map ent collision (triggers, bomb zones, etc) // Submodels are used for the world and map ent collision (triggers, bomb zones, etc)
auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(bsp->bspName); auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(bsp->bspName);
assert(gfxWorldAsset != NULL); assert(gfxWorldAsset != nullptr);
GfxWorld* gfxWorld = gfxWorldAsset->Asset(); GfxWorld* gfxWorld = gfxWorldAsset->Asset();
// Right now there is only one submodel, the world sub model // Right now there is only one submodel, the world sub model
@@ -166,7 +161,7 @@ namespace BSP
clipMap->cmodels[0].leaf.leafBrushNode = 0; clipMap->cmodels[0].leaf.leafBrushNode = 0;
clipMap->cmodels[0].leaf.cluster = 0; clipMap->cmodels[0].leaf.cluster = 0;
clipMap->cmodels[0].info = NULL; // always set to 0 clipMap->cmodels[0].info = nullptr; // always set to 0
} }
void ClipMapLinker::loadXModelCollision(clipMap_t* clipMap) void ClipMapLinker::loadXModelCollision(clipMap_t* clipMap)
@@ -178,7 +173,7 @@ namespace BSP
// WIP code left in for future support // WIP code left in for future support
/* /*
auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(bsp->bspName); auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(bsp->bspName);
assert(gfxWorldAsset != NULL); assert(gfxWorldAsset != nullptr);
GfxWorld* gfxWorld = gfxWorldAsset->Asset(); GfxWorld* gfxWorld = gfxWorldAsset->Asset();
clipMap->numStaticModels = gfxWorld->dpvs.smodelCount; clipMap->numStaticModels = gfxWorld->dpvs.smodelCount;
@@ -306,7 +301,7 @@ namespace BSP
{ {
uint16_t vertIndex = tri[l]; uint16_t vertIndex = tri[l];
vec3_t vertCoord = clipMap->verts[vertIndex]; vec3_t vertCoord = clipMap->verts[vertIndex];
BSPUtil::calcNewBoundsWithPoint(&vertCoord, &aabbMins, &aabbMaxs); BSPUtil::updateAABBWithpoint(&vertCoord, &aabbMins, &aabbMaxs);
} }
} }
} }
@@ -343,7 +338,7 @@ namespace BSP
uint16_t currUind = clipMap->info.uinds[aabbPartition->fuind + i]; uint16_t currUind = clipMap->info.uinds[aabbPartition->fuind + i];
vec3_t* currVertex = &clipMap->verts[currUind]; vec3_t* currVertex = &clipMap->verts[currUind];
BSPUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs); BSPUtil::updateAABBWithpoint(currVertex, &mins, &maxs);
} }
aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize); aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize);
@@ -631,17 +626,17 @@ namespace BSP
{ {
// No support for brushes, only tris right now // No support for brushes, only tris right now
clipMap->info.numBrushSides = 0; clipMap->info.numBrushSides = 0;
clipMap->info.brushsides = NULL; clipMap->info.brushsides = nullptr;
clipMap->info.leafbrushNodesCount = 0; clipMap->info.leafbrushNodesCount = 0;
clipMap->info.leafbrushNodes = NULL; clipMap->info.leafbrushNodes = nullptr;
clipMap->info.numLeafBrushes = 0; clipMap->info.numLeafBrushes = 0;
clipMap->info.leafbrushes = NULL; clipMap->info.leafbrushes = nullptr;
clipMap->info.numBrushVerts = 0; clipMap->info.numBrushVerts = 0;
clipMap->info.brushVerts = NULL; clipMap->info.brushVerts = nullptr;
clipMap->info.numBrushes = NULL; clipMap->info.numBrushes = 0;
clipMap->info.brushes = NULL; clipMap->info.brushes = nullptr;
clipMap->info.brushBounds = NULL; clipMap->info.brushBounds = nullptr;
clipMap->info.brushContents = NULL; clipMap->info.brushContents = nullptr;
// clipmap BSP creation must go last as it depends on unids, tris and verts already being populated // clipmap BSP creation must go last as it depends on unids, tris and verts already being populated
// HACK: // HACK:
@@ -667,7 +662,7 @@ namespace BSP
for (unsigned int i = 1; i < clipMap->vertCount; i++) for (unsigned int i = 1; i < clipMap->vertCount; i++)
{ {
vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[i]); vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[i]);
BSPUtil::calcNewBoundsWithPoint(&vertCoord, &clipMins, &clipMaxs); BSPUtil::updateAABBWithpoint(&vertCoord, &clipMins, &clipMaxs);
} }
BSPTree* tree = new BSPTree(clipMins.x, clipMins.y, clipMins.z, clipMaxs.x, clipMaxs.y, clipMaxs.z, 0); BSPTree* tree = new BSPTree(clipMins.x, clipMins.y, clipMins.z, clipMaxs.x, clipMaxs.y, clipMaxs.z, 0);
@@ -697,7 +692,7 @@ namespace BSP
{ {
uint16_t vertIndex = tri[l]; uint16_t vertIndex = tri[l];
vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[vertIndex]); vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[vertIndex]);
BSPUtil::calcNewBoundsWithPoint(&vertCoord, &mins, &maxs); BSPUtil::updateAABBWithpoint(&vertCoord, &mins, &maxs);
} }
} }

View File

@@ -15,23 +15,22 @@ namespace BSP
ComWorld* comWorld = m_memory.Alloc<ComWorld>(); ComWorld* comWorld = m_memory.Alloc<ComWorld>();
comWorld->name = m_memory.Dup(bsp->bspName.c_str()); comWorld->name = m_memory.Dup(bsp->bspName.c_str());
comWorld->isInUse = 1; comWorld->isInUse = 1;
comWorld->primaryLightCount = 2; comWorld->primaryLightCount = BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT;
comWorld->primaryLights = m_memory.Alloc<ComPrimaryLight>(comWorld->primaryLightCount); comWorld->primaryLights = m_memory.Alloc<ComPrimaryLight>(comWorld->primaryLightCount);
// static light is always empty // first (static) light is always empty
ComPrimaryLight* staticLight = &comWorld->primaryLights[0];
memset(staticLight, 0, sizeof(ComPrimaryLight));
ComPrimaryLight* sunLight = &comWorld->primaryLights[1]; ComPrimaryLight* sunLight = &comWorld->primaryLights[1];
memset(sunLight, 0, sizeof(ComPrimaryLight)); const vec4_t sunLightColor = BSPEditableConstants::SUNLIGHT_COLOR;
sunLight->type = 1; const vec3_t sunLightDirection = BSPEditableConstants::SUNLIGHT_DIRECTION;
sunLight->diffuseColor.r = 0.75f; sunLight->type = GFX_LIGHT_TYPE_DIR;
sunLight->diffuseColor.g = 0.75f; sunLight->diffuseColor.r = sunLightColor.r;
sunLight->diffuseColor.b = 0.75f; sunLight->diffuseColor.g = sunLightColor.g;
sunLight->diffuseColor.a = 1.0f; sunLight->diffuseColor.b = sunLightColor.b;
sunLight->dir.x = 0.0f; sunLight->diffuseColor.a = sunLightColor.a;
sunLight->dir.y = 0.0f; sunLight->dir.x = sunLightDirection.x;
sunLight->dir.z = 0.0f; sunLight->dir.y = sunLightDirection.y;
sunLight->dir.z = sunLightDirection.z;
auto comWorldAsset = m_context.AddAsset<AssetComWorld>(comWorld->name, comWorld); auto comWorldAsset = m_context.AddAsset<AssetComWorld>(comWorld->name, comWorld);
return AssetCreationResult::Success(comWorldAsset); return AssetCreationResult::Success(comWorldAsset);

View File

@@ -21,12 +21,10 @@ namespace BSP
gameWorldMp->path.smoothBytes = 0; gameWorldMp->path.smoothBytes = 0;
gameWorldMp->path.nodeTreeCount = 0; gameWorldMp->path.nodeTreeCount = 0;
int nodeCount = gameWorldMp->path.nodeCount + 128; // The game has 128 empty nodes allocated
gameWorldMp->path.nodes = m_memory.Alloc<pathnode_t>(nodeCount); int extraNodeCount = gameWorldMp->path.nodeCount + 128;
gameWorldMp->path.basenodes = m_memory.Alloc<pathbasenode_t>(nodeCount); gameWorldMp->path.nodes = m_memory.Alloc<pathnode_t>(extraNodeCount);
memset(gameWorldMp->path.nodes, 0, nodeCount * sizeof(pathnode_t)); gameWorldMp->path.basenodes = m_memory.Alloc<pathbasenode_t>(extraNodeCount);
memset(gameWorldMp->path.basenodes, 0, nodeCount * sizeof(pathbasenode_t));
gameWorldMp->path.pathVis = nullptr; gameWorldMp->path.pathVis = nullptr;
gameWorldMp->path.smoothCache = nullptr; gameWorldMp->path.smoothCache = nullptr;
gameWorldMp->path.nodeTree = nullptr; gameWorldMp->path.nodeTree = nullptr;

View File

@@ -130,7 +130,7 @@ namespace BSP
for (int k = 0; k < currSurface->tris.triCount * 3; k++) for (int k = 0; k < currSurface->tris.triCount * 3; k++)
{ {
uint16_t vertIndex = gfxWorld->draw.indices[currSurface->tris.baseIndex + k]; uint16_t vertIndex = gfxWorld->draw.indices[currSurface->tris.baseIndex + k];
BSPUtil::calcNewBoundsWithPoint(&firstVert[vertIndex].xyz, &currSurface->bounds[0], &currSurface->bounds[1]); BSPUtil::updateAABBWithpoint(&firstVert[vertIndex].xyz, &currSurface->bounds[0], &currSurface->bounds[1]);
} }
// unused values // unused values
@@ -191,68 +191,69 @@ namespace BSP
/* /*
Models are unsupported right now Models are unsupported right now
Code is left in in case it is supported later on Code is left in in case it is supported later on
unsigned int modelCount = projInfo->modelCount;
gfxWorld->dpvs.smodelCount = modelCount;
gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount];
gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
for (unsigned int i = 0; i < modelCount; i++)
{
auto currModel = &gfxWorld->dpvs.smodelDrawInsts[i];
auto currModelInst = &gfxWorld->dpvs.smodelInsts[i];
customMapModel* inModel = &projInfo->models[i];
auto xModelAsset = m_context.LoadDependency<AssetXModel>(inModel->name);
if (xModelAsset == NULL)
{
printf("XModel %s not found!\n", inModel->name.c_str());
currModel->model = NULL;
}
else
currModel->model = (XModel*)xModelAsset->Asset();
currModel->placement.origin.x = inModel->origin.x;
currModel->placement.origin.y = inModel->origin.y;
currModel->placement.origin.z = inModel->origin.z;
currModel->placement.origin = BSPUtil::convertToBO2Coords(currModel->placement.origin);
currModel->placement.scale = inModel->scale;
BSPUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
// mins and maxs are calculated in world space not local space
// TODO: this does not account for model rotation or scale
currModelInst->mins.x = currModel->model->mins.x + currModel->placement.origin.x;
currModelInst->mins.y = currModel->model->mins.y + currModel->placement.origin.y;
currModelInst->mins.z = currModel->model->mins.z + currModel->placement.origin.z;
currModelInst->maxs.x = currModel->model->maxs.x + currModel->placement.origin.x;
currModelInst->maxs.y = currModel->model->maxs.y + currModel->placement.origin.y;
currModelInst->maxs.z = currModel->model->maxs.z + currModel->placement.origin.z;
currModel->cullDist = DEFAULT_SMODEL_CULL_DIST;
currModel->flags = DEFAULT_SMODEL_FLAGS;
currModel->primaryLightIndex = DEFAULT_SMODEL_LIGHT;
currModel->reflectionProbeIndex = DEFAULT_SMODEL_REFLECTION_PROBE;
// unknown use / unused
currModel->smid = i;
memset(&currModel->lightingSH, 0, sizeof(GfxLightingSHQuantized));
currModel->invScaleSq = 0.0f;
currModel->lightingHandle = 0;
currModel->colorsIndex = 0;
currModel->visibility = 0;
// setting these to NULL makes any static/baked lighting go black when not rendered by real-time lighting or in a shadow
// TODO: calculate lighting and store it here
currModel->lmapVertexInfo[0].numLmapVertexColors = 0;
currModel->lmapVertexInfo[0].lmapVertexColors = NULL;
currModel->lmapVertexInfo[1].numLmapVertexColors = 0;
currModel->lmapVertexInfo[1].lmapVertexColors = NULL;
currModel->lmapVertexInfo[2].numLmapVertexColors = 0;
currModel->lmapVertexInfo[2].lmapVertexColors = NULL;
currModel->lmapVertexInfo[3].numLmapVertexColors = 0;
currModel->lmapVertexInfo[3].lmapVertexColors = NULL;
}
*/ */
//unsigned int modelCount = projInfo->modelCount;
//gfxWorld->dpvs.smodelCount = modelCount;
//gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount];
//gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
//
//for (unsigned int i = 0; i < modelCount; i++)
//{
// auto currModel = &gfxWorld->dpvs.smodelDrawInsts[i];
// auto currModelInst = &gfxWorld->dpvs.smodelInsts[i];
// customMapModel* inModel = &projInfo->models[i];
//
// auto xModelAsset = m_context.LoadDependency<AssetXModel>(inModel->name);
// if (xModelAsset == NULL)
// {
// printf("XModel %s not found!\n", inModel->name.c_str());
// currModel->model = NULL;
// }
// else
// currModel->model = (XModel*)xModelAsset->Asset();
//
// currModel->placement.origin.x = inModel->origin.x;
// currModel->placement.origin.y = inModel->origin.y;
// currModel->placement.origin.z = inModel->origin.z;
// currModel->placement.origin = BSPUtil::convertToBO2Coords(currModel->placement.origin);
// currModel->placement.scale = inModel->scale;
//
// BSPUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
//
// // mins and maxs are calculated in world space not local space
// // TODO: this does not account for model rotation or scale
// currModelInst->mins.x = currModel->model->mins.x + currModel->placement.origin.x;
// currModelInst->mins.y = currModel->model->mins.y + currModel->placement.origin.y;
// currModelInst->mins.z = currModel->model->mins.z + currModel->placement.origin.z;
// currModelInst->maxs.x = currModel->model->maxs.x + currModel->placement.origin.x;
// currModelInst->maxs.y = currModel->model->maxs.y + currModel->placement.origin.y;
// currModelInst->maxs.z = currModel->model->maxs.z + currModel->placement.origin.z;
//
// currModel->cullDist = DEFAULT_SMODEL_CULL_DIST;
// currModel->flags = DEFAULT_SMODEL_FLAGS;
// currModel->primaryLightIndex = DEFAULT_SMODEL_LIGHT;
// currModel->reflectionProbeIndex = DEFAULT_SMODEL_REFLECTION_PROBE;
//
// // unknown use / unused
// currModel->smid = i;
// memset(&currModel->lightingSH, 0, sizeof(GfxLightingSHQuantized));
// currModel->invScaleSq = 0.0f;
// currModel->lightingHandle = 0;
// currModel->colorsIndex = 0;
// currModel->visibility = 0;
//
// // setting these to NULL makes any static/baked lighting go black when not rendered by real-time lighting or in a shadow
// // TODO: calculate lighting and store it here
// currModel->lmapVertexInfo[0].numLmapVertexColors = 0;
// currModel->lmapVertexInfo[0].lmapVertexColors = NULL;
// currModel->lmapVertexInfo[1].numLmapVertexColors = 0;
// currModel->lmapVertexInfo[1].lmapVertexColors = NULL;
// currModel->lmapVertexInfo[2].numLmapVertexColors = 0;
// currModel->lmapVertexInfo[2].lmapVertexColors = NULL;
// currModel->lmapVertexInfo[3].numLmapVertexColors = 0;
// currModel->lmapVertexInfo[3].lmapVertexColors = NULL;
//}
unsigned int modelCount = 0; unsigned int modelCount = 0;
gfxWorld->dpvs.smodelCount = modelCount; gfxWorld->dpvs.smodelCount = modelCount;
@@ -546,7 +547,7 @@ namespace BSP
for (int i = 0; i < gfxWorld->surfaceCount; i++) for (int i = 0; i < gfxWorld->surfaceCount; i++)
{ {
BSPUtil::calcNewBounds(&gfxWorld->dpvs.surfaces[i].bounds[0], &gfxWorld->dpvs.surfaces[i].bounds[1], &gfxWorld->mins, &gfxWorld->maxs); BSPUtil::updateAABB(&gfxWorld->dpvs.surfaces[i].bounds[0], &gfxWorld->dpvs.surfaces[i].bounds[1], &gfxWorld->mins, &gfxWorld->maxs);
} }
} }
@@ -665,7 +666,7 @@ namespace BSP
gfxWorld->draw.reflectionProbes[0].probeVolumeCount = 0; gfxWorld->draw.reflectionProbes[0].probeVolumeCount = 0;
gfxWorld->draw.reflectionProbes[0].probeVolumes = NULL; gfxWorld->draw.reflectionProbes[0].probeVolumes = NULL;
std::string probeImageName = "*reflection_probe0"; std::string probeImageName = "reflection_probe0";
auto probeImageAsset = m_context.LoadDependency<AssetImage>(probeImageName); auto probeImageAsset = m_context.LoadDependency<AssetImage>(probeImageName);
if (probeImageAsset == NULL) if (probeImageAsset == NULL)
{ {
@@ -689,7 +690,7 @@ namespace BSP
memset(gfxWorld->draw.lightmapPrimaryTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.lightmapCount); memset(gfxWorld->draw.lightmapPrimaryTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.lightmapCount);
memset(gfxWorld->draw.lightmapSecondaryTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.lightmapCount); memset(gfxWorld->draw.lightmapSecondaryTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.lightmapCount);
std::string secondaryTexture = "*lightmap0_secondary"; std::string secondaryTexture = "lightmap0_secondary";
auto secondaryTextureAsset = m_context.LoadDependency<AssetImage>(secondaryTexture); auto secondaryTextureAsset = m_context.LoadDependency<AssetImage>(secondaryTexture);
if (secondaryTextureAsset == NULL) if (secondaryTextureAsset == NULL)
{ {

View File

@@ -8,14 +8,14 @@ namespace
{ {
bool parseMapEntsJSON(json& entArrayJs, std::string& entityString) bool parseMapEntsJSON(json& entArrayJs, std::string& entityString)
{ {
int entityCount = entArrayJs.size(); for (size_t entIdx = 0; entIdx < entArrayJs.size(); entIdx++)
for (int i = 0; i < entityCount; i++)
{ {
auto currEntity = entArrayJs[i]; auto& entity = entArrayJs[entIdx];
if (i == 0) if (entIdx == 0)
{ {
std::string className = currEntity["classname"]; std::string className;
entity.at("classname").get_to(className);
if (className.compare("worldspawn") != 0) if (className.compare("worldspawn") != 0)
{ {
con::error("ERROR: first entity in the map entity string must be the worldspawn class!"); con::error("ERROR: first entity in the map entity string must be the worldspawn class!");
@@ -25,7 +25,7 @@ namespace
entityString.append("{\n"); entityString.append("{\n");
for (auto& element : currEntity.items()) for (auto& element : entity.items())
{ {
std::string key = element.key(); std::string key = element.key();
std::string value = element.value(); std::string value = element.value();
@@ -38,26 +38,31 @@ namespace
return true; return true;
} }
void parseSpawnpointJSON(json& entArrayJs, std::string& entityString, const char* spawnpointNames[], int nameCount) void parseSpawnpointJSON(json& entArrayJs, std::string& entityString, const char* spawnpointNames[], size_t nameCount)
{ {
int entityCount = entArrayJs.size(); for (auto& element : entArrayJs.items())
for (int i = 0; i < entityCount; i++)
{ {
auto currEntity = entArrayJs[i]; std::string origin;
std::string angles;
auto& entity = element.value();
entity.at("origin").get_to(origin);
entity.at("angles").get_to(angles);
std::string origin = currEntity["origin"]; for (size_t nameIdx = 0; nameIdx < nameCount; nameIdx++)
std::string angles = currEntity["angles"];
for (int k = 0; k < nameCount; k++)
{ {
entityString.append("{\n"); entityString.append("{\n");
entityString.append(std::format("\"origin\" \"{}\"\n", origin)); entityString.append(std::format("\"origin\" \"{}\"\n", origin));
entityString.append(std::format("\"angles\" \"{}\"\n", angles)); entityString.append(std::format("\"angles\" \"{}\"\n", angles));
entityString.append(std::format("\"classname\" \"{}\"\n", spawnpointNames[k])); entityString.append(std::format("\"classname\" \"{}\"\n", spawnpointNames[nameIdx]));
entityString.append("}\n"); entityString.append("}\n");
} }
} }
} }
std::string loadMapEnts()
{
}
} }
namespace BSP namespace BSP
@@ -71,8 +76,8 @@ namespace BSP
AssetCreationResult MapEntsLinker::linkMapEnts(BSPData* bsp) AssetCreationResult MapEntsLinker::linkMapEnts(BSPData* bsp)
{ {
std::string entityString; try
{
json entJs; json entJs;
std::string entityFilePath = BSPUtil::getFileNameForBSPAsset("entities.json"); std::string entityFilePath = BSPUtil::getFileNameForBSPAsset("entities.json");
const auto entFile = m_search_path.Open(entityFilePath); const auto entFile = m_search_path.Open(entityFilePath);
@@ -85,6 +90,7 @@ namespace BSP
{ {
entJs = json::parse(*entFile.m_stream); entJs = json::parse(*entFile.m_stream);
} }
std::string entityString;
if (!parseMapEntsJSON(entJs["entities"], entityString)) if (!parseMapEntsJSON(entJs["entities"], entityString))
return AssetCreationResult::Failure(); return AssetCreationResult::Failure();
@@ -100,9 +106,9 @@ namespace BSP
{ {
spawnJs = json::parse(*spawnFile.m_stream); spawnJs = json::parse(*spawnFile.m_stream);
} }
int defenderNameCount = std::extent<decltype(BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES)>::value; size_t defenderNameCount = std::extent<decltype(BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES)>::value;
int attackerNameCount = std::extent<decltype(BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES)>::value; size_t attackerNameCount = std::extent<decltype(BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES)>::value;
int ffaNameCount = std::extent<decltype(BSPGameConstants::FFA_SPAWN_POINT_NAMES)>::value; size_t ffaNameCount = std::extent<decltype(BSPGameConstants::FFA_SPAWN_POINT_NAMES)>::value;
parseSpawnpointJSON(spawnJs["attackers"], entityString, BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES, defenderNameCount); parseSpawnpointJSON(spawnJs["attackers"], entityString, BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES, defenderNameCount);
parseSpawnpointJSON(spawnJs["defenders"], entityString, BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES, attackerNameCount); parseSpawnpointJSON(spawnJs["defenders"], entityString, BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES, attackerNameCount);
parseSpawnpointJSON(spawnJs["FFA"], entityString, BSPGameConstants::FFA_SPAWN_POINT_NAMES, ffaNameCount); parseSpawnpointJSON(spawnJs["FFA"], entityString, BSPGameConstants::FFA_SPAWN_POINT_NAMES, ffaNameCount);
@@ -124,5 +130,11 @@ namespace BSP
auto mapEntsAsset = m_context.AddAsset<AssetMapEnts>(mapEnts->name, mapEnts); auto mapEntsAsset = m_context.AddAsset<AssetMapEnts>(mapEnts->name, mapEnts);
return AssetCreationResult::Success(mapEntsAsset); return AssetCreationResult::Success(mapEntsAsset);
} }
catch (const json::exception& e)
{
con::error("JSON error when parsing map ents and spawns: {}", e.what());
return AssetCreationResult::Failure();
}
}
} }