diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index 0a33bf51..d62c378c 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -7096,6 +7096,23 @@ namespace T6 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 } // namespace T6 #endif diff --git a/src/ObjLoading/Game/T6/BSP/BSP.h b/src/ObjLoading/Game/T6/BSP/BSP.h index 0fb6934c..95e04897 100644 --- a/src/ObjLoading/Game/T6/BSP/BSP.h +++ b/src/ObjLoading/Game/T6/BSP/BSP.h @@ -64,8 +64,12 @@ namespace BSP { constexpr int MAX_COLLISION_VERTS = UINT16_MAX; - constexpr int STATIC_LIGHT_INDEX = 0; - constexpr int SUN_LIGHT_INDEX = 1; + enum BSPDefaultLights + { + STATIC_LIGHT_INDEX = 0, + SUN_LIGHT_INDEX = 1, + BSP_DEFAULT_LIGHT_COUNT = 2 + }; inline const char* DEFENDER_SPAWN_POINT_NAMES[] = { "mp_ctf_spawn_allies", @@ -182,5 +186,9 @@ namespace BSP // lightgrid (global) lighting colour // 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; + + // 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 }; }; } \ No newline at end of file diff --git a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp index c8173089..63a41224 100644 --- a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp +++ b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp @@ -59,87 +59,85 @@ namespace if (meshPart.num_faces == 0) continue; - surfaceVec.emplace_back(); - BSPSurface* surface = &surfaceVec[surfaceVec.size() - 1]; - + BSPSurface surface; size_t partTriangleNum = meshPart.num_triangles; - surface->triCount = static_cast(partTriangleNum); - surface->indexOfFirstVertex = vertexVec.size(); - surface->indexOfFirstIndex = indexVec.size(); + surface.triCount = static_cast(partTriangleNum); + surface.indexOfFirstVertex = static_cast(vertexVec.size()); + surface.indexOfFirstIndex = static_cast(indexVec.size()); if (mesh->materials.count == 0) { - surface->material.materialType = MATERIAL_TYPE_EMPTY; - surface->material.materialName = ""; + surface.material.materialType = MATERIAL_TYPE_EMPTY; + surface.material.materialName = ""; } else { - surface->material.materialType = MATERIAL_TYPE_TEXTURE; - surface->material.materialName = mesh->materials.data[meshPart.index]->name.data; + surface.material.materialType = MATERIAL_TYPE_TEXTURE; + surface.material.materialName = mesh->materials.data[meshPart.index]->name.data; } - std::vector vertices; - std::vector indices; - indices.resize(mesh->max_face_triangles * 3); + std::vector tempVertices; + std::vector tempIndices; + tempIndices.resize(mesh->max_face_triangles * 3); for (uint32_t faceIndex : meshPart.face_indices) { ufbx_face* face = &mesh->faces.data[faceIndex]; // 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++) { - vertices.emplace_back(); - BSPVertex* vertex = &vertices[vertices.size() - 1]; - uint32_t index = indices[idxOfIndex]; + BSPVertex vertex; + uint32_t index = tempIndices[idxOfIndex]; ufbx_vec3 transformedPos = ufbx_transform_position(&meshMatrix, ufbx_get_vertex_vec3(&mesh->vertex_position, index)); - vertex->pos.x = static_cast(transformedPos.x); - vertex->pos.y = static_cast(transformedPos.y); - vertex->pos.z = static_cast(transformedPos.z); + vertex.pos.x = static_cast(transformedPos.x); + vertex.pos.y = static_cast(transformedPos.y); + vertex.pos.z = static_cast(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.y = 1.0f; - vertex->color.z = 1.0f; - vertex->color.w = 1.0f; + vertex.color.x = 1.0f; + vertex.color.y = 1.0f; + vertex.color.z = 1.0f; + vertex.color.w = 1.0f; } else // surface->material.materialType == MATERIAL_TYPE_COLOUR { float factor = static_cast(mesh->materials.data[meshPart.index]->fbx.diffuse_factor.value_real); ufbx_vec4 diffuse = mesh->materials.data[meshPart.index]->fbx.diffuse_color.value_vec4; - vertex->color.x = static_cast(diffuse.x * factor); - vertex->color.y = static_cast(diffuse.y * factor); - vertex->color.z = static_cast(diffuse.z * factor); - vertex->color.w = static_cast(diffuse.w * factor); + vertex.color.x = static_cast(diffuse.x * factor); + vertex.color.y = static_cast(diffuse.y * factor); + vertex.color.z = static_cast(diffuse.z * factor); + vertex.color.w = static_cast(diffuse.w * factor); } // 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); - vertex->texCoord.x = static_cast(uv.x); - vertex->texCoord.y = static_cast(1.0f - uv.y); + vertex.texCoord.x = static_cast(uv.x); + vertex.texCoord.y = static_cast(1.0f - uv.y); ufbx_vec3 normal = ufbx_get_vertex_vec3(&mesh->vertex_normal, index); - vertex->normal.x = static_cast(normal.x); - vertex->normal.y = static_cast(normal.y); - vertex->normal.z = static_cast(normal.z); + vertex.normal.x = static_cast(normal.x); + vertex.normal.y = static_cast(normal.y); + vertex.normal.z = static_cast(normal.z); if (mesh->vertex_tangent.exists) { ufbx_vec3 tangent = ufbx_get_vertex_vec3(&mesh->vertex_tangent, index); - vertex->tangent.x = static_cast(tangent.x); - vertex->tangent.y = static_cast(tangent.y); - vertex->tangent.z = static_cast(tangent.z); + vertex.tangent.x = static_cast(tangent.x); + vertex.tangent.y = static_cast(tangent.y); + vertex.tangent.z = static_cast(tangent.z); } else { - vertex->tangent.x = 0.0f; - vertex->tangent.y = 0.0f; - vertex->tangent.z = 0.0f; + vertex.tangent.x = 0.0f; + vertex.tangent.y = 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, // indices are written to outIndices and the number of unique vertices is returned. ufbx_vertex_stream streams[1] = { - {vertices.data(), vertices.size(), sizeof(BSPVertex)}, + {tempVertices.data(), tempVertices.size(), sizeof(BSPVertex)}, }; std::vector outIndices; outIndices.resize(partTriangleNum * 3); @@ -155,14 +153,16 @@ namespace assert(numGeneratedVertices != 0); // trim non-unique vertexes and add to the world vertex vector - vertices.resize(numGeneratedVertices); - vertexVec.insert(vertexVec.end(), vertices.begin(), vertices.end()); + tempVertices.resize(numGeneratedVertices); + 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 for (size_t idx = 0; idx < outIndices.size(); idx++) { indexVec.emplace_back(static_cast(outIndices[idx])); } + + surfaceVec.emplace_back(surface); } } diff --git a/src/ObjLoading/Game/T6/BSP/BSPUtil.cpp b/src/ObjLoading/Game/T6/BSP/BSPUtil.cpp index 118594bb..878f318d 100644 --- a/src/ObjLoading/Game/T6/BSP/BSPUtil.cpp +++ b/src/ObjLoading/Game/T6/BSP/BSPUtil.cpp @@ -10,79 +10,73 @@ std::string BSPUtil::getFileNameForBSPAsset(std::string 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 OGL_coordinate) +vec3_t BSPUtil::convertToBO2Coords(vec3_t coordinate) { vec3_t result; - result.x = OGL_coordinate.x; - result.y = -OGL_coordinate.z; - result.z = OGL_coordinate.y; + result.x = coordinate.x; + result.y = -coordinate.z; + result.z = coordinate.y; return result; } -// BO2 uses a weird coordinate system, so this converts it to OpenGLs default -vec3_t BSPUtil::convertFromBO2Coords(vec3_t bo2_coordinate) +vec3_t BSPUtil::convertFromBO2Coords(vec3_t coordinate) { vec3_t result; - result.x = bo2_coordinate.x; - result.y = bo2_coordinate.z; - result.z = -bo2_coordinate.y; + result.x = coordinate.x; + result.y = coordinate.z; + result.z = -coordinate.y; 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) - currmins->x = newmins->x; + if (AABBMins->x > newAABBMins->x) + AABBMins->x = newAABBMins->x; - if (newmaxs->x > currmaxs->x) - currmaxs->x = newmaxs->x; + if (newAABBMaxs->x > AABBMaxs->x) + AABBMaxs->x = newAABBMaxs->x; - if (currmins->y > newmins->y) - currmins->y = newmins->y; + if (AABBMins->y > newAABBMins->y) + AABBMins->y = newAABBMins->y; - if (newmaxs->y > currmaxs->y) - currmaxs->y = newmaxs->y; + if (newAABBMaxs->y > AABBMaxs->y) + AABBMaxs->y = newAABBMaxs->y; - if (currmins->z > newmins->z) - currmins->z = newmins->z; + if (AABBMins->z > newAABBMins->z) + AABBMins->z = newAABBMins->z; - if (newmaxs->z > currmaxs->z) - currmaxs->z = newmaxs->z; + if (newAABBMaxs->z > AABBMaxs->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) - currmins->x = point->x; + if (AABBMins->x > point->x) + AABBMins->x = point->x; - if (point->x > currmaxs->x) - currmaxs->x = point->x; + if (point->x > AABBMaxs->x) + AABBMaxs->x = point->x; - if (currmins->y > point->y) - currmins->y = point->y; + if (AABBMins->y > point->y) + AABBMins->y = point->y; - if (point->y > currmaxs->y) - currmaxs->y = point->y; + if (point->y > AABBMaxs->y) + AABBMaxs->y = point->y; - if (currmins->z > point->z) - currmins->z = point->z; + if (AABBMins->z > point->z) + AABBMins->z = point->z; - if (point->z > currmaxs->z) - currmaxs->z = point->z; + if (point->z > AABBMaxs->z) + AABBMaxs->z = point->z; } vec3_t BSPUtil::calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs) { - // Origin is the midpoint: (min + max) / 2 - vec3_t temp; - temp.x = mins->x + maxs->x; - temp.y = mins->y + maxs->y; - temp.z = mins->z + maxs->z; - temp.x *= 0.5f; - temp.y *= 0.5f; - temp.z *= 0.5f; - return temp; + vec3_t result; + result.x = (mins->x + maxs->x) * 0.5f; + result.y = (mins->y + maxs->y) * 0.5f; + result.z = (mins->z + maxs->z) * 0.5f; + return result; } int BSPUtil::allignBy128(int size) diff --git a/src/ObjLoading/Game/T6/BSP/BSPUtil.h b/src/ObjLoading/Game/T6/BSP/BSPUtil.h index 7bad527f..30307bcf 100644 --- a/src/ObjLoading/Game/T6/BSP/BSPUtil.h +++ b/src/ObjLoading/Game/T6/BSP/BSPUtil.h @@ -9,8 +9,8 @@ public: static std::string getFileNameForBSPAsset(std::string assetName); static vec3_t convertToBO2Coords(vec3_t OGL_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 calcNewBoundsWithPoint(vec3_t* point, vec3_t* currmins, vec3_t* currmaxs); + static void updateAABB(vec3_t* newAABBMins, vec3_t* newAABBMaxs, vec3_t* AABBMins, vec3_t* AABBMaxs); + static void updateAABBWithpoint(vec3_t* point, vec3_t* AABBMins, vec3_t* AABBMaxs); static vec3_t calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs); static int allignBy128(int size); static float distBetweenPoints(vec3_t p1, vec3_t p2); diff --git a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp index 8710f93c..e8617928 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp @@ -27,7 +27,6 @@ namespace BSP clipMap->dynEntClientList[0] = m_memory.Alloc(clipMap->dynEntCount[0]); clipMap->dynEntClientList[1] = nullptr; - memset(clipMap->dynEntClientList[0], 0, sizeof(DynEntityClient) * clipMap->dynEntCount[0]); clipMap->dynEntServerList[0] = nullptr; clipMap->dynEntServerList[1] = nullptr; @@ -36,15 +35,12 @@ namespace BSP clipMap->dynEntCollList[1] = nullptr; clipMap->dynEntCollList[2] = nullptr; clipMap->dynEntCollList[3] = nullptr; - memset(clipMap->dynEntCollList[0], 0, sizeof(DynEntityColl) * clipMap->dynEntCount[0]); clipMap->dynEntPoseList[0] = m_memory.Alloc(clipMap->dynEntCount[0]); clipMap->dynEntPoseList[1] = nullptr; - memset(clipMap->dynEntPoseList[0], 0, sizeof(DynEntityPose) * clipMap->dynEntCount[0]); clipMap->dynEntDefList[0] = m_memory.Alloc(clipMap->dynEntCount[0]); clipMap->dynEntDefList[1] = nullptr; - memset(clipMap->dynEntDefList[0], 0, sizeof(DynEntityDef) * clipMap->dynEntCount[0]); } void ClipMapLinker::loadVisibility(clipMap_t* clipMap) @@ -122,19 +118,18 @@ namespace BSP void ClipMapLinker::loadRopesAndConstraints(clipMap_t* clipMap) { clipMap->num_constraints = 0; // max 511 - clipMap->constraints = NULL; + clipMap->constraints = nullptr; // The game allocates 32 empty ropes clipMap->max_ropes = 32; // max 300 clipMap->ropes = m_memory.Alloc (clipMap->max_ropes); - memset(clipMap->ropes, 0, sizeof(rope_t) * clipMap->max_ropes); } void ClipMapLinker::loadSubModelCollision(clipMap_t* clipMap, BSPData* bsp) { // Submodels are used for the world and map ent collision (triggers, bomb zones, etc) auto gfxWorldAsset = m_context.LoadDependency(bsp->bspName); - assert(gfxWorldAsset != NULL); + assert(gfxWorldAsset != nullptr); GfxWorld* gfxWorld = gfxWorldAsset->Asset(); // 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.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) @@ -178,7 +173,7 @@ namespace BSP // WIP code left in for future support /* auto gfxWorldAsset = m_context.LoadDependency(bsp->bspName); - assert(gfxWorldAsset != NULL); + assert(gfxWorldAsset != nullptr); GfxWorld* gfxWorld = gfxWorldAsset->Asset(); clipMap->numStaticModels = gfxWorld->dpvs.smodelCount; @@ -306,7 +301,7 @@ namespace BSP { uint16_t vertIndex = tri[l]; 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]; vec3_t* currVertex = &clipMap->verts[currUind]; - BSPUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs); + BSPUtil::updateAABBWithpoint(currVertex, &mins, &maxs); } aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize); @@ -631,17 +626,17 @@ namespace BSP { // No support for brushes, only tris right now clipMap->info.numBrushSides = 0; - clipMap->info.brushsides = NULL; + clipMap->info.brushsides = nullptr; clipMap->info.leafbrushNodesCount = 0; - clipMap->info.leafbrushNodes = NULL; + clipMap->info.leafbrushNodes = nullptr; clipMap->info.numLeafBrushes = 0; - clipMap->info.leafbrushes = NULL; + clipMap->info.leafbrushes = nullptr; clipMap->info.numBrushVerts = 0; - clipMap->info.brushVerts = NULL; - clipMap->info.numBrushes = NULL; - clipMap->info.brushes = NULL; - clipMap->info.brushBounds = NULL; - clipMap->info.brushContents = NULL; + clipMap->info.brushVerts = nullptr; + clipMap->info.numBrushes = 0; + clipMap->info.brushes = nullptr; + clipMap->info.brushBounds = nullptr; + clipMap->info.brushContents = nullptr; // clipmap BSP creation must go last as it depends on unids, tris and verts already being populated // HACK: @@ -667,7 +662,7 @@ namespace BSP for (unsigned int i = 1; i < clipMap->vertCount; 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); @@ -697,7 +692,7 @@ namespace BSP { uint16_t vertIndex = tri[l]; vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[vertIndex]); - BSPUtil::calcNewBoundsWithPoint(&vertCoord, &mins, &maxs); + BSPUtil::updateAABBWithpoint(&vertCoord, &mins, &maxs); } } diff --git a/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp index db15bd4c..88e8b8a8 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/ComWorldLinker.cpp @@ -15,23 +15,22 @@ namespace BSP ComWorld* comWorld = m_memory.Alloc(); comWorld->name = m_memory.Dup(bsp->bspName.c_str()); comWorld->isInUse = 1; - comWorld->primaryLightCount = 2; + comWorld->primaryLightCount = BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT; comWorld->primaryLights = m_memory.Alloc(comWorld->primaryLightCount); - // static light is always empty - ComPrimaryLight* staticLight = &comWorld->primaryLights[0]; - memset(staticLight, 0, sizeof(ComPrimaryLight)); - + // first (static) light is always empty + ComPrimaryLight* sunLight = &comWorld->primaryLights[1]; - memset(sunLight, 0, sizeof(ComPrimaryLight)); - sunLight->type = 1; - sunLight->diffuseColor.r = 0.75f; - sunLight->diffuseColor.g = 0.75f; - sunLight->diffuseColor.b = 0.75f; - sunLight->diffuseColor.a = 1.0f; - sunLight->dir.x = 0.0f; - sunLight->dir.y = 0.0f; - sunLight->dir.z = 0.0f; + const vec4_t sunLightColor = BSPEditableConstants::SUNLIGHT_COLOR; + const vec3_t sunLightDirection = BSPEditableConstants::SUNLIGHT_DIRECTION; + sunLight->type = GFX_LIGHT_TYPE_DIR; + sunLight->diffuseColor.r = sunLightColor.r; + sunLight->diffuseColor.g = sunLightColor.g; + sunLight->diffuseColor.b = sunLightColor.b; + sunLight->diffuseColor.a = sunLightColor.a; + sunLight->dir.x = sunLightDirection.x; + sunLight->dir.y = sunLightDirection.y; + sunLight->dir.z = sunLightDirection.z; auto comWorldAsset = m_context.AddAsset(comWorld->name, comWorld); return AssetCreationResult::Success(comWorldAsset); diff --git a/src/ObjLoading/Game/T6/BSP/Linker/GameWorldMpLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/GameWorldMpLinker.cpp index 1286837b..460f71d3 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/GameWorldMpLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/GameWorldMpLinker.cpp @@ -21,12 +21,10 @@ namespace BSP gameWorldMp->path.smoothBytes = 0; gameWorldMp->path.nodeTreeCount = 0; - int nodeCount = gameWorldMp->path.nodeCount + 128; - gameWorldMp->path.nodes = m_memory.Alloc(nodeCount); - gameWorldMp->path.basenodes = m_memory.Alloc(nodeCount); - memset(gameWorldMp->path.nodes, 0, nodeCount * sizeof(pathnode_t)); - memset(gameWorldMp->path.basenodes, 0, nodeCount * sizeof(pathbasenode_t)); - + // The game has 128 empty nodes allocated + int extraNodeCount = gameWorldMp->path.nodeCount + 128; + gameWorldMp->path.nodes = m_memory.Alloc(extraNodeCount); + gameWorldMp->path.basenodes = m_memory.Alloc(extraNodeCount); gameWorldMp->path.pathVis = nullptr; gameWorldMp->path.smoothCache = nullptr; gameWorldMp->path.nodeTree = nullptr; diff --git a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp index 82fe31c5..570ecb53 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/GfxWorldLinker.cpp @@ -130,7 +130,7 @@ namespace BSP for (int k = 0; k < currSurface->tris.triCount * 3; 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 @@ -191,68 +191,69 @@ namespace BSP /* Models are unsupported right now 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(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(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; gfxWorld->dpvs.smodelCount = modelCount; @@ -546,7 +547,7 @@ namespace BSP 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].probeVolumes = NULL; - std::string probeImageName = "*reflection_probe0"; + std::string probeImageName = "reflection_probe0"; auto probeImageAsset = m_context.LoadDependency(probeImageName); if (probeImageAsset == NULL) { @@ -689,7 +690,7 @@ namespace BSP memset(gfxWorld->draw.lightmapPrimaryTextures, 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(secondaryTexture); if (secondaryTextureAsset == NULL) { diff --git a/src/ObjLoading/Game/T6/BSP/Linker/MapEntsLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/MapEntsLinker.cpp index 5ba3145b..6849a3ed 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/MapEntsLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/MapEntsLinker.cpp @@ -8,14 +8,14 @@ namespace { bool parseMapEntsJSON(json& entArrayJs, std::string& entityString) { - int entityCount = entArrayJs.size(); - for (int i = 0; i < entityCount; i++) + for (size_t entIdx = 0; entIdx < entArrayJs.size(); entIdx++) { - 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) { con::error("ERROR: first entity in the map entity string must be the worldspawn class!"); @@ -25,7 +25,7 @@ namespace entityString.append("{\n"); - for (auto& element : currEntity.items()) + for (auto& element : entity.items()) { std::string key = element.key(); std::string value = element.value(); @@ -38,26 +38,31 @@ namespace 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 (int i = 0; i < entityCount; i++) + for (auto& element : entArrayJs.items()) { - 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"]; - std::string angles = currEntity["angles"]; - - for (int k = 0; k < nameCount; k++) + for (size_t nameIdx = 0; nameIdx < nameCount; nameIdx++) { entityString.append("{\n"); entityString.append(std::format("\"origin\" \"{}\"\n", origin)); 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"); } } } + + std::string loadMapEnts() + { + + } } namespace BSP @@ -71,58 +76,65 @@ namespace BSP AssetCreationResult MapEntsLinker::linkMapEnts(BSPData* bsp) { - std::string entityString; + try + { + json entJs; + std::string entityFilePath = BSPUtil::getFileNameForBSPAsset("entities.json"); + const auto entFile = m_search_path.Open(entityFilePath); + if (!entFile.IsOpen()) + { + con::warn("Can't find entity file {}, using default entities instead", entityFilePath); + entJs = json::parse(BSPLinkingConstants::DEFAULT_MAP_ENTS_STRING); + } + else + { + entJs = json::parse(*entFile.m_stream); + } + std::string entityString; + if (!parseMapEntsJSON(entJs["entities"], entityString)) + return AssetCreationResult::Failure(); - json entJs; - std::string entityFilePath = BSPUtil::getFileNameForBSPAsset("entities.json"); - const auto entFile = m_search_path.Open(entityFilePath); - if (!entFile.IsOpen()) - { - con::warn("Can't find entity file {}, using default entities instead", entityFilePath); - entJs = json::parse(BSPLinkingConstants::DEFAULT_MAP_ENTS_STRING); + json spawnJs; + std::string spawnFilePath = BSPUtil::getFileNameForBSPAsset("spawns.json"); + const auto spawnFile = m_search_path.Open(spawnFilePath); + if (!spawnFile.IsOpen()) + { + con::warn("Cant find spawn file {}, setting spawns to 0 0 0", spawnFilePath); + spawnJs = json::parse(BSPLinkingConstants::DEFAULT_SPAWN_POINT_STRING); + } + else + { + spawnJs = json::parse(*spawnFile.m_stream); + } + size_t defenderNameCount = std::extent::value; + size_t attackerNameCount = std::extent::value; + size_t ffaNameCount = std::extent::value; + parseSpawnpointJSON(spawnJs["attackers"], entityString, BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES, defenderNameCount); + parseSpawnpointJSON(spawnJs["defenders"], entityString, BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES, attackerNameCount); + parseSpawnpointJSON(spawnJs["FFA"], entityString, BSPGameConstants::FFA_SPAWN_POINT_NAMES, ffaNameCount); + + MapEnts* mapEnts = m_memory.Alloc(); + mapEnts->name = m_memory.Dup(bsp->bspName.c_str()); + + mapEnts->entityString = m_memory.Dup(entityString.c_str()); + mapEnts->numEntityChars = entityString.length() + 1; // numEntityChars includes the null character + + // don't need these + mapEnts->trigger.count = 0; + mapEnts->trigger.models = nullptr; + mapEnts->trigger.hullCount = 0; + mapEnts->trigger.hulls = nullptr; + mapEnts->trigger.slabCount = 0; + mapEnts->trigger.slabs = nullptr; + + auto mapEntsAsset = m_context.AddAsset(mapEnts->name, mapEnts); + return AssetCreationResult::Success(mapEntsAsset); } - else + catch (const json::exception& e) { - entJs = json::parse(*entFile.m_stream); - } - if (!parseMapEntsJSON(entJs["entities"], entityString)) + con::error("JSON error when parsing map ents and spawns: {}", e.what()); return AssetCreationResult::Failure(); - - json spawnJs; - std::string spawnFilePath = BSPUtil::getFileNameForBSPAsset("spawns.json"); - const auto spawnFile = m_search_path.Open(spawnFilePath); - if (!spawnFile.IsOpen()) - { - con::warn("Cant find spawn file {}, setting spawns to 0 0 0", spawnFilePath); - spawnJs = json::parse(BSPLinkingConstants::DEFAULT_SPAWN_POINT_STRING); } - else - { - spawnJs = json::parse(*spawnFile.m_stream); - } - int defenderNameCount = std::extent::value; - int attackerNameCount = std::extent::value; - int ffaNameCount = std::extent::value; - parseSpawnpointJSON(spawnJs["attackers"], entityString, BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES, defenderNameCount); - parseSpawnpointJSON(spawnJs["defenders"], entityString, BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES, attackerNameCount); - parseSpawnpointJSON(spawnJs["FFA"], entityString, BSPGameConstants::FFA_SPAWN_POINT_NAMES, ffaNameCount); - - MapEnts* mapEnts = m_memory.Alloc(); - mapEnts->name = m_memory.Dup(bsp->bspName.c_str()); - - mapEnts->entityString = m_memory.Dup(entityString.c_str()); - mapEnts->numEntityChars = entityString.length() + 1; // numEntityChars includes the null character - - // don't need these - mapEnts->trigger.count = 0; - mapEnts->trigger.models = nullptr; - mapEnts->trigger.hullCount = 0; - mapEnts->trigger.hulls = nullptr; - mapEnts->trigger.slabCount = 0; - mapEnts->trigger.slabs = nullptr; - - auto mapEntsAsset = m_context.AddAsset(mapEnts->name, mapEnts); - return AssetCreationResult::Success(mapEntsAsset); } }