2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-12-07 03:37:48 +00:00

chore: mixed code improvements

This commit is contained in:
Jan Laupetin
2025-11-04 22:52:34 +00:00
parent b754be5a68
commit 30e63186f3
21 changed files with 270 additions and 250 deletions

View File

@@ -3,12 +3,13 @@
#include "Game/T6/T6.h"
#include "Utils/Logging/Log.h"
#include <cstdint>
#include <string>
#include <vector>
namespace BSP
{
enum BSPMaterialType
enum class BSPMaterialType : std::uint8_t
{
MATERIAL_TYPE_COLOUR,
MATERIAL_TYPE_TEXTURE,
@@ -33,9 +34,9 @@ namespace BSP
struct BSPSurface
{
BSPMaterial material;
int triCount;
int indexOfFirstVertex;
int indexOfFirstIndex;
unsigned triCount;
unsigned indexOfFirstVertex;
unsigned indexOfFirstIndex;
};
struct BSPWorld
@@ -58,7 +59,7 @@ namespace BSP
// These values are hardcoded ingame and will break the map if they are changed
namespace BSPGameConstants
{
constexpr unsigned int MAX_COLLISION_VERTS = UINT16_MAX;
constexpr unsigned int MAX_COLLISION_VERTS = std::numeric_limits<std::uint16_t>::max();
constexpr size_t MAX_AABB_TREE_CHILDREN = 128;

View File

@@ -2,7 +2,7 @@
namespace BSP
{
constexpr int MAX_NODE_SIZE = 512; // maximum size a BSP node can be before it becomes a leaf
constexpr auto MAX_NODE_SIZE = 512u; // maximum size a BSP node can be before it becomes a leaf
BSPObject::BSPObject(
const float xMin, const float yMin, const float zMin, const float xMax, const float yMax, const float zMax, const int objPartitionIndex)
@@ -16,17 +16,17 @@ namespace BSP
partitionIndex = objPartitionIndex;
}
void BSPLeaf::addObject(std::shared_ptr<BSPObject> object)
void BSPLeaf::AddObject(std::shared_ptr<BSPObject> object)
{
objectList.emplace_back(std::move(object));
}
BSPObject* BSPLeaf::getObject(const size_t index) const
BSPObject* BSPLeaf::GetObject(const size_t index) const
{
return objectList.at(index).get();
}
size_t BSPLeaf::getObjectCount() const
size_t BSPLeaf::GetObjectCount() const
{
return objectList.size();
}
@@ -39,17 +39,17 @@ namespace BSP
distance = nodeDistance;
}
PlaneSide BSPNode::objectIsInFront(const BSPObject& object) const
PlaneSide BSPNode::ObjectIsInFront(const BSPObject& object) const
{
float minCoord, maxCoord;
// Select the relevant coordinate based on the plane's axis
if (axis == AXIS_X)
if (axis == PlaneAxis::AXIS_X)
{
minCoord = object.min.x;
maxCoord = object.max.x;
}
else if (axis == AXIS_Y)
else if (axis == PlaneAxis::AXIS_Y)
{
minCoord = object.min.y;
maxCoord = object.max.y;
@@ -63,15 +63,15 @@ namespace BSP
// Compare with the plane's distance
if (maxCoord < distance)
{
return SIDE_BACK; // Object is entirely on the negative side
return PlaneSide::SIDE_BACK; // Object is entirely on the negative side
}
else if (minCoord > distance)
{
return SIDE_FRONT; // Object is entirely on the positive side
return PlaneSide::SIDE_FRONT; // Object is entirely on the positive side
}
else
{
return SIDE_INTERSECTS;
return PlaneSide::SIDE_INTERSECTS;
}
}
@@ -84,10 +84,11 @@ namespace BSP
max.y = yMax;
max.z = zMax;
level = treeLevel;
splitTree();
SplitTree();
}
void BSPTree::splitTree()
void BSPTree::SplitTree()
{
std::unique_ptr<BSPTree> front;
std::unique_ptr<BSPTree> back;
@@ -101,7 +102,7 @@ namespace BSP
back = std::make_unique<BSPTree>(min.x, min.y, min.z, halfLength, max.y, max.z, level + 1);
isLeaf = false;
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_X, halfLength);
node = std::make_unique<BSPNode>(std::move(front), std::move(back), PlaneAxis::AXIS_X, halfLength);
leaf = nullptr;
}
else if (max.y - min.y > MAX_NODE_SIZE)
@@ -112,7 +113,7 @@ namespace BSP
back = std::make_unique<BSPTree>(min.x, min.y, min.z, max.x, halfLength, max.z, level + 1);
isLeaf = false;
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_Y, halfLength);
node = std::make_unique<BSPNode>(std::move(front), std::move(back), PlaneAxis::AXIS_Y, halfLength);
leaf = nullptr;
}
else if (max.z - min.z > MAX_NODE_SIZE)
@@ -123,7 +124,7 @@ namespace BSP
back = std::make_unique<BSPTree>(min.x, min.y, min.z, max.x, max.y, halfLength, level + 1);
isLeaf = false;
node = std::make_unique<BSPNode>(std::move(front), std::move(back), AXIS_Z, halfLength);
node = std::make_unique<BSPNode>(std::move(front), std::move(back), PlaneAxis::AXIS_Z, halfLength);
leaf = nullptr;
}
else
@@ -134,27 +135,28 @@ namespace BSP
}
}
void BSPTree::addObjectToTree(std::shared_ptr<BSPObject> object) const
void BSPTree::AddObjectToTree(std::shared_ptr<BSPObject> object) const
{
if (isLeaf)
{
leaf->addObject(std::move(object));
leaf->AddObject(std::move(object));
}
else
{
const auto side = node->objectIsInFront(*object);
if (side == SIDE_FRONT)
const auto side = node->ObjectIsInFront(*object);
if (side == PlaneSide::SIDE_FRONT)
{
node->front->addObjectToTree(std::move(object));
node->front->AddObjectToTree(std::move(object));
}
else if (side == SIDE_BACK)
else if (side == PlaneSide::SIDE_BACK)
{
node->back->addObjectToTree(std::move(object));
node->back->AddObjectToTree(std::move(object));
}
else // intersects
{
node->front->addObjectToTree(object);
node->back->addObjectToTree(object);
node->front->AddObjectToTree(object);
node->back->AddObjectToTree(object);
}
}
}

View File

@@ -2,16 +2,18 @@
#include "BSP.h"
#include <cstdint>
namespace BSP
{
enum PlaneAxis
enum class PlaneAxis : std::uint8_t
{
AXIS_X,
AXIS_Y,
AXIS_Z
};
enum PlaneSide
enum class PlaneSide : std::uint8_t
{
SIDE_FRONT,
SIDE_BACK,
@@ -21,21 +23,21 @@ namespace BSP
class BSPObject
{
public:
BSPObject(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex);
T6::vec3_t min;
T6::vec3_t max;
int partitionIndex; // index of the partition the object is contained in
BSPObject(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex);
};
class BSPLeaf
{
public:
std::vector<std::shared_ptr<BSPObject>> objectList;
void AddObject(std::shared_ptr<BSPObject> object);
[[nodiscard]] BSPObject* GetObject(size_t index) const;
[[nodiscard]] size_t GetObjectCount() const;
void addObject(std::shared_ptr<BSPObject> object);
[[nodiscard]] BSPObject* getObject(size_t index) const;
[[nodiscard]] size_t getObjectCount() const;
std::vector<std::shared_ptr<BSPObject>> objectList;
};
class BSPTree;
@@ -43,19 +45,24 @@ namespace BSP
class BSPNode
{
public:
BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> backTree, PlaneAxis nodeAxis, float nodeDistance);
[[nodiscard]] PlaneSide ObjectIsInFront(const BSPObject& object) const;
std::unique_ptr<BSPTree> front;
std::unique_ptr<BSPTree> back;
PlaneAxis axis; // axis that the split plane is on
float distance; // distance from the origin (0, 0, 0) to the plane
BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> backTree, PlaneAxis nodeAxis, float nodeDistance);
[[nodiscard]] PlaneSide objectIsInFront(const BSPObject& object) const;
};
class BSPTree
{
public:
BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel);
void SplitTree();
void AddObjectToTree(std::shared_ptr<BSPObject> object) const;
bool isLeaf;
std::unique_ptr<BSPLeaf> leaf;
std::unique_ptr<BSPNode> node;
@@ -63,9 +70,5 @@ namespace BSP
int level; // level in the BSP tree
T6::vec3_t min;
T6::vec3_t max;
BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel);
void splitTree();
void addObjectToTree(std::shared_ptr<BSPObject> object) const;
};
} // namespace BSP

View File

@@ -2,14 +2,16 @@
#include "BSPUtil.h"
#include <cassert>
#include <format>
#include <limits>
#include <ufbx.h>
using namespace BSP;
namespace
{
void addFBXMeshToWorld(
void AddFBXMeshToWorld(
ufbx_node* node, std::vector<BSPSurface>& surfaceVec, std::vector<BSPVertex>& vertexVec, std::vector<uint16_t>& indexVec, bool& hasTangentSpace)
{
ufbx_mesh* mesh = node->mesh;
@@ -17,7 +19,7 @@ namespace
assert(node->attrib_type == UFBX_ELEMENT_MESH);
if (mesh->instances.count != 1)
con::warn("mesh {} has {} instances, only the 1st instace will be used.", node->name.data, mesh->instances.count);
con::warn("mesh {} has {} instances, only the 1st instance will be used.", node->name.data, mesh->instances.count);
if (mesh->num_triangles == 0)
{
@@ -33,9 +35,9 @@ namespace
for (size_t k = 0; k < mesh->num_indices; k++)
{
if (mesh->vertex_indices[k] > UINT16_MAX)
if (mesh->vertex_indices[k] > std::numeric_limits<std::uint16_t>::max())
{
con::warn("ignoring mesh {}, it has more than {} indices.", node->name.data, UINT16_MAX);
con::warn("ignoring mesh {}, it has more than {} indices.", node->name.data, std::numeric_limits<std::uint16_t>::max());
return;
}
}
@@ -61,18 +63,18 @@ namespace
BSPSurface surface;
size_t partTriangleNum = meshPart.num_triangles;
surface.triCount = static_cast<int>(partTriangleNum);
surface.indexOfFirstVertex = static_cast<int>(vertexVec.size());
surface.indexOfFirstIndex = static_cast<int>(indexVec.size());
surface.triCount = static_cast<unsigned>(partTriangleNum);
surface.indexOfFirstVertex = static_cast<unsigned>(vertexVec.size());
surface.indexOfFirstIndex = static_cast<unsigned>(indexVec.size());
if (mesh->materials.count == 0)
{
surface.material.materialType = MATERIAL_TYPE_EMPTY;
surface.material.materialType = BSPMaterialType::MATERIAL_TYPE_EMPTY;
surface.material.materialName = "";
}
else
{
surface.material.materialType = MATERIAL_TYPE_TEXTURE;
surface.material.materialType = BSPMaterialType::MATERIAL_TYPE_TEXTURE;
surface.material.materialName = mesh->materials.data[meshPart.index]->name.data;
}
@@ -84,9 +86,9 @@ namespace
ufbx_face* face = &mesh->faces.data[faceIndex];
// Triangulate the face into the indices vector
uint32_t triangluatedTriCount = ufbx_triangulate_face(tempIndices.data(), tempIndices.size(), mesh, *face);
uint32_t triangulatedTriCount = ufbx_triangulate_face(tempIndices.data(), tempIndices.size(), mesh, *face);
for (uint32_t idxOfIndex = 0; idxOfIndex < triangluatedTriCount * 3; idxOfIndex++)
for (uint32_t idxOfIndex = 0; idxOfIndex < triangulatedTriCount * 3; idxOfIndex++)
{
BSPVertex vertex;
uint32_t index = tempIndices[idxOfIndex];
@@ -98,7 +100,8 @@ namespace
blenderCoords.z = static_cast<float>(transformedPos.z);
vertex.pos = ConvertToBO2Coords(blenderCoords);
if (surface.material.materialType == MATERIAL_TYPE_TEXTURE || surface.material.materialType == MATERIAL_TYPE_EMPTY)
if (surface.material.materialType == BSPMaterialType::MATERIAL_TYPE_TEXTURE
|| surface.material.materialType == BSPMaterialType::MATERIAL_TYPE_EMPTY)
{
vertex.color.x = 1.0f;
vertex.color.y = 1.0f;
@@ -171,7 +174,7 @@ namespace
}
}
void loadWorldData(const ufbx_scene& scene, BSPData& bsp, const bool isGfxData)
void LoadWorldData(const ufbx_scene& scene, BSPData& bsp, const bool isGfxData)
{
bool hasTangentSpace = true;
for (ufbx_node* node : scene.nodes)
@@ -179,9 +182,9 @@ namespace
if (node->attrib_type == UFBX_ELEMENT_MESH)
{
if (isGfxData)
addFBXMeshToWorld(node, bsp.gfxWorld.surfaces, bsp.gfxWorld.vertices, bsp.gfxWorld.indices, hasTangentSpace);
AddFBXMeshToWorld(node, bsp.gfxWorld.surfaces, bsp.gfxWorld.vertices, bsp.gfxWorld.indices, hasTangentSpace);
else
addFBXMeshToWorld(node, bsp.colWorld.surfaces, bsp.colWorld.vertices, bsp.colWorld.indices, hasTangentSpace);
AddFBXMeshToWorld(node, bsp.colWorld.surfaces, bsp.colWorld.vertices, bsp.colWorld.indices, hasTangentSpace);
}
else
{
@@ -196,19 +199,18 @@ namespace
namespace BSP
{
std::unique_ptr<BSPData> createBSPData(const std::string& mapName, ISearchPath& searchPath)
std::unique_ptr<BSPData> CreateBSPData(const std::string& mapName, ISearchPath& searchPath)
{
std::string gfxFbxFileName = "map_gfx.fbx";
std::string gfxFbxPath = GetFileNameForBSPAsset(gfxFbxFileName);
auto gfxFile = searchPath.Open(gfxFbxPath);
const auto gfxFbxPath = GetFileNameForBSPAsset("map_gfx.fbx");
const auto gfxFile = searchPath.Open(gfxFbxPath);
if (!gfxFile.IsOpen())
{
con::error("Failed to open map gfx fbx file: {}", gfxFbxPath);
return nullptr;
}
std::unique_ptr<char> gfxMapData(new char[static_cast<size_t>(gfxFile.m_length)]);
gfxFile.m_stream->read(gfxMapData.get(), gfxFile.m_length);
std::vector<char> gfxMapData(static_cast<size_t>(gfxFile.m_length));
gfxFile.m_stream->read(gfxMapData.data(), gfxFile.m_length);
if (gfxFile.m_stream->gcount() != gfxFile.m_length)
{
con::error("Read error of gfx fbx file: {}", gfxFbxPath);
@@ -220,7 +222,7 @@ namespace BSP
optsGfx.target_axes = ufbx_axes_right_handed_y_up;
optsGfx.generate_missing_normals = true;
optsGfx.allow_missing_vertex_position = false;
ufbx_scene* gfxScene = ufbx_load_memory(gfxMapData.get(), static_cast<size_t>(gfxFile.m_length), &optsGfx, &errorGfx);
ufbx_scene* gfxScene = ufbx_load_memory(gfxMapData.data(), static_cast<size_t>(gfxFile.m_length), &optsGfx, &errorGfx);
if (!gfxScene)
{
con::error("Failed to load map gfx fbx file: {}", errorGfx.description.data);
@@ -228,19 +230,18 @@ namespace BSP
}
ufbx_scene* colScene;
std::string colFbxFileName = "map_col.fbx";
const auto colFbxPath = GetFileNameForBSPAsset(colFbxFileName);
const auto colFbxPath = GetFileNameForBSPAsset("map_col.fbx");
const auto colFile = searchPath.Open(colFbxPath);
if (!colFile.IsOpen())
{
con::warn("Failed to open map collison fbx file: {}. map gfx will be used for collision instead.", colFbxPath);
con::warn("Failed to open map collision fbx file: {}. map gfx will be used for collision instead.", colFbxPath);
colScene = gfxScene;
}
else
{
std::unique_ptr<char> colMapData(new char[static_cast<size_t>(colFile.m_length)]);
std::vector<char> colMapData(static_cast<size_t>(colFile.m_length));
colFile.m_stream->seekg(0);
colFile.m_stream->read(colMapData.get(), colFile.m_length);
colFile.m_stream->read(colMapData.data(), colFile.m_length);
if (colFile.m_stream->gcount() != colFile.m_length)
{
con::error("Read error of collision fbx file: {}", colFbxPath);
@@ -252,7 +253,7 @@ namespace BSP
optsCol.target_axes = ufbx_axes_right_handed_y_up;
optsCol.generate_missing_normals = true;
optsCol.allow_missing_vertex_position = false;
colScene = ufbx_load_memory(colMapData.get(), static_cast<size_t>(colFile.m_length), &optsCol, &errorCol);
colScene = ufbx_load_memory(colMapData.data(), static_cast<size_t>(colFile.m_length), &optsCol, &errorCol);
if (!colScene)
{
con::error("Failed to load map collision fbx file: {}", errorCol.description.data);
@@ -265,8 +266,8 @@ namespace BSP
bsp->name = mapName;
bsp->bspName = std::format("maps/mp/{}.d3dbsp", mapName);
loadWorldData(*gfxScene, *bsp, true);
loadWorldData(*colScene, *bsp, false);
LoadWorldData(*gfxScene, *bsp, true);
LoadWorldData(*colScene, *bsp, false);
ufbx_free_scene(gfxScene);
if (gfxScene != colScene)

View File

@@ -5,5 +5,5 @@
namespace BSP
{
std::unique_ptr<BSPData> createBSPData(const std::string& mapName, ISearchPath& searchPath);
std::unique_ptr<BSPData> CreateBSPData(const std::string& mapName, ISearchPath& searchPath);
}; // namespace BSP

View File

@@ -92,12 +92,12 @@ namespace BSP
const auto yRadians = angles->y * conversionValue;
const auto zRadians = angles->z * conversionValue;
const auto cosX = cos(xRadians);
const auto sinX = sin(xRadians);
const auto cosY = cos(yRadians);
const auto sinY = sin(yRadians);
const auto cosZ = cos(zRadians);
const auto sinZ = sin(zRadians);
const auto cosX = std::cos(xRadians);
const auto sinX = std::sin(xRadians);
const auto cosY = std::cos(yRadians);
const auto sinY = std::sin(yRadians);
const auto cosZ = std::cos(zRadians);
const auto sinZ = std::sin(zRadians);
axis[0].x = cosX * cosY;
axis[0].y = cosX * sinY;

View File

@@ -13,7 +13,7 @@ using namespace T6;
namespace BSP
{
void BSPLinker::addEmptyFootstepTableAsset(const std::string& assetName) const
void BSPLinker::AddEmptyFootstepTableAsset(const std::string& assetName) const
{
if (assetName.empty())
return;
@@ -25,30 +25,30 @@ namespace BSP
m_context.AddAsset<AssetFootstepTable>(assetName, footstepTable);
}
bool BSPLinker::addDefaultRequiredAssets(const BSPData& bsp) const
bool BSPLinker::AddDefaultRequiredAssets(const BSPData& bsp) const
{
if (m_context.LoadDependency<AssetScript>(std::format("maps/mp/{}.gsc", bsp.name)) == nullptr)
if (!m_context.LoadDependency<AssetScript>(std::format("maps/mp/{}.gsc", bsp.name)))
return false;
if (m_context.LoadDependency<AssetScript>(std::format("maps/mp/{}_amb.gsc", bsp.name)) == nullptr)
if (!m_context.LoadDependency<AssetScript>(std::format("maps/mp/{}_amb.gsc", bsp.name)))
return false;
if (m_context.LoadDependency<AssetScript>(std::format("maps/mp/{}_fx.gsc", bsp.name)) == nullptr)
if (!m_context.LoadDependency<AssetScript>(std::format("maps/mp/{}_fx.gsc", bsp.name)))
return false;
if (m_context.LoadDependency<AssetScript>(std::format("clientscripts/mp/{}.csc", bsp.name)) == nullptr)
if (!m_context.LoadDependency<AssetScript>(std::format("clientscripts/mp/{}.csc", bsp.name)))
return false;
if (m_context.LoadDependency<AssetScript>(std::format("clientscripts/mp/{}_amb.csc", bsp.name)) == nullptr)
if (!m_context.LoadDependency<AssetScript>(std::format("clientscripts/mp/{}_amb.csc", bsp.name)))
return false;
if (m_context.LoadDependency<AssetScript>(std::format("clientscripts/mp/{}_fx.csc", bsp.name)) == nullptr)
if (!m_context.LoadDependency<AssetScript>(std::format("clientscripts/mp/{}_fx.csc", bsp.name)))
return false;
addEmptyFootstepTableAsset("default_1st_person");
addEmptyFootstepTableAsset("default_3rd_person");
addEmptyFootstepTableAsset("default_1st_person_quiet");
addEmptyFootstepTableAsset("default_3rd_person_quiet");
addEmptyFootstepTableAsset("default_3rd_person_loud");
addEmptyFootstepTableAsset("default_ai");
AddEmptyFootstepTableAsset("default_1st_person");
AddEmptyFootstepTableAsset("default_3rd_person");
AddEmptyFootstepTableAsset("default_1st_person_quiet");
AddEmptyFootstepTableAsset("default_3rd_person_quiet");
AddEmptyFootstepTableAsset("default_3rd_person_loud");
AddEmptyFootstepTableAsset("default_ai");
if (m_context.LoadDependency<AssetRawFile>("animtrees/fxanim_props.atr") == nullptr)
if (!m_context.LoadDependency<AssetRawFile>("animtrees/fxanim_props.atr"))
return false;
return true;
@@ -61,9 +61,9 @@ namespace BSP
{
}
bool BSPLinker::linkBSP(const BSPData& bsp) const
bool BSPLinker::LinkBSP(const BSPData& bsp) const
{
if (!addDefaultRequiredAssets(bsp))
if (!AddDefaultRequiredAssets(bsp))
return false;
ComWorldLinker comWorldLinker(m_memory, m_search_path, m_context);
@@ -73,32 +73,32 @@ namespace BSP
MapEntsLinker mapEntsLinker(m_memory, m_search_path, m_context);
SkinnedVertsLinker skinnedVertsLinker(m_memory, m_search_path, m_context);
auto* comWorld = comWorldLinker.linkComWorld(bsp);
auto* comWorld = comWorldLinker.LinkComWorld(bsp);
if (comWorld == nullptr)
return false;
m_context.AddAsset<AssetComWorld>(comWorld->name, comWorld);
auto* mapEnts = mapEntsLinker.linkMapEnts(bsp);
auto* mapEnts = mapEntsLinker.LinkMapEnts(bsp);
if (mapEnts == nullptr)
return false;
m_context.AddAsset<AssetMapEnts>(mapEnts->name, mapEnts);
auto* gameWorldMp = gameWorldMpLinker.linkGameWorldMp(bsp);
auto* gameWorldMp = gameWorldMpLinker.LinkGameWorldMp(bsp);
if (gameWorldMp == nullptr)
return false;
m_context.AddAsset<AssetGameWorldMp>(gameWorldMp->name, gameWorldMp);
auto* skinnedVerts = skinnedVertsLinker.linkSkinnedVerts(bsp);
auto* skinnedVerts = skinnedVertsLinker.LinkSkinnedVerts(bsp);
if (skinnedVerts == nullptr)
return false;
m_context.AddAsset<AssetSkinnedVerts>(skinnedVerts->name, skinnedVerts);
auto* gfxWorld = gfxWorldLinker.linkGfxWorld(bsp); // requires mapents asset
auto* gfxWorld = gfxWorldLinker.LinkGfxWorld(bsp); // requires mapents asset
if (gfxWorld == nullptr)
return false;
m_context.AddAsset<AssetGfxWorld>(gfxWorld->name, gfxWorld);
auto* clipMap = clipMapLinker.linkClipMap(bsp); // requires gfxworld and mapents asset
auto* clipMap = clipMapLinker.LinkClipMap(bsp); // requires gfxworld and mapents asset
if (clipMap == nullptr)
return false;
m_context.AddAsset<AssetClipMap>(clipMap->name, clipMap);

View File

@@ -12,11 +12,11 @@ namespace BSP
public:
BSPLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] bool linkBSP(const BSPData& bsp) const;
[[nodiscard]] bool LinkBSP(const BSPData& bsp) const;
private:
void addEmptyFootstepTableAsset(const std::string& assetName) const;
[[nodiscard]] bool addDefaultRequiredAssets(const BSPData& bsp) const;
void AddEmptyFootstepTableAsset(const std::string& assetName) const;
[[nodiscard]] bool AddDefaultRequiredAssets(const BSPData& bsp) const;
MemoryManager& m_memory;
ISearchPath& m_search_path;

View File

@@ -2,6 +2,7 @@
#include "Game/T6/BSP/BSPUtil.h"
#include <algorithm>
#include <cassert>
using namespace T6;
@@ -15,9 +16,9 @@ namespace BSP
{
}
void ClipMapLinker::loadDynEnts(clipMap_t& clipMap) const
void ClipMapLinker::LoadDynEnts(clipMap_t& clipMap) const
{
int dynEntCount = 0;
uint16_t dynEntCount = 0;
clipMap.originalDynEntCount = dynEntCount;
clipMap.dynEntCount[0] = clipMap.originalDynEntCount + 256; // the game allocs 256 empty dynents, as they may be used ingame
clipMap.dynEntCount[1] = 0;
@@ -42,7 +43,7 @@ namespace BSP
clipMap.dynEntDefList[1] = nullptr;
}
void ClipMapLinker::loadVisibility(clipMap_t& clipMap) const
void ClipMapLinker::LoadVisibility(clipMap_t& clipMap) const
{
// Only use one visbility cluster for the entire map
clipMap.numClusters = 1;
@@ -53,7 +54,7 @@ namespace BSP
memset(clipMap.visibility, 0xFF, clipMap.clusterBytes);
}
void ClipMapLinker::loadBoxData(clipMap_t& clipMap) const
void ClipMapLinker::LoadBoxData(clipMap_t& clipMap) const
{
// box_model and box_brush are what are used by game traces as "temporary" collision when
// no brush or model is specified to do the trace with.
@@ -114,7 +115,7 @@ namespace BSP
clipMap.box_brush->verts = nullptr;
}
void ClipMapLinker::loadRopesAndConstraints(clipMap_t& clipMap) const
void ClipMapLinker::LoadRopesAndConstraints(clipMap_t& clipMap) const
{
clipMap.num_constraints = 0; // max 511
clipMap.constraints = nullptr;
@@ -124,7 +125,7 @@ namespace BSP
clipMap.ropes = m_memory.Alloc<rope_t>(clipMap.max_ropes);
}
void ClipMapLinker::loadSubModelCollision(clipMap_t& clipMap, const BSPData& bsp) const
void ClipMapLinker::LoadSubModelCollision(clipMap_t& clipMap, const BSPData& bsp) const
{
// Submodels are used for the world and map ent collision (triggers, bomb zones, etc)
auto gfxWorldAsset = m_context.LoadDependency<AssetGfxWorld>(bsp.bspName);
@@ -163,7 +164,7 @@ namespace BSP
clipMap.cmodels[0].info = nullptr; // always set to 0
}
void ClipMapLinker::loadXModelCollision(clipMap_t& clipMap) const
void ClipMapLinker::LoadXModelCollision(clipMap_t& clipMap) const
{
// Right now XModels aren't supported
clipMap.numStaticModels = 0;
@@ -213,11 +214,11 @@ namespace BSP
*/
}
void ClipMapLinker::addAABBTreeFromLeaf(clipMap_t& clipMap, const BSPTree& tree, size_t& outParentCount, size_t& outParentStartIndex)
void ClipMapLinker::AddAABBTreeFromLeaf(clipMap_t& clipMap, const BSPTree& tree, size_t& outParentCount, size_t& outParentStartIndex)
{
assert(tree.isLeaf);
size_t leafObjectCount = tree.leaf->getObjectCount();
size_t leafObjectCount = tree.leaf->GetObjectCount();
assert(leafObjectCount > 0);
highestLeafObjectCount = std::max(leafObjectCount, highestLeafObjectCount);
@@ -246,7 +247,7 @@ namespace BSP
vec3_t parentMaxs;
for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++)
{
int partitionIndex = tree.leaf->getObject(addedObjectCount + objectIdx)->partitionIndex;
int partitionIndex = tree.leaf->GetObject(addedObjectCount + objectIdx)->partitionIndex;
CollisionPartition* partition = &clipMap.partitions[partitionIndex];
for (int uindIdx = 0; uindIdx < partition->nuinds; uindIdx++)
{
@@ -276,7 +277,7 @@ namespace BSP
// add child AABBs
for (size_t objectIdx = 0; objectIdx < childObjectCount; objectIdx++)
{
int partitionIndex = tree.leaf->getObject(addedObjectCount + objectIdx)->partitionIndex;
int partitionIndex = tree.leaf->GetObject(addedObjectCount + objectIdx)->partitionIndex;
CollisionPartition* partition = &clipMap.partitions[partitionIndex];
vec3_t childMins;
vec3_t childMaxs;
@@ -295,7 +296,7 @@ namespace BSP
UpdateAABBWithPoint(vert, childMins, childMaxs);
}
CollisionAabbTree childAABBTree;
CollisionAabbTree childAABBTree{};
childAABBTree.materialIndex = 0; // always use the first material
childAABBTree.childCount = 0;
childAABBTree.u.partitionIndex = partitionIndex;
@@ -311,15 +312,21 @@ namespace BSP
outParentStartIndex = parentAABBArrayIndex;
}
constexpr vec3_t normalX = {1.0f, 0.0f, 0.0f};
constexpr vec3_t normalY = {0.0f, 1.0f, 0.0f};
constexpr vec3_t normalZ = {0.0f, 0.0f, 1.0f};
constexpr vec3_t normalX = {
{.x = 1.0f, .y = 0.0f, .z = 0.0f}
};
constexpr vec3_t normalY = {
{.x = 0.0f, .y = 1.0f, .z = 0.0f}
};
constexpr vec3_t normalZ = {
{.x = 0.0f, .y = 0.0f, .z = 1.0f}
};
// returns the index of the node/leaf parsed by the function
// Nodes are indexed by their index in the node array
// Leafs are indexed by (-1 - <leaf index>)
// See https://developer.valvesoftware.com/wiki/BSP_(Source)
int16_t ClipMapLinker::loadBSPNode(clipMap_t& clipMap, const BSPTree& tree)
int16_t ClipMapLinker::LoadBSPNode(clipMap_t& clipMap, const BSPTree& tree)
{
if (tree.isLeaf)
{
@@ -338,11 +345,11 @@ namespace BSP
leaf.maxs.z = 0.0f;
leaf.leafBrushNode = 0;
if (tree.leaf->getObjectCount() > 0)
if (tree.leaf->GetObjectCount() > 0)
{
size_t parentCount = 0;
size_t parentStartIndex = 0;
addAABBTreeFromLeaf(clipMap, tree, parentCount, parentStartIndex);
AddAABBTreeFromLeaf(clipMap, tree, parentCount, parentStartIndex);
leaf.collAabbCount = static_cast<uint16_t>(parentCount);
leaf.firstCollAabbIndex = static_cast<uint16_t>(parentStartIndex);
}
@@ -361,18 +368,20 @@ namespace BSP
{
cplane_s plane;
plane.dist = tree.node->distance;
if (tree.node->axis == AXIS_X)
if (tree.node->axis == PlaneAxis::AXIS_X)
{
plane.normal = normalX;
plane.type = 0;
}
else if (tree.node->axis == AXIS_Y)
else if (tree.node->axis == PlaneAxis::AXIS_Y)
{
plane.normal = normalY;
plane.type = 1;
}
else // tree->node->axis == AXIS_Z
else
{
assert(tree.node->axis == PlaneAxis::AXIS_Z);
plane.normal = normalZ;
plane.type = 2;
}
@@ -390,14 +399,14 @@ namespace BSP
planeVec.emplace_back(plane);
// The recursion of adding the children through loadBSPNode means the parent node needs to be added before the chilren are loaded
// The recursion of adding the children through LoadBSPNode means the parent node needs to be added before the children are loaded
size_t nodeIndex = nodeVec.size();
nodeVec.emplace_back();
cNode_t node;
node.plane = nullptr; // initalised after the BSP tree has been loaded
node.children[0] = loadBSPNode(clipMap, *tree.node->front);
node.children[1] = loadBSPNode(clipMap, *tree.node->back);
node.plane = nullptr; // initialised after the BSP tree has been loaded
node.children[0] = LoadBSPNode(clipMap, *tree.node->front);
node.children[1] = LoadBSPNode(clipMap, *tree.node->back);
nodeVec.at(nodeIndex) = node;
@@ -405,14 +414,14 @@ namespace BSP
}
}
void ClipMapLinker::loadBSPTree(clipMap_t& clipMap, const BSPData& bsp)
void ClipMapLinker::LoadBSPTree(clipMap_t& clipMap, const BSPData& bsp)
{
vec3_t worldMins;
vec3_t worldMaxs;
for (unsigned int vertIdx = 0; vertIdx < clipMap.vertCount; vertIdx++)
{
vec3_t vertex = clipMap.verts[vertIdx];
// initalise AABB with the first vertex
// initialise AABB with the first vertex
if (vertIdx == 0)
{
worldMins = vertex;
@@ -442,11 +451,11 @@ namespace BSP
}
auto currObject =
std::make_shared<BSPObject>(partitionMins.x, partitionMins.y, partitionMins.z, partitionMaxs.x, partitionMaxs.y, partitionMaxs.z, partitionIdx);
tree->addObjectToTree(std::move(currObject));
tree->AddObjectToTree(std::move(currObject));
}
// load planes, nodes, leafs, and AABB trees
loadBSPNode(clipMap, *tree);
LoadBSPNode(clipMap, *tree);
clipMap.info.planeCount = static_cast<int>(planeVec.size());
clipMap.info.planes = m_memory.Alloc<cplane_s>(planeVec.size());
@@ -471,7 +480,7 @@ namespace BSP
con::info("Highest leaf object count: {}", highestLeafObjectCount);
}
bool ClipMapLinker::loadPartitions(clipMap_t& clipMap, const BSPData& bsp) const
bool ClipMapLinker::LoadPartitions(clipMap_t& clipMap, const BSPData& bsp) const
{
// due to tris using uint16_t as the type for indexing the vert array,
// any vertex count over the uint16_t max means the vertices above the uint16_t max can't be indexed
@@ -493,9 +502,9 @@ namespace BSP
{
const auto indexOfFirstIndex = surface.indexOfFirstIndex;
const auto indexOfFirstVertex = surface.indexOfFirstVertex;
for (auto indexIdx = 0; indexIdx < surface.triCount * 3; indexIdx++)
for (auto indexIdx = 0u; indexIdx < surface.triCount * 3; indexIdx++)
{
auto triIndex = bsp.colWorld.indices[indexOfFirstIndex + indexIdx] + indexOfFirstVertex;
auto triIndex = static_cast<uint16_t>(bsp.colWorld.indices[indexOfFirstIndex + indexIdx] + indexOfFirstVertex);
triIndexVec.emplace_back(triIndex);
}
}
@@ -513,12 +522,11 @@ namespace BSP
// one for each surface causes physics bugs, as the entire bounding box is considered solid instead of the surface itself (for some reason).
// so a partition is made for each triangle which removes the physics bugs but likely makes the game run slower
const auto indexOfFirstTri = surface.indexOfFirstIndex / 3;
const auto indexOfFirstVertex = surface.indexOfFirstVertex;
for (auto triIdx = 0; triIdx < surface.triCount; triIdx++)
for (auto triIdx = 0u; triIdx < surface.triCount; triIdx++)
{
CollisionPartition partition;
partition.triCount = 1;
partition.firstTri = indexOfFirstTri + triIdx;
partition.firstTri = static_cast<int>(indexOfFirstTri + triIdx);
partition.nuinds = 3;
partition.fuind = static_cast<int>(uniqueIndicesVec.size());
@@ -583,7 +591,7 @@ namespace BSP
*/
}
bool ClipMapLinker::loadWorldCollision(clipMap_t& clipMap, const BSPData& bsp)
bool ClipMapLinker::LoadWorldCollision(clipMap_t& clipMap, const BSPData& bsp)
{
// No support for brushes, only tris right now
clipMap.info.numBrushSides = 0;
@@ -600,15 +608,15 @@ namespace BSP
clipMap.info.brushContents = nullptr;
// load verts, tris, uinds and partitions
if (!loadPartitions(clipMap, bsp))
if (!LoadPartitions(clipMap, bsp))
return false;
loadBSPTree(clipMap, bsp);
LoadBSPTree(clipMap, bsp);
return true;
}
clipMap_t* ClipMapLinker::linkClipMap(const BSPData& bsp)
clipMap_t* ClipMapLinker::LinkClipMap(const BSPData& bsp)
{
clipMap_t* clipMap = m_memory.Alloc<clipMap_t>();
clipMap->name = m_memory.Dup(bsp.bspName.c_str());
@@ -622,17 +630,17 @@ namespace BSP
assert(mapEntsAsset != nullptr);
clipMap->mapEnts = mapEntsAsset->Asset();
loadBoxData(*clipMap);
LoadBoxData(*clipMap);
loadVisibility(*clipMap);
LoadVisibility(*clipMap);
loadRopesAndConstraints(*clipMap);
LoadRopesAndConstraints(*clipMap);
loadSubModelCollision(*clipMap, bsp);
LoadSubModelCollision(*clipMap, bsp);
loadDynEnts(*clipMap);
LoadDynEnts(*clipMap);
loadXModelCollision(*clipMap);
LoadXModelCollision(*clipMap);
// Clipmap materials define the properties of a material (bullet penetration, no collision, water, etc)
// Right now there is no way to define properties per material so only one material is used
@@ -648,7 +656,7 @@ namespace BSP
clipMap->triEdgeIsWalkable = new char[walkableEdgeSize];
memset(clipMap->triEdgeIsWalkable, 1, walkableEdgeSize * sizeof(char));
if (!loadWorldCollision(*clipMap, bsp))
if (!LoadWorldCollision(*clipMap, bsp))
return nullptr;
return clipMap;

View File

@@ -13,30 +13,30 @@ namespace BSP
public:
ClipMapLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] T6::clipMap_t* linkClipMap(const BSPData& bsp);
[[nodiscard]] T6::clipMap_t* LinkClipMap(const BSPData& bsp);
private:
void LoadBoxData(T6::clipMap_t& clipMap) const;
void LoadVisibility(T6::clipMap_t& clipMap) const;
void LoadDynEnts(T6::clipMap_t& clipMap) const;
void LoadRopesAndConstraints(T6::clipMap_t& clipMap) const;
void LoadSubModelCollision(T6::clipMap_t& clipMap, const BSPData& bsp) const;
void LoadXModelCollision(T6::clipMap_t& clipMap) const;
void AddAABBTreeFromLeaf(T6::clipMap_t& clipMap, const BSPTree& tree, size_t& outParentCount, size_t& outParentStartIndex);
int16_t LoadBSPNode(T6::clipMap_t& clipMap, const BSPTree& tree);
void LoadBSPTree(T6::clipMap_t& clipMap, const BSPData& bsp);
bool LoadPartitions(T6::clipMap_t& clipMap, const BSPData& bsp) const;
bool LoadWorldCollision(T6::clipMap_t& clipMap, const BSPData& bsp);
MemoryManager& m_memory;
ISearchPath& m_search_path;
AssetCreationContext& m_context;
void loadBoxData(T6::clipMap_t& clipMap) const;
void loadVisibility(T6::clipMap_t& clipMap) const;
void loadDynEnts(T6::clipMap_t& clipMap) const;
void loadRopesAndConstraints(T6::clipMap_t& clipMap) const;
void loadSubModelCollision(T6::clipMap_t& clipMap, const BSPData& bsp) const;
void loadXModelCollision(T6::clipMap_t& clipMap) const;
std::vector<T6::cplane_s> planeVec;
std::vector<T6::cNode_t> nodeVec;
std::vector<T6::cLeaf_s> leafVec;
std::vector<T6::CollisionAabbTree> AABBTreeVec;
size_t highestLeafObjectCount = 0;
void addAABBTreeFromLeaf(T6::clipMap_t& clipMap, const BSPTree& tree, size_t& out_parentCount, size_t& out_parentStartIndex);
int16_t loadBSPNode(T6::clipMap_t& clipMap, const BSPTree& tree);
void loadBSPTree(T6::clipMap_t& clipMap, const BSPData& bsp);
bool loadPartitions(T6::clipMap_t& clipMap, const BSPData& bsp) const;
bool loadWorldCollision(T6::clipMap_t& clipMap, const BSPData& bsp);
};
} // namespace BSP

View File

@@ -11,10 +11,11 @@ namespace BSP
{
}
ComWorld* ComWorldLinker::linkComWorld(const BSPData& bsp) const
ComWorld* ComWorldLinker::LinkComWorld(const BSPData& bsp) const
{
// all lights that aren't the sunlight or default light need their own GfxLightDef asset
ComWorld* comWorld = m_memory.Alloc<ComWorld>();
comWorld->name = m_memory.Dup(bsp.bspName.c_str());
comWorld->isInUse = 1;
comWorld->primaryLightCount = BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT;
@@ -25,6 +26,7 @@ namespace BSP
ComPrimaryLight* sunLight = &comWorld->primaryLights[1];
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;

View File

@@ -11,7 +11,8 @@ namespace BSP
{
public:
ComWorldLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] T6::ComWorld* linkComWorld(const BSPData& bsp) const;
[[nodiscard]] T6::ComWorld* LinkComWorld(const BSPData& bsp) const;
private:
MemoryManager& m_memory;

View File

@@ -11,7 +11,7 @@ namespace BSP
{
}
GameWorldMp* GameWorldMpLinker::linkGameWorldMp(const BSPData& bsp) const
GameWorldMp* GameWorldMpLinker::LinkGameWorldMp(const BSPData& bsp) const
{
GameWorldMp* gameWorldMp = m_memory.Alloc<GameWorldMp>();
@@ -24,7 +24,7 @@ namespace BSP
gameWorldMp->path.nodeTreeCount = 0;
// The game has 128 empty nodes allocated
const auto extraNodeCount = gameWorldMp->path.nodeCount + 128;
const auto extraNodeCount = gameWorldMp->path.nodeCount + 128u;
gameWorldMp->path.nodes = m_memory.Alloc<pathnode_t>(extraNodeCount);
gameWorldMp->path.basenodes = m_memory.Alloc<pathbasenode_t>(extraNodeCount);
gameWorldMp->path.pathVis = nullptr;

View File

@@ -11,7 +11,8 @@ namespace BSP
{
public:
GameWorldMpLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] T6::GameWorldMp* linkGameWorldMp(const BSPData& bsp) const;
[[nodiscard]] T6::GameWorldMp* LinkGameWorldMp(const BSPData& bsp) const;
private:
MemoryManager& m_memory;

View File

@@ -18,7 +18,7 @@ namespace BSP
{
}
void GfxWorldLinker::loadDrawData(const BSPData& bsp, GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadDrawData(const BSPData& bsp, GfxWorld& gfxWorld) const
{
size_t vertexCount = bsp.gfxWorld.vertices.size();
gfxWorld.draw.vertexCount = static_cast<unsigned int>(vertexCount);
@@ -56,9 +56,9 @@ namespace BSP
}
}
bool GfxWorldLinker::loadMapSurfaces(const BSPData& bsp, GfxWorld& gfxWorld) const
bool GfxWorldLinker::LoadMapSurfaces(const BSPData& bsp, GfxWorld& gfxWorld) const
{
loadDrawData(bsp, gfxWorld);
LoadDrawData(bsp, gfxWorld);
size_t surfaceCount = bsp.gfxWorld.surfaces.size();
gfxWorld.surfaceCount = static_cast<int>(surfaceCount);
@@ -75,13 +75,13 @@ namespace BSP
gfxSurface->flags = BSPEditableConstants::DEFAULT_SURFACE_FLAGS;
gfxSurface->tris.triCount = static_cast<uint16_t>(bspSurface.triCount);
gfxSurface->tris.baseIndex = bspSurface.indexOfFirstIndex;
gfxSurface->tris.baseIndex = static_cast<int>(bspSurface.indexOfFirstIndex);
gfxSurface->tris.vertexDataOffset0 = bspSurface.indexOfFirstVertex * sizeof(GfxPackedWorldVertex);
gfxSurface->tris.vertexDataOffset0 = static_cast<int>(bspSurface.indexOfFirstVertex * sizeof(GfxPackedWorldVertex));
gfxSurface->tris.vertexDataOffset1 = 0;
std::string surfMaterialName;
if (bspSurface.material.materialType == MATERIAL_TYPE_TEXTURE)
if (bspSurface.material.materialType == BSPMaterialType::MATERIAL_TYPE_TEXTURE)
surfMaterialName = bspSurface.material.materialName;
else // MATERIAL_TYPE_COLOUR || MATERIAL_TYPE_EMPTY
surfMaterialName = BSPLinkingConstants::COLOR_ONLY_IMAGE_NAME;
@@ -156,7 +156,7 @@ namespace BSP
return true;
}
void GfxWorldLinker::loadXModels(const BSPData& bsp, GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadXModels(const BSPData& bsp, GfxWorld& gfxWorld) const
{
/*
Models are unsupported right now
@@ -185,10 +185,10 @@ namespace BSP
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.origin = ConvertToBO2Coords(currModel->placement.origin);
currModel->placement.scale = inModel->scale;
BSPUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
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
@@ -200,9 +200,9 @@ namespace BSP
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;
currModel->flags = BSPEditableConstants::DEFAULT_SMODEL_FLAGS;
currModel->primaryLightIndex = BSPEditableConstants::DEFAULT_SMODEL_LIGHT;
currModel->reflectionProbeIndex = BSPEditableConstants::DEFAULT_SMODEL_REFLECTION_PROBE;
// unknown use / unused
currModel->smid = i;
@@ -231,7 +231,7 @@ namespace BSP
gfxWorld.dpvs.smodelDrawInsts = m_memory.Alloc<GfxStaticModelDrawInst>(modelCount);
// visdata is written to by the game
// all visdata is alligned by 128
// all visdata is aligned by 128
const auto alignedModelCount = utils::Align(modelCount, 128uz);
gfxWorld.dpvs.smodelVisDataCount = static_cast<unsigned int>(alignedModelCount);
gfxWorld.dpvs.smodelVisData[0] = m_memory.Alloc<char>(alignedModelCount);
@@ -251,7 +251,7 @@ namespace BSP
gfxWorld.dpvs.usageCount = 0;
}
void GfxWorldLinker::cleanGfxWorld(GfxWorld& gfxWorld) const
void GfxWorldLinker::CleanGfxWorld(GfxWorld& gfxWorld) const
{
// checksum is generated by the game
gfxWorld.checksum = 0;
@@ -337,7 +337,7 @@ namespace BSP
gfxWorld.sunLight = m_memory.Alloc<GfxLight>();
}
void GfxWorldLinker::loadGfxLights(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadGfxLights(GfxWorld& gfxWorld) const
{
// there must be 2 or more lights, first is the static light and second is the sun light
gfxWorld.primaryLightCount = BSPGameConstants::BSP_DEFAULT_LIGHT_COUNT;
@@ -366,7 +366,7 @@ namespace BSP
gfxWorld.primaryLightEntityShadowVis = nullptr;
}
void GfxWorldLinker::loadLightGrid(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadLightGrid(GfxWorld& gfxWorld) const
{
// there is almost no basis for the values in this code, they were chosen based on what looks correct when reverse engineering.
@@ -424,7 +424,7 @@ namespace BSP
gfxWorld.lightGrid.skyGridVolumes = nullptr;
}
void GfxWorldLinker::loadGfxCells(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadGfxCells(GfxWorld& gfxWorld) const
{
// Cells are basically data used to determine what can be seen and what cant be seen
// Right now custom maps have no optimisation so there is only 1 cell
@@ -488,7 +488,7 @@ namespace BSP
gfxWorld.dpvsPlanes.planes = nullptr;
}
void GfxWorldLinker::loadWorldBounds(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadWorldBounds(GfxWorld& gfxWorld) const
{
gfxWorld.mins.x = 0.0f;
gfxWorld.mins.y = 0.0f;
@@ -503,7 +503,7 @@ namespace BSP
}
}
void GfxWorldLinker::loadModels(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadModels(GfxWorld& gfxWorld) const
{
// Models (Submodels in the clipmap code) are used for the world and map ent collision (triggers, bomb zones, etc)
// Right now there is only one submodel, the world sub model
@@ -540,7 +540,7 @@ namespace BSP
//}
}
void GfxWorldLinker::loadSunData(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadSunData(GfxWorld& gfxWorld) const
{
// default values taken from mp_dig
gfxWorld.sunParse.fogTransitionTime = 0.001f;
@@ -586,7 +586,7 @@ namespace BSP
gfxWorld.sunParse.initWorldFog->sunFogYaw = 254.0f;
}
bool GfxWorldLinker::loadReflectionProbeData(GfxWorld& gfxWorld) const
bool GfxWorldLinker::LoadReflectionProbeData(GfxWorld& gfxWorld) const
{
gfxWorld.draw.reflectionProbeCount = 1;
@@ -616,7 +616,7 @@ namespace BSP
std::string probeImageName = "reflection_probe0";
auto probeImageAsset = m_context.LoadDependency<AssetImage>(probeImageName);
if (probeImageAsset == nullptr)
if (!probeImageAsset)
{
con::error("ERROR! unable to find reflection probe image {}!", probeImageName);
return false;
@@ -626,7 +626,7 @@ namespace BSP
return true;
}
bool GfxWorldLinker::loadLightmapData(GfxWorld& gfxWorld) const
bool GfxWorldLinker::LoadLightmapData(GfxWorld& gfxWorld) const
{
gfxWorld.draw.lightmapCount = 1;
@@ -635,7 +635,7 @@ namespace BSP
std::string secondaryTexture = "lightmap0_secondary";
auto secondaryTextureAsset = m_context.LoadDependency<AssetImage>(secondaryTexture);
if (secondaryTextureAsset == nullptr)
if (!secondaryTextureAsset)
{
con::error("ERROR! unable to find lightmap image {}!", secondaryTexture);
return false;
@@ -647,7 +647,7 @@ namespace BSP
return true;
}
void GfxWorldLinker::loadSkyBox(const BSPData& projInfo, GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadSkyBox(const BSPData& projInfo, GfxWorld& gfxWorld) const
{
const auto skyBoxName = std::format("skybox_{}", projInfo.name);
gfxWorld.skyBoxModel = m_memory.Dup(skyBoxName.c_str());
@@ -664,9 +664,9 @@ namespace BSP
gfxWorld.skyDynIntensity.factor1 = 1.0f;
}
void GfxWorldLinker::loadDynEntData(GfxWorld& gfxWorld) const
void GfxWorldLinker::LoadDynEntData(GfxWorld& gfxWorld) const
{
int dynEntCount = 0;
unsigned dynEntCount = 0u;
gfxWorld.dpvsDyn.dynEntClientCount[0] = dynEntCount + 256; // the game allocs 256 empty dynents, as they may be used ingame
gfxWorld.dpvsDyn.dynEntClientCount[1] = 0;
@@ -676,11 +676,11 @@ namespace BSP
gfxWorld.dpvsDyn.dynEntClientWordCount[1] = 0;
gfxWorld.dpvsDyn.usageCount = 0;
const auto dynEntCellBitsSize = gfxWorld.dpvsDyn.dynEntClientWordCount[0] * gfxWorld.dpvsPlanes.cellCount;
const auto dynEntCellBitsSize = gfxWorld.dpvsDyn.dynEntClientWordCount[0] * static_cast<unsigned>(gfxWorld.dpvsPlanes.cellCount);
gfxWorld.dpvsDyn.dynEntCellBits[0] = m_memory.Alloc<unsigned int>(dynEntCellBitsSize);
gfxWorld.dpvsDyn.dynEntCellBits[1] = nullptr;
const auto dynEntVisData0Size = gfxWorld.dpvsDyn.dynEntClientWordCount[0] * 32;
const auto dynEntVisData0Size = gfxWorld.dpvsDyn.dynEntClientWordCount[0] * 32u;
gfxWorld.dpvsDyn.dynEntVisData[0][0] = m_memory.Alloc<char>(dynEntVisData0Size);
gfxWorld.dpvsDyn.dynEntVisData[0][1] = m_memory.Alloc<char>(dynEntVisData0Size);
gfxWorld.dpvsDyn.dynEntVisData[0][2] = m_memory.Alloc<char>(dynEntVisData0Size);
@@ -688,7 +688,7 @@ namespace BSP
gfxWorld.dpvsDyn.dynEntVisData[1][1] = nullptr;
gfxWorld.dpvsDyn.dynEntVisData[1][2] = nullptr;
const auto dynEntShadowVisCount = gfxWorld.dpvsDyn.dynEntClientCount[0] * (gfxWorld.primaryLightCount - gfxWorld.sunPrimaryLightIndex - 1);
const auto dynEntShadowVisCount = gfxWorld.dpvsDyn.dynEntClientCount[0] * (gfxWorld.primaryLightCount - gfxWorld.sunPrimaryLightIndex - 1u);
gfxWorld.primaryLightDynEntShadowVis[0] = m_memory.Alloc<unsigned int>(dynEntShadowVisCount);
gfxWorld.primaryLightDynEntShadowVis[1] = nullptr;
@@ -696,7 +696,7 @@ namespace BSP
gfxWorld.sceneDynBrush = nullptr;
}
bool GfxWorldLinker::loadOutdoors(GfxWorld& gfxWorld) const
bool GfxWorldLinker::LoadOutdoors(GfxWorld& gfxWorld) const
{
const auto xRecip = 1.0f / (gfxWorld.maxs.x - gfxWorld.mins.x);
const auto xScale = -(xRecip * gfxWorld.mins.x);
@@ -717,9 +717,8 @@ namespace BSP
gfxWorld.outdoorLookupMatrix[3].z = zScale;
gfxWorld.outdoorLookupMatrix[3].w = 1.0f;
const std::string outdoorImageName = std::string("$outdoor");
auto outdoorImageAsset = m_context.LoadDependency<AssetImage>(outdoorImageName);
if (outdoorImageAsset == nullptr)
const auto outdoorImageAsset = m_context.LoadDependency<AssetImage>("$outdoor");
if (!outdoorImageAsset)
{
con::error("ERROR! unable to find outdoor image $outdoor!");
return false;
@@ -729,7 +728,7 @@ namespace BSP
return true;
}
GfxWorld* GfxWorldLinker::linkGfxWorld(const BSPData& bsp) const
GfxWorld* GfxWorldLinker::LinkGfxWorld(const BSPData& bsp) const
{
GfxWorld* gfxWorld = m_memory.Alloc<GfxWorld>();
gfxWorld->baseName = m_memory.Dup(bsp.name.c_str());
@@ -739,39 +738,39 @@ namespace BSP
gfxWorld->lightingFlags = 0;
gfxWorld->lightingQuality = 4096;
cleanGfxWorld(*gfxWorld);
CleanGfxWorld(*gfxWorld);
if (!loadMapSurfaces(bsp, *gfxWorld))
if (!LoadMapSurfaces(bsp, *gfxWorld))
return nullptr;
loadXModels(bsp, *gfxWorld);
LoadXModels(bsp, *gfxWorld);
if (!loadLightmapData(*gfxWorld))
if (!LoadLightmapData(*gfxWorld))
return nullptr;
loadSkyBox(bsp, *gfxWorld);
LoadSkyBox(bsp, *gfxWorld);
if (!loadReflectionProbeData(*gfxWorld))
if (!LoadReflectionProbeData(*gfxWorld))
return nullptr;
// world bounds are based on loaded surface mins/maxs
loadWorldBounds(*gfxWorld);
LoadWorldBounds(*gfxWorld);
if (!loadOutdoors(*gfxWorld))
if (!LoadOutdoors(*gfxWorld))
return nullptr;
// gfx cells depend on surface/smodel count
loadGfxCells(*gfxWorld);
LoadGfxCells(*gfxWorld);
loadLightGrid(*gfxWorld);
LoadLightGrid(*gfxWorld);
loadGfxLights(*gfxWorld);
LoadGfxLights(*gfxWorld);
loadModels(*gfxWorld);
LoadModels(*gfxWorld);
loadSunData(*gfxWorld);
LoadSunData(*gfxWorld);
loadDynEntData(*gfxWorld);
LoadDynEntData(*gfxWorld);
return gfxWorld;
}

View File

@@ -11,27 +11,28 @@ namespace BSP
{
public:
GfxWorldLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] T6::GfxWorld* linkGfxWorld(const BSPData& bsp) const;
[[nodiscard]] T6::GfxWorld* LinkGfxWorld(const BSPData& bsp) const;
private:
void LoadDrawData(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
bool LoadMapSurfaces(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
void LoadXModels(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
void CleanGfxWorld(T6::GfxWorld& gfxWorld) const;
void LoadGfxLights(T6::GfxWorld& gfxWorld) const;
void LoadLightGrid(T6::GfxWorld& gfxWorld) const;
void LoadGfxCells(T6::GfxWorld& gfxWorld) const;
void LoadModels(T6::GfxWorld& gfxWorld) const;
bool LoadReflectionProbeData(T6::GfxWorld& gfxWorld) const;
bool LoadLightmapData(T6::GfxWorld& gfxWorld) const;
void LoadSkyBox(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
void LoadDynEntData(T6::GfxWorld& gfxWorld) const;
bool LoadOutdoors(T6::GfxWorld& gfxWorld) const;
void LoadSunData(T6::GfxWorld& gfxWorld) const;
void LoadWorldBounds(T6::GfxWorld& gfxWorld) const;
MemoryManager& m_memory;
ISearchPath& m_search_path;
AssetCreationContext& m_context;
void loadDrawData(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
bool loadMapSurfaces(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
void loadXModels(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
void cleanGfxWorld(T6::GfxWorld& gfxWorld) const;
void loadGfxLights(T6::GfxWorld& gfxWorld) const;
void loadLightGrid(T6::GfxWorld& gfxWorld) const;
void loadGfxCells(T6::GfxWorld& gfxWorld) const;
void loadModels(T6::GfxWorld& gfxWorld) const;
bool loadReflectionProbeData(T6::GfxWorld& gfxWorld) const;
bool loadLightmapData(T6::GfxWorld& gfxWorld) const;
void loadSkyBox(const BSPData& projInfo, T6::GfxWorld& gfxWorld) const;
void loadDynEntData(T6::GfxWorld& gfxWorld) const;
bool loadOutdoors(T6::GfxWorld& gfxWorld) const;
void loadSunData(T6::GfxWorld& gfxWorld) const;
void loadWorldBounds(T6::GfxWorld& gfxWorld) const;
};
} // namespace BSP

View File

@@ -74,13 +74,12 @@ namespace BSP
{
}
MapEnts* MapEntsLinker::linkMapEnts(const BSPData& bsp) const
MapEnts* MapEntsLinker::LinkMapEnts(const BSPData& bsp) const
{
try
{
json entJs;
std::string entityFileName = "entities.json";
std::string entityFilePath = GetFileNameForBSPAsset(entityFileName);
std::string entityFilePath = GetFileNameForBSPAsset("entities.json");
const auto entFile = m_search_path.Open(entityFilePath);
if (!entFile.IsOpen())
{
@@ -108,9 +107,9 @@ namespace BSP
{
spawnJs = json::parse(*spawnFile.m_stream);
}
size_t defenderNameCount = std::extent<decltype(BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES)>::value;
size_t attackerNameCount = std::extent<decltype(BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES)>::value;
size_t ffaNameCount = std::extent<decltype(BSPGameConstants::FFA_SPAWN_POINT_NAMES)>::value;
size_t defenderNameCount = std::extent_v<decltype(BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES)>;
size_t attackerNameCount = std::extent_v<decltype(BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES)>;
size_t ffaNameCount = std::extent_v<decltype(BSPGameConstants::FFA_SPAWN_POINT_NAMES)>;
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);

View File

@@ -11,7 +11,8 @@ namespace BSP
{
public:
MapEntsLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] T6::MapEnts* linkMapEnts(const BSPData& bsp) const;
[[nodiscard]] T6::MapEnts* LinkMapEnts(const BSPData& bsp) const;
private:
MemoryManager& m_memory;

View File

@@ -9,7 +9,7 @@ namespace BSP
{
}
T6::SkinnedVertsDef* SkinnedVertsLinker::linkSkinnedVerts(const BSPData& bsp) const
T6::SkinnedVertsDef* SkinnedVertsLinker::LinkSkinnedVerts(const BSPData& bsp) const
{
// Pretty sure maxSkinnedVerts relates to the max amount of xmodel skinned verts a map will have
// But setting it to the world vertex count seems to work

View File

@@ -11,7 +11,8 @@ namespace BSP
{
public:
SkinnedVertsLinker(MemoryManager& memory, ISearchPath& searchPath, AssetCreationContext& context);
[[nodiscard]] T6::SkinnedVertsDef* linkSkinnedVerts(const BSPData& bsp) const;
[[nodiscard]] T6::SkinnedVertsDef* LinkSkinnedVerts(const BSPData& bsp) const;
private:
MemoryManager& m_memory;

View File

@@ -32,12 +32,12 @@ namespace
bool FinalizeZone(AssetCreationContext& context) override
{
const std::unique_ptr<BSPData> bsp = BSP::createBSPData(m_zone.m_name, m_search_path);
if (bsp == nullptr)
const auto bsp = CreateBSPData(m_zone.m_name, m_search_path);
if (!bsp)
return false;
BSPLinker linker(m_memory, m_search_path, context);
const auto result = linker.linkBSP(*bsp);
const auto result = linker.LinkBSP(*bsp);
if (!result)
con::error("BSP link has failed.");