2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-11-23 05:12:05 +00:00
- Updated names to allign with the BSP naming structure
- Updated constants file and assoicated uses
This commit is contained in:
LJW-Dev
2025-10-21 18:54:26 +08:00
parent 7d09877d02
commit b4073d74d9
10 changed files with 411 additions and 369 deletions

View File

@@ -3908,6 +3908,17 @@ namespace T6
int baseIndex; int baseIndex;
}; };
enum GfxSurfaceFlags
{
GFX_SURFACE_CASTS_SUN_SHADOW = 0x1,
GFX_SURFACE_HAS_PRIMARY_LIGHT_CONFLICT = 0x2,
GFX_SURFACE_IS_SKY = 0x4,
GFX_SURFACE_NO_DRAW = 0x8,
GFX_SURFACE_CASTS_SHADOW = 0x10,
GFX_SURFACE_QUANTIZED = 0x20,
GFX_SURFACE_NO_COLOR = 0x40
};
struct type_align32(16) GfxSurface struct type_align32(16) GfxSurface
{ {
srfTriangles_t tris; srfTriangles_t tris;
@@ -3940,6 +3951,12 @@ namespace T6
uint16_t numLmapVertexColors; uint16_t numLmapVertexColors;
}; };
enum StaticModelFlag
{
STATIC_MODEL_FLAG_NO_SHADOW = 0x1,
STATIC_MODEL_FLAG_LIGHTMAP_VC = 0x2,
};
struct GfxStaticModelDrawInst struct GfxStaticModelDrawInst
{ {
float cullDist; float cullDist;

View File

@@ -1,7 +1,7 @@
#include "BinarySpacePartitionTree.h" #include "BSPCalculation.h"
Object::Object(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex) BSPObject::BSPObject(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex)
{ {
min.x = xMin; min.x = xMin;
min.y = yMin; min.y = yMin;
@@ -12,12 +12,12 @@ Object::Object(float xMin, float yMin, float zMin, float xMax, float yMax, float
partitionIndex = objPartitionIndex; partitionIndex = objPartitionIndex;
} }
void BSPLeaf::addObject(std::shared_ptr<Object> object) void BSPLeaf::addObject(std::shared_ptr<BSPObject> object)
{ {
objectList.emplace_back(std::move(object)); objectList.emplace_back(std::move(object));
} }
Object* BSPLeaf::getObject(int index) BSPObject* BSPLeaf::getObject(int index)
{ {
return objectList.at(index).get(); return objectList.at(index).get();
} }
@@ -35,7 +35,7 @@ BSPNode::BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> ba
distance = nodeDistance; distance = nodeDistance;
} }
PlaneSide BSPNode::objectIsInfront(Object* object) PlaneSide BSPNode::objectIsInfront(BSPObject* object)
{ {
float minCoord, maxCoord; float minCoord, maxCoord;
@@ -121,7 +121,7 @@ void BSPTree::splitTree()
} }
} }
void BSPTree::addObjectToTree(std::shared_ptr<Object> object) void BSPTree::addObjectToTree(std::shared_ptr<BSPObject> object)
{ {
if (isLeaf) if (isLeaf)
{ {

View File

@@ -22,24 +22,24 @@ enum PlaneSide
SIDE_INTERSECTS SIDE_INTERSECTS
}; };
class Object class BSPObject
{ {
public: public:
vec3_t min; vec3_t min;
vec3_t max; vec3_t max;
int partitionIndex; // index of the partition the object is contained in int partitionIndex; // index of the partition the object is contained in
Object(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex); BSPObject(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int objPartitionIndex);
}; };
class BSPLeaf class BSPLeaf
{ {
public: public:
std::vector<std::shared_ptr<Object>> objectList; std::vector<std::shared_ptr<BSPObject>> objectList;
void addObject(std::shared_ptr<Object> object); void addObject(std::shared_ptr<BSPObject> object);
Object* getObject(int index); BSPObject* getObject(int index);
int getObjectCount(); int getObjectCount();
}; };
@@ -55,7 +55,7 @@ public:
float distance; // distance from the origin (0, 0, 0) to the plane 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); BSPNode(std::unique_ptr<BSPTree> frontTree, std::unique_ptr<BSPTree> backTree, PlaneAxis nodeAxis, float nodeDistance);
PlaneSide objectIsInfront(Object* object); PlaneSide objectIsInfront(BSPObject* object);
}; };
class BSPTree class BSPTree
@@ -71,5 +71,5 @@ public:
BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel); BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel);
void splitTree(); void splitTree();
void addObjectToTree(std::shared_ptr<Object> object); void addObjectToTree(std::shared_ptr<BSPObject> object);
}; };

View File

@@ -0,0 +1,127 @@
#pragma once
// BSPGameConstants:
// These values are hardcoded ingame and will break the map if they are changed
namespace BSPGameConstants
{
constexpr int MAX_COLLISION_VERTS = UINT16_MAX;
constexpr int STATIC_LIGHT_INDEX = 0;
constexpr int SUN_LIGHT_INDEX = 1;
inline const char* DEFENDER_SPAWN_POINT_NAMES[] = {
"mp_ctf_spawn_allies",
"mp_ctf_spawn_allies_start",
"mp_sd_spawn_defender",
"mp_dom_spawn_allies_start",
"mp_dem_spawn_defender_start",
"mp_dem_spawn_defenderOT_start",
"mp_dem_spawn_defender",
"mp_tdm_spawn_allies_start",
"mp_tdm_spawn_team1_start",
"mp_tdm_spawn_team2_start",
"mp_tdm_spawn_team3_start"
};
inline const char* ATTACKER_SPAWN_POINT_NAMES[] = {
"mp_ctf_spawn_axis",
"mp_ctf_spawn_axis_start",
"mp_sd_spawn_attacker",
"mp_dom_spawn_axis_start",
"mp_dem_spawn_attacker_start",
"mp_dem_spawn_attackerOT_start",
"mp_dem_spawn_defender",
"mp_tdm_spawn_axis_start",
"mp_tdm_spawn_team4_start",
"mp_tdm_spawn_team5_start",
"mp_tdm_spawn_team6_start"
};
inline const char* FFA_SPAWN_POINT_NAMES[] = {
"mp_tdm_spawn",
"mp_dm_spawn",
"mp_dom_spawn"
};
}
// BSPLinkingConstants:
// These values are BSP linking constants that are required for the link to be successful
namespace BSPLinkingConstants
{
constexpr const char* MISSING_IMAGE_NAME = "missing_image";
constexpr const char* COLOR_ONLY_IMAGE_NAME = "color_only_image";
constexpr const char* DEFAULT_SPAWN_POINT_STRING = R"({
"attackers": [
{
"origin": "0 0 0",
"angles": "0 0 0"
}
],
"defenders": [
{
"origin": "0 0 0",
"angles": "0 0 0"
}
],
"FFA": [
{
"origin": "0 0 0",
"angles": "0 0 0"
}
]
})";
constexpr const char* DEFAULT_MAP_ENTS_STRING = R"({
"entities": [
{
"classname": "worldspawn"
},
{
"angles": "0 0 0",
"classname": "info_player_start",
"origin": "0 0 0"
},
{
"angles": "0 0 0",
"classname": "mp_global_intermission",
"origin": "0 0 0"
}
]
})";
}
// BSPEditableConstants:
// These values are BSP constants that can be edited and won't break the linker/game if changed
namespace BSPEditableConstants
{
// Default xmodel values
// Unused as there is no support for xmodels right now
constexpr float DEFAULT_SMODEL_CULL_DIST = 10000.0f;
constexpr int DEFAULT_SMODEL_FLAGS = STATIC_MODEL_FLAG_NO_SHADOW;
constexpr int DEFAULT_SMODEL_LIGHT = 1;
constexpr int DEFAULT_SMODEL_REFLECTION_PROBE = 0;
// Default surface values
constexpr int DEFAULT_SURFACE_LIGHT = BSPGameConstants::SUN_LIGHT_INDEX;
constexpr int DEFAULT_SURFACE_LIGHTMAP = 0;
constexpr int DEFAULT_SURFACE_REFLECTION_PROBE = 0;
constexpr int DEFAULT_SURFACE_FLAGS = (GFX_SURFACE_CASTS_SUN_SHADOW | GFX_SURFACE_CASTS_SHADOW);
// material flags determine the features of a surface
// unsure which flag type changes what right now
// -1 results in: no running, water splashes all the time, low friction, slanted angles make you slide very fast
// 1 results in: normal surface features, grenades work, seems normal
constexpr int MATERIAL_SURFACE_FLAGS = 1;
constexpr int MATERIAL_CONTENT_FLAGS = 1;
// terrain/world flags: does not change the type of terrain or what features they have
// from testing, as long at it isn't 0 things will work correctly
constexpr int LEAF_TERRAIN_CONTENTS = 1;
constexpr int WORLD_TERRAIN_CONTENTS = 1;
// 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;
};

View File

@@ -44,7 +44,6 @@ bool addFBXMeshToWorld(ufbx_node* node,
if (mesh->vertex_tangent.exists == false) if (mesh->vertex_tangent.exists == false)
hasTangentSpace = false; hasTangentSpace = false;
// Fix the target_unit_meters opt not working // Fix the target_unit_meters opt not working
// UFBX stores the transform data in units that are 100x larger than what blender uses, so this converts them back // UFBX stores the transform data in units that are 100x larger than what blender uses, so this converts them back
ufbx_transform origTransform = node->local_transform; ufbx_transform origTransform = node->local_transform;

View File

@@ -0,0 +1,161 @@
#pragma once
#include <cmath>
#include <format>
#include "BSPUtil.h"
// BO2 uses a different coordinate system, so this converts it back from OpenGLs default
vec3_t BSPUtil::convertToBO2Coords(vec3_t OGL_coordinate)
{
vec3_t result;
result.x = OGL_coordinate.x;
result.y = -OGL_coordinate.z;
result.z = OGL_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 result;
result.x = bo2_coordinate.x;
result.y = bo2_coordinate.z;
result.z = -bo2_coordinate.y;
return result;
}
void BSPUtil::calcNewBounds(vec3_t* newmins, vec3_t* newmaxs, vec3_t* currmins, vec3_t* currmaxs)
{
if (currmins->x > newmins->x)
currmins->x = newmins->x;
if (newmaxs->x > currmaxs->x)
currmaxs->x = newmaxs->x;
if (currmins->y > newmins->y)
currmins->y = newmins->y;
if (newmaxs->y > currmaxs->y)
currmaxs->y = newmaxs->y;
if (currmins->z > newmins->z)
currmins->z = newmins->z;
if (newmaxs->z > currmaxs->z)
currmaxs->z = newmaxs->z;
}
void BSPUtil::calcNewBoundsWithPoint(vec3_t* point, vec3_t* currmins, vec3_t* currmaxs)
{
if (currmins->x > point->x)
currmins->x = point->x;
if (point->x > currmaxs->x)
currmaxs->x = point->x;
if (currmins->y > point->y)
currmins->y = point->y;
if (point->y > currmaxs->y)
currmaxs->y = point->y;
if (currmins->z > point->z)
currmins->z = point->z;
if (point->z > currmaxs->z)
currmaxs->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;
}
int BSPUtil::allignBy128(int size)
{
return ((size + 127) & 0xFFFFFF80);
}
float BSPUtil::distBetweenPoints(vec3_t p1, vec3_t p2)
{
float x = p2.x - p1.x;
float y = p2.y - p1.y;
float z = p2.z - p1.z;
return sqrtf((x * x) + (y * y) + (z * z));
}
// angles are in euler degrees
void BSPUtil::convertAnglesToAxis(vec3_t* angles, vec3_t* axis)
{
float xRadians = angles->x * 0.017453292f; // M_PI / 180.0f
float yRadians = angles->y * 0.017453292f; // M_PI / 180.0f
float zRadians = angles->z * 0.017453292f; // M_PI / 180.0f
float cosX = cos(xRadians);
float sinX = sin(xRadians);
float cosY = cos(yRadians);
float sinY = sin(yRadians);
float cosZ = cos(zRadians);
float sinZ = sin(zRadians);
axis[0].x = cosX * cosY;
axis[0].y = cosX * sinY;
axis[0].z = -sinX;
axis[1].x = (sinZ * sinX * cosY) - (cosZ * sinY);
axis[1].y = (sinZ * sinX * sinY) + (cosZ * cosY);
axis[1].z = sinZ * cosX;
axis[2].x = (cosZ * sinX * cosY) + (sinZ * sinY);
axis[2].y = (cosZ * sinX * sinY) - (sinZ * cosY);
axis[2].z = cosZ * cosX;
}
void BSPUtil::matrixTranspose3x3(const vec3_t* in, vec3_t* out)
{
out[0].x = in[0].x;
out[0].y = in[1].x;
out[0].z = in[2].x;
out[1].x = in[0].y;
out[1].y = in[1].y;
out[1].z = in[2].y;
out[2].x = in[0].z;
out[2].y = in[1].z;
out[2].z = in[2].z;
}
vec3_t BSPUtil::convertStringToVec3(std::string str)
{
std::string v1Str = str;
int nextValIndex = 0;
while (v1Str[nextValIndex] != ' ')
nextValIndex++;
nextValIndex++; // skip past space
std::string v2Str = &v1Str[nextValIndex];
nextValIndex = 0;
while (v2Str[nextValIndex] != ' ')
nextValIndex++;
nextValIndex++; // skip past space
std::string v3Str = &v2Str[nextValIndex];
vec3_t result;
result.x = static_cast<float>(atof(v1Str.c_str()));
result.y = static_cast<float>(atof(v2Str.c_str()));
result.z = static_cast<float>(atof(v3Str.c_str()));
return result;
}
std::string BSPUtil::convertVec3ToString(vec3_t vec)
{
std::string result = std::format("{} {} {}", vec.x, vec.y, vec.z);
return result;
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <string>
#include "Game/T6/T6.h"
using namespace T6;
class BSPUtil
{
public:
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 vec3_t calcMiddleOfBounds(vec3_t* mins, vec3_t* maxs);
static int allignBy128(int size);
static float distBetweenPoints(vec3_t p1, vec3_t p2);
static void convertAnglesToAxis(vec3_t* angles, vec3_t* axis);
static void matrixTranspose3x3(const vec3_t* in, vec3_t* out);
static vec3_t convertStringToVec3(std::string str);
static std::string convertVec3ToString(vec3_t vec);
};

View File

@@ -1,123 +0,0 @@
#pragma once
#include <string>
// do not change any values in this header file
#define DYN_ENT_COUNT 0
std::string missingImageName = "missing_image";
std::string colorOnlyImageName = "color_only_image";
#define MAX_COL_VERTS (UINT16_MAX - 1) // max amount of collision verts a map can have
#define DEFAULT_LIGHT_INDEX 0
#define SUN_LIGHT_INDEX 1
enum SMODEL_FLAGS
{
SMODEL_FLAG_NO_SHADOW = 1,
SMODEL_FLAG_IS_LIT = 2
};
enum GFX_SURFACE_FLAGS
{
GFX_SURFACE_CASTS_SUN_SHADOW = 0x1,
GFX_SURFACE_HAS_PRIMARY_LIGHT_CONFLICT = 0x2,
GFX_SURFACE_IS_SKY = 0x4,
GFX_SURFACE_NO_DRAW = 0x8,
GFX_SURFACE_CASTS_SHADOW = 0x10,
GFX_SURFACE_QUANTIZED = 0x20,
GFX_SURFACE_NO_COLOR = 0x40
};
#define DEFAULT_SMODEL_CULL_DIST 10000.0f
#define DEFAULT_SMODEL_FLAGS SMODEL_FLAG_NO_SHADOW
#define DEFAULT_SMODEL_LIGHT 1
#define DEFAULT_SMODEL_REFLECTION_PROBE 0
#define DEFAULT_SURFACE_LIGHT SUN_LIGHT_INDEX
#define DEFAULT_SURFACE_LIGHTMAP 0
#define DEFAULT_SURFACE_REFLECTION_PROBE 0
#define DEFAULT_SURFACE_FLAGS (GFX_SURFACE_CASTS_SUN_SHADOW | GFX_SURFACE_CASTS_SHADOW)
const std::vector<std::string> spawnpointDefenderTypeArray = {
"mp_ctf_spawn_allies",
"mp_ctf_spawn_allies_start",
"mp_sd_spawn_defender",
"mp_dom_spawn_allies_start",
"mp_dem_spawn_defender_start",
"mp_dem_spawn_defenderOT_start",
"mp_dem_spawn_defender",
"mp_tdm_spawn_allies_start",
"mp_tdm_spawn_team1_start",
"mp_tdm_spawn_team2_start",
"mp_tdm_spawn_team3_start"
};
const std::vector<std::string> spawnpointAttackerTypeArray = {
"mp_ctf_spawn_axis",
"mp_ctf_spawn_axis_start",
"mp_sd_spawn_attacker",
"mp_dom_spawn_axis_start",
"mp_dem_spawn_attacker_start",
"mp_dem_spawn_attackerOT_start",
"mp_dem_spawn_defender",
"mp_tdm_spawn_axis_start",
"mp_tdm_spawn_team4_start",
"mp_tdm_spawn_team5_start",
"mp_tdm_spawn_team6_start"
};
const std::vector<std::string> spawnpointFFATypeArray = {
"mp_tdm_spawn",
"mp_dm_spawn",
"mp_dom_spawn"
};
const std::vector<std::string> spawnpointObjectiveTypeArray = {
"mp_dom_spawn_flag_c",
"mp_dom_spawn_flag_a"
};
const std::string defaultSpawnpointString = "{"
"\"attackers\": ["
" {"
" \"origin\": \"0 0 0\","
" \"angles\": \"0 0 0\""
" }"
"],"
"\"defenders\": ["
" {"
" \"origin\": \"0 0 0\","
" \"angles\": \"0 0 0\""
" }"
"],"
"\"FFA\": ["
" {"
" \"origin\": \"0 0 0\","
" \"angles\": \"0 0 0\""
" }"
"]"
"}";
const std::string defaultMapEntsString = "{"
"\"entities\": ["
"{"
"\"classname\": \"worldspawn\""
"},"
"{"
"\"angles\": \"0 0 0\","
"\"classname\": \"info_player_start\","
"\"origin\": \"0 0 0\""
"},"
"{"
"\"angles\": \"0 0 0\","
"\"classname\": \"mp_global_intermission\","
"\"origin\": \"0 0 0\""
"}"
"]"
"}";

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include "BinarySpacePartitionTree.h" #include "BSPCalculation.h"
#include "CustomMapConsts.h" #include "BSPConstants.h"
#include "CustomMapOptions.h" #include "BSPUtil.h"
#include "Util.h"
#include "Game/T6/Material/JsonMaterialLoaderT6.h" #include "Game/T6/Material/JsonMaterialLoaderT6.h"
#include "Utils/Pack.h" #include "Utils/Pack.h"
@@ -84,17 +83,17 @@ private:
CustomMapVertex* WorldVertex = &projInfo->gfxWorld.vertices[i]; CustomMapVertex* WorldVertex = &projInfo->gfxWorld.vertices[i];
GfxPackedWorldVertex* GfxVertex = &vertexBuffer[i]; GfxPackedWorldVertex* GfxVertex = &vertexBuffer[i];
GfxVertex->xyz = CMUtil::convertToBO2Coords(WorldVertex->pos); GfxVertex->xyz = BSPUtil::convertToBO2Coords(WorldVertex->pos);
//GfxVertex->xyz = WorldVertex->pos; //GfxVertex->xyz = WorldVertex->pos;
GfxVertex->color.packed = pack32::Vec4PackGfxColor(WorldVertex->color.v); GfxVertex->color.packed = pack32::Vec4PackGfxColor(WorldVertex->color.v);
GfxVertex->texCoord.packed = pack32::Vec2PackTexCoordsUV(WorldVertex->texCoord.v); GfxVertex->texCoord.packed = pack32::Vec2PackTexCoordsUV(WorldVertex->texCoord.v);
GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->normal).v); GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(BSPUtil::convertToBO2Coords(WorldVertex->normal).v);
//GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->normal.v); //GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->normal.v);
GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->tangent).v); GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(BSPUtil::convertToBO2Coords(WorldVertex->tangent).v);
//GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->tangent.v); //GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(WorldVertex->tangent.v);
// unknown use variables // unknown use variables
@@ -180,10 +179,10 @@ private:
auto currSurface = &gfxWorld->dpvs.surfaces[i]; auto currSurface = &gfxWorld->dpvs.surfaces[i];
auto objSurface = &projInfo->gfxWorld.surfaces[i]; auto objSurface = &projInfo->gfxWorld.surfaces[i];
currSurface->primaryLightIndex = DEFAULT_SURFACE_LIGHT; currSurface->primaryLightIndex = BSPEditableConstants::DEFAULT_SURFACE_LIGHT;
currSurface->lightmapIndex = DEFAULT_SURFACE_LIGHTMAP; currSurface->lightmapIndex = BSPEditableConstants::DEFAULT_SURFACE_LIGHTMAP;
currSurface->reflectionProbeIndex = DEFAULT_SURFACE_REFLECTION_PROBE; currSurface->reflectionProbeIndex = BSPEditableConstants::DEFAULT_SURFACE_REFLECTION_PROBE;
currSurface->flags = DEFAULT_SURFACE_FLAGS; currSurface->flags = BSPEditableConstants::DEFAULT_SURFACE_FLAGS;
currSurface->tris.triCount = objSurface->triCount; currSurface->tris.triCount = objSurface->triCount;
currSurface->tris.baseIndex = objSurface->indexOfFirstIndex; currSurface->tris.baseIndex = objSurface->indexOfFirstIndex;
@@ -200,7 +199,7 @@ private:
case MATERIAL_TYPE_COLOUR: case MATERIAL_TYPE_COLOUR:
case MATERIAL_TYPE_EMPTY: case MATERIAL_TYPE_EMPTY:
surfMaterialName = colorOnlyImageName; surfMaterialName = BSPLinkingConstants::COLOR_ONLY_IMAGE_NAME;
break; break;
default: default:
@@ -209,6 +208,7 @@ private:
Material* surfMaterial = loadImageIntoMaterial(surfMaterialName); Material* surfMaterial = loadImageIntoMaterial(surfMaterialName);
if (surfMaterial == NULL) if (surfMaterial == NULL)
{ {
std::string missingImageName = std::string(BSPLinkingConstants::MISSING_IMAGE_NAME);
surfMaterial = loadImageIntoMaterial(missingImageName); surfMaterial = loadImageIntoMaterial(missingImageName);
if (surfMaterial == NULL) if (surfMaterial == NULL)
{ {
@@ -229,7 +229,7 @@ private:
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];
CMUtil::calcNewBoundsWithPoint(&firstVert[vertIndex].xyz, &currSurface->bounds[0], &currSurface->bounds[1]); BSPUtil::calcNewBoundsWithPoint(&firstVert[vertIndex].xyz, &currSurface->bounds[0], &currSurface->bounds[1]);
} }
// unused values // unused values
@@ -255,7 +255,7 @@ private:
memset(gfxWorld->dpvs.surfaceMaterials, 0, sizeof(GfxDrawSurf_align4) * surfaceCount); memset(gfxWorld->dpvs.surfaceMaterials, 0, sizeof(GfxDrawSurf_align4) * surfaceCount);
// all visdata is alligned by 128 // all visdata is alligned by 128
gfxWorld->dpvs.surfaceVisDataCount = CMUtil::allignBy128(surfaceCount); gfxWorld->dpvs.surfaceVisDataCount = BSPUtil::allignBy128(surfaceCount);
gfxWorld->dpvs.surfaceVisData[0] = new char[surfaceCount]; gfxWorld->dpvs.surfaceVisData[0] = new char[surfaceCount];
gfxWorld->dpvs.surfaceVisData[1] = new char[surfaceCount]; gfxWorld->dpvs.surfaceVisData[1] = new char[surfaceCount];
gfxWorld->dpvs.surfaceVisData[2] = new char[surfaceCount]; gfxWorld->dpvs.surfaceVisData[2] = new char[surfaceCount];
@@ -308,10 +308,10 @@ private:
// currModel->placement.origin.x = inModel->origin.x; // currModel->placement.origin.x = inModel->origin.x;
// currModel->placement.origin.y = inModel->origin.y; // currModel->placement.origin.y = inModel->origin.y;
// currModel->placement.origin.z = inModel->origin.z; // currModel->placement.origin.z = inModel->origin.z;
// currModel->placement.origin = CMUtil::convertToBO2Coords(currModel->placement.origin); // currModel->placement.origin = BSPUtil::convertToBO2Coords(currModel->placement.origin);
// currModel->placement.scale = inModel->scale; // currModel->placement.scale = inModel->scale;
// //
// CMUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis); // BSPUtil::convertAnglesToAxis(&inModel->rotation, currModel->placement.axis);
// //
// // mins and maxs are calculated in world space not local space // // mins and maxs are calculated in world space not local space
// // TODO: this does not account for model rotation or scale // // TODO: this does not account for model rotation or scale
@@ -353,7 +353,7 @@ private:
gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount]; gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount];
// all visdata is alligned by 128 // all visdata is alligned by 128
int allignedModelCount = CMUtil::allignBy128(modelCount); int allignedModelCount = BSPUtil::allignBy128(modelCount);
gfxWorld->dpvs.smodelVisDataCount = allignedModelCount; gfxWorld->dpvs.smodelVisDataCount = allignedModelCount;
gfxWorld->dpvs.smodelVisData[0] = new char[allignedModelCount]; gfxWorld->dpvs.smodelVisData[0] = new char[allignedModelCount];
gfxWorld->dpvs.smodelVisData[1] = new char[allignedModelCount]; gfxWorld->dpvs.smodelVisData[1] = new char[allignedModelCount];
@@ -367,7 +367,7 @@ private:
memset(gfxWorld->dpvs.smodelCastsShadow, 0, allignedModelCount); memset(gfxWorld->dpvs.smodelCastsShadow, 0, allignedModelCount);
for (unsigned int i = 0; i < modelCount; i++) for (unsigned int i = 0; i < modelCount; i++)
{ {
if ((gfxWorld->dpvs.smodelDrawInsts[i].flags & SMODEL_FLAG_NO_SHADOW) == 0) if ((gfxWorld->dpvs.smodelDrawInsts[i].flags & STATIC_MODEL_FLAG_NO_SHADOW) == 0)
gfxWorld->dpvs.smodelCastsShadow[i] = 1; gfxWorld->dpvs.smodelCastsShadow[i] = 1;
else else
gfxWorld->dpvs.smodelCastsShadow[i] = 0; gfxWorld->dpvs.smodelCastsShadow[i] = 0;
@@ -468,7 +468,7 @@ private:
{ {
// there must be 2 or more lights, first is the default light and second is the sun // there must be 2 or more lights, first is the default light and second is the sun
gfxWorld->primaryLightCount = 2; gfxWorld->primaryLightCount = 2;
gfxWorld->sunPrimaryLightIndex = SUN_LIGHT_INDEX; // the sun is always index 1 gfxWorld->sunPrimaryLightIndex = BSPGameConstants::SUN_LIGHT_INDEX;
gfxWorld->shadowGeom = new GfxShadowGeometry[gfxWorld->primaryLightCount]; gfxWorld->shadowGeom = new GfxShadowGeometry[gfxWorld->primaryLightCount];
for (unsigned int i = 0; i < gfxWorld->primaryLightCount; i++) for (unsigned int i = 0; i < gfxWorld->primaryLightCount; i++)
@@ -517,7 +517,7 @@ private:
gfxWorld->lightGrid.rowAxis = 0; // default value gfxWorld->lightGrid.rowAxis = 0; // default value
gfxWorld->lightGrid.colAxis = 1; // default value gfxWorld->lightGrid.colAxis = 1; // default value
gfxWorld->lightGrid.sunPrimaryLightIndex = SUN_LIGHT_INDEX; gfxWorld->lightGrid.sunPrimaryLightIndex = BSPGameConstants::SUN_LIGHT_INDEX;
gfxWorld->lightGrid.offset = 0.0f; // default value gfxWorld->lightGrid.offset = 0.0f; // default value
// this will make the lookup into rawRowData always return the first row // this will make the lookup into rawRowData always return the first row
@@ -544,7 +544,7 @@ private:
for (unsigned int i = 0; i < gfxWorld->lightGrid.entryCount; i++) for (unsigned int i = 0; i < gfxWorld->lightGrid.entryCount; i++)
{ {
entryArray[i].colorsIndex = 0; // always index first colour entryArray[i].colorsIndex = 0; // always index first colour
entryArray[i].primaryLightIndex = SUN_LIGHT_INDEX; entryArray[i].primaryLightIndex = BSPGameConstants::SUN_LIGHT_INDEX;
entryArray[i].visibility = 0; entryArray[i].visibility = 0;
} }
gfxWorld->lightGrid.entries = entryArray; gfxWorld->lightGrid.entries = entryArray;
@@ -552,7 +552,7 @@ private:
// colours are looked up by an entries colourindex // colours are looked up by an entries colourindex
gfxWorld->lightGrid.colorCount = 0x1000; //0x1000 as it should be enough to hold every index gfxWorld->lightGrid.colorCount = 0x1000; //0x1000 as it should be enough to hold every index
gfxWorld->lightGrid.colors = new GfxCompressedLightGridColors[gfxWorld->lightGrid.colorCount]; gfxWorld->lightGrid.colors = new GfxCompressedLightGridColors[gfxWorld->lightGrid.colorCount];
memset(gfxWorld->lightGrid.colors, LIGHTGRID_COLOUR, rowDataStartSize * sizeof(uint16_t)); memset(gfxWorld->lightGrid.colors, BSPEditableConstants::LIGHTGRID_COLOUR, rowDataStartSize * sizeof(uint16_t));
// we use the colours array instead of coeffs array // we use the colours array instead of coeffs array
gfxWorld->lightGrid.coeffCount = 0; gfxWorld->lightGrid.coeffCount = 0;
@@ -586,7 +586,7 @@ private:
// there is only 1 reflection probe // there is only 1 reflection probe
gfxWorld->cells[0].reflectionProbeCount = 1; gfxWorld->cells[0].reflectionProbeCount = 1;
char* reflectionProbeIndexes = new char[gfxWorld->cells[0].reflectionProbeCount]; char* reflectionProbeIndexes = new char[gfxWorld->cells[0].reflectionProbeCount];
reflectionProbeIndexes[0] = DEFAULT_SURFACE_REFLECTION_PROBE; reflectionProbeIndexes[0] = BSPEditableConstants::DEFAULT_SURFACE_REFLECTION_PROBE;
gfxWorld->cells[0].reflectionProbes = reflectionProbeIndexes; gfxWorld->cells[0].reflectionProbes = reflectionProbeIndexes;
// AABB trees are used to detect what should be rendered and what shouldn't // AABB trees are used to detect what should be rendered and what shouldn't
@@ -639,7 +639,7 @@ private:
for (int i = 0; i < gfxWorld->surfaceCount; i++) for (int i = 0; i < gfxWorld->surfaceCount; i++)
{ {
CMUtil::calcNewBounds(&gfxWorld->dpvs.surfaces[i].bounds[0], &gfxWorld->dpvs.surfaces[i].bounds[1], &gfxWorld->mins, &gfxWorld->maxs); BSPUtil::calcNewBounds(&gfxWorld->dpvs.surfaces[i].bounds[0], &gfxWorld->dpvs.surfaces[i].bounds[1], &gfxWorld->mins, &gfxWorld->maxs);
} }
} }
@@ -811,7 +811,8 @@ private:
void updateDynEntData(GfxWorld* gfxWorld) void updateDynEntData(GfxWorld* gfxWorld)
{ {
gfxWorld->dpvsDyn.dynEntClientCount[0] = DYN_ENT_COUNT + 256; // the game allocs 256 empty dynents, as they may be used ingame int dynEntCount = 0;
gfxWorld->dpvsDyn.dynEntClientCount[0] = dynEntCount + 256; // the game allocs 256 empty dynents, as they may be used ingame
gfxWorld->dpvsDyn.dynEntClientCount[1] = 0; gfxWorld->dpvsDyn.dynEntClientCount[1] = 0;
// +100: there is a crash that happens when regdolls are created, and dynEntClientWordCount[0] is the issue. // +100: there is a crash that happens when regdolls are created, and dynEntClientWordCount[0] is the issue.
@@ -952,7 +953,7 @@ private:
currModel->absmax.y = gfxModelInst->maxs.y; currModel->absmax.y = gfxModelInst->maxs.y;
currModel->absmax.z = gfxModelInst->maxs.z; currModel->absmax.z = gfxModelInst->maxs.z;
CMUtil::matrixTranspose3x3(gfxModelDrawInst->placement.axis, currModel->invScaledAxis); BSPUtil::matrixTranspose3x3(gfxModelDrawInst->placement.axis, currModel->invScaledAxis);
currModel->invScaledAxis[0].x = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].x; currModel->invScaledAxis[0].x = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].x;
currModel->invScaledAxis[0].y = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].y; currModel->invScaledAxis[0].y = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].y;
currModel->invScaledAxis[0].z = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].z; currModel->invScaledAxis[0].z = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].z;
@@ -1060,7 +1061,7 @@ private:
{ {
uint16_t vertIndex = tri[l]; uint16_t vertIndex = tri[l];
vec3_t vertCoord = clipMap->verts[vertIndex]; vec3_t vertCoord = clipMap->verts[vertIndex];
CMUtil::calcNewBoundsWithPoint(&vertCoord, &aabbMins, &aabbMaxs); BSPUtil::calcNewBoundsWithPoint(&vertCoord, &aabbMins, &aabbMaxs);
} }
} }
} }
@@ -1097,7 +1098,7 @@ private:
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];
CMUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs); BSPUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs);
} }
aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize); aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize);
@@ -1122,7 +1123,7 @@ private:
currLeaf->cluster = 0; currLeaf->cluster = 0;
currLeaf->brushContents = 0; // no brushes used so contents is 0 currLeaf->brushContents = 0; // no brushes used so contents is 0
currLeaf->terrainContents = LEAF_TERRAIN_CONTENTS; // clipMap->cmodels[0].leaf.terrainContents takes prescedence currLeaf->terrainContents = BSPEditableConstants::LEAF_TERRAIN_CONTENTS; // clipMap->cmodels[0].leaf.terrainContents takes prescedence
// unused when leafBrushNode == 0 // unused when leafBrushNode == 0
currLeaf->mins.x = 0.0f; currLeaf->mins.x = 0.0f;
@@ -1276,7 +1277,7 @@ private:
std::vector<vec3_t> collisionVertVec; std::vector<vec3_t> collisionVertVec;
for (int i = 0; i < collisionVertexCount; i++) for (int i = 0; i < collisionVertexCount; i++)
{ {
collisionVertVec.push_back(CMUtil::convertToBO2Coords(projInfo->colWorld.vertices[i].pos)); collisionVertVec.push_back(BSPUtil::convertToBO2Coords(projInfo->colWorld.vertices[i].pos));
//collisionVertVec.push_back(projInfo->colWorld.vertices[i].pos); //collisionVertVec.push_back(projInfo->colWorld.vertices[i].pos);
} }
clipMap->vertCount = collisionVertexCount; clipMap->vertCount = collisionVertexCount;
@@ -1285,9 +1286,9 @@ private:
// due to tris using uint16_t as the type for indexing the vert array, // 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 it can't be indexed // any vertex count over the uint16_t max means the vertices above it can't be indexed
if (collisionVertexCount > MAX_COL_VERTS) if (collisionVertexCount > BSPGameConstants::MAX_COLLISION_VERTS)
{ {
printf("ERROR: collision vertex count %i exceeds the maximum number: %i!\n", collisionVertexCount, MAX_COL_VERTS); printf("ERROR: collision vertex count %i exceeds the maximum number: %i!\n", collisionVertexCount, BSPGameConstants::MAX_COLLISION_VERTS);
hasLinkFailed = true; hasLinkFailed = true;
return; return;
} }
@@ -1478,7 +1479,8 @@ private:
clipMap->info.brushBounds = NULL; clipMap->info.brushBounds = NULL;
clipMap->info.brushContents = NULL; clipMap->info.brushContents = NULL;
clipMap->originalDynEntCount = DYN_ENT_COUNT; int 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[0] = clipMap->originalDynEntCount + 256; // the game allocs 256 empty dynents, as they may be used ingame
clipMap->dynEntCount[1] = 0; clipMap->dynEntCount[1] = 0;
clipMap->dynEntCount[2] = 0; clipMap->dynEntCount[2] = 0;
@@ -1522,7 +1524,7 @@ private:
cmModel->leaf.firstCollAabbIndex = 0; cmModel->leaf.firstCollAabbIndex = 0;
cmModel->leaf.collAabbCount = 0; cmModel->leaf.collAabbCount = 0;
cmModel->leaf.brushContents = 0; cmModel->leaf.brushContents = 0;
cmModel->leaf.terrainContents = WORLD_TERRAIN_CONTENTS; cmModel->leaf.terrainContents = BSPEditableConstants::WORLD_TERRAIN_CONTENTS;
cmModel->leaf.mins.x = 0.0f; cmModel->leaf.mins.x = 0.0f;
cmModel->leaf.mins.y = 0.0f; cmModel->leaf.mins.y = 0.0f;
cmModel->leaf.mins.z = 0.0f; cmModel->leaf.mins.z = 0.0f;
@@ -1538,16 +1540,16 @@ private:
cmModel->maxs.x = gfxModel->bounds[1].x; cmModel->maxs.x = gfxModel->bounds[1].x;
cmModel->maxs.y = gfxModel->bounds[1].y; cmModel->maxs.y = gfxModel->bounds[1].y;
cmModel->maxs.z = gfxModel->bounds[1].z; cmModel->maxs.z = gfxModel->bounds[1].z;
cmModel->radius = CMUtil::distBetweenPoints(cmModel->mins, cmModel->maxs) / 2; cmModel->radius = BSPUtil::distBetweenPoints(cmModel->mins, cmModel->maxs) / 2;
} }
addXModelsToCollision(projInfo, clipMap); addXModelsToCollision(projInfo, clipMap);
clipMap->info.numMaterials = 1; clipMap->info.numMaterials = 1;
clipMap->info.materials = new ClipMaterial[clipMap->info.numMaterials]; clipMap->info.materials = new ClipMaterial[clipMap->info.numMaterials];
clipMap->info.materials[0].name = _strdup(missingImageName.c_str()); clipMap->info.materials[0].name = _strdup(BSPLinkingConstants::MISSING_IMAGE_NAME);
clipMap->info.materials[0].contentFlags = MATERIAL_CONTENT_FLAGS; clipMap->info.materials[0].contentFlags = BSPEditableConstants::MATERIAL_CONTENT_FLAGS;
clipMap->info.materials[0].surfaceFlags = MATERIAL_SURFACE_FLAGS; clipMap->info.materials[0].surfaceFlags = BSPEditableConstants::MATERIAL_SURFACE_FLAGS;
// set all edges to walkable (all walkable edge bits are set to 1, see isEdgeWalkable) until changing it is a possiblility // set all edges to walkable (all walkable edge bits are set to 1, see isEdgeWalkable) until changing it is a possiblility
// might do weird stuff on walls, but from testing doesnt seem to do much // might do weird stuff on walls, but from testing doesnt seem to do much
@@ -1573,12 +1575,12 @@ private:
clipMaxs.x = firstVert->x; clipMaxs.x = firstVert->x;
clipMaxs.y = firstVert->y; clipMaxs.y = firstVert->y;
clipMaxs.z = firstVert->z; clipMaxs.z = firstVert->z;
clipMins = CMUtil::convertFromBO2Coords(clipMins); clipMins = BSPUtil::convertFromBO2Coords(clipMins);
clipMaxs = CMUtil::convertFromBO2Coords(clipMaxs); clipMaxs = BSPUtil::convertFromBO2Coords(clipMaxs);
for (unsigned int i = 1; i < clipMap->vertCount; i++) for (unsigned int i = 1; i < clipMap->vertCount; i++)
{ {
vec3_t vertCoord = CMUtil::convertFromBO2Coords(clipMap->verts[i]); vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[i]);
CMUtil::calcNewBoundsWithPoint(&vertCoord, &clipMins, &clipMaxs); BSPUtil::calcNewBoundsWithPoint(&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);
@@ -1599,20 +1601,20 @@ private:
maxs.x = firstVert->x; maxs.x = firstVert->x;
maxs.y = firstVert->y; maxs.y = firstVert->y;
maxs.z = firstVert->z; maxs.z = firstVert->z;
mins = CMUtil::convertFromBO2Coords(mins); mins = BSPUtil::convertFromBO2Coords(mins);
maxs = CMUtil::convertFromBO2Coords(maxs); maxs = BSPUtil::convertFromBO2Coords(maxs);
for (int k = 0; k < currPartition->triCount; k++) for (int k = 0; k < currPartition->triCount; k++)
{ {
uint16_t* tri = clipMap->triIndices[currPartition->firstTri + k]; uint16_t* tri = clipMap->triIndices[currPartition->firstTri + k];
for (int l = 0; l < 3; l++) for (int l = 0; l < 3; l++)
{ {
uint16_t vertIndex = tri[l]; uint16_t vertIndex = tri[l];
vec3_t vertCoord = CMUtil::convertFromBO2Coords(clipMap->verts[vertIndex]); vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[vertIndex]);
CMUtil::calcNewBoundsWithPoint(&vertCoord, &mins, &maxs); BSPUtil::calcNewBoundsWithPoint(&vertCoord, &mins, &maxs);
} }
} }
std::shared_ptr<Object> currObject = std::make_shared<Object>(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i); std::shared_ptr<BSPObject> currObject = std::make_shared<BSPObject>(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i);
tree->addObjectToTree(std::move(currObject)); tree->addObjectToTree(std::move(currObject));
} }
@@ -1680,7 +1682,7 @@ private:
} }
} }
void parseSpawnpointJSON(json& entArrayJs, std::string& entityString, std::vector<std::string> spawnpointTypeArray) void parseSpawnpointJSON(json& entArrayJs, std::string& entityString, const char* spawnpointNames[], int nameCount)
{ {
int entityCount = entArrayJs.size(); int entityCount = entArrayJs.size();
for (int i = 0; i < entityCount; i++) for (int i = 0; i < entityCount; i++)
@@ -1690,12 +1692,12 @@ private:
std::string origin = currEntity["origin"]; std::string origin = currEntity["origin"];
std::string angles = currEntity["angles"]; std::string angles = currEntity["angles"];
for (std::string& spawnType : spawnpointTypeArray) 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", spawnType)); entityString.append(std::format("\"classname\" \"{}\"\n", spawnpointNames[k]));
entityString.append("}\n"); entityString.append("}\n");
} }
} }
@@ -1725,7 +1727,7 @@ private:
// add the bomb pickup trigger // add the bomb pickup trigger
{ {
std::string bombOriginStr = bombJs["sd_bomb"]["origin"]; std::string bombOriginStr = bombJs["sd_bomb"]["origin"];
vec3_t bomboriginV3 = CMUtil::convertStringToVec3(bombOriginStr); vec3_t bomboriginV3 = BSPUtil::convertStringToVec3(bombOriginStr);
entModelBounds bounds; entModelBounds bounds;
bounds.mins.x = bomboriginV3.x - 32.0f; // bounds taken from mp_dig bounds.mins.x = bomboriginV3.x - 32.0f; // bounds taken from mp_dig
bounds.mins.y = bomboriginV3.y - 32.0f; bounds.mins.y = bomboriginV3.y - 32.0f;
@@ -1748,8 +1750,8 @@ private:
{ {
std::string siteAPoint1Str = bombJs["sd_bombzone_a"]["point1"]; std::string siteAPoint1Str = bombJs["sd_bombzone_a"]["point1"];
std::string siteAPoint2Str = bombJs["sd_bombzone_a"]["point2"]; std::string siteAPoint2Str = bombJs["sd_bombzone_a"]["point2"];
vec3_t siteAPoint1V3 = CMUtil::convertStringToVec3(siteAPoint1Str); vec3_t siteAPoint1V3 = BSPUtil::convertStringToVec3(siteAPoint1Str);
vec3_t siteAPoint2V3 = CMUtil::convertStringToVec3(siteAPoint2Str); vec3_t siteAPoint2V3 = BSPUtil::convertStringToVec3(siteAPoint2Str);
entModelBounds bounds; entModelBounds bounds;
bounds.mins.x = siteAPoint1V3.x; bounds.mins.x = siteAPoint1V3.x;
bounds.mins.y = siteAPoint1V3.y; bounds.mins.y = siteAPoint1V3.y;
@@ -1757,12 +1759,12 @@ private:
bounds.maxs.x = siteAPoint1V3.x; bounds.maxs.x = siteAPoint1V3.x;
bounds.maxs.y = siteAPoint1V3.y; bounds.maxs.y = siteAPoint1V3.y;
bounds.maxs.z = siteAPoint1V3.z; bounds.maxs.z = siteAPoint1V3.z;
CMUtil::calcNewBoundsWithPoint(&siteAPoint2V3, &bounds.mins, &bounds.mins); BSPUtil::calcNewBoundsWithPoint(&siteAPoint2V3, &bounds.mins, &bounds.mins);
int entityModelIndex = entityModelList.size() + 1; // +1 as the first model is always the world model int entityModelIndex = entityModelList.size() + 1; // +1 as the first model is always the world model
entityModelList.push_back(bounds); entityModelList.push_back(bounds);
vec3_t siteAOrigin = CMUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins); vec3_t siteAOrigin = BSPUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins);
std::string siteAOriginStr = CMUtil::convertVec3ToString(siteAOrigin); std::string siteAOriginStr = BSPUtil::convertVec3ToString(siteAOrigin);
entityString.append("{\n"); entityString.append("{\n");
entityString.append("\"classname\" \"trigger_use_touch\"\n"); entityString.append("\"classname\" \"trigger_use_touch\"\n");
@@ -1779,8 +1781,8 @@ private:
{ {
std::string siteBPoint1Str = bombJs["sd_bombzone_b"]["point1"]; std::string siteBPoint1Str = bombJs["sd_bombzone_b"]["point1"];
std::string siteBPoint2Str = bombJs["sd_bombzone_b"]["point2"]; std::string siteBPoint2Str = bombJs["sd_bombzone_b"]["point2"];
vec3_t siteBPoint1V3 = CMUtil::convertStringToVec3(siteBPoint1Str); vec3_t siteBPoint1V3 = BSPUtil::convertStringToVec3(siteBPoint1Str);
vec3_t siteBPoint2V3 = CMUtil::convertStringToVec3(siteBPoint2Str); vec3_t siteBPoint2V3 = BSPUtil::convertStringToVec3(siteBPoint2Str);
entModelBounds bounds; entModelBounds bounds;
bounds.mins.x = siteBPoint1V3.x; bounds.mins.x = siteBPoint1V3.x;
bounds.mins.y = siteBPoint1V3.y; bounds.mins.y = siteBPoint1V3.y;
@@ -1788,12 +1790,12 @@ private:
bounds.maxs.x = siteBPoint1V3.x; bounds.maxs.x = siteBPoint1V3.x;
bounds.maxs.y = siteBPoint1V3.y; bounds.maxs.y = siteBPoint1V3.y;
bounds.maxs.z = siteBPoint1V3.z; bounds.maxs.z = siteBPoint1V3.z;
CMUtil::calcNewBoundsWithPoint(&siteBPoint2V3, &bounds.mins, &bounds.mins); BSPUtil::calcNewBoundsWithPoint(&siteBPoint2V3, &bounds.mins, &bounds.mins);
int entityModelIndex = entityModelList.size() + 1; // +1 as the first model is always the world model int entityModelIndex = entityModelList.size() + 1; // +1 as the first model is always the world model
entityModelList.push_back(bounds); entityModelList.push_back(bounds);
vec3_t siteAOrigin = CMUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins); vec3_t siteAOrigin = BSPUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins);
std::string siteAOriginStr = CMUtil::convertVec3ToString(siteAOrigin); std::string siteAOriginStr = BSPUtil::convertVec3ToString(siteAOrigin);
entityString.append("{\n"); entityString.append("{\n");
entityString.append("\"classname\" \"trigger_use_touch\"\n"); entityString.append("\"classname\" \"trigger_use_touch\"\n");
@@ -1828,7 +1830,7 @@ private:
if (!entFile.IsOpen()) if (!entFile.IsOpen())
{ {
printf("WARN: can't find entity json custom_map/entities.json, using default entities\n"); printf("WARN: can't find entity json custom_map/entities.json, using default entities\n");
entJs = json::parse(defaultMapEntsString); entJs = json::parse(BSPLinkingConstants::DEFAULT_MAP_ENTS_STRING);
} }
else else
{ {
@@ -1841,16 +1843,19 @@ private:
if (!spawnFile.IsOpen()) if (!spawnFile.IsOpen())
{ {
printf("WARN: cant find custom_map/spawns.json, setting spawns to 0 0 0\n"); printf("WARN: cant find custom_map/spawns.json, setting spawns to 0 0 0\n");
spawnJs = json::parse(defaultSpawnpointString); spawnJs = json::parse(BSPLinkingConstants::DEFAULT_SPAWN_POINT_STRING);
} }
else else
{ {
spawnJs = json::parse(*spawnFile.m_stream); spawnJs = json::parse(*spawnFile.m_stream);
} }
parseSpawnpointJSON(spawnJs["attackers"], entityString, spawnpointDefenderTypeArray); int defenderNameCount = std::extent<decltype(BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES)>::value;
parseSpawnpointJSON(spawnJs["defenders"], entityString, spawnpointAttackerTypeArray); int attackerNameCount = std::extent<decltype(BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES)>::value;
parseSpawnpointJSON(spawnJs["FFA"], entityString, spawnpointFFATypeArray); int ffaNameCount = std::extent<decltype(BSPGameConstants::FFA_SPAWN_POINT_NAMES)>::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);
//const auto objectiveFile = m_search_path.Open("objectives.json"); //const auto objectiveFile = m_search_path.Open("objectives.json");
//if (!spawnFile.IsOpen()) //if (!spawnFile.IsOpen())

View File

@@ -1,166 +0,0 @@
#pragma once
#include <cmath>
#include <format>
#include "Game/T6/T6.h"
using namespace T6;
class CMUtil
{
public:
// BO2 uses a different coordinate system, so this converts it back from OpenGLs default
static vec3_t convertToBO2Coords(vec3_t OGL_coordinate)
{
vec3_t result;
result.x = OGL_coordinate.x;
result.y = -OGL_coordinate.z;
result.z = OGL_coordinate.y;
return result;
}
// BO2 uses a weird coordinate system, so this converts it to OpenGLs default
static vec3_t convertFromBO2Coords(vec3_t bo2_coordinate)
{
vec3_t result;
result.x = bo2_coordinate.x;
result.y = bo2_coordinate.z;
result.z = -bo2_coordinate.y;
return result;
}
static void calcNewBounds(vec3_t* newmins, vec3_t* newmaxs, vec3_t* currmins, vec3_t* currmaxs)
{
if (currmins->x > newmins->x)
currmins->x = newmins->x;
if (newmaxs->x > currmaxs->x)
currmaxs->x = newmaxs->x;
if (currmins->y > newmins->y)
currmins->y = newmins->y;
if (newmaxs->y > currmaxs->y)
currmaxs->y = newmaxs->y;
if (currmins->z > newmins->z)
currmins->z = newmins->z;
if (newmaxs->z > currmaxs->z)
currmaxs->z = newmaxs->z;
}
static void calcNewBoundsWithPoint(vec3_t* point, vec3_t* currmins, vec3_t* currmaxs)
{
if (currmins->x > point->x)
currmins->x = point->x;
if (point->x > currmaxs->x)
currmaxs->x = point->x;
if (currmins->y > point->y)
currmins->y = point->y;
if (point->y > currmaxs->y)
currmaxs->y = point->y;
if (currmins->z > point->z)
currmins->z = point->z;
if (point->z > currmaxs->z)
currmaxs->z = point->z;
}
static vec3_t 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;
}
static int allignBy128(int size)
{
return ((size + 127) & 0xFFFFFF80);
}
static float distBetweenPoints(vec3_t p1, vec3_t p2)
{
float x = p2.x - p1.x;
float y = p2.y - p1.y;
float z = p2.z - p1.z;
return sqrtf((x * x) + (y * y) + (z * z));
}
// angles are in euler degrees
static void convertAnglesToAxis(vec3_t* angles, vec3_t* axis)
{
float xRadians = angles->x * 0.017453292f; // M_PI / 180.0f
float yRadians = angles->y * 0.017453292f; // M_PI / 180.0f
float zRadians = angles->z * 0.017453292f; // M_PI / 180.0f
float cosX = cos(xRadians);
float sinX = sin(xRadians);
float cosY = cos(yRadians);
float sinY = sin(yRadians);
float cosZ = cos(zRadians);
float sinZ = sin(zRadians);
axis[0].x = cosX * cosY;
axis[0].y = cosX * sinY;
axis[0].z = -sinX;
axis[1].x = (sinZ * sinX * cosY) - (cosZ * sinY);
axis[1].y = (sinZ * sinX * sinY) + (cosZ * cosY);
axis[1].z = sinZ * cosX;
axis[2].x = (cosZ * sinX * cosY) + (sinZ * sinY);
axis[2].y = (cosZ * sinX * sinY) - (sinZ * cosY);
axis[2].z = cosZ * cosX;
}
static void matrixTranspose3x3(const vec3_t* in, vec3_t* out)
{
out[0].x = in[0].x;
out[0].y = in[1].x;
out[0].z = in[2].x;
out[1].x = in[0].y;
out[1].y = in[1].y;
out[1].z = in[2].y;
out[2].x = in[0].z;
out[2].y = in[1].z;
out[2].z = in[2].z;
}
static vec3_t convertStringToVec3(std::string str)
{
std::string v1Str = str;
int nextValIndex = 0;
while (v1Str[nextValIndex] != ' ')
nextValIndex++;
nextValIndex++; // skip past space
std::string v2Str = &v1Str[nextValIndex];
nextValIndex = 0;
while (v2Str[nextValIndex] != ' ')
nextValIndex++;
nextValIndex++; // skip past space
std::string v3Str = &v2Str[nextValIndex];
vec3_t result;
result.x = static_cast<float>(atof(v1Str.c_str()));
result.y = static_cast<float>(atof(v2Str.c_str()));
result.z = static_cast<float>(atof(v3Str.c_str()));
return result;
}
static std::string convertVec3ToString(vec3_t vec)
{
std::string result = std::format("{} {} {}", vec.x, vec.y, vec.z);
return result;
}
};