From 0662f2adbec6cb1188a1ec8ba95cf12a68128bde Mon Sep 17 00:00:00 2001 From: LJW-Dev Date: Wed, 8 Oct 2025 21:09:15 +0800 Subject: [PATCH] Another refactor to clean up comments and code --- .../BinarySpacePartitionTreePreCalc.h | 4 +- .../Game/T6/CustomMap/CustomMapConsts.h | 24 +- .../Game/T6/CustomMap/CustomMapLinker.cpp | 1648 ----------------- .../Game/T6/CustomMap/CustomMapLinker.h | 9 +- .../Game/T6/CustomMap/CustomMapOptions.h | 17 + .../Game/T6/CustomMap/LoaderCustomMapT6.cpp | 12 +- src/ObjLoading/Game/T6/CustomMap/OBJ_Loader.h | 1153 ------------ .../Game/T6/CustomMap/ProjectCreator.cpp | 68 +- .../Game/T6/CustomMap/ProjectCreator.h | 2 +- .../Game/T6/CustomMap/TriangleSort.h | 99 - src/ObjLoading/Game/T6/ObjLoaderT6.cpp | 3 +- .../Game/T6/Script/LoaderScriptT6.cpp | 6 +- .../Game/T6/Script/LoaderScriptT6.h | 6 +- 13 files changed, 70 insertions(+), 2981 deletions(-) delete mode 100644 src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.cpp create mode 100644 src/ObjLoading/Game/T6/CustomMap/CustomMapOptions.h delete mode 100644 src/ObjLoading/Game/T6/CustomMap/OBJ_Loader.h delete mode 100644 src/ObjLoading/Game/T6/CustomMap/TriangleSort.h diff --git a/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTreePreCalc.h b/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTreePreCalc.h index 3c02217c..eda7bca0 100644 --- a/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTreePreCalc.h +++ b/src/ObjLoading/Game/T6/CustomMap/BinarySpacePartitionTreePreCalc.h @@ -5,7 +5,7 @@ Heavily modified version of https://github.com/sudeshnapal12/Space-Partitioning- Credit to sudeshnapal12 -Precalculated, evenly sized BSPs are much more efficient and smaller compared to dynamically creating them +BSP leaf sizes are precalculated, evenly sized BSPs are much more efficient and smaller compared to dynamically creating them */ #include @@ -16,7 +16,7 @@ Precalculated, evenly sized BSPs are much more efficient and smaller compared to #include #include -#include "CustomMapConsts.h" +#define MAX_AABB_SIZE 512 // maximum size a BSP node can be before it becomes a leaf enum PlaneAxis { diff --git a/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h b/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h index 6acc66fc..c8ce1d0d 100644 --- a/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h +++ b/src/ObjLoading/Game/T6/CustomMap/CustomMapConsts.h @@ -1,46 +1,26 @@ #pragma once - #include +// do not change any values in this header file + #define DYN_ENT_COUNT 0 -// the clipMap->cmodels[0].leaf.terrainContents takes precendence over leaf and material terrain contents - -// material flags determine the features of the 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 -#define MATERIAL_SURFACE_FLAGS 1 -#define 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 -#define LEAF_TERRAIN_CONTENTS 1 -#define WORLD_TERRAIN_CONTENTS 1 - std::string missingImageName = "missing_image"; std::string colorOnlyImageName = "color_only_image"; -#define MAX_AABB_SIZE 512 // maximum size a BSP node can be before it becomes a leaf -#define LIGHTGRID_COLOUR 128 // global lighting colour - -// do not change #define MAX_COL_VERTS (UINT16_MAX - 1) // max amount of collision verts a map can have -// do not change #define DEFAULT_LIGHT_INDEX 0 #define SUN_LIGHT_INDEX 1 -// do not change enum SMODEL_FLAGS { SMODEL_FLAG_NO_SHADOW = 1, SMODEL_FLAG_IS_LIT = 2 }; -// do not change enum GFX_SURFACE_FLAGS { GFX_SURFACE_CASTS_SUN_SHADOW = 0x1, diff --git a/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.cpp b/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.cpp deleted file mode 100644 index e865f6ba..00000000 --- a/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.cpp +++ /dev/null @@ -1,1648 +0,0 @@ -//#include "CustomMapLinker.h" -// -//#include "Utils/Pack.h" -//#include "Util.h" -//#include "CustomMapConsts.h" -//#include "BinarySpacePartitionTreePreCalc.h" -// -//#include -//#include -//using json = nlohmann::json; -// -//class CustomMapLinker -//{ -//public: -// CustomMapLinker(MemoryManager& memory, ISearchPath& searchPath, Zone& zone, AssetCreationContext& context) -// : m_memory(memory), -// m_search_path(searchPath), -// m_zone(zone), -// m_context(context) -// { -// hasLinkFailed = false; -// } -// -// bool linkCustomMap(customMapInfo* projInfo) -// { -// _ASSERT(projInfo != NULL); -// -// createGfxWorld(projInfo); -// createComWorld(projInfo); -// createMapEnts(projInfo); -// createGameWorldMp(projInfo); -// createSkinnedVerts(projInfo); -// createClipMap(projInfo); // must go last (requires gfx and mapents asset) -// -// checkAndAddDefaultRequiredAssets(projInfo); -// -// if (hasLinkFailed) -// { -// printf("Custom Map link has failed.\n"); -// return false; -// } -// -// return true; -// } -// -//private: -// MemoryManager& m_memory; -// ISearchPath& m_search_path; -// Zone& m_zone; -// AssetCreationContext& m_context; -// -// bool hasLinkFailed; -// -// // TODO vd1: -// // used for UVs of sub-textures, when it is set to empty all of them turn a blank colour -// // could fix by removing sub textures or figure out how they are created and redo that -// // its not an important issue though -// bool overwriteDrawData(customMapInfo* projInfo, GfxWorld* gfxWorld) -// { -// int vertexCount = projInfo->gfxInfo.vertexCount; -// customMapVertex* worldVertices = projInfo->gfxInfo.vertices; -// -// gfxWorld->draw.vertexCount = vertexCount; -// gfxWorld->draw.vertexDataSize0 = vertexCount * sizeof(GfxPackedWorldVertex); -// GfxPackedWorldVertex* vertexBuffer = new GfxPackedWorldVertex[vertexCount]; -// for (int i = 0; i < vertexCount; i++) -// { -// customMapVertex* WorldVertex = &worldVertices[i]; -// GfxPackedWorldVertex* GfxVertex = &vertexBuffer[i]; -// -// GfxVertex->xyz = CMUtil::convertToBO2Coords(WorldVertex->pos); -// -// GfxVertex->binormalSign = WorldVertex->binormalSign; -// -// GfxVertex->color.packed = pack32::Vec4PackGfxColor(WorldVertex->color); -// -// GfxVertex->texCoord.packed = pack32::Vec2PackTexCoordsUV(WorldVertex->texCoord); -// -// GfxVertex->normal.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->normal).v); -// -// GfxVertex->tangent.packed = pack32::Vec3PackUnitVecThirdBased(CMUtil::convertToBO2Coords(WorldVertex->tangent).v); -// -// GfxVertex->lmapCoord.packed = WorldVertex->packedLmapCoord; -// } -// gfxWorld->draw.vd0.data = (char*)vertexBuffer; -// -// // we don't use vd1 but still needs to be initialised -// // the data type varies and 0x20 is enough for all types -// gfxWorld->draw.vertexDataSize1 = 0x20; -// gfxWorld->draw.vd1.data = new char[gfxWorld->draw.vertexDataSize1]; -// memset(gfxWorld->draw.vd1.data, 0, gfxWorld->draw.vertexDataSize1); -// -// int indexCount = projInfo->gfxInfo.indexCount; -// _ASSERT(indexCount % 3 == 0); -// gfxWorld->draw.indexCount = indexCount; -// gfxWorld->draw.indices = new uint16_t[indexCount]; -// for (int i = 0; i < indexCount; i += 3) -// { -// // the editor orders their vertices opposite to bo2, so its converted here -// gfxWorld->draw.indices[i + 2] = projInfo->gfxInfo.indices[i + 0]; -// gfxWorld->draw.indices[i + 1] = projInfo->gfxInfo.indices[i + 1]; -// gfxWorld->draw.indices[i + 0] = projInfo->gfxInfo.indices[i + 2]; -// } -// -// return true; -// } -// -// struct s_sortedSurf -// { -// int surfaceIndex; -// int vertexCount; -// }; -// -// bool compareSurfaces(s_sortedSurf& surf0, s_sortedSurf& surf1) -// { -// return surf0.vertexCount > surf1.vertexCount; -// } -// -// void overwriteMapSurfaces(customMapInfo* projInfo, GfxWorld* gfxWorld) -// { -// bool overwriteResult = overwriteDrawData(projInfo, gfxWorld); -// if (!overwriteResult) -// return; -// -// unsigned int surfaceCount = projInfo->gfxInfo.surfaceCount; -// gfxWorld->surfaceCount = surfaceCount; -// gfxWorld->dpvs.staticSurfaceCount = surfaceCount; -// gfxWorld->dpvs.surfaces = new GfxSurface[surfaceCount]; -// for (int i = 0; i < surfaceCount; i++) -// { -// auto currSurface = &gfxWorld->dpvs.surfaces[i]; -// auto objSurface = &projInfo->gfxInfo.surfaces[i]; -// -// currSurface->lightmapIndex = objSurface->lightmapIndex; -// currSurface->primaryLightIndex = objSurface->primaryLightIndex; -// currSurface->reflectionProbeIndex = objSurface->reflectionProbeIndex; -// currSurface->flags = objSurface->flags; -// -// currSurface->tris.triCount = objSurface->triCount; -// currSurface->tris.baseIndex = objSurface->firstIndex_Index; -// -// currSurface->tris.vertexDataOffset0 = objSurface->firstVertexIndex * sizeof(GfxPackedWorldVertex); -// currSurface->tris.vertexDataOffset1 = 0; -// -// auto* assetInfo = m_context.LoadDependency(objSurface->materialName); -// if (assetInfo == NULL) -// { -// printf("Warning: unable to load surface material %s, replacing with the default texture\n", objSurface->materialName.c_str()); -// assetInfo = m_context.LoadDependency(defaultMaterialName); -// _ASSERT(assetInfo != NULL); -// } -// currSurface->material = assetInfo->Asset(); -// -// GfxPackedWorldVertex* firstVert = (GfxPackedWorldVertex*)&gfxWorld->draw.vd0.data[currSurface->tris.vertexDataOffset0]; -// currSurface->bounds[0].x = firstVert[0].xyz.x; -// currSurface->bounds[0].y = firstVert[0].xyz.y; -// currSurface->bounds[0].z = firstVert[0].xyz.z; -// currSurface->bounds[1].x = firstVert[0].xyz.x; -// currSurface->bounds[1].y = firstVert[0].xyz.y; -// currSurface->bounds[1].z = firstVert[0].xyz.z; -// for (int k = 0; k < currSurface->tris.triCount * 3; k++) -// { -// CMUtil::calcNewBoundsWithPoint(&firstVert[k].xyz, &currSurface->bounds[0], &currSurface->bounds[1]); -// } -// -// // unused values -// currSurface->tris.mins.x = 0.0f; -// currSurface->tris.mins.y = 0.0f; -// currSurface->tris.mins.z = 0.0f; -// currSurface->tris.maxs.x = 0.0f; -// currSurface->tris.maxs.y = 0.0f; -// currSurface->tris.maxs.z = 0.0f; -// currSurface->tris.himipRadiusInvSq = 0.0f; -// currSurface->tris.vertexCount = 0; -// currSurface->tris.firstVertex = 0; -// } -// -// // sort all vertexes by vertex count -// // unsure if this does anything -// s_sortedSurf* sortedSurfs = new s_sortedSurf[surfaceCount]; -// for (int i = 0; i < surfaceCount; i++) -// { -// sortedSurfs[i].surfaceIndex = i; -// sortedSurfs[i].vertexCount = gfxWorld->dpvs.surfaces[i].tris.triCount * 3; -// } -// std::sort(sortedSurfs, &sortedSurfs[surfaceCount], compareSurfaces); -// -// gfxWorld->dpvs.sortedSurfIndex = new uint16_t[surfaceCount]; -// for (int i = 0; i < surfaceCount; i++) -// { -// gfxWorld->dpvs.sortedSurfIndex[i] = sortedSurfs[i].surfaceIndex; -// } -// -// gfxWorld->dpvs.surfaceMaterials = new GfxDrawSurf_align4[surfaceCount]; -// memset(gfxWorld->dpvs.surfaceMaterials, 0, sizeof(GfxDrawSurf_align4) * surfaceCount); -// -// // all visdata is alligned by 128 -// gfxWorld->dpvs.surfaceVisDataCount = CMUtil::allignBy128(surfaceCount); -// gfxWorld->dpvs.surfaceVisData[0] = new char[surfaceCount]; -// gfxWorld->dpvs.surfaceVisData[1] = new char[surfaceCount]; -// gfxWorld->dpvs.surfaceVisData[2] = new char[surfaceCount]; -// gfxWorld->dpvs.surfaceVisDataCameraSaved = new char[surfaceCount]; -// gfxWorld->dpvs.surfaceCastsShadow = new char[surfaceCount]; -// gfxWorld->dpvs.surfaceCastsSunShadow = new char[surfaceCount]; -// memset(gfxWorld->dpvs.surfaceVisData[0], 0, surfaceCount); -// memset(gfxWorld->dpvs.surfaceVisData[1], 0, surfaceCount); -// memset(gfxWorld->dpvs.surfaceVisData[2], 0, surfaceCount); -// memset(gfxWorld->dpvs.surfaceVisDataCameraSaved, 0, surfaceCount); -// memset(gfxWorld->dpvs.surfaceCastsShadow, 0, surfaceCount); -// memset(gfxWorld->dpvs.surfaceCastsSunShadow, 0, surfaceCount); -// -// gfxWorld->dpvs.litSurfsBegin = 0; -// gfxWorld->dpvs.litSurfsEnd = surfaceCount; -// gfxWorld->dpvs.emissiveOpaqueSurfsBegin = surfaceCount; -// gfxWorld->dpvs.emissiveOpaqueSurfsEnd = surfaceCount; -// gfxWorld->dpvs.emissiveTransSurfsBegin = surfaceCount; -// gfxWorld->dpvs.emissiveTransSurfsEnd = surfaceCount; -// gfxWorld->dpvs.litTransSurfsBegin = surfaceCount; -// gfxWorld->dpvs.litTransSurfsEnd = surfaceCount; -// } -// -//#define SMODEL_FLAG_NO_SHADOW 1 -//#define SMODEL_FLAG_IS_LIT 2 -// -// void overwriteMapSModels(GfxWorld* gfxWorld) -// { -// unsigned int modelCount = 0; -// gfxWorld->dpvs.smodelCount = modelCount; -// -// gfxWorld->dpvs.smodelInsts = new GfxStaticModelInst[modelCount]; -// gfxWorld->dpvs.smodelDrawInsts = new GfxStaticModelDrawInst[modelCount]; -// /* -// for (unsigned int i = 0; i < modelCount; i++) -// { -// auto currModel = &gfxWorld->dpvs.smodelDrawInsts[i]; -// auto currModelInst = &gfxWorld->dpvs.smodelInsts[i]; -// json currModelJs = js["models"][i]; -// -// // TODO: load custom xmodels -// std::string modelName = currModelJs["model"]; -// auto xModelAsset = findAsset(assetPool, ASSET_TYPE_XMODEL, modelName); -// if (xModelAsset == NULL) -// { -// printf("Custom model (%s) not supported!\n", modelName.c_str()); -// hasLinkFailed = true; -// return; -// } -// currModel->model = (XModel*)xModelAsset->m_ptr; -// -// currModel->placement.origin.x = currModelJs["origin"]["x"]; -// currModel->placement.origin.y = currModelJs["origin"]["y"]; -// currModel->placement.origin.z = currModelJs["origin"]["z"]; -// currModel->placement.origin = CMUtil::convertToBO2Coords(currModel->placement.origin); -// currModel->placement.axis[0].x = currModelJs["forward"]["x"]; -// currModel->placement.axis[0].y = currModelJs["forward"]["y"]; -// currModel->placement.axis[0].z = currModelJs["forward"]["z"]; -// currModel->placement.axis[1].x = currModelJs["right"]["x"]; -// currModel->placement.axis[1].y = currModelJs["right"]["y"]; -// currModel->placement.axis[1].z = currModelJs["right"]["z"]; -// currModel->placement.axis[2].x = currModelJs["up"]["x"]; -// currModel->placement.axis[2].y = currModelJs["up"]["y"]; -// currModel->placement.axis[2].z = currModelJs["up"]["z"]; -// currModel->placement.scale = currModelJs["scale"]; -// -// // mins and maxs are calculated in world space not local space -// // TODO: mins and maxs are slightly different to what bo2 uses, which results in some wierd culling ingame -// currModelInst->mins.x = currModel->model->mins.x + currModel->placement.origin.x; -// currModelInst->mins.y = currModel->model->mins.y + currModel->placement.origin.y; -// currModelInst->mins.z = currModel->model->mins.z + currModel->placement.origin.z; -// currModelInst->maxs.x = currModel->model->maxs.x + currModel->placement.origin.x; -// currModelInst->maxs.y = currModel->model->maxs.y + currModel->placement.origin.y; -// currModelInst->maxs.z = currModel->model->maxs.z + currModel->placement.origin.z; -// -// currModel->cullDist = currModelJs["cullDist"]; -// currModel->flags = currModelJs["flags"]; -// currModel->primaryLightIndex = (unsigned char)currModelJs["primaryLightIndex"]; -// currModel->reflectionProbeIndex = (unsigned char)currModelJs["reflectionProbeIndex"]; -// -// // unknown use / unused -// currModel->smid = i; -// memset(&currModel->lightingSH, 0, sizeof(GfxLightingSHQuantized)); -// currModel->invScaleSq = 0.0f; -// currModel->lightingHandle = 0; -// currModel->colorsIndex = 0; -// currModel->visibility = 0; -// -// // setting these to NULL makes any static/baked lighting go black when not rendered by real-time lighting or in a shadow -// // TODO: calculate lighting and store it here -// currModel->lmapVertexInfo[0].numLmapVertexColors = 0; -// currModel->lmapVertexInfo[0].lmapVertexColors = NULL; -// currModel->lmapVertexInfo[1].numLmapVertexColors = 0; -// currModel->lmapVertexInfo[1].lmapVertexColors = NULL; -// currModel->lmapVertexInfo[2].numLmapVertexColors = 0; -// currModel->lmapVertexInfo[2].lmapVertexColors = NULL; -// currModel->lmapVertexInfo[3].numLmapVertexColors = 0; -// currModel->lmapVertexInfo[3].lmapVertexColors = NULL; -// } -// */ -// -// // all visdata is alligned by 128 -// gfxWorld->dpvs.smodelVisDataCount = CMUtil::allignBy128(modelCount); -// gfxWorld->dpvs.smodelVisData[0] = new char[modelCount]; -// gfxWorld->dpvs.smodelVisData[1] = new char[modelCount]; -// gfxWorld->dpvs.smodelVisData[2] = new char[modelCount]; -// gfxWorld->dpvs.smodelVisDataCameraSaved = new char[modelCount]; -// gfxWorld->dpvs.smodelCastsShadow = new char[modelCount]; -// for (unsigned int i = 0; i < modelCount; i++) -// { -// if ((gfxWorld->dpvs.smodelDrawInsts[i].flags & SMODEL_FLAG_NO_SHADOW) == 0) -// gfxWorld->dpvs.smodelCastsShadow[i] = 1; -// else -// gfxWorld->dpvs.smodelCastsShadow[i] = 0; -// } -// memset(gfxWorld->dpvs.smodelVisData[0], 0, modelCount); -// memset(gfxWorld->dpvs.smodelVisData[1], 0, modelCount); -// memset(gfxWorld->dpvs.smodelVisData[2], 0, modelCount); -// memset(gfxWorld->dpvs.smodelVisDataCameraSaved, 0, modelCount); -// -// gfxWorld->dpvs.usageCount = 0; -// } -// -// void cleanGfxWorld(GfxWorld* gfxWorld) -// { -// gfxWorld->checksum = 0; -// -// // Remove Coronas -// gfxWorld->coronaCount = 0; -// gfxWorld->coronas = NULL; -// -// // Remove exposure volumes -// gfxWorld->exposureVolumeCount = 0; -// gfxWorld->exposureVolumes = NULL; -// gfxWorld->exposureVolumePlaneCount = 0; -// gfxWorld->exposureVolumePlanes = NULL; -// -// // Remove hero lights -// gfxWorld->heroLightCount = 0; -// gfxWorld->heroLights = NULL; -// gfxWorld->heroLightTreeCount = 0; -// gfxWorld->heroLightTree = NULL; -// -// // remove LUT data -// gfxWorld->lutVolumeCount = 0; -// gfxWorld->lutVolumes = NULL; -// gfxWorld->lutVolumePlaneCount = 0; -// gfxWorld->lutVolumePlanes = NULL; -// -// // remove occluders -// gfxWorld->numOccluders = 0; -// gfxWorld->occluders = NULL; -// -// // remove Siege Skins -// gfxWorld->numSiegeSkinInsts = 0; -// gfxWorld->siegeSkinInsts = NULL; -// -// // remove outdoor bounds -// gfxWorld->numOutdoorBounds = 0; -// gfxWorld->outdoorBounds = NULL; -// -// // remove materials -// gfxWorld->ropeMaterial = NULL; -// gfxWorld->lutMaterial = NULL; -// gfxWorld->waterMaterial = NULL; -// gfxWorld->coronaMaterial = NULL; -// -// // remove shadow maps -// gfxWorld->shadowMapVolumeCount = 0; -// gfxWorld->shadowMapVolumes = NULL; -// gfxWorld->shadowMapVolumePlaneCount = 0; -// gfxWorld->shadowMapVolumePlanes = NULL; -// -// // remove stream info -// gfxWorld->streamInfo.aabbTreeCount = 0; -// gfxWorld->streamInfo.aabbTrees = NULL; -// gfxWorld->streamInfo.leafRefCount = 0; -// gfxWorld->streamInfo.leafRefs = NULL; -// -// // remove sun data -// memset(&gfxWorld->sun, 0, sizeof(sunflare_t)); -// gfxWorld->sun.hasValidData = false; -// -// // Remove Water -// gfxWorld->waterDirection = 0.0f; -// gfxWorld->waterBuffers[0].buffer = NULL; -// gfxWorld->waterBuffers[0].bufferSize = NULL; -// gfxWorld->waterBuffers[1].buffer = NULL; -// gfxWorld->waterBuffers[1].bufferSize = NULL; -// -// // Remove Fog -// gfxWorld->worldFogModifierVolumeCount = 0; -// gfxWorld->worldFogModifierVolumes = NULL; -// gfxWorld->worldFogModifierVolumePlaneCount = 0; -// gfxWorld->worldFogModifierVolumePlanes = NULL; -// gfxWorld->worldFogVolumeCount = 0; -// gfxWorld->worldFogVolumes = NULL; -// gfxWorld->worldFogVolumePlaneCount = 0; -// gfxWorld->worldFogVolumePlanes = NULL; -// -// // materialMemory is unused -// gfxWorld->materialMemoryCount = 0; -// gfxWorld->materialMemory = NULL; -// -// // sunLight is overwritten by the game, just needs to be a valid pointer -// gfxWorld->sunLight = new GfxLight; -// memset(gfxWorld->sunLight, 0, sizeof(GfxLight)); -// } -// -// void overwriteGfxLights(GfxWorld* gfxWorld) -// { -// // there must be 2 or more lights, first is the default light and second is the sun -// gfxWorld->primaryLightCount = 2; -// gfxWorld->sunPrimaryLightIndex = 1; // the sun is always index 1 -// -// gfxWorld->shadowGeom = new GfxShadowGeometry[gfxWorld->primaryLightCount]; -// for (int i = 0; i < gfxWorld->primaryLightCount; i++) -// { -// gfxWorld->shadowGeom[i].smodelCount = 0; -// gfxWorld->shadowGeom[i].surfaceCount = 0; -// gfxWorld->shadowGeom[i].smodelIndex = NULL; -// gfxWorld->shadowGeom[i].sortedSurfIndex = NULL; -// } -// -// gfxWorld->lightRegion = new GfxLightRegion[gfxWorld->primaryLightCount]; -// for (int i = 0; i < gfxWorld->primaryLightCount; i++) -// { -// gfxWorld->lightRegion[i].hullCount = 0; -// gfxWorld->lightRegion[i].hulls = NULL; -// } -// -// int lightEntShadowVisSize = (gfxWorld->primaryLightCount - gfxWorld->sunPrimaryLightIndex - 1) * 8192; -// if (lightEntShadowVisSize != 0) -// { -// gfxWorld->primaryLightEntityShadowVis = new unsigned int[lightEntShadowVisSize]; -// memset(gfxWorld->primaryLightEntityShadowVis, 0, lightEntShadowVisSize * sizeof(unsigned int)); -// } -// else -// { -// gfxWorld->primaryLightEntityShadowVis = NULL; -// } -// } -// -// void overwriteLightGrid(GfxWorld* gfxWorld) -// { -// gfxWorld->lightGrid.mins[0] = 0; -// gfxWorld->lightGrid.mins[1] = 0; -// gfxWorld->lightGrid.mins[2] = 0; -// gfxWorld->lightGrid.maxs[0] = 0; -// gfxWorld->lightGrid.maxs[1] = 0; -// gfxWorld->lightGrid.maxs[2] = 0; -// -// gfxWorld->lightGrid.rowAxis = 0; // default value -// gfxWorld->lightGrid.colAxis = 1; // default value -// gfxWorld->lightGrid.sunPrimaryLightIndex = 1; // the sun is always index 1 -// gfxWorld->lightGrid.offset = 0.0f; -// -// // if rowDataStart's first value is -1, it will not look up any lightmap data -// gfxWorld->lightGrid.rowDataStart = new uint16_t[1]; -// *gfxWorld->lightGrid.rowDataStart = (uint16_t)(-1); -// -// gfxWorld->lightGrid.rawRowDataSize = 0; -// gfxWorld->lightGrid.rawRowData = NULL; -// -// gfxWorld->lightGrid.colorCount = 0; -// gfxWorld->lightGrid.colors = NULL; -// -// gfxWorld->lightGrid.coeffCount = 0; -// gfxWorld->lightGrid.coeffs = NULL; -// -// gfxWorld->lightGrid.entryCount = 0; -// gfxWorld->lightGrid.entries = NULL; -// -// gfxWorld->lightGrid.skyGridVolumeCount = 0; -// gfxWorld->lightGrid.skyGridVolumes = NULL; -// } -// -// void updateGfxCells(GfxWorld* gfxWorld) -// { -// // 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 -// int cellCount = 1; -// -// gfxWorld->cellBitsCount = ((cellCount + 127) >> 3) & 0x1FFFFFF0; -// -// int cellCasterBitsCount = cellCount * ((cellCount + 31) / 32); -// gfxWorld->cellCasterBits = new unsigned int[cellCasterBitsCount]; -// memset(gfxWorld->cellCasterBits, 0x00, cellCasterBitsCount * sizeof(unsigned int)); -// -// gfxWorld->cells = new GfxCell[cellCount]; -// gfxWorld->cells[0].portalCount = 0; -// gfxWorld->cells[0].portals = NULL; -// gfxWorld->cells[0].reflectionProbeCount = 0; -// gfxWorld->cells[0].reflectionProbes = NULL; -// gfxWorld->cells[0].mins.x = gfxWorld->mins.x; -// gfxWorld->cells[0].mins.y = gfxWorld->mins.y; -// gfxWorld->cells[0].mins.z = gfxWorld->mins.z; -// gfxWorld->cells[0].maxs.x = gfxWorld->maxs.x; -// gfxWorld->cells[0].maxs.y = gfxWorld->maxs.y; -// gfxWorld->cells[0].maxs.z = gfxWorld->maxs.z; -// -// // AABB trees are used to detect what should be rendered and what shouldn't -// // Just use the first AABB node to hold all models, no optimisation but all models/surfaces wil lbe drawn -// gfxWorld->cells[0].aabbTreeCount = 1; -// gfxWorld->cells[0].aabbTree = new GfxAabbTree[gfxWorld->cells[0].aabbTreeCount]; -// gfxWorld->cells[0].aabbTree[0].childCount = 0; -// gfxWorld->cells[0].aabbTree[0].childrenOffset = 0; -// gfxWorld->cells[0].aabbTree[0].startSurfIndex = 0; -// gfxWorld->cells[0].aabbTree[0].surfaceCount = gfxWorld->surfaceCount; -// gfxWorld->cells[0].aabbTree[0].smodelIndexCount = gfxWorld->dpvs.smodelCount; -// gfxWorld->cells[0].aabbTree[0].smodelIndexes = new unsigned short[gfxWorld->dpvs.smodelCount]; -// for (unsigned short i = 0; i < gfxWorld->dpvs.smodelCount; i++) -// { -// gfxWorld->cells[0].aabbTree[0].smodelIndexes[i] = i; -// } -// gfxWorld->cells[0].aabbTree[0].mins.x = gfxWorld->mins.x; -// gfxWorld->cells[0].aabbTree[0].mins.y = gfxWorld->mins.y; -// gfxWorld->cells[0].aabbTree[0].mins.z = gfxWorld->mins.z; -// gfxWorld->cells[0].aabbTree[0].maxs.x = gfxWorld->maxs.x; -// gfxWorld->cells[0].aabbTree[0].maxs.y = gfxWorld->maxs.y; -// gfxWorld->cells[0].aabbTree[0].maxs.z = gfxWorld->maxs.z; -// -// gfxWorld->dpvsPlanes.cellCount = cellCount; -// -// int sceneEntCellBitsCount = cellCount * 512; -// gfxWorld->dpvsPlanes.sceneEntCellBits = new unsigned int[sceneEntCellBitsCount]; -// memset(gfxWorld->dpvsPlanes.sceneEntCellBits, 0x00, sceneEntCellBitsCount * sizeof(unsigned int)); -// -// // nodes have the struct mnode_t, and there must be at least 1 node -// // Nodes mnode_t.cellIndex indexes gfxWorld->cells -// // and (mnode_t.cellIndex - (world->dpvsPlanes.cellCount + 1) indexes world->dpvsPlanes.planes -// gfxWorld->nodeCount = 1; -// gfxWorld->planeCount = 0; -// gfxWorld->dpvsPlanes.nodes = new uint16_t[gfxWorld->nodeCount]; -// gfxWorld->dpvsPlanes.nodes[0] = 1; // nodes reference cells by index + 1 -// gfxWorld->dpvsPlanes.planes = NULL; -// } -// -// void updateWorldBounds(GfxWorld* gfxWorld) -// { -// gfxWorld->mins.x = 0.0f; -// gfxWorld->mins.y = 0.0f; -// gfxWorld->mins.z = 0.0f; -// gfxWorld->maxs.x = 0.0f; -// gfxWorld->maxs.y = 0.0f; -// gfxWorld->maxs.z = 0.0f; -// -// 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); -// } -// } -// -// void overwriteModels(GfxWorld* gfxWorld) -// { -// gfxWorld->modelCount = 1; -// gfxWorld->models = new GfxBrushModel[gfxWorld->modelCount]; -// -// // first model is the world model, the world json doesn't include it so its added here -// gfxWorld->models[0].startSurfIndex = 0; -// gfxWorld->models[0].surfaceCount = gfxWorld->surfaceCount; -// gfxWorld->models[0].bounds[0].x = gfxWorld->mins.x; -// gfxWorld->models[0].bounds[0].y = gfxWorld->mins.y; -// gfxWorld->models[0].bounds[0].z = gfxWorld->mins.z; -// gfxWorld->models[0].bounds[1].x = gfxWorld->maxs.x; -// gfxWorld->models[0].bounds[1].y = gfxWorld->maxs.y; -// gfxWorld->models[0].bounds[1].z = gfxWorld->maxs.z; -// memset(&gfxWorld->models[0].writable, 0, sizeof(GfxBrushModelWritable)); -// -// // for (int i = 1; i < gfxWorld->modelCount; i++) -// //{ -// // auto currEntModel = &gfxWorld->models[i]; -// // json currEntModelJs = js["entityModels"][i - 1]; -// // -// // currEntModel->bounds[0].x = currEntModelJs["mins"]["x"]; -// // currEntModel->bounds[0].y = currEntModelJs["mins"]["y"]; -// // currEntModel->bounds[0].z = currEntModelJs["mins"]["z"]; -// // currEntModel->bounds[1].x = currEntModelJs["maxs"]["x"]; -// // currEntModel->bounds[1].y = currEntModelJs["maxs"]["y"]; -// // currEntModel->bounds[1].z = currEntModelJs["maxs"]["z"]; -// // -// // currEntModel->surfaceCount = 0; -// // currEntModel->startSurfIndex = (unsigned int)(-1); -// // memset(&currEntModel->writable, 0, sizeof(GfxBrushModelWritable)); -// // } -// } -// -// void updateSunData(GfxWorld* gfxWorld) -// { -// // default values taken from mp_dig -// gfxWorld->sunParse.fogTransitionTime = 0.001; -// gfxWorld->sunParse.name[0] = 0x00; -// -// gfxWorld->sunParse.initWorldSun->control = 0; -// gfxWorld->sunParse.initWorldSun->exposure = 2.5f; -// gfxWorld->sunParse.initWorldSun->angles.x = -29.0f; -// gfxWorld->sunParse.initWorldSun->angles.y = 254.0f; -// gfxWorld->sunParse.initWorldSun->angles.z = 0.0f; -// gfxWorld->sunParse.initWorldSun->sunCd.x = 1.0f; -// gfxWorld->sunParse.initWorldSun->sunCd.y = 0.89f; -// gfxWorld->sunParse.initWorldSun->sunCd.z = 0.69f; -// gfxWorld->sunParse.initWorldSun->sunCd.w = 13.5f; -// gfxWorld->sunParse.initWorldSun->ambientColor.x = 0.0f; -// gfxWorld->sunParse.initWorldSun->ambientColor.y = 0.0f; -// gfxWorld->sunParse.initWorldSun->ambientColor.z = 0.0f; -// gfxWorld->sunParse.initWorldSun->ambientColor.w = 0.0f; -// gfxWorld->sunParse.initWorldSun->skyColor.x = 0.0f; -// gfxWorld->sunParse.initWorldSun->skyColor.y = 0.0f; -// gfxWorld->sunParse.initWorldSun->skyColor.z = 0.0f; -// gfxWorld->sunParse.initWorldSun->skyColor.w = 0.0f; -// gfxWorld->sunParse.initWorldSun->sunCs.x = 0.0f; -// gfxWorld->sunParse.initWorldSun->sunCs.y = 0.0f; -// gfxWorld->sunParse.initWorldSun->sunCs.z = 0.0f; -// gfxWorld->sunParse.initWorldSun->sunCs.w = 0.0f; -// -// gfxWorld->sunParse.initWorldFog->baseDist = 150.0f; -// gfxWorld->sunParse.initWorldFog->baseHeight = -100.0f; -// gfxWorld->sunParse.initWorldFog->fogColor.x = 2.35f; -// gfxWorld->sunParse.initWorldFog->fogColor.y = 3.10f; -// gfxWorld->sunParse.initWorldFog->fogColor.z = 3.84f; -// gfxWorld->sunParse.initWorldFog->fogOpacity = 0.52f; -// gfxWorld->sunParse.initWorldFog->halfDist = 4450.f; -// gfxWorld->sunParse.initWorldFog->halfHeight = 2000.f; -// gfxWorld->sunParse.initWorldFog->sunFogColor.x = 5.27f; -// gfxWorld->sunParse.initWorldFog->sunFogColor.y = 4.73f; -// gfxWorld->sunParse.initWorldFog->sunFogColor.z = 3.88f; -// gfxWorld->sunParse.initWorldFog->sunFogInner = 0.0f; -// gfxWorld->sunParse.initWorldFog->sunFogOpacity = 0.67f; -// gfxWorld->sunParse.initWorldFog->sunFogOuter = 80.84f; -// gfxWorld->sunParse.initWorldFog->sunFogPitch = -29.0f; -// gfxWorld->sunParse.initWorldFog->sunFogYaw = 254.0f; -// } -// -// void updateReflectionProbeData(GfxWorld* gfxWorld) -// { -// gfxWorld->draw.reflectionProbeCount = 1; -// -// gfxWorld->draw.reflectionProbeTextures = new GfxTexture[gfxWorld->draw.reflectionProbeCount]; -// memset(gfxWorld->draw.reflectionProbeTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.reflectionProbeCount); -// -// gfxWorld->draw.reflectionProbes = new GfxReflectionProbe[gfxWorld->draw.reflectionProbeCount]; -// -// // default values taken from mp_dig -// gfxWorld->draw.reflectionProbes[0].mipLodBias = -8.0; -// -// gfxWorld->draw.reflectionProbes[0].origin.x = 0.0f; -// gfxWorld->draw.reflectionProbes[0].origin.y = 0.0f; -// gfxWorld->draw.reflectionProbes[0].origin.z = 0.0f; -// -// gfxWorld->draw.reflectionProbes[0].lightingSH.V0.x = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V0.y = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V0.z = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V0.w = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V1.x = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V1.y = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V1.z = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V1.w = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V2.x = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V2.y = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V2.z = 0.0f; -// gfxWorld->draw.reflectionProbes[0].lightingSH.V2.w = 0.0f; -// -// gfxWorld->draw.reflectionProbes[0].probeVolumeCount = 0; -// gfxWorld->draw.reflectionProbes[0].probeVolumes = NULL; -// -// std::string probeImageName = "*reflection_probe0"; -// auto probeImageAsset = m_context.LoadDependency(probeImageName); -// if (probeImageAsset == NULL) -// { -// printf("ERROR! unable to find image %s!\n", probeImageName.c_str()); -// hasLinkFailed = true; -// return; -// } -// gfxWorld->draw.reflectionProbes[0].reflectionImage = probeImageAsset->Asset(); -// } -// -// void overwriteLightmapData(GfxWorld* gfxWorld) -// { -// gfxWorld->draw.lightmapCount = 1; -// -// gfxWorld->draw.lightmapPrimaryTextures = new GfxTexture[gfxWorld->draw.lightmapCount]; -// gfxWorld->draw.lightmapSecondaryTextures = new GfxTexture[gfxWorld->draw.lightmapCount]; -// gfxWorld->draw.lightmaps = new GfxLightmapArray[gfxWorld->draw.lightmapCount]; -// -// // always set to 0 -// memset(gfxWorld->draw.lightmapPrimaryTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.lightmapCount); -// memset(gfxWorld->draw.lightmapSecondaryTextures, 0, sizeof(GfxTexture) * gfxWorld->draw.lightmapCount); -// -// std::string secondaryTexture = "*lightmap0_secondary"; -// auto secondaryTextureAsset = m_context.LoadDependency(secondaryTexture); -// if (secondaryTextureAsset == NULL) -// { -// printf("ERROR! unable to find lightmap image %s!\n", secondaryTexture.c_str()); -// hasLinkFailed = true; -// return; -// } -// gfxWorld->draw.lightmaps[0].primary = NULL; // always NULL -// gfxWorld->draw.lightmaps[0].secondary = secondaryTextureAsset->Asset(); -// } -// -// void overwriteSkyBox(GfxWorld* gfxWorld) -// { -// const char* skyBoxName = "skybox_mp_dig"; -// gfxWorld->skyBoxModel = skyBoxName; -// -// if (m_context.LoadDependency(skyBoxName) == NULL) -// { -// printf("WARN: Unable to find the skybox model %s\n", skyBoxName); -// } -// -// // default skybox values from mp_dig -// gfxWorld->skyDynIntensity.angle0 = 0.0f; -// gfxWorld->skyDynIntensity.angle1 = 0.0f; -// gfxWorld->skyDynIntensity.factor0 = 1.0f; -// gfxWorld->skyDynIntensity.factor1 = 1.0f; -// } -// -// void updateDynEntData(GfxWorld* gfxWorld) -// { -// gfxWorld->dpvsDyn.dynEntClientCount[0] = DYN_ENT_COUNT + 256; -// gfxWorld->dpvsDyn.dynEntClientCount[1] = 0; -// gfxWorld->dpvsDyn.dynEntClientWordCount[0] = 1; // needs to be at least 1 -// gfxWorld->dpvsDyn.dynEntClientWordCount[1] = 0; -// gfxWorld->dpvsDyn.usageCount = 0; -// -// int dynEntCellBitsSize = gfxWorld->dpvsDyn.dynEntClientWordCount[0] * gfxWorld->dpvsPlanes.cellCount; -// gfxWorld->dpvsDyn.dynEntCellBits[0] = new unsigned int[dynEntCellBitsSize]; -// gfxWorld->dpvsDyn.dynEntCellBits[1] = NULL; -// memset(gfxWorld->dpvsDyn.dynEntCellBits[0], 0, sizeof(unsigned int) * dynEntCellBitsSize); -// -// int dynEntVisData0Size = gfxWorld->dpvsDyn.dynEntClientWordCount[0] * 32; -// gfxWorld->dpvsDyn.dynEntVisData[0][0] = new char[dynEntVisData0Size]; -// gfxWorld->dpvsDyn.dynEntVisData[0][1] = new char[dynEntVisData0Size]; -// gfxWorld->dpvsDyn.dynEntVisData[0][2] = new char[dynEntVisData0Size]; -// gfxWorld->dpvsDyn.dynEntVisData[1][0] = NULL; -// gfxWorld->dpvsDyn.dynEntVisData[1][1] = NULL; -// gfxWorld->dpvsDyn.dynEntVisData[1][2] = NULL; -// memset(gfxWorld->dpvsDyn.dynEntVisData[0][0], 0, dynEntVisData0Size); -// memset(gfxWorld->dpvsDyn.dynEntVisData[0][1], 0, dynEntVisData0Size); -// memset(gfxWorld->dpvsDyn.dynEntVisData[0][2], 0, dynEntVisData0Size); -// -// int dynEntShadowVisCount = gfxWorld->dpvsDyn.dynEntClientCount[0] * (gfxWorld->primaryLightCount - gfxWorld->sunPrimaryLightIndex - 1); -// gfxWorld->primaryLightDynEntShadowVis[0] = new unsigned int[dynEntShadowVisCount]; -// gfxWorld->primaryLightDynEntShadowVis[1] = NULL; -// memset(gfxWorld->primaryLightDynEntShadowVis[0], 0, sizeof(unsigned int) * dynEntShadowVisCount); -// -// gfxWorld->sceneDynModel = new GfxSceneDynModel[gfxWorld->dpvsDyn.dynEntClientCount[0]]; -// gfxWorld->sceneDynBrush = NULL; -// memset(gfxWorld->sceneDynModel, 0, sizeof(GfxSceneDynModel) * gfxWorld->dpvsDyn.dynEntClientCount[0]); -// } -// -// void updateOutdoors(GfxWorld* gfxWorld) -// { -// float xRecip = 1.0f / (gfxWorld->maxs.x - gfxWorld->mins.x); -// float xScale = -(xRecip * gfxWorld->mins.x); -// -// float yRecip = 1.0f / (gfxWorld->maxs.y - gfxWorld->mins.y); -// float yScale = -(yRecip * gfxWorld->mins.y); -// -// float zRecip = 1.0f / (gfxWorld->maxs.z - gfxWorld->mins.z); -// float zScale = -(zRecip * gfxWorld->mins.z); -// -// memset(gfxWorld->outdoorLookupMatrix, 0, sizeof(gfxWorld->outdoorLookupMatrix)); -// -// gfxWorld->outdoorLookupMatrix[0].x = xRecip; -// gfxWorld->outdoorLookupMatrix[1].y = yRecip; -// gfxWorld->outdoorLookupMatrix[2].z = zRecip; -// gfxWorld->outdoorLookupMatrix[3].x = xScale; -// gfxWorld->outdoorLookupMatrix[3].y = yScale; -// gfxWorld->outdoorLookupMatrix[3].z = zScale; -// gfxWorld->outdoorLookupMatrix[3].w = 1.0f; -// -// std::string outdoorImageName = std::string("$outdoor"); -// auto outdoorImageAsset = m_context.LoadDependency(outdoorImageName); -// if (outdoorImageAsset == NULL) -// { -// printf("ERROR! unable to find image $outdoor, this will crash your game!\n"); -// hasLinkFailed = true; -// return; -// } -// gfxWorld->outdoorImage = outdoorImageAsset->Asset(); -// } -// -// void createGfxWorld(customMapInfo* projInfo) -// { -// GfxWorld* gfxWorld = new GfxWorld; -// gfxWorld->baseName = _strdup(projInfo->name.c_str()); -// gfxWorld->name = _strdup(projInfo->bspName.c_str()); -// -// // Default values taken from mp_dig -// gfxWorld->lightingFlags = 0; -// gfxWorld->lightingQuality = 4096; -// -// cleanGfxWorld(gfxWorld); -// -// overwriteMapSurfaces(projInfo, gfxWorld); -// -// overwriteMapSModels(gfxWorld); -// -// overwriteLightmapData(gfxWorld); -// -// overwriteSkyBox(gfxWorld); -// -// updateReflectionProbeData(gfxWorld); -// -// // world bounds are based on surface mins/maxs -// // Other update functions depend on the bounds being set first -// updateWorldBounds(gfxWorld); -// -// updateOutdoors(gfxWorld); -// -// // gfx cells depend on surface/smodel count -// updateGfxCells(gfxWorld); -// -// overwriteLightGrid(gfxWorld); -// -// overwriteGfxLights(gfxWorld); -// -// overwriteModels(gfxWorld); -// -// updateSunData(gfxWorld); -// -// updateDynEntData(gfxWorld); -// -// m_context.AddAsset(gfxWorld->name, gfxWorld); -// } -// -// void aabbCalcOriginAndHalfSize(vec3_t* mins, vec3_t* maxs, vec3_t* out_origin, vec3_t* out_halfSize) -// { -// // 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; -// out_origin->x = temp.x * 0.5f; -// out_origin->y = temp.y * 0.5f; -// out_origin->z = temp.z * 0.5f; -// -// // Half-size is half the difference: (max - min) / 2 -// temp.x = maxs->x - mins->x; -// temp.y = maxs->y - mins->y; -// temp.z = maxs->z - mins->z; -// out_halfSize->x = temp.x * 0.5f; -// out_halfSize->y = temp.y * 0.5f; -// out_halfSize->z = temp.z * 0.5f; -// } -// -// bool CM_IsEdgeWalkable(clipMap_t* clipMap, int triIndex, int edgeIndex) -// { -// -// unsigned __int8 edgeBitMask = 1 << ((triIndex + edgeIndex + 2 * triIndex) & 7); -// -// return (edgeBitMask & clipMap->triEdgeIsWalkable[(triIndex + edgeIndex + 2 * triIndex) >> 3]) != 0; -// } -// -// 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)); -// } -// -// -// -// void traverseBSPTreeForCounts(BSPTree* node, int* numPlanes, int* numNodes, int* numLeafs, int* numAABBTrees, int* maxObjsPerLeaf) -// { -// if (node->isLeaf) -// { -// (*numLeafs)++; -// // there won't be an AABB tree when objectList is empty -// if (node->u.leaf->getObjectCount() > 0) -// { -// *numAABBTrees += node->u.leaf->getObjectCount() + 1; -// -// if (node->u.leaf->getObjectCount() > *maxObjsPerLeaf) -// *maxObjsPerLeaf = node->u.leaf->getObjectCount(); -// } -// } -// else -// { -// (*numPlanes)++; -// (*numNodes)++; -// traverseBSPTreeForCounts(node->u.node->front, numPlanes, numNodes, numLeafs, numAABBTrees, maxObjsPerLeaf); -// traverseBSPTreeForCounts(node->u.node->back, numPlanes, numNodes, numLeafs, numAABBTrees, maxObjsPerLeaf); -// } -// } -// -// vec3_t normalX = {1.0f, 0.0f, 0.0f}; -// vec3_t normalY = {0.0f, 1.0f, 0.0f}; -// vec3_t normalZ = {0.0f, 0.0f, 1.0f}; -// -// int currPlaneCount = 0; -// int currNodeCount = 0; -// int currLeafCount = 0; -// int currAABBCount = 0; -// -// int addAABBTreeFromLeaf(BSPTree* node, clipMap_t* clipMap) -// { -// _ASSERT(node->isLeaf); -// -// int objectCount = node->u.leaf->getObjectCount(); -// int firstAABBIndex = currAABBCount; -// currAABBCount += objectCount + 1; -// -// // calculate root AABB node mins and maxs -// // cannot convert mins and maxs coord to BO2 directly as this will result in incorrect mins and maxs -// // so we have to recompute every min and max, not hard just tedious -// int firstPartitionIndex = node->u.leaf->getObject(0)->partitionIndex; -// auto firstPartition = &clipMap->partitions[firstPartitionIndex]; -// uint16_t* firstTri = clipMap->triIndices[firstPartition->firstTri]; -// vec3_t* firstVert = &clipMap->verts[firstTri[0]]; -// vec3_t aabbMins; -// vec3_t aabbMaxs; -// aabbMins.x = firstVert->x; -// aabbMins.y = firstVert->y; -// aabbMins.z = firstVert->z; -// aabbMaxs.x = firstVert->x; -// aabbMaxs.y = firstVert->y; -// aabbMaxs.z = firstVert->z; -// for (int i = 0; i < objectCount; i++) -// { -// int currPartitionIndex = node->u.leaf->getObject(i)->partitionIndex; -// auto currPartition = &clipMap->partitions[currPartitionIndex]; -// -// 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 = clipMap->verts[vertIndex]; -// CMUtil::calcNewBoundsWithPoint(&vertCoord, &aabbMins, &aabbMaxs); -// } -// } -// } -// // create root AABB node -// CollisionAabbTree* rootAABB = &clipMap->aabbTrees[firstAABBIndex]; -// aabbCalcOriginAndHalfSize(&aabbMins, &aabbMaxs, &rootAABB->origin, &rootAABB->halfSize); -// rootAABB->materialIndex = 0; -// rootAABB->childCount = objectCount; -// rootAABB->u.firstChildIndex = firstAABBIndex + 1; -// -// // populate child AABB nodes -// for (int i = 0; i < objectCount; i++) -// { -// CollisionAabbTree* currAabbTree = &clipMap->aabbTrees[rootAABB->u.firstChildIndex + i]; -// int currPartitionIndex = node->u.leaf->getObject(i)->partitionIndex; -// -// currAabbTree->materialIndex = 0; -// currAabbTree->childCount = 0; -// currAabbTree->u.partitionIndex = currPartitionIndex; -// -// // calculate partition origin and half size -// CollisionPartition* aabbPartition = &clipMap->partitions[currPartitionIndex]; -// uint16_t firstUind = clipMap->info.uinds[aabbPartition->fuind]; -// vec3_t* firstVertex = &clipMap->verts[firstUind]; -// vec3_t mins; -// vec3_t maxs; -// mins.x = firstVertex->x; -// mins.y = firstVertex->y; -// mins.z = firstVertex->z; -// maxs.x = firstVertex->x; -// maxs.y = firstVertex->y; -// maxs.z = firstVertex->z; -// for (int i = 1; i < aabbPartition->nuinds; i++) -// { -// uint16_t currUind = clipMap->info.uinds[aabbPartition->fuind + i]; -// vec3_t* currVertex = &clipMap->verts[currUind]; -// -// CMUtil::calcNewBoundsWithPoint(currVertex, &mins, &maxs); -// } -// -// aabbCalcOriginAndHalfSize(&mins, &maxs, &currAabbTree->origin, &currAabbTree->halfSize); -// -// } -// -// return firstAABBIndex; -// } -// -// // returns the index corresponding to the BSPTree* node parsed -// int16_t populateBSPTree_r(clipMap_t* clipMap, BSPTree* node) -// { -// new cplane_s; -// new cNode_t; -// new cLeaf_s; -// new CollisionAabbTree; -// -// if (node->isLeaf) -// { -// int currLeafIndex = currLeafCount; -// currLeafCount++; -// cLeaf_s* currLeaf = &clipMap->leafs[currLeafIndex]; -// -// 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 -// -// // unused when leafBrushNode == 0 -// currLeaf->mins.x = 0.0f; -// currLeaf->mins.y = 0.0f; -// currLeaf->mins.z = 0.0f; -// currLeaf->maxs.x = 0.0f; -// currLeaf->maxs.y = 0.0f; -// currLeaf->maxs.z = 0.0f; -// currLeaf->leafBrushNode = 0; -// -// if (node->u.leaf->getObjectCount() > 0) -// { -// currLeaf->firstCollAabbIndex = addAABBTreeFromLeaf(node, clipMap); -// currLeaf->collAabbCount = 1; -// } -// else -// { -// currLeaf->firstCollAabbIndex = 0; -// currLeaf->collAabbCount = 0; -// } -// -// return -1 - currLeafIndex; -// } -// else -// { -// cplane_s* currPlane = &clipMap->info.planes[currPlaneCount]; -// currPlaneCount++; -// -// if (node->u.node->axis == AXIS_X) -// { -// // X is unchanged when going from OGL x -> BO2 x -// currPlane->normal = normalX; -// -// // converting OGL -> BO2 X coords doesn't change the x coords at all, so -// // the dist stays the same -// currPlane->dist = node->u.node->distance; -// } -// else -// { -// // converting OGL -> BO2 Z coords negates the z coords and sets it to the y coord. -// // convert the z normal to the y normal, but don't negate it. Negative normals don't do -// // what is expected when the game uses them -// _ASSERT(node->u.node->axis == AXIS_Z); -// currPlane->normal = normalY; -// -// // converting OGL -> BO2 Z coords negates the z coords and sets it to the y coord. -// // just negate it here as it is just the distance from the orgin along the axis -// currPlane->dist = -node->u.node->distance; -// } -// -// bool foundType = false; -// if (currPlane->normal.x == 1.0f) -// { -// _ASSERT(!foundType); -// foundType = true; -// currPlane->type = 0; -// } -// else if (currPlane->normal.y == 1.0f) -// { -// _ASSERT(!foundType); -// foundType = true; -// currPlane->type = 1; -// } -// else if (currPlane->normal.z == 1.0f) -// { -// _ASSERT(!foundType); -// foundType = true; -// currPlane->type = 2; -// } -// else -// _ASSERT(foundType); -// -// currPlane->signbits = 0; -// if (currPlane->normal.x < 0.0f) -// currPlane->signbits |= 1; -// if (currPlane->normal.y < 0.0f) -// currPlane->signbits |= 2; -// if (currPlane->normal.z < 0.0f) -// currPlane->signbits |= 4; -// -// currPlane->pad[0] = 0; -// currPlane->pad[1] = 0; -// -// int currNodeIndex = currNodeCount; -// currNodeCount++; -// cNode_t* currNode = &clipMap->nodes[currNodeIndex]; -// -// currNode->plane = currPlane; -// // Reason for the front and back flip (due to the hacky nature of making the mins and maxs work (see createClipMap)): -// // after converting between OGL and BO2 coords and when and updating the normal from Z -> Y, -// // the normal vector flips and objects behind the plane are now in front, and vise versa -// // so the back node now represents the front, and the front node represents the back. -// // Do the OGL -> Bo2 coord change on paper and it will make sense -// if (currPlane->type == 1) -// { -// currNode->children[1] = populateBSPTree_r(clipMap, node->u.node->front); -// currNode->children[0] = populateBSPTree_r(clipMap, node->u.node->back); -// } -// else -// { -// currNode->children[0] = populateBSPTree_r(clipMap, node->u.node->front); -// currNode->children[1] = populateBSPTree_r(clipMap, node->u.node->back); -// } -// -// return currNodeIndex; -// } -// } -// -// void populateBSPTree(clipMap_t* clipMap, BSPTree* tree) -// { -// int numPlanes = 0; -// int numNodes = 0; -// int numLeafs = 0; -// int numAABBTrees = 0; -// int maxObjsPerLeaf = 0; -// -// traverseBSPTreeForCounts(tree, &numPlanes, &numNodes, &numLeafs, &numAABBTrees, &maxObjsPerLeaf); -// -// printf("Max Objects per leaf: %i\n", maxObjsPerLeaf); -// -// clipMap->info.planeCount = numPlanes; -// clipMap->info.planes = new cplane_s[clipMap->info.planeCount]; -// clipMap->numNodes = numNodes; -// clipMap->nodes = new cNode_t[clipMap->numNodes]; -// // aabb trees: each leaf will have their own AABB tree of the objects within it, and the root aabb node will be the parent of every other aabb node. -// // therefore, each aabb tree will be of size (numObjects + 1) as the tree needs a root aabb node to reference it's children. -// clipMap->aabbTreeCount = numAABBTrees; -// clipMap->aabbTrees = new CollisionAabbTree[clipMap->aabbTreeCount]; -// -// currPlaneCount = 0; -// currNodeCount = 0; -// currAABBCount = 0; -// -// // first leaf is always empty -// clipMap->numLeafs = numLeafs + 1; -// clipMap->leafs = new cLeaf_s[clipMap->numLeafs]; -// memset(&clipMap->leafs[0], 0, sizeof(cLeaf_s)); -// currLeafCount = 1; -// -// populateBSPTree_r(clipMap, tree); -// -// _ASSERT(clipMap->info.planeCount == currPlaneCount); -// _ASSERT(clipMap->numNodes == currNodeCount); -// _ASSERT(clipMap->numLeafs == currLeafCount); -// _ASSERT(clipMap->aabbTreeCount == currAABBCount); -// } -// -// void createClipMap(customMapInfo* projInfo) -// { -// clipMap_t* clipMap = new clipMap_t; -// -// clipMap->name = _strdup(projInfo->bspName.c_str()); -// -// std::string mapEntsName = projInfo->bspName.c_str(); -// auto mapEntsAsset = m_context.LoadDependency(mapEntsName); -// _ASSERT(mapEntsAsset != NULL); -// clipMap->mapEnts = mapEntsAsset->Asset(); -// -// clipMap->pInfo = NULL; -// -// clipMap->box_model.mins.x = 0.0f; -// clipMap->box_model.mins.y = 0.0f; -// clipMap->box_model.mins.z = 0.0f; -// clipMap->box_model.maxs.x = 0.0f; -// clipMap->box_model.maxs.y = 0.0f; -// clipMap->box_model.maxs.z = 0.0f; -// clipMap->box_model.radius = 0.0f; -// clipMap->box_model.info = NULL; -// clipMap->box_model.leaf.mins.x = 3.4028235e38; -// clipMap->box_model.leaf.mins.y = 3.4028235e38; -// clipMap->box_model.leaf.mins.z = 3.4028235e38; -// clipMap->box_model.leaf.maxs.x = -3.4028235e38; // for some reason the maxs are negative, and mins are positive -// clipMap->box_model.leaf.maxs.y = -3.4028235e38; -// clipMap->box_model.leaf.maxs.z = -3.4028235e38; -// clipMap->box_model.leaf.brushContents = -1; -// clipMap->box_model.leaf.terrainContents = 0; -// clipMap->box_model.leaf.cluster = 0; -// clipMap->box_model.leaf.collAabbCount = 0; -// clipMap->box_model.leaf.firstCollAabbIndex = 0; -// clipMap->box_model.leaf.leafBrushNode = 0; -// -// clipMap->box_brush = new cbrush_t; -// clipMap->box_brush->axial_sflags[0][0] = -1; -// clipMap->box_brush->axial_sflags[0][1] = -1; -// clipMap->box_brush->axial_sflags[0][2] = -1; -// clipMap->box_brush->axial_sflags[1][0] = -1; -// clipMap->box_brush->axial_sflags[1][1] = -1; -// clipMap->box_brush->axial_sflags[1][2] = -1; -// clipMap->box_brush->axial_cflags[0][0] = -1; -// clipMap->box_brush->axial_cflags[0][1] = -1; -// clipMap->box_brush->axial_cflags[0][2] = -1; -// clipMap->box_brush->axial_cflags[1][0] = -1; -// clipMap->box_brush->axial_cflags[1][1] = -1; -// clipMap->box_brush->axial_cflags[1][2] = -1; -// clipMap->box_brush->contents = -1; -// clipMap->box_brush->mins.x = 0.0f; -// clipMap->box_brush->mins.y = 0.0f; -// clipMap->box_brush->mins.z = 0.0f; -// clipMap->box_brush->maxs.x = 0.0f; -// clipMap->box_brush->maxs.y = 0.0f; -// clipMap->box_brush->maxs.z = 0.0f; -// clipMap->box_brush->numsides = 0; -// clipMap->box_brush->numverts = 0; -// clipMap->box_brush->sides = NULL; -// clipMap->box_brush->verts = NULL; -// -// clipMap->numClusters = 1; -// clipMap->vised = 0; -// clipMap->clusterBytes = ((clipMap->numClusters + 63) >> 3) & 0xFFFFFFF8; -// clipMap->visibility = new char[clipMap->clusterBytes]; -// memset(clipMap->visibility, 0xFF, clipMap->clusterBytes); -// -// clipMap->isInUse = true; -// clipMap->checksum = 0; -// -// clipMap->num_constraints = 0; -// clipMap->constraints = NULL; -// clipMap->max_ropes = 32; -// clipMap->ropes = new rope_t[clipMap->max_ropes]; -// memset(clipMap->ropes, 0, sizeof(rope_t) * clipMap->max_ropes); -// -// clipMap->info.numBrushSides = 0; -// clipMap->info.brushsides = NULL; -// clipMap->info.leafbrushNodesCount = 0; -// clipMap->info.leafbrushNodes = NULL; -// clipMap->info.numLeafBrushes = 0; -// clipMap->info.leafbrushes = NULL; -// clipMap->info.numBrushVerts = 0; -// clipMap->info.brushVerts = NULL; -// clipMap->info.numBrushes = NULL; -// clipMap->info.brushes = NULL; -// clipMap->info.brushBounds = NULL; -// clipMap->info.brushContents = NULL; -// -// clipMap->originalDynEntCount = DYN_ENT_COUNT; -// clipMap->dynEntCount[0] = clipMap->originalDynEntCount + 256; -// clipMap->dynEntCount[1] = 0; -// clipMap->dynEntCount[2] = 0; -// clipMap->dynEntCount[3] = 0; -// -// // assume that there are 0 dyn ents from here on -// clipMap->dynEntClientList[0] = new DynEntityClient[clipMap->dynEntCount[0]]; -// clipMap->dynEntClientList[1] = NULL; -// memset(clipMap->dynEntClientList[0], 0, sizeof(DynEntityClient) * clipMap->dynEntCount[0]); -// -// clipMap->dynEntServerList[0] = NULL; -// clipMap->dynEntServerList[1] = NULL; -// -// clipMap->dynEntCollList[0] = new DynEntityColl[clipMap->dynEntCount[0]]; -// clipMap->dynEntCollList[1] = NULL; -// clipMap->dynEntCollList[2] = NULL; -// clipMap->dynEntCollList[3] = NULL; -// memset(clipMap->dynEntCollList[0], 0, sizeof(DynEntityColl) * clipMap->dynEntCount[0]); -// -// clipMap->dynEntPoseList[0] = new DynEntityPose[clipMap->dynEntCount[0]]; -// clipMap->dynEntPoseList[1] = NULL; -// memset(clipMap->dynEntPoseList[0], 0, sizeof(DynEntityPose) * clipMap->dynEntCount[0]); -// -// clipMap->dynEntDefList[0] = new DynEntityDef[clipMap->dynEntCount[0]]; -// clipMap->dynEntDefList[1] = NULL; -// memset(clipMap->dynEntDefList[0], 0, sizeof(DynEntityDef) * clipMap->dynEntCount[0]); -// for (int i = 0; i < clipMap->dynEntCount[0]; i++) -// { -// DynEntityDef* currDef = &clipMap->dynEntDefList[0][i]; -// currDef->physConstraints[0] = 0x1FF; -// currDef->physConstraints[1] = 0x1FF; -// currDef->physConstraints[2] = 0x1FF; -// currDef->physConstraints[3] = 0x1FF; -// } -// -// clipMap->numSubModels = 1; -// clipMap->cmodels = new cmodel_t[clipMap->numSubModels]; -// clipMap->cmodels[0].leaf.firstCollAabbIndex = 0; -// clipMap->cmodels[0].leaf.collAabbCount = 0; -// clipMap->cmodels[0].leaf.brushContents = 0; -// clipMap->cmodels[0].leaf.terrainContents = WORLD_TERRAIN_CONTENTS; -// clipMap->cmodels[0].leaf.mins.x = 0.0f; -// clipMap->cmodels[0].leaf.mins.y = 0.0f; -// clipMap->cmodels[0].leaf.mins.z = 0.0f; -// clipMap->cmodels[0].leaf.maxs.x = 0.0f; -// clipMap->cmodels[0].leaf.maxs.y = 0.0f; -// clipMap->cmodels[0].leaf.maxs.z = 0.0f; -// clipMap->cmodels[0].leaf.leafBrushNode = 0; -// clipMap->cmodels[0].leaf.cluster = 0; -// clipMap->cmodels[0].info = NULL; -// -// auto gfxWorldAsset = m_context.LoadDependency(projInfo->bspName); -// _ASSERT(gfxWorldAsset != NULL); -// GfxWorld* gfxWorld = gfxWorldAsset->Asset(); -// -// clipMap->cmodels[0].mins.x = gfxWorld->models[0].bounds[0].x; -// clipMap->cmodels[0].mins.y = gfxWorld->models[0].bounds[0].y; -// clipMap->cmodels[0].mins.z = gfxWorld->models[0].bounds[0].z; -// clipMap->cmodels[0].maxs.x = gfxWorld->models[0].bounds[1].x; -// clipMap->cmodels[0].maxs.y = gfxWorld->models[0].bounds[1].y; -// clipMap->cmodels[0].maxs.z = gfxWorld->models[0].bounds[1].z; -// clipMap->cmodels[0].radius = distBetweenPoints(clipMap->cmodels[0].mins, clipMap->cmodels[0].maxs) / 2; -// -// clipMap->numStaticModels = 0; -// clipMap->staticModelList = NULL; -// -// clipMap->info.numMaterials = 1; -// clipMap->info.materials = new ClipMaterial[clipMap->info.numMaterials]; -// clipMap->info.materials[0].name = _strdup(defaultMaterialName.c_str()); -// clipMap->info.materials[0].contentFlags = MATERIAL_CONTENT_FLAGS; -// clipMap->info.materials[0].surfaceFlags = MATERIAL_SURFACE_FLAGS; -// -// int collisionVertexCount = projInfo->gfxInfo.vertexCount; -// vec3_t* convertedCollisionVerts = new vec3_t[collisionVertexCount]; -// for (int i = 0; i < collisionVertexCount; i++) -// { -// convertedCollisionVerts[i] = CMUtil::convertToBO2Coords(projInfo->gfxInfo.vertices[i].pos); -// } -// clipMap->vertCount = collisionVertexCount; -// clipMap->verts = convertedCollisionVerts; -// -// // 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 -// const int maxVerts = UINT16_MAX - 1; -// if (collisionVertexCount > maxVerts) -// { -// printf("ERROR: collision vertex count %i exceeds the maximum number: %i!\n", collisionVertexCount, maxVerts); -// hasLinkFailed = true; -// return; -// } -// -// clipMap->triCount = projInfo->gfxInfo.indexCount / 3; -// clipMap->triIndices = (uint16_t(*)[3])(new uint16_t[projInfo->gfxInfo.indexCount]); // 3 indexes per tri -// int triIndex = 0; -// for (int i = 0; i < projInfo->gfxInfo.indexCount; i += 3) -// { -// clipMap->triIndices[triIndex][2] = projInfo->gfxInfo.indices[i + 0]; -// clipMap->triIndices[triIndex][1] = projInfo->gfxInfo.indices[i + 1]; -// clipMap->triIndices[triIndex][0] = projInfo->gfxInfo.indices[i + 2]; -// triIndex++; -// } -// -// int partitionCount = 0; -// for (int i = 0; i < projInfo->gfxInfo.surfaceCount; i++) -// { -// int triCount = projInfo->gfxInfo.surfaces[i].triCount; -// int subdividedSize = triCount / 16; // integer division used -// partitionCount += subdividedSize; -// -// // add another partition if the triangle count doesn't add up to a multiple of 16 -// if (triCount % 16 != 0) -// partitionCount++; -// } -// clipMap->partitionCount = partitionCount; -// clipMap->partitions = new CollisionPartition[clipMap->partitionCount]; -// -// int partitionIndex = 0; -// for (int i = 0; i < projInfo->gfxInfo.surfaceCount; i++) -// { -// int triCount = projInfo->gfxInfo.surfaces[i].triCount; -// int firstIndex = projInfo->gfxInfo.surfaces[i].firstIndex_Index; -// int firstVertex = projInfo->gfxInfo.surfaces[i].firstVertexIndex; -// int firstTri = firstIndex / 3; -// -// //////////////////////////////////////////////////////////////////////////////////////////////////// -// // TODO: fixup tri indices does not fully work correctly, and leaves some gaps or removes faces. -// // NEED TO FIX -// // fixup the tri indices. -// // GfxWorld calculates what vertex to render through vertexBuffer[indexBuffer[index] + firstVertex] -// // while clipmap caclulates it through vertexBuffer[indexBuffer[index]] -// // this loop fixes the index buffer by adding the firstVertex to each index -// for (int k = 0; k < triCount; k++) -// { -// clipMap->triIndices[k + firstTri][0] += firstVertex; -// clipMap->triIndices[k + firstTri][1] += firstVertex; -// clipMap->triIndices[k + firstTri][2] += firstVertex; -// } -// -// while (triCount > 0) -// { -// if (triCount > 16) -// clipMap->partitions[partitionIndex].triCount = 16; -// else -// clipMap->partitions[partitionIndex].triCount = triCount; -// -// clipMap->partitions[partitionIndex].firstTri = firstTri; -// -// triCount -= 16; -// firstIndex += 16 * 3; -// partitionIndex++; -// } -// } -// -// int uindCount = 0; -// clipMap->info.uinds = new uint16_t[3 * 16 * clipMap->partitionCount]; // 3 vertexes per tri, and max 16 tris per partition -// for (int i = 0; i < clipMap->partitionCount; i++) -// { -// auto currPartition = &clipMap->partitions[i]; -// -// int uniqueVertBufferCount = 0; -// uint16_t uniqueVertBuffer[3 * 16]; // 3 vertexes per tri, and max 16 tris -// -// for (int k = 0; k < currPartition->triCount; k++) -// { -// uint16_t* tri = clipMap->triIndices[currPartition->firstTri + k]; -// for (int l = 0; l < 3; l++) -// { -// bool isVertexIndexUnique = true; -// uint16_t vertIndex = tri[l]; -// -// for (int m = 0; m < uniqueVertBufferCount; m++) -// { -// if (uniqueVertBuffer[m] == vertIndex) -// { -// isVertexIndexUnique = false; -// break; -// } -// } -// -// if (isVertexIndexUnique) -// { -// uniqueVertBuffer[uniqueVertBufferCount] = vertIndex; -// uniqueVertBufferCount++; -// } -// } -// } -// -// _ASSERT(uniqueVertBufferCount <= 3 * 16); -// -// currPartition->fuind = uindCount; -// currPartition->nuinds = uniqueVertBufferCount; -// memcpy(&clipMap->info.uinds[uindCount], uniqueVertBuffer, uniqueVertBufferCount * sizeof(uint16_t)); -// uindCount += uniqueVertBufferCount; -// } -// _ASSERT(uindCount < 3 * 16 * clipMap->partitionCount); -// clipMap->info.nuinds = uindCount; -// -// // 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 -// int walkableEdgeSize = (3 * clipMap->triCount + 31) / 32 * 4; -// clipMap->triEdgeIsWalkable = new char[walkableEdgeSize]; -// memset(clipMap->triEdgeIsWalkable, 0xFF, walkableEdgeSize * sizeof(char)); -// -// // BSP creation must go last as it depends on unids, tris and verts already being populated -// // HACK: -// // the BSP tree creation does not work when BO2's coordinate system is used for mins and maxs. -// // Workaround is to convert every BO2 coordinate to OGL's before it is added into the BSP tree, -// // and then convert them back when it is being parsed into the clipmap. Requires some hacky -// // logic, check populateBSPTree_r and addAABBTreeFromLeaf -// -// vec3_t* firstVert = &clipMap->verts[0]; -// vec3_t clipMins; -// vec3_t clipMaxs; -// clipMins.x = firstVert->x; -// clipMins.y = firstVert->y; -// clipMins.z = firstVert->z; -// clipMaxs.x = firstVert->x; -// clipMaxs.y = firstVert->y; -// clipMaxs.z = firstVert->z; -// clipMins = CMUtil::convertFromBO2Coords(clipMins); -// clipMaxs = CMUtil::convertFromBO2Coords(clipMaxs); -// for (int i = 1; i < clipMap->vertCount; i++) -// { -// vec3_t vertCoord = CMUtil::convertFromBO2Coords(clipMap->verts[i]); -// CMUtil::calcNewBoundsWithPoint(&vertCoord, &clipMins, &clipMaxs); -// } -// -// BSPTree* tree = new BSPTree(clipMins.x, clipMins.y, clipMins.z, clipMaxs.x, clipMaxs.y, clipMaxs.z, 0); -// for (int i = 0; i < clipMap->partitionCount; i++) -// { -// auto currPartition = &clipMap->partitions[i]; -// -// uint16_t* firstTri = clipMap->triIndices[currPartition->firstTri]; -// vec3_t* firstVert = &clipMap->verts[firstTri[0]]; -// vec3_t mins; -// vec3_t maxs; -// mins.x = firstVert->x; -// mins.y = firstVert->y; -// mins.z = firstVert->z; -// maxs.x = firstVert->x; -// maxs.y = firstVert->y; -// maxs.z = firstVert->z; -// mins = CMUtil::convertFromBO2Coords(mins); -// maxs = CMUtil::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); -// } -// } -// -// Object* currObject = new Object(mins.x, mins.y, mins.z, maxs.x, maxs.y, maxs.z, i); -// -// tree->addObject(currObject); -// } -// -// populateBSPTree(clipMap, tree); -// -// m_context.AddAsset(clipMap->name, clipMap); -// } -// -// void createComWorld(customMapInfo* projInfo) -// { -// // all lights that aren't the sunlight or default light need their own GfxLightDef asset -// ComWorld* comWorld = new ComWorld; -// comWorld->name = _strdup(projInfo->bspName.c_str()); -// comWorld->isInUse = 1; -// comWorld->primaryLightCount = 2; -// comWorld->primaryLights = new ComPrimaryLight[comWorld->primaryLightCount]; -// -// ComPrimaryLight* defaultLight = &comWorld->primaryLights[0]; -// memset(defaultLight, 0, sizeof(ComPrimaryLight)); -// -// ComPrimaryLight* sunLight = &comWorld->primaryLights[1]; -// memset(sunLight, 0, sizeof(ComPrimaryLight)); -// sunLight->type = 1; -// // Below are default values taken from mp_dig -// sunLight->diffuseColor.r = 1.0f; -// sunLight->diffuseColor.g = 1.0f; -// sunLight->diffuseColor.b = 1.0f; -// sunLight->diffuseColor.a = 0.0f; -// sunLight->dir.x = -0.2410777360200882; -// sunLight->dir.y = -0.8407384753227234; -// sunLight->dir.z = 0.48480960726737976; -// -// m_context.AddAsset(comWorld->name, comWorld); -// } -// -// void createMapEnts(customMapInfo* projInfo) -// { -// MapEnts* mapEnts = new MapEnts; -// -// mapEnts->name = _strdup(projInfo->bspName.c_str()); -// -// // don't need these -// mapEnts->trigger.count = 0; -// mapEnts->trigger.models = NULL; -// mapEnts->trigger.hullCount = 0; -// mapEnts->trigger.hulls = NULL; -// mapEnts->trigger.slabCount = 0; -// mapEnts->trigger.slabs = NULL; -// -// const auto file = m_search_path.Open("custom_map/entities.json"); -// if (!file.IsOpen()) -// { -// printf("WARN: can't find entity json!\n"); -// return; -// } -// -// json entJs = json::parse(*file.m_stream); -// -// std::string entityString; -// int entityCount = entJs["entityCount"]; -// for (int i = 0; i < entityCount; i++) -// { -// auto currEntity = entJs["entities"][i]; -// -// if (i == 0) -// { -// std::string className = currEntity["classname"]; -// if (className.compare("worldspawn") != 0) -// { -// printf("ERROR: first entity in the map entity string must be the worldspawn class!"); -// hasLinkFailed = true; -// return; -// } -// } -// -// entityString.append("{\n"); -// -// for (auto& element : currEntity.items()) -// { -// std::string key = element.key(); -// std::string value = element.value(); -// entityString.append(std::format("\"{}\" \"{}\"\n", key, value)); -// } -// -// entityString.append("}\n"); -// } -// entityString.pop_back(); // remove newline character from the end of the string -// -// mapEnts->entityString = _strdup(entityString.c_str()); -// mapEnts->numEntityChars = entityString.length() + 1; // numEntityChars includes the null character -// -// m_context.AddAsset(mapEnts->name, mapEnts); -// } -// -// void createGameWorldMp(customMapInfo* projInfo) -// { -// GameWorldMp* gameWorldMp = new GameWorldMp; -// -// gameWorldMp->name = _strdup(projInfo->bspName.c_str()); -// -// gameWorldMp->path.nodeCount = 0; -// gameWorldMp->path.originalNodeCount = 0; -// gameWorldMp->path.visBytes = 0; -// gameWorldMp->path.smoothBytes = 0; -// gameWorldMp->path.nodeTreeCount = 0; -// -// int nodeCount = gameWorldMp->path.nodeCount + 128; -// gameWorldMp->path.nodes = new pathnode_t[nodeCount]; -// gameWorldMp->path.basenodes = new pathbasenode_t[nodeCount]; -// memset(gameWorldMp->path.nodes, 0, nodeCount * sizeof(pathnode_t)); -// memset(gameWorldMp->path.basenodes, 0, nodeCount * sizeof(pathbasenode_t)); -// -// gameWorldMp->path.pathVis = NULL; -// gameWorldMp->path.smoothCache = NULL; -// gameWorldMp->path.nodeTree = NULL; -// -// m_context.AddAsset(gameWorldMp->name, gameWorldMp); -// } -// -// void createSkinnedVerts(customMapInfo* projInfo) -// { -// SkinnedVertsDef* skinnedVerts = new SkinnedVertsDef; -// skinnedVerts->name = "skinnedverts"; -// skinnedVerts->maxSkinnedVerts = projInfo->gfxInfo.vertexCount; -// -// m_context.AddAsset("skinnedverts", skinnedVerts); -// } -// -// FootstepTableDef* addEmptyFootstepTableAsset(std::string assetName) -// { -// if (assetName.length() == 0) -// return NULL; -// -// FootstepTableDef* footstepTable = new FootstepTableDef; -// footstepTable->name = _strdup(assetName.c_str()); -// memset(footstepTable->sndAliasTable, 0, sizeof(footstepTable->sndAliasTable)); -// -// m_context.AddAsset(assetName, footstepTable); -// -// return footstepTable; -// } -// -// void checkAndAddDefaultRequiredAssets(customMapInfo* projectInfo) -// { -// if (m_context.LoadDependency("maps/mp/mp_dig.gsc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("maps/mp/mp_dig_amb.gsc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("maps/mp/mp_dig_fx.gsc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("maps/mp/createfx/mp_dig_fx.gsc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("clientscripts/mp/mp_dig.csc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("clientscripts/mp/mp_dig_amb.csc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("clientscripts/mp/mp_dig_fx.csc") == NULL) { hasLinkFailed = true; return; } -// if (m_context.LoadDependency("clientscripts/mp/createfx/mp_dig_fx.csc") == NULL) { hasLinkFailed = true; return; } -// -// 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"); -// } -//}; diff --git a/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h b/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h index 61ec5b68..0ba12b45 100644 --- a/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h +++ b/src/ObjLoading/Game/T6/CustomMap/CustomMapLinker.h @@ -1,16 +1,15 @@ #pragma once -#include "Game/T6/Material/JsonMaterialLoaderT6.h" - #include "BinarySpacePartitionTreePreCalc.h" -#include "TriangleSort.h" #include "CustomMapConsts.h" +#include "CustomMapOptions.h" #include "Util.h" + +#include "Game/T6/Material/JsonMaterialLoaderT6.h" #include "Utils/Pack.h" -#include #include -using json = nlohmann::json; +using namespace nlohmann; class CustomMapLinker { diff --git a/src/ObjLoading/Game/T6/CustomMap/CustomMapOptions.h b/src/ObjLoading/Game/T6/CustomMap/CustomMapOptions.h new file mode 100644 index 00000000..b18a97c6 --- /dev/null +++ b/src/ObjLoading/Game/T6/CustomMap/CustomMapOptions.h @@ -0,0 +1,17 @@ +#pragma once + +// These options can be edited + +// material flags determine the features of the 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 +#define MATERIAL_SURFACE_FLAGS 1 +#define 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 +#define LEAF_TERRAIN_CONTENTS 1 +#define WORLD_TERRAIN_CONTENTS 1 + +#define LIGHTGRID_COLOUR 128 // global lighting colour diff --git a/src/ObjLoading/Game/T6/CustomMap/LoaderCustomMapT6.cpp b/src/ObjLoading/Game/T6/CustomMap/LoaderCustomMapT6.cpp index f780448c..29983f78 100644 --- a/src/ObjLoading/Game/T6/CustomMap/LoaderCustomMapT6.cpp +++ b/src/ObjLoading/Game/T6/CustomMap/LoaderCustomMapT6.cpp @@ -22,26 +22,20 @@ namespace AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override { + // custom maps must have a map_gfx file auto mapGfxFile = m_search_path.Open("custom_map/map_gfx.fbx"); if (!mapGfxFile.IsOpen()) return AssetCreationResult::NoAction(); - printf("Loading map data...\n"); - - // create map info from the obj file - customMapInfo* mapInfo = CustomMapInfo::createCustomMapInfo(m_zone.m_name, m_search_path); + // create map info from the fbx file + customMapInfo* mapInfo = ProjectCreator::createCustomMapInfo(m_zone.m_name, m_search_path); if (mapInfo == NULL) return AssetCreationResult::Failure(); - - printf("Creating map from data...\n"); // linker will add all the assets needed CustomMapLinker* linker = new CustomMapLinker(m_memory, m_search_path, m_zone, context); bool result = linker->linkCustomMap(mapInfo); - //auto gfxWorldAsset = context.LoadDependency("default_1st_person"); - //return AssetCreationResult::Success(gfxWorldAsset); - if (result) { auto gfxWorldAsset = context.LoadDependency(mapInfo->bspName); diff --git a/src/ObjLoading/Game/T6/CustomMap/OBJ_Loader.h b/src/ObjLoading/Game/T6/CustomMap/OBJ_Loader.h deleted file mode 100644 index 8ee1a62d..00000000 --- a/src/ObjLoading/Game/T6/CustomMap/OBJ_Loader.h +++ /dev/null @@ -1,1153 +0,0 @@ -// OBJ_Loader.h - A Single Header OBJ Model Loader -// modified to work better with OpenAssetTools - -#pragma once - -// Iostream - STD I/O Library -#include - -// Vector - STD Vector/Array Library -#include - -// String - STD String Library -#include - -// fStream - STD File I/O Library -#include - -// Math.h - STD math Library -#include - -#include "SearchPath/ISearchPath.h" - -// Print progress to console while loading (large models) -// #define OBJL_CONSOLE_OUTPUT - -// Namespace: OBJL -// -// Description: The namespace that holds eveyrthing that -// is needed and used for the OBJ Model Loader -namespace objl -{ - // Structure: Vector2 - // - // Description: A 2D Vector that Holds Positional Data - struct Vector2 - { - // Default Constructor - Vector2() - { - X = 0.0f; - Y = 0.0f; - } - - // Variable Set Constructor - Vector2(float X_, float Y_) - { - X = X_; - Y = Y_; - } - - // Bool Equals Operator Overload - bool operator==(const Vector2& other) const - { - return (this->X == other.X && this->Y == other.Y); - } - - // Bool Not Equals Operator Overload - bool operator!=(const Vector2& other) const - { - return !(this->X == other.X && this->Y == other.Y); - } - - // Addition Operator Overload - Vector2 operator+(const Vector2& right) const - { - return Vector2(this->X + right.X, this->Y + right.Y); - } - - // Subtraction Operator Overload - Vector2 operator-(const Vector2& right) const - { - return Vector2(this->X - right.X, this->Y - right.Y); - } - - // Float Multiplication Operator Overload - Vector2 operator*(const float& other) const - { - return Vector2(this->X * other, this->Y * other); - } - - // Positional Variables - float X; - float Y; - }; - - // Structure: Vector3 - // - // Description: A 3D Vector that Holds Positional Data - struct Vector3 - { - // Default Constructor - Vector3() - { - X = 0.0f; - Y = 0.0f; - Z = 0.0f; - } - - // Variable Set Constructor - Vector3(float X_, float Y_, float Z_) - { - X = X_; - Y = Y_; - Z = Z_; - } - - // Bool Equals Operator Overload - bool operator==(const Vector3& other) const - { - return (this->X == other.X && this->Y == other.Y && this->Z == other.Z); - } - - // Bool Not Equals Operator Overload - bool operator!=(const Vector3& other) const - { - return !(this->X == other.X && this->Y == other.Y && this->Z == other.Z); - } - - // Addition Operator Overload - Vector3 operator+(const Vector3& right) const - { - return Vector3(this->X + right.X, this->Y + right.Y, this->Z + right.Z); - } - - // Subtraction Operator Overload - Vector3 operator-(const Vector3& right) const - { - return Vector3(this->X - right.X, this->Y - right.Y, this->Z - right.Z); - } - - // Float Multiplication Operator Overload - Vector3 operator*(const float& other) const - { - return Vector3(this->X * other, this->Y * other, this->Z * other); - } - - // Float Division Operator Overload - Vector3 operator/(const float& other) const - { - return Vector3(this->X / other, this->Y / other, this->Z / other); - } - - // Positional Variables - float X; - float Y; - float Z; - }; - - // Structure: Vertex - // - // Description: Model Vertex object that holds - // a Position, Normal, and Texture Coordinate - struct Vertex - { - // Position Vector - Vector3 Position; - - // Normal Vector - Vector3 Normal; - - // Texture Coordinate Vector - Vector2 TextureCoordinate; - }; - - struct Material - { - Material() - { - name; - Ns = 0.0f; - Ni = 0.0f; - d = 0.0f; - illum = 0; - } - - // Material Name - std::string name; - // Ambient Color - Vector3 Ka; - // Diffuse Color - Vector3 Kd; - // Specular Color - Vector3 Ks; - // Specular Exponent - float Ns; - // Optical Density - float Ni; - // Dissolve - float d; - // Illumination - int illum; - // Ambient Texture Map - std::string map_Ka; - // Diffuse Texture Map - std::string map_Kd; - // Specular Texture Map - std::string map_Ks; - // Specular Hightlight Map - std::string map_Ns; - // Alpha Texture Map - std::string map_d; - // Bump Map - std::string map_bump; - }; - - // Structure: Mesh - // - // Description: A Simple Mesh Object that holds - // a name, a vertex list, and an index list - struct Mesh - { - // Default Constructor - Mesh() {} - - // Variable Set Constructor - Mesh(std::vector& _Vertices, std::vector& _Indices) - { - Vertices = _Vertices; - Indices = _Indices; - } - - // Mesh Name - std::string MeshName; - // Vertex List - std::vector Vertices; - // Index List - std::vector Indices; - - // Material - Material MeshMaterial; - }; - - // Namespace: Math - // - // Description: The namespace that holds all of the math - // functions need for OBJL - namespace math - { - // Vector3 Cross Product - Vector3 CrossV3(const Vector3 a, const Vector3 b) - { - return Vector3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); - } - - // Vector3 Magnitude Calculation - float MagnitudeV3(const Vector3 in) - { - return (sqrtf(powf(in.X, 2) + powf(in.Y, 2) + powf(in.Z, 2))); - } - - // Vector3 DotProduct - float DotV3(const Vector3 a, const Vector3 b) - { - return (a.X * b.X) + (a.Y * b.Y) + (a.Z * b.Z); - } - - // Angle between 2 Vector3 Objects - float AngleBetweenV3(const Vector3 a, const Vector3 b) - { - float angle = DotV3(a, b); - angle /= (MagnitudeV3(a) * MagnitudeV3(b)); - return angle = acosf(angle); - } - - // Projection Calculation of a onto b - Vector3 ProjV3(const Vector3 a, const Vector3 b) - { - Vector3 bn = b / MagnitudeV3(b); - return bn * DotV3(a, bn); - } - } // namespace math - - // Namespace: Algorithm - // - // Description: The namespace that holds all of the - // Algorithms needed for OBJL - namespace algorithm - { - // Vector3 Multiplication Opertor Overload - Vector3 operator*(const float& left, const Vector3& right) - { - return Vector3(right.X * left, right.Y * left, right.Z * left); - } - - // A test to see if P1 is on the same side as P2 of a line segment ab - bool SameSide(Vector3 p1, Vector3 p2, Vector3 a, Vector3 b) - { - Vector3 cp1 = math::CrossV3(b - a, p1 - a); - Vector3 cp2 = math::CrossV3(b - a, p2 - a); - - if (math::DotV3(cp1, cp2) >= 0) - return true; - else - return false; - } - - // Generate a cross produect normal for a triangle - Vector3 GenTriNormal(Vector3 t1, Vector3 t2, Vector3 t3) - { - Vector3 u = t2 - t1; - Vector3 v = t3 - t1; - - Vector3 normal = math::CrossV3(u, v); - - return normal; - } - - // Check to see if a Vector3 Point is within a 3 Vector3 Triangle - bool inTriangle(Vector3 point, Vector3 tri1, Vector3 tri2, Vector3 tri3) - { - // Test to see if it is within an infinite prism that the triangle outlines. - bool within_tri_prisim = SameSide(point, tri1, tri2, tri3) && SameSide(point, tri2, tri1, tri3) && SameSide(point, tri3, tri1, tri2); - - // If it isn't it will never be on the triangle - if (!within_tri_prisim) - return false; - - // Calulate Triangle's Normal - Vector3 n = GenTriNormal(tri1, tri2, tri3); - - // Project the point onto this normal - Vector3 proj = math::ProjV3(point, n); - - // If the distance from the triangle to the point is 0 - // it lies on the triangle - if (math::MagnitudeV3(proj) == 0) - return true; - else - return false; - } - - // Split a String into a string array at a given token - inline void split(const std::string& in, std::vector& out, std::string token) - { - out.clear(); - - std::string temp; - - for (int i = 0; i < int(in.size()); i++) - { - std::string test = in.substr(i, token.size()); - - if (test == token) - { - if (!temp.empty()) - { - out.push_back(temp); - temp.clear(); - i += (int)token.size() - 1; - } - else - { - out.push_back(""); - } - } - else if (i + token.size() >= in.size()) - { - temp += in.substr(i, token.size()); - out.push_back(temp); - break; - } - else - { - temp += in[i]; - } - } - } - - // Get tail of string after first token and possibly following spaces - inline std::string tail(const std::string& in) - { - size_t token_start = in.find_first_not_of(" \t"); - size_t space_start = in.find_first_of(" \t", token_start); - size_t tail_start = in.find_first_not_of(" \t", space_start); - size_t tail_end = in.find_last_not_of(" \t"); - if (tail_start != std::string::npos && tail_end != std::string::npos) - { - return in.substr(tail_start, tail_end - tail_start + 1); - } - else if (tail_start != std::string::npos) - { - return in.substr(tail_start); - } - return ""; - } - - // Get first token of string - inline std::string firstToken(const std::string& in) - { - if (!in.empty()) - { - size_t token_start = in.find_first_not_of(" \t"); - size_t token_end = in.find_first_of(" \t", token_start); - if (token_start != std::string::npos && token_end != std::string::npos) - { - return in.substr(token_start, token_end - token_start); - } - else if (token_start != std::string::npos) - { - return in.substr(token_start); - } - } - return ""; - } - - // Get element at given index position - template inline const T& getElement(const std::vector& elements, std::string& index) - { - int idx = std::stoi(index); - if (idx < 0) - idx = int(elements.size()) + idx; - else - idx--; - return elements[idx]; - } - } // namespace algorithm - - // Class: Loader - // - // Description: The OBJ Model Loader - class Loader - { - public: - // Default Constructor - Loader() {} - - ~Loader() - { - LoadedMeshes.clear(); - } - - // Load a file into the loader - // - // If file is loaded return true - // - // If the file is unable to be found - // or unable to be loaded return false - bool LoadFile(ISearchPath& searchPath, std::string fileName) - { - auto file = searchPath.Open(fileName); - - if (!file.IsOpen()) - return false; - - LoadedMeshes.clear(); - LoadedVertices.clear(); - LoadedIndices.clear(); - - std::vector Positions; - std::vector TCoords; - std::vector Normals; - - std::vector Vertices; - std::vector Indices; - - std::vector MeshMatNames; - - bool listening = false; - std::string meshname; - - Mesh tempMesh; - -#ifdef OBJL_CONSOLE_OUTPUT - const unsigned int outputEveryNth = 1000; - unsigned int outputIndicator = outputEveryNth; -#endif - - std::string curline; - while (std::getline(*file.m_stream, curline)) - { -#ifdef OBJL_CONSOLE_OUTPUT - if ((outputIndicator = ((outputIndicator + 1) % outputEveryNth)) == 1) - { - if (!meshname.empty()) - { - std::cout << "\r- " << meshname << "\t| vertices > " << Positions.size() << "\t| texcoords > " << TCoords.size() << "\t| normals > " - << Normals.size() << "\t| triangles > " << (Vertices.size() / 3) - << (!MeshMatNames.empty() ? "\t| material: " + MeshMatNames.back() : ""); - } - } -#endif - - // Generate a Mesh Object or Prepare for an object to be created - if (algorithm::firstToken(curline) == "o" || algorithm::firstToken(curline) == "g" || curline[0] == 'g') - { - if (!listening) - { - listening = true; - - if (algorithm::firstToken(curline) == "o" || algorithm::firstToken(curline) == "g") - { - meshname = algorithm::tail(curline); - } - else - { - meshname = "unnamed"; - } - } - else - { - // Generate the mesh to put into the array - - if (!Indices.empty() && !Vertices.empty()) - { - // Create Mesh - tempMesh = Mesh(Vertices, Indices); - tempMesh.MeshName = meshname; - - // Insert Mesh - LoadedMeshes.push_back(tempMesh); - - // Cleanup - Vertices.clear(); - Indices.clear(); - meshname.clear(); - - meshname = algorithm::tail(curline); - } - else - { - if (algorithm::firstToken(curline) == "o" || algorithm::firstToken(curline) == "g") - { - meshname = algorithm::tail(curline); - } - else - { - meshname = "unnamed"; - } - } - } -#ifdef OBJL_CONSOLE_OUTPUT - std::cout << std::endl; - outputIndicator = 0; -#endif - } - // Generate a Vertex Position - if (algorithm::firstToken(curline) == "v") - { - std::vector spos; - Vector3 vpos; - algorithm::split(algorithm::tail(curline), spos, " "); - - vpos.X = std::stof(spos[0]); - vpos.Y = std::stof(spos[1]); - vpos.Z = std::stof(spos[2]); - - Positions.push_back(vpos); - } - // Generate a Vertex Texture Coordinate - if (algorithm::firstToken(curline) == "vt") - { - std::vector stex; - Vector2 vtex; - algorithm::split(algorithm::tail(curline), stex, " "); - - vtex.X = std::stof(stex[0]); - vtex.Y = std::stof(stex[1]); - - TCoords.push_back(vtex); - } - // Generate a Vertex Normal; - if (algorithm::firstToken(curline) == "vn") - { - std::vector snor; - Vector3 vnor; - algorithm::split(algorithm::tail(curline), snor, " "); - - vnor.X = std::stof(snor[0]); - vnor.Y = std::stof(snor[1]); - vnor.Z = std::stof(snor[2]); - - Normals.push_back(vnor); - } - // Generate a Face (vertices & indices) - if (algorithm::firstToken(curline) == "f") - { - // Generate the vertices - std::vector vVerts; - GenVerticesFromRawOBJ(vVerts, Positions, TCoords, Normals, curline); - - // Add Vertices - for (int i = 0; i < int(vVerts.size()); i++) - { - Vertices.push_back(vVerts[i]); - - LoadedVertices.push_back(vVerts[i]); - } - - std::vector iIndices; - - VertexTriangluation(iIndices, vVerts); - - // Add Indices - for (int i = 0; i < int(iIndices.size()); i++) - { - unsigned int indnum = (unsigned int)((Vertices.size()) - vVerts.size()) + iIndices[i]; - Indices.push_back(indnum); - - indnum = (unsigned int)((LoadedVertices.size()) - vVerts.size()) + iIndices[i]; - LoadedIndices.push_back(indnum); - } - } - // Get Mesh Material Name - if (algorithm::firstToken(curline) == "usemtl") - { - MeshMatNames.push_back(algorithm::tail(curline)); - - // Create new Mesh, if Material changes within a group - if (!Indices.empty() && !Vertices.empty()) - { - // Create Mesh - tempMesh = Mesh(Vertices, Indices); - tempMesh.MeshName = meshname; - int i = 2; - while (1) - { - tempMesh.MeshName = meshname + "_" + std::to_string(i); - - for (auto& m : LoadedMeshes) - if (m.MeshName == tempMesh.MeshName) - continue; - break; - } - - // Insert Mesh - LoadedMeshes.push_back(tempMesh); - - // Cleanup - Vertices.clear(); - Indices.clear(); - } - -#ifdef OBJL_CONSOLE_OUTPUT - outputIndicator = 0; -#endif - } - // Load Materials - if (algorithm::firstToken(curline) == "mtllib") - { - // Generate LoadedMaterial - - // Generate a path to the material file - std::vector temp; - algorithm::split(fileName, temp, "/"); // update: use windows file seperators - - std::string pathtomat = ""; - - if (temp.size() != 1) - { - for (size_t i = 0; i < temp.size() - 1; i++) - { - pathtomat += temp[i] + "/"; - } - } - - pathtomat += algorithm::tail(curline); - -#ifdef OBJL_CONSOLE_OUTPUT - std::cout << std::endl << "- find materials in: " << pathtomat << std::endl; -#endif - - // Load Materials - LoadMaterials(searchPath, pathtomat); - } - } - -#ifdef OBJL_CONSOLE_OUTPUT - std::cout << std::endl; -#endif - - // Deal with last mesh - - if (!Indices.empty() && !Vertices.empty()) - { - // Create Mesh - tempMesh = Mesh(Vertices, Indices); - tempMesh.MeshName = meshname; - - // Insert Mesh - LoadedMeshes.push_back(tempMesh); - } - - // Set Materials for each Mesh - for (size_t i = 0; i < MeshMatNames.size(); i++) - { - std::string matname = MeshMatNames[i]; - - // Find corresponding material name in loaded materials - // when found copy material variables into mesh material - for (size_t j = 0; j < LoadedMaterials.size(); j++) - { - if (LoadedMaterials[j].name == matname) - { - LoadedMeshes[i].MeshMaterial = LoadedMaterials[j]; - break; - } - } - } - - if (LoadedMeshes.empty() && LoadedVertices.empty() && LoadedIndices.empty()) - { - return false; - } - else - { - return true; - } - } - - // Loaded Mesh Objects - std::vector LoadedMeshes; - // Loaded Vertex Objects - std::vector LoadedVertices; - // Loaded Index Positions - std::vector LoadedIndices; - // Loaded Material Objects - std::vector LoadedMaterials; - - private: - // Generate vertices from a list of positions, - // tcoords, normals and a face line - void GenVerticesFromRawOBJ(std::vector& oVerts, - const std::vector& iPositions, - const std::vector& iTCoords, - const std::vector& iNormals, - std::string icurline) - { - std::vector sface, svert; - Vertex vVert; - algorithm::split(algorithm::tail(icurline), sface, " "); - - bool noNormal = false; - - // For every given vertex do this - for (int i = 0; i < int(sface.size()); i++) - { - // See What type the vertex is. - int vtype; - - algorithm::split(sface[i], svert, "/"); - - // Check for just position - v1 - if (svert.size() == 1) - { - // Only position - vtype = 1; - } - - // Check for position & texture - v1/vt1 - if (svert.size() == 2) - { - // Position & Texture - vtype = 2; - } - - // Check for Position, Texture and Normal - v1/vt1/vn1 - // or if Position and Normal - v1//vn1 - if (svert.size() == 3) - { - if (svert[1] != "") - { - // Position, Texture, and Normal - vtype = 4; - } - else - { - // Position & Normal - vtype = 3; - } - } - - // Calculate and store the vertex - switch (vtype) - { - case 1: // P - { - vVert.Position = algorithm::getElement(iPositions, svert[0]); - vVert.TextureCoordinate = Vector2(0, 0); - noNormal = true; - oVerts.push_back(vVert); - break; - } - case 2: // P/T - { - vVert.Position = algorithm::getElement(iPositions, svert[0]); - vVert.TextureCoordinate = algorithm::getElement(iTCoords, svert[1]); - noNormal = true; - oVerts.push_back(vVert); - break; - } - case 3: // P//N - { - vVert.Position = algorithm::getElement(iPositions, svert[0]); - vVert.TextureCoordinate = Vector2(0, 0); - vVert.Normal = algorithm::getElement(iNormals, svert[2]); - oVerts.push_back(vVert); - break; - } - case 4: // P/T/N - { - vVert.Position = algorithm::getElement(iPositions, svert[0]); - vVert.TextureCoordinate = algorithm::getElement(iTCoords, svert[1]); - vVert.Normal = algorithm::getElement(iNormals, svert[2]); - oVerts.push_back(vVert); - break; - } - default: - { - break; - } - } - } - - // take care of missing normals - // these may not be truly acurate but it is the - // best they get for not compiling a mesh with normals - if (noNormal) - { - Vector3 A = oVerts[0].Position - oVerts[1].Position; - Vector3 B = oVerts[2].Position - oVerts[1].Position; - - Vector3 normal = math::CrossV3(A, B); - - for (int i = 0; i < int(oVerts.size()); i++) - { - oVerts[i].Normal = normal; - } - } - } - - // Triangulate a list of vertices into a face by printing - // inducies corresponding with triangles within it - void VertexTriangluation(std::vector& oIndices, const std::vector& iVerts) - { - // If there are 2 or less verts, - // no triangle can be created, - // so exit - if (iVerts.size() < 3) - { - return; - } - // If it is a triangle no need to calculate it - if (iVerts.size() == 3) - { - oIndices.push_back(0); - oIndices.push_back(1); - oIndices.push_back(2); - return; - } - - // Create a list of vertices - std::vector tVerts = iVerts; - - while (true) - { - // For every vertex - for (int i = 0; i < int(tVerts.size()); i++) - { - // pPrev = the previous vertex in the list - Vertex pPrev; - if (i == 0) - { - pPrev = tVerts[tVerts.size() - 1]; - } - else - { - pPrev = tVerts[i - 1]; - } - - // pCur = the current vertex; - Vertex pCur = tVerts[i]; - - // pNext = the next vertex in the list - Vertex pNext; - if (i == tVerts.size() - 1) - { - pNext = tVerts[0]; - } - else - { - pNext = tVerts[i + 1]; - } - - // Check to see if there are only 3 verts left - // if so this is the last triangle - if (tVerts.size() == 3) - { - // Create a triangle from pCur, pPrev, pNext - for (int j = 0; j < int(tVerts.size()); j++) - { - if (iVerts[j].Position == pCur.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pPrev.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pNext.Position) - oIndices.push_back(j); - } - - tVerts.clear(); - break; - } - if (tVerts.size() == 4) - { - // Create a triangle from pCur, pPrev, pNext - for (int j = 0; j < int(iVerts.size()); j++) - { - if (iVerts[j].Position == pCur.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pPrev.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pNext.Position) - oIndices.push_back(j); - } - - Vector3 tempVec; - for (int j = 0; j < int(tVerts.size()); j++) - { - if (tVerts[j].Position != pCur.Position && tVerts[j].Position != pPrev.Position && tVerts[j].Position != pNext.Position) - { - tempVec = tVerts[j].Position; - break; - } - } - - // Create a triangle from pCur, pPrev, pNext - for (int j = 0; j < int(iVerts.size()); j++) - { - if (iVerts[j].Position == pPrev.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pNext.Position) - oIndices.push_back(j); - if (iVerts[j].Position == tempVec) - oIndices.push_back(j); - } - - tVerts.clear(); - break; - } - - // If Vertex is not an interior vertex - float angle = math::AngleBetweenV3(pPrev.Position - pCur.Position, pNext.Position - pCur.Position) * (float)(180 / 3.14159265359); - if (angle <= 0 && angle >= 180) - continue; - - // If any vertices are within this triangle - bool inTri = false; - for (int j = 0; j < int(iVerts.size()); j++) - { - if (algorithm::inTriangle(iVerts[j].Position, pPrev.Position, pCur.Position, pNext.Position) && iVerts[j].Position != pPrev.Position - && iVerts[j].Position != pCur.Position && iVerts[j].Position != pNext.Position) - { - inTri = true; - break; - } - } - if (inTri) - continue; - - // Create a triangle from pCur, pPrev, pNext - for (int j = 0; j < int(iVerts.size()); j++) - { - if (iVerts[j].Position == pCur.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pPrev.Position) - oIndices.push_back(j); - if (iVerts[j].Position == pNext.Position) - oIndices.push_back(j); - } - - // Delete pCur from the list - for (int j = 0; j < int(tVerts.size()); j++) - { - if (tVerts[j].Position == pCur.Position) - { - tVerts.erase(tVerts.begin() + j); - break; - } - } - - // reset i to the start - // -1 since loop will add 1 to it - i = -1; - } - - // if no triangles were created - if (oIndices.size() == 0) - break; - - // if no more vertices - if (tVerts.size() == 0) - break; - } - } - - // Load Materials from .mtl file - bool LoadMaterials(ISearchPath& searchPath, std::string fileName) - { - auto file = searchPath.Open(fileName); - - // If the file is not found return false - if (!file.IsOpen()) - return false; - - Material tempMaterial; - - bool listening = false; - - // Go through each line looking for material variables - std::string curline; - while (std::getline(*file.m_stream, curline)) - { - // new material and material name - if (algorithm::firstToken(curline) == "newmtl") - { - if (!listening) - { - listening = true; - - if (curline.size() > 7) - { - tempMaterial.name = algorithm::tail(curline); - } - else - { - tempMaterial.name = "none"; - } - } - else - { - // Generate the material - - // Push Back loaded Material - LoadedMaterials.push_back(tempMaterial); - - // Clear Loaded Material - tempMaterial = Material(); - - if (curline.size() > 7) - { - tempMaterial.name = algorithm::tail(curline); - } - else - { - tempMaterial.name = "none"; - } - } - } - // Ambient Color - if (algorithm::firstToken(curline) == "Ka") - { - std::vector temp; - algorithm::split(algorithm::tail(curline), temp, " "); - - if (temp.size() != 3) - continue; - - tempMaterial.Ka.X = std::stof(temp[0]); - tempMaterial.Ka.Y = std::stof(temp[1]); - tempMaterial.Ka.Z = std::stof(temp[2]); - } - // Diffuse Color - if (algorithm::firstToken(curline) == "Kd") - { - std::vector temp; - algorithm::split(algorithm::tail(curline), temp, " "); - - if (temp.size() != 3) - continue; - - tempMaterial.Kd.X = std::stof(temp[0]); - tempMaterial.Kd.Y = std::stof(temp[1]); - tempMaterial.Kd.Z = std::stof(temp[2]); - } - // Specular Color - if (algorithm::firstToken(curline) == "Ks") - { - std::vector temp; - algorithm::split(algorithm::tail(curline), temp, " "); - - if (temp.size() != 3) - continue; - - tempMaterial.Ks.X = std::stof(temp[0]); - tempMaterial.Ks.Y = std::stof(temp[1]); - tempMaterial.Ks.Z = std::stof(temp[2]); - } - // Specular Exponent - if (algorithm::firstToken(curline) == "Ns") - { - tempMaterial.Ns = std::stof(algorithm::tail(curline)); - } - // Optical Density - if (algorithm::firstToken(curline) == "Ni") - { - tempMaterial.Ni = std::stof(algorithm::tail(curline)); - } - // Dissolve - if (algorithm::firstToken(curline) == "d") - { - tempMaterial.d = std::stof(algorithm::tail(curline)); - } - // Illumination - if (algorithm::firstToken(curline) == "illum") - { - tempMaterial.illum = std::stoi(algorithm::tail(curline)); - } - // Ambient Texture Map - if (algorithm::firstToken(curline) == "map_Ka") - { - tempMaterial.map_Ka = algorithm::tail(curline); - } - // Diffuse Texture Map - if (algorithm::firstToken(curline) == "map_Kd") - { - tempMaterial.map_Kd = algorithm::tail(curline); - } - // Specular Texture Map - if (algorithm::firstToken(curline) == "map_Ks") - { - tempMaterial.map_Ks = algorithm::tail(curline); - } - // Specular Hightlight Map - if (algorithm::firstToken(curline) == "map_Ns") - { - tempMaterial.map_Ns = algorithm::tail(curline); - } - // Alpha Texture Map - if (algorithm::firstToken(curline) == "map_d") - { - tempMaterial.map_d = algorithm::tail(curline); - } - // Bump Map - if (algorithm::firstToken(curline) == "map_Bump" || algorithm::firstToken(curline) == "map_bump" || algorithm::firstToken(curline) == "bump") - { - tempMaterial.map_bump = algorithm::tail(curline); - } - } - - // Deal with last material - - // Push Back loaded Material - LoadedMaterials.push_back(tempMaterial); - - // Test to see if anything was loaded - // If not return false - if (LoadedMaterials.empty()) - return false; - // If so return true - else - return true; - } - }; -} // namespace objl diff --git a/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.cpp b/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.cpp index ec982b7b..0f00ed15 100644 --- a/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.cpp +++ b/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.cpp @@ -44,6 +44,8 @@ bool loadFBXMesh(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 ufbx_transform origTransform = node->local_transform; origTransform.translation.x /= 100.0f; @@ -113,6 +115,11 @@ bool loadFBXMesh(ufbx_node* node) customMapVertex* vertex = &vertices[num_vertices++]; + //ufbx_vec3 pos = ufbx_get_vertex_vec3(&mesh->vertex_position, index); + //vertex->pos.x = static_cast(pos.x); + //vertex->pos.y = static_cast(pos.y); + //vertex->pos.z = static_cast(pos.z); + // Fix the target_unit_meters opt not working ufbx_vec3 transformedPos = ufbx_transform_position(&meshMatrix, ufbx_get_vertex_vec3(&mesh->vertex_position, index)); vertex->pos.x = static_cast(transformedPos.x); vertex->pos.y = static_cast(transformedPos.y); @@ -131,10 +138,11 @@ bool loadFBXMesh(ufbx_node* node) case CM_MATERIAL_COLOUR: { float factor = static_cast(mesh->materials.data[i]->fbx.diffuse_factor.value_real); - vertex->color[0] = static_cast(mesh->materials.data[i]->fbx.diffuse_color.value_vec3.x * factor); - vertex->color[1] = static_cast(mesh->materials.data[i]->fbx.diffuse_color.value_vec3.y * factor); - vertex->color[2] = static_cast(mesh->materials.data[i]->fbx.diffuse_color.value_vec3.z * factor); - vertex->color[3] = static_cast(mesh->materials.data[i]->fbx.diffuse_color.value_vec4.w * factor); + ufbx_vec4 diffuse = mesh->materials.data[i]->fbx.diffuse_color.value_vec4; + vertex->color[0] = static_cast(diffuse.x * factor); + vertex->color[1] = static_cast(diffuse.y * factor); + vertex->color[2] = static_cast(diffuse.z * factor); + vertex->color[3] = static_cast(diffuse.w * factor); break; } @@ -144,20 +152,23 @@ bool loadFBXMesh(ufbx_node* node) - // 1.0f - uv.v: + // 1.0f - uv.y reason: // https://gamedev.stackexchange.com/questions/92886/fbx-uv-coordinates-is-strange - vertex->texCoord[0] = (float)(ufbx_get_vertex_vec2(&mesh->vertex_uv, index).x); - vertex->texCoord[1] = (float)(1.0f - ufbx_get_vertex_vec2(&mesh->vertex_uv, index).y); + ufbx_vec2 uv = ufbx_get_vertex_vec2(&mesh->vertex_uv, index); + vertex->texCoord[0] = (float)(uv.x); + vertex->texCoord[1] = (float)(1.0f - uv.y); - vertex->normal.x = static_cast(ufbx_get_vertex_vec3(&mesh->vertex_normal, index).x); - vertex->normal.y = static_cast(ufbx_get_vertex_vec3(&mesh->vertex_normal, index).y); - vertex->normal.z = static_cast(ufbx_get_vertex_vec3(&mesh->vertex_normal, index).z); + ufbx_vec3 normal = ufbx_get_vertex_vec3(&mesh->vertex_normal, index); + vertex->normal.x = static_cast(normal.x); + vertex->normal.y = static_cast(normal.y); + vertex->normal.z = static_cast(normal.z); if (mesh->vertex_tangent.exists) { - vertex->tangent.x = static_cast(ufbx_get_vertex_vec3(&mesh->vertex_tangent, index).x); - vertex->tangent.y = static_cast(ufbx_get_vertex_vec3(&mesh->vertex_tangent, index).y); - vertex->tangent.z = static_cast(ufbx_get_vertex_vec3(&mesh->vertex_tangent, index).z); + ufbx_vec3 tangent = ufbx_get_vertex_vec3(&mesh->vertex_tangent, index); + vertex->tangent.x = static_cast(tangent.x); + vertex->tangent.y = static_cast(tangent.y); + vertex->tangent.z = static_cast(tangent.z); } else { @@ -208,22 +219,13 @@ bool loadFBXModel(ufbx_node* node) model.name = node->name.data; - ufbx_transform origTransform = node->local_transform; - origTransform.translation.x /= 100.0f; - origTransform.translation.y /= 100.0f; - origTransform.translation.z /= 100.0f; - origTransform.scale.x /= 100.0f; - origTransform.scale.y /= 100.0f; - origTransform.scale.z /= 100.0f; - ufbx_matrix meshMatrix = ufbx_transform_to_matrix(&origTransform); - - model.origin.x = static_cast(node->local_transform.translation.x) / 100.0f; - model.origin.y = static_cast(node->local_transform.translation.y) / 100.0f; - model.origin.z = static_cast(node->local_transform.translation.z) / 100.0f; + model.origin.x = static_cast(node->local_transform.translation.x); + model.origin.y = static_cast(node->local_transform.translation.y); + model.origin.z = static_cast(node->local_transform.translation.z); model.rotation.x = static_cast(node->euler_rotation.x); model.rotation.y = static_cast(node->euler_rotation.y); model.rotation.z = static_cast(node->euler_rotation.z); - model.scale = static_cast(node->local_transform.scale.x) / 100.0f; + model.scale = static_cast(node->local_transform.scale.x); if (model.scale == 0.0f) { @@ -324,7 +326,7 @@ void parseCollisionData(ufbx_scene* scene, customMapInfo* projInfo) printf("warning: one or more meshes have no tangent space. Be sure to select the tangent space box when exporting the FBX from blender.\n"); } -customMapInfo* CustomMapInfo::createCustomMapInfo(std::string& projectName, ISearchPath& searchPath) +customMapInfo* ProjectCreator::createCustomMapInfo(std::string& projectName, ISearchPath& searchPath) { ufbx_scene* gfxScene; ufbx_scene* colScene; @@ -342,10 +344,13 @@ customMapInfo* CustomMapInfo::createCustomMapInfo(std::string& projectName, ISea gfxFile.m_stream->read(gfxMapData, gfxFile.m_length); ufbx_error error; - ufbx_load_opts opts; + ufbx_load_opts opts; // IDK why but opts don't seem to be working correctly, target_unit_meters isn't being used + memset(&opts, 0, sizeof(ufbx_load_opts)); opts.target_axes = ufbx_axes_right_handed_y_up; opts.generate_missing_normals = true; opts.allow_missing_vertex_position = false; + opts.target_unit_meters = 100.0f; + //gfxScene = ufbx_load_memory(gfxMapData, static_cast(gfxFile.m_length), &opts, &error); gfxScene = ufbx_load_memory(gfxMapData, static_cast(gfxFile.m_length), NULL, &error); if (!gfxScene) { @@ -366,12 +371,7 @@ customMapInfo* CustomMapInfo::createCustomMapInfo(std::string& projectName, ISea colFile.m_stream->seekg(0); colFile.m_stream->read(colMapData, colFile.m_length); - ufbx_error error; - ufbx_load_opts opts; - opts.target_axes = ufbx_axes_right_handed_y_up; - opts.generate_missing_normals = true; - opts.allow_missing_vertex_position = false; - colScene = ufbx_load_memory(colMapData, static_cast(colFile.m_length), NULL, &error); + colScene = ufbx_load_memory(colMapData, static_cast(colFile.m_length), &opts, &error); if (!colScene) { fprintf(stderr, "Failed to load map collision fbx file: %s\n", error.description.data); diff --git a/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.h b/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.h index a75d041a..e60b6b53 100644 --- a/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.h +++ b/src/ObjLoading/Game/T6/CustomMap/ProjectCreator.h @@ -5,7 +5,7 @@ #include "Game/T6/T6.h" using namespace T6; -class CustomMapInfo +class ProjectCreator { public: static customMapInfo* createCustomMapInfo(std::string& projectName, ISearchPath& searchPath); diff --git a/src/ObjLoading/Game/T6/CustomMap/TriangleSort.h b/src/ObjLoading/Game/T6/CustomMap/TriangleSort.h deleted file mode 100644 index 4e417c41..00000000 --- a/src/ObjLoading/Game/T6/CustomMap/TriangleSort.h +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "Util.h" -#include "CustomMapConsts.h" - -using TriangleGroup = std::vector; // Group of triangle indices -using AdjacencyList = std::vector; // Triangle-to-triangle connections - -class TriangleSort -{ -private: - static void computeTriCentroid(vec3_t& result, std::vector& vertices, uint16_t i0, uint16_t i1, uint16_t i2) - { - result.x = 0.0f; - result.y = 0.0f; - result.z = 0.0f; - - result.x += vertices[i0].x; - result.y += vertices[i0].y; - result.z += vertices[i0].z; - result.x += vertices[i1].x; - result.y += vertices[i1].y; - result.z += vertices[i1].z; - result.x += vertices[i2].x; - result.y += vertices[i2].y; - result.z += vertices[i2].z; - - result.x /= 3.0f; - result.y /= 3.0f; - result.z /= 3.0f; - } - - static AdjacencyList buildAdjacencyList(const std::vector& indices, std::vector& vertices, int maxTrianglesPerGroup) - { - size_t numTriangles = indices.size() / 3; - AdjacencyList adjList(numTriangles); - - std::vector centroids; - for (size_t i = 0; i < numTriangles; i++) - { - vec3_t center; - computeTriCentroid(center, vertices, indices[i * 3], indices[i * 3 + 1], indices[i * 3 + 2]); - centroids.push_back(center); - } - - std::vector visited(numTriangles, false); - for (size_t i = 0; i < numTriangles; ++i) - { - _ASSERT(i < MAX_COL_VERTS); - - if (visited[i] == true) - continue; - visited[i] = true; - - // Store distances to other triangles - std::vector> distances; - for (size_t j = 0; j < numTriangles; ++j) - { - if (visited[j] == true) - continue; - - if (i != j) - { - float dist = CMUtil::distBetweenPoints(centroids[i], centroids[j]); - distances.emplace_back(dist, j); - } - } - - // Sort by distance and take the closest maxNeighbors - std::sort(distances.begin(), distances.end()); - for (size_t k = 0; k < std::min((size_t)maxTrianglesPerGroup, distances.size()); ++k) - { - unsigned int neighbour = distances[k].second; - adjList[i].push_back(neighbour); - visited[neighbour] = true; - } - } - - for (size_t i = 0; i < visited.size(); i++) - { - if (visited[i] == false) - printf("WARN: missing triangle: %i\n", i); - } - - return adjList; - } - -public: - static AdjacencyList groupTriangles(std::vector& indices, std::vector& vertices, int maxTrianglesPerGroup) - { - return buildAdjacencyList(indices, vertices, maxTrianglesPerGroup); - } -}; \ No newline at end of file diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index e1bcc7f1..18f79214 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -336,7 +336,6 @@ namespace T6 collection.AddDefaultAssetCreator(std::make_unique>(memory)); collection.AddDefaultAssetCreator(std::make_unique>(memory)); collection.AddDefaultAssetCreator(std::make_unique>(memory)); - // custom maps have no default } void ConfigureGlobalAssetPoolsLoaders(AssetCreatorCollection& collection, Zone& zone) @@ -389,7 +388,6 @@ namespace T6 collection.AddAssetCreator(std::make_unique>(zone)); collection.AddAssetCreator(std::make_unique>(zone)); collection.AddAssetCreator(std::make_unique>(zone)); - //collection.AddAssetCreator(std::make_unique>(zone)); } void ConfigureLoaders(AssetCreatorCollection& collection, Zone& zone, ISearchPath& searchPath, IGdtQueryable& gdt) @@ -451,6 +449,7 @@ namespace T6 collection.AddAssetCreator(CreateRawZBarrierLoader(memory, searchPath, zone)); collection.AddAssetCreator(CreateGdtZBarrierLoader(memory, searchPath, gdt, zone)); + // The Custom Map Loader uses gfxworld as the starting asset collection.AddAssetCreator(CreateCustomMapLoader(memory, searchPath, zone)); } } // namespace diff --git a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp index a7284bc7..5d30b473 100644 --- a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp +++ b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.cpp @@ -44,10 +44,10 @@ namespace }; } // namespace -namespace script +namespace T6 { - std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath) + std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath) { return std::make_unique(memory, searchPath); } -} // namespace script +} // namespace T6 diff --git a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h index ebaab5da..754da2ec 100644 --- a/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h +++ b/src/ObjLoading/Game/T6/Script/LoaderScriptT6.h @@ -7,7 +7,7 @@ #include -namespace script +namespace T6 { - std::unique_ptr> CreateLoaderT6(MemoryManager& memory, ISearchPath& searchPath); -} // namespace script + std::unique_ptr> CreateScriptLoader(MemoryManager& memory, ISearchPath& searchPath); +} // namespace T6