diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index f50c72fc..0a33bf51 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -3908,6 +3908,17 @@ namespace T6 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 { srfTriangles_t tris; @@ -3940,6 +3951,12 @@ namespace T6 uint16_t numLmapVertexColors; }; + enum StaticModelFlag + { + STATIC_MODEL_FLAG_NO_SHADOW = 0x1, + STATIC_MODEL_FLAG_LIGHTMAP_VC = 0x2, + }; + struct GfxStaticModelDrawInst { float cullDist; diff --git a/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTree.cpp b/src/ObjLoading/Game/T6/CustomMap/BSPCalculation.cpp similarity index 90% rename from src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTree.cpp rename to src/ObjLoading/Game/T6/CustomMap/BSPCalculation.cpp index 644f86a7..56396ab5 100644 --- a/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTree.cpp +++ b/src/ObjLoading/Game/T6/CustomMap/BSPCalculation.cpp @@ -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.y = yMin; @@ -12,12 +12,12 @@ Object::Object(float xMin, float yMin, float zMin, float xMax, float yMax, float partitionIndex = objPartitionIndex; } -void BSPLeaf::addObject(std::shared_ptr object) +void BSPLeaf::addObject(std::shared_ptr object) { objectList.emplace_back(std::move(object)); } -Object* BSPLeaf::getObject(int index) +BSPObject* BSPLeaf::getObject(int index) { return objectList.at(index).get(); } @@ -35,7 +35,7 @@ BSPNode::BSPNode(std::unique_ptr frontTree, std::unique_ptr ba distance = nodeDistance; } -PlaneSide BSPNode::objectIsInfront(Object* object) +PlaneSide BSPNode::objectIsInfront(BSPObject* object) { float minCoord, maxCoord; @@ -121,7 +121,7 @@ void BSPTree::splitTree() } } -void BSPTree::addObjectToTree(std::shared_ptr object) +void BSPTree::addObjectToTree(std::shared_ptr object) { if (isLeaf) { diff --git a/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTree.h b/src/ObjLoading/Game/T6/CustomMap/BSPCalculation.h similarity index 75% rename from src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTree.h rename to src/ObjLoading/Game/T6/CustomMap/BSPCalculation.h index 7a63478a..8f15fee7 100644 --- a/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTree.h +++ b/src/ObjLoading/Game/T6/CustomMap/BSPCalculation.h @@ -22,24 +22,24 @@ enum PlaneSide SIDE_INTERSECTS }; -class Object +class BSPObject { public: vec3_t min; vec3_t max; 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 { public: - std::vector> objectList; + std::vector> objectList; - void addObject(std::shared_ptr object); - Object* getObject(int index); + void addObject(std::shared_ptr object); + BSPObject* getObject(int index); int getObjectCount(); }; @@ -55,7 +55,7 @@ public: float distance; // distance from the origin (0, 0, 0) to the plane BSPNode(std::unique_ptr frontTree, std::unique_ptr backTree, PlaneAxis nodeAxis, float nodeDistance); - PlaneSide objectIsInfront(Object* object); + PlaneSide objectIsInfront(BSPObject* object); }; class BSPTree @@ -71,5 +71,5 @@ public: BSPTree(float xMin, float yMin, float zMin, float xMax, float yMax, float zMax, int treeLevel); void splitTree(); - void addObjectToTree(std::shared_ptr object); + void addObjectToTree(std::shared_ptr object); }; diff --git a/src/ObjLoading/Game/T6/CustomMap/BSPConstants.h b/src/ObjLoading/Game/T6/CustomMap/BSPConstants.h new file mode 100644 index 00000000..959ca376 --- /dev/null +++ b/src/ObjLoading/Game/T6/CustomMap/BSPConstants.h @@ -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; +}; \ No newline at end of file diff --git a/src/ObjLoading/Game/T6/CustomMap/BSPCreator.cpp b/src/ObjLoading/Game/T6/CustomMap/BSPCreator.cpp index 8b47fd2a..64aad2b2 100644 --- a/src/ObjLoading/Game/T6/CustomMap/BSPCreator.cpp +++ b/src/ObjLoading/Game/T6/CustomMap/BSPCreator.cpp @@ -43,7 +43,6 @@ bool addFBXMeshToWorld(ufbx_node* node, if (mesh->vertex_tangent.exists == false) hasTangentSpace = false; - // 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 diff --git a/src/ObjLoading/Game/T6/CustomMap/BSPUtil.cpp b/src/ObjLoading/Game/T6/CustomMap/BSPUtil.cpp new file mode 100644 index 00000000..a6a1b8f4 --- /dev/null +++ b/src/ObjLoading/Game/T6/CustomMap/BSPUtil.cpp @@ -0,0 +1,161 @@ +#pragma once + +#include +#include + +#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(atof(v1Str.c_str())); + result.y = static_cast(atof(v2Str.c_str())); + result.z = static_cast(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; +} \ No newline at end of file diff --git a/src/ObjLoading/Game/T6/CustomMap/BSPUtil.h b/src/ObjLoading/Game/T6/CustomMap/BSPUtil.h new file mode 100644 index 00000000..63961986 --- /dev/null +++ b/src/ObjLoading/Game/T6/CustomMap/BSPUtil.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#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); +}; diff --git a/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h b/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h deleted file mode 100644 index e65152f4..00000000 --- a/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include - -// 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 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 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 spawnpointFFATypeArray = { - "mp_tdm_spawn", - "mp_dm_spawn", - "mp_dom_spawn" -}; - -const std::vector 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\"" - "}" - "]" -"}"; diff --git a/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h b/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h index 4361f834..c46af5f7 100644 --- a/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h +++ b/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h @@ -1,9 +1,8 @@ #pragma once -#include "BinarySpacePartitionTree.h" -#include "CustomMapConsts.h" -#include "CustomMapOptions.h" -#include "Util.h" +#include "BSPCalculation.h" +#include "BSPConstants.h" +#include "BSPUtil.h" #include "Game/T6/Material/JsonMaterialLoaderT6.h" #include "Utils/Pack.h" @@ -84,17 +83,17 @@ private: CustomMapVertex* WorldVertex = &projInfo->gfxWorld.vertices[i]; GfxPackedWorldVertex* GfxVertex = &vertexBuffer[i]; - GfxVertex->xyz = CMUtil::convertToBO2Coords(WorldVertex->pos); + GfxVertex->xyz = BSPUtil::convertToBO2Coords(WorldVertex->pos); //GfxVertex->xyz = WorldVertex->pos; GfxVertex->color.packed = pack32::Vec4PackGfxColor(WorldVertex->color.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->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); // unknown use variables @@ -180,10 +179,10 @@ private: auto currSurface = &gfxWorld->dpvs.surfaces[i]; auto objSurface = &projInfo->gfxWorld.surfaces[i]; - currSurface->primaryLightIndex = DEFAULT_SURFACE_LIGHT; - currSurface->lightmapIndex = DEFAULT_SURFACE_LIGHTMAP; - currSurface->reflectionProbeIndex = DEFAULT_SURFACE_REFLECTION_PROBE; - currSurface->flags = DEFAULT_SURFACE_FLAGS; + currSurface->primaryLightIndex = BSPEditableConstants::DEFAULT_SURFACE_LIGHT; + currSurface->lightmapIndex = BSPEditableConstants::DEFAULT_SURFACE_LIGHTMAP; + currSurface->reflectionProbeIndex = BSPEditableConstants::DEFAULT_SURFACE_REFLECTION_PROBE; + currSurface->flags = BSPEditableConstants::DEFAULT_SURFACE_FLAGS; currSurface->tris.triCount = objSurface->triCount; currSurface->tris.baseIndex = objSurface->indexOfFirstIndex; @@ -200,7 +199,7 @@ private: case MATERIAL_TYPE_COLOUR: case MATERIAL_TYPE_EMPTY: - surfMaterialName = colorOnlyImageName; + surfMaterialName = BSPLinkingConstants::COLOR_ONLY_IMAGE_NAME; break; default: @@ -209,6 +208,7 @@ private: Material* surfMaterial = loadImageIntoMaterial(surfMaterialName); if (surfMaterial == NULL) { + std::string missingImageName = std::string(BSPLinkingConstants::MISSING_IMAGE_NAME); surfMaterial = loadImageIntoMaterial(missingImageName); if (surfMaterial == NULL) { @@ -229,7 +229,7 @@ private: for (int k = 0; k < currSurface->tris.triCount * 3; 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 @@ -255,7 +255,7 @@ private: memset(gfxWorld->dpvs.surfaceMaterials, 0, sizeof(GfxDrawSurf_align4) * surfaceCount); // 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[1] = 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.y = inModel->origin.y; // 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; // - // 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 // // TODO: this does not account for model rotation or scale @@ -353,7 +353,7 @@ private: gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount]; // all visdata is alligned by 128 - int allignedModelCount = CMUtil::allignBy128(modelCount); + int allignedModelCount = BSPUtil::allignBy128(modelCount); gfxWorld->dpvs.smodelVisDataCount = allignedModelCount; gfxWorld->dpvs.smodelVisData[0] = new char[allignedModelCount]; gfxWorld->dpvs.smodelVisData[1] = new char[allignedModelCount]; @@ -367,7 +367,7 @@ private: memset(gfxWorld->dpvs.smodelCastsShadow, 0, allignedModelCount); 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; else 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 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]; for (unsigned int i = 0; i < gfxWorld->primaryLightCount; i++) @@ -517,7 +517,7 @@ private: gfxWorld->lightGrid.rowAxis = 0; // 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 // 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++) { 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; } gfxWorld->lightGrid.entries = entryArray; @@ -552,7 +552,7 @@ private: // colours are looked up by an entries colourindex gfxWorld->lightGrid.colorCount = 0x1000; //0x1000 as it should be enough to hold every index 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 gfxWorld->lightGrid.coeffCount = 0; @@ -586,7 +586,7 @@ private: // there is only 1 reflection probe gfxWorld->cells[0].reflectionProbeCount = 1; 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; // 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++) { - 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) { - 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; // +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.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].y = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].y; currModel->invScaledAxis[0].z = (1.0f / gfxModelDrawInst->placement.scale) * currModel->invScaledAxis[0].z; @@ -1060,7 +1061,7 @@ private: { uint16_t vertIndex = tri[l]; 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]; vec3_t* currVertex = &clipMap->verts[currUind]; - CMUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs); + BSPUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs); } aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize); @@ -1122,7 +1123,7 @@ private: currLeaf->cluster = 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 currLeaf->mins.x = 0.0f; @@ -1276,7 +1277,7 @@ private: std::vector collisionVertVec; 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); } clipMap->vertCount = collisionVertexCount; @@ -1285,9 +1286,9 @@ private: // 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 - 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; return; } @@ -1478,7 +1479,8 @@ private: clipMap->info.brushBounds = 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[1] = 0; clipMap->dynEntCount[2] = 0; @@ -1522,7 +1524,7 @@ private: cmModel->leaf.firstCollAabbIndex = 0; cmModel->leaf.collAabbCount = 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.y = 0.0f; cmModel->leaf.mins.z = 0.0f; @@ -1538,16 +1540,16 @@ private: cmModel->maxs.x = gfxModel->bounds[1].x; cmModel->maxs.y = gfxModel->bounds[1].y; 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); clipMap->info.numMaterials = 1; clipMap->info.materials = new ClipMaterial[clipMap->info.numMaterials]; - clipMap->info.materials[0].name = _strdup(missingImageName.c_str()); - clipMap->info.materials[0].contentFlags = MATERIAL_CONTENT_FLAGS; - clipMap->info.materials[0].surfaceFlags = MATERIAL_SURFACE_FLAGS; + clipMap->info.materials[0].name = _strdup(BSPLinkingConstants::MISSING_IMAGE_NAME); + clipMap->info.materials[0].contentFlags = BSPEditableConstants::MATERIAL_CONTENT_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 // might do weird stuff on walls, but from testing doesnt seem to do much @@ -1573,12 +1575,12 @@ private: clipMaxs.x = firstVert->x; clipMaxs.y = firstVert->y; clipMaxs.z = firstVert->z; - clipMins = CMUtil::convertFromBO2Coords(clipMins); - clipMaxs = CMUtil::convertFromBO2Coords(clipMaxs); + clipMins = BSPUtil::convertFromBO2Coords(clipMins); + clipMaxs = BSPUtil::convertFromBO2Coords(clipMaxs); for (unsigned int i = 1; i < clipMap->vertCount; i++) { - vec3_t vertCoord = CMUtil::convertFromBO2Coords(clipMap->verts[i]); - CMUtil::calcNewBoundsWithPoint(&vertCoord, &clipMins, &clipMaxs); + vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[i]); + BSPUtil::calcNewBoundsWithPoint(&vertCoord, &clipMins, &clipMaxs); } 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.y = firstVert->y; maxs.z = firstVert->z; - mins = CMUtil::convertFromBO2Coords(mins); - maxs = CMUtil::convertFromBO2Coords(maxs); + mins = BSPUtil::convertFromBO2Coords(mins); + maxs = BSPUtil::convertFromBO2Coords(maxs); for (int k = 0; k < currPartition->triCount; k++) { uint16_t* tri = clipMap->triIndices[currPartition->firstTri + k]; for (int l = 0; l < 3; l++) { uint16_t vertIndex = tri[l]; - vec3_t vertCoord = CMUtil::convertFromBO2Coords(clipMap->verts[vertIndex]); - CMUtil::calcNewBoundsWithPoint(&vertCoord, &mins, &maxs); + vec3_t vertCoord = BSPUtil::convertFromBO2Coords(clipMap->verts[vertIndex]); + BSPUtil::calcNewBoundsWithPoint(&vertCoord, &mins, &maxs); } } - std::shared_ptr currObject = std::make_shared(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i); + std::shared_ptr currObject = std::make_shared(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i); tree->addObjectToTree(std::move(currObject)); } @@ -1680,7 +1682,7 @@ private: } } - void parseSpawnpointJSON(json& entArrayJs, std::string& entityString, std::vector spawnpointTypeArray) + void parseSpawnpointJSON(json& entArrayJs, std::string& entityString, const char* spawnpointNames[], int nameCount) { int entityCount = entArrayJs.size(); for (int i = 0; i < entityCount; i++) @@ -1690,12 +1692,12 @@ private: std::string origin = currEntity["origin"]; std::string angles = currEntity["angles"]; - for (std::string& spawnType : spawnpointTypeArray) + for (int k = 0; k < nameCount; k++) { entityString.append("{\n"); entityString.append(std::format("\"origin\" \"{}\"\n", origin)); 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"); } } @@ -1725,7 +1727,7 @@ private: // add the bomb pickup trigger { std::string bombOriginStr = bombJs["sd_bomb"]["origin"]; - vec3_t bomboriginV3 = CMUtil::convertStringToVec3(bombOriginStr); + vec3_t bomboriginV3 = BSPUtil::convertStringToVec3(bombOriginStr); entModelBounds bounds; bounds.mins.x = bomboriginV3.x - 32.0f; // bounds taken from mp_dig bounds.mins.y = bomboriginV3.y - 32.0f; @@ -1748,8 +1750,8 @@ private: { std::string siteAPoint1Str = bombJs["sd_bombzone_a"]["point1"]; std::string siteAPoint2Str = bombJs["sd_bombzone_a"]["point2"]; - vec3_t siteAPoint1V3 = CMUtil::convertStringToVec3(siteAPoint1Str); - vec3_t siteAPoint2V3 = CMUtil::convertStringToVec3(siteAPoint2Str); + vec3_t siteAPoint1V3 = BSPUtil::convertStringToVec3(siteAPoint1Str); + vec3_t siteAPoint2V3 = BSPUtil::convertStringToVec3(siteAPoint2Str); entModelBounds bounds; bounds.mins.x = siteAPoint1V3.x; bounds.mins.y = siteAPoint1V3.y; @@ -1757,12 +1759,12 @@ private: bounds.maxs.x = siteAPoint1V3.x; bounds.maxs.y = siteAPoint1V3.y; 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 entityModelList.push_back(bounds); - vec3_t siteAOrigin = CMUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins); - std::string siteAOriginStr = CMUtil::convertVec3ToString(siteAOrigin); + vec3_t siteAOrigin = BSPUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins); + std::string siteAOriginStr = BSPUtil::convertVec3ToString(siteAOrigin); entityString.append("{\n"); entityString.append("\"classname\" \"trigger_use_touch\"\n"); @@ -1779,8 +1781,8 @@ private: { std::string siteBPoint1Str = bombJs["sd_bombzone_b"]["point1"]; std::string siteBPoint2Str = bombJs["sd_bombzone_b"]["point2"]; - vec3_t siteBPoint1V3 = CMUtil::convertStringToVec3(siteBPoint1Str); - vec3_t siteBPoint2V3 = CMUtil::convertStringToVec3(siteBPoint2Str); + vec3_t siteBPoint1V3 = BSPUtil::convertStringToVec3(siteBPoint1Str); + vec3_t siteBPoint2V3 = BSPUtil::convertStringToVec3(siteBPoint2Str); entModelBounds bounds; bounds.mins.x = siteBPoint1V3.x; bounds.mins.y = siteBPoint1V3.y; @@ -1788,12 +1790,12 @@ private: bounds.maxs.x = siteBPoint1V3.x; bounds.maxs.y = siteBPoint1V3.y; 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 entityModelList.push_back(bounds); - vec3_t siteAOrigin = CMUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins); - std::string siteAOriginStr = CMUtil::convertVec3ToString(siteAOrigin); + vec3_t siteAOrigin = BSPUtil::calcMiddleOfBounds(&bounds.mins, &bounds.mins); + std::string siteAOriginStr = BSPUtil::convertVec3ToString(siteAOrigin); entityString.append("{\n"); entityString.append("\"classname\" \"trigger_use_touch\"\n"); @@ -1828,7 +1830,7 @@ private: if (!entFile.IsOpen()) { 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 { @@ -1841,16 +1843,19 @@ private: if (!spawnFile.IsOpen()) { 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 { spawnJs = json::parse(*spawnFile.m_stream); } - parseSpawnpointJSON(spawnJs["attackers"], entityString, spawnpointDefenderTypeArray); - parseSpawnpointJSON(spawnJs["defenders"], entityString, spawnpointAttackerTypeArray); - parseSpawnpointJSON(spawnJs["FFA"], entityString, spawnpointFFATypeArray); + int defenderNameCount = std::extent::value; + int attackerNameCount = std::extent::value; + int ffaNameCount = std::extent::value; + parseSpawnpointJSON(spawnJs["attackers"], entityString, BSPGameConstants::DEFENDER_SPAWN_POINT_NAMES, defenderNameCount); + parseSpawnpointJSON(spawnJs["defenders"], entityString, BSPGameConstants::ATTACKER_SPAWN_POINT_NAMES, attackerNameCount); + parseSpawnpointJSON(spawnJs["FFA"], entityString, BSPGameConstants::FFA_SPAWN_POINT_NAMES, ffaNameCount); //const auto objectiveFile = m_search_path.Open("objectives.json"); //if (!spawnFile.IsOpen()) diff --git a/src/ObjLoading/Game/T6/CustomMap/Util.h b/src/ObjLoading/Game/T6/CustomMap/Util.h deleted file mode 100644 index e8292aba..00000000 --- a/src/ObjLoading/Game/T6/CustomMap/Util.h +++ /dev/null @@ -1,166 +0,0 @@ -#pragma once - -#include -#include - -#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(atof(v1Str.c_str())); - result.y = static_cast(atof(v2Str.c_str())); - result.z = static_cast(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; - } -};