From 3a2d332d0c08af6b1537d4a3523a3dbbfc5d5b2d Mon Sep 17 00:00:00 2001 From: LJW-Dev <48092720+LJW-Dev@users.noreply.github.com> Date: Sat, 21 Mar 2026 17:26:20 +0800 Subject: [PATCH] feat: surface type and flags can now be set through the GLTF file --- src/ObjCommon/XModel/Gltf/JsonGltf.h | 13 +- src/ObjLoading/Game/T6/BSP/BSP.h | 155 +---------- src/ObjLoading/Game/T6/BSP/BSPCreator.cpp | 77 +++++ src/ObjLoading/Game/T6/BSP/BSPFlags.h | 263 ++++++++++++++++++ .../Game/T6/BSP/Linker/ClipMapLinker.cpp | 22 +- .../Game/T6/BSP/Linker/ClipMapLinker.h | 2 +- 6 files changed, 371 insertions(+), 161 deletions(-) create mode 100644 src/ObjLoading/Game/T6/BSP/BSPFlags.h diff --git a/src/ObjCommon/XModel/Gltf/JsonGltf.h b/src/ObjCommon/XModel/Gltf/JsonGltf.h index 0fa9749a..a38ab9fc 100644 --- a/src/ObjCommon/XModel/Gltf/JsonGltf.h +++ b/src/ObjCommon/XModel/Gltf/JsonGltf.h @@ -301,6 +301,15 @@ namespace gltf NLOHMANN_DEFINE_TYPE_EXTENSION(JsonNormalTextureInfo, index); + class JsonMaterialExtras + { + public: + std::optional type; + std::optional flags; + }; + + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterialExtras, type, flags); + class JsonMaterial { public: @@ -308,9 +317,11 @@ namespace gltf std::optional pbrMetallicRoughness; std::optional normalTexture; std::optional doubleSided; + + std::optional extras; }; - NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterial, name, pbrMetallicRoughness, normalTexture, doubleSided); + NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterial, name, pbrMetallicRoughness, normalTexture, doubleSided, extras); enum class JsonMeshPrimitivesMode { diff --git a/src/ObjLoading/Game/T6/BSP/BSP.h b/src/ObjLoading/Game/T6/BSP/BSP.h index 2635981e..731435b6 100644 --- a/src/ObjLoading/Game/T6/BSP/BSP.h +++ b/src/ObjLoading/Game/T6/BSP/BSP.h @@ -1,5 +1,6 @@ #pragma once +#include "BSPFlags.h" #include "Game/T6/T6.h" #include "Utils/Logging/Log.h" @@ -32,6 +33,9 @@ namespace BSP std::string materialName; BSPMaterialType materialType; vec4_t materialColour; + + int surfaceFlags; + int contentFlags; }; struct BSPSurface @@ -175,155 +179,4 @@ namespace BSP constexpr vec4_t SUNLIGHT_COLOR = {0.75f, 0.75f, 0.75f, 1.0f}; constexpr vec3_t SUNLIGHT_DIRECTION = {0.0f, 0.0f, 0.0f}; }; // namespace BSPEditableConstants - - namespace BSPFlags - { - // enum SurfaceType - //{ - // SURF_TYPE_BARK, - // SURF_TYPE_BRICK, - // SURF_TYPE_CARPET, - // SURF_TYPE_CLOTH, - // SURF_TYPE_CONCRETE, - // SURF_TYPE_DIRT, - // SURF_TYPE_FLESH, - // SURF_TYPE_FOLIAGE, - // SURF_TYPE_GLASS, - // SURF_TYPE_GRASS, - // SURF_TYPE_GRAVEL, - // SURF_TYPE_ICE, - // SURF_TYPE_METAL, - // SURF_TYPE_MUD, - // SURF_TYPE_PAPER, - // SURF_TYPE_PLASTER, - // SURF_TYPE_ROCK, - // SURF_TYPE_SAND, - // SURF_TYPE_SNOW, - // SURF_TYPE_WATER, - // SURF_TYPE_WOOD, - // SURF_TYPE_ASPHALT, - // SURF_TYPE_CERAMIC, - // SURF_TYPE_PLASTIC, - // SURF_TYPE_RUBBER, - // SURF_TYPE_CUSHION, - // SURF_TYPE_FRUIT, - // SURF_TYPE_PAINTEDMETAL, - // SURF_TYPE_PLAYER, - // SURF_TYPE_TALLGRASS, - // SURF_TYPE_RIOTSHIELD, - // SURF_TYPE_OPAQUEGLASS, - // SURF_TYPE_CLIPMISSILE, - // SURF_TYPE_AI_NOSIGHT, - // SURF_TYPE_CLIPSHOT, - // SURF_TYPE_PLAYERCLIP, - // SURF_TYPE_MONSTERCLIP, - // SURF_TYPE_VEHICLECLIP, - // SURF_TYPE_ITEMCLIP, - // SURF_TYPE_NODROP, - // SURF_TYPE_NONSOLID, - // SURF_TYPE_DETAIL, - // SURF_TYPE_STRUCTURAL, - // SURF_TYPE_PORTAL, - // SURF_TYPE_CANSHOOTCLIP, - // SURF_TYPE_ORIGIN, - // SURF_TYPE_SKY, - // SURF_TYPE_NOCASTSHADOW, - // SURF_TYPE_ONLYCASTSHADOW, - // SURF_TYPE_PHYSICSGEOM, - // SURF_TYPE_LIGHTPORTAL, - // SURF_TYPE_CAULK, - // SURF_TYPE_AREALIGHT, - // SURF_TYPE_SLICK, - // SURF_TYPE_NOIMPACT, - // SURF_TYPE_NOMARKS, - // SURF_TYPE_NOPENETRATE, - // SURF_TYPE_LADDER, - // SURF_TYPE_NODAMAGE, - // SURF_TYPE_MANTLEON, - // SURF_TYPE_MANTLEOVER, - // SURF_TYPE_MOUNT, - // SURF_TYPE_NOSTEPS, - // SURF_TYPE_NODRAW, - // SURF_TYPE_NORECEIVEDYNAMICSHADOW, - // SURF_TYPE_NODLIGHT, - // SURF_TYPE_COUNT - // }; - // - // struct s_SurfaceTypeFlags - //{ - // unsigned int surfaceFlags; - // unsigned int contentFlags; - // }; - // - // s_SurfaceTypeFlags surfaceTypeToFlagMap[SURF_TYPE_COUNT] = { - // {0x100000, 0 }, // bark - // {0x200000, 0 }, // brick - // {0x300000, 0 }, // carpet - // {0x400000, 0 }, // cloth - // {0x500000, 0 }, // concrete - // {0x600000, 0 }, // dirt - // {0x700000, 0 }, // flesh - // {0x800000, 2 }, // foliage - // {0x900000, 0x10 }, // glass - // {0x0A00000, 0 }, // grass - // {0x0B00000, 0 }, // gravel - // {0x0C00000, 0 }, // ice - // {0x0D00000, 0 }, // metal - // {0x0E00000, 0 }, // mud - // {0x0F00000, 0 }, // paper - // {0x1000000, 0 }, // plaster - // {0x1100000, 0 }, // rock - // {0x1200000, 0 }, // sand - // {0x1300000, 0 }, // snow - // {0x1400000, 0x20 }, // water - // {0x1500000, 0 }, // wood - // {0x1600000, 0 }, // asphalt - // {0x1700000, 0 }, // ceramic - // {0x1800000, 0 }, // plastic - // {0x1900000, 0 }, // rubber - // {0x1A00000, 0 }, // cushion - // {0x1B00000, 0 }, // fruit - // {0x1C00000, 0 }, // paintedmetal - // {0x1D00000, 0 }, // player - // {0x1E00000, 0 }, // tallgrass - // {0x1F00000, 0 }, // riotshield - // {0x900000, 0 }, // opaqueglass - // {0, 0x80 }, // clipmissile - // {0, 0x1000 }, // ai_nosight - // {0, 0x2000 }, // clipshot - // {0, 0x10000 }, // playerclip - // {0, 0x20000 }, // monsterclip - // {0, 0x200 }, // vehicleclip - // {0, 0x400 }, // itemclip - // {0, 0x80000000}, // noDrop - // {0x4000, 0 }, // nonSolid - // {0, 0x8000000 }, // detail - // {0, 0x10000000}, // structural - // {0x80000000, 0 }, // portal - // {0, 0x40 }, // canShootClip - // {0, 0 }, // origin - // {4, 0x800 }, // sky - // {0x40000, 0 }, // noCastShadow - // {0x80000, 0 }, // onlyCastShadow - // {0, 0 }, // physicsGeom - // {0, 0 }, // lightPortal - // {0x1000, 0 }, // caulk - // {0x8000, 0 }, // areaLight - // {2, 0 }, // slick - // {0x10, 0 }, // noImpact - // {0x20, 0 }, // noMarks - // {0x100, 0 }, // noPenetrate - // {8, 0 }, // ladder - // {1, 0 }, // noDamage - // {0x4000000, 0x1000000 }, // mantleOn - // {0x8000000, 0x1000000 }, // mantleOver - // {0x10000000, 0x1000000 }, // mount - // {0x2000, 0 }, // noSteps - // {0x80, 0 }, // noDraw - // {0x800, 0 }, // noReceiveDynamicShadow - // {0x20000, 0 } // noDlight - // }; - // - //// TODO: template/define to get the surface type from the surface flags - } // namespace BSPFlags } // namespace BSP diff --git a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp index 49206de7..904d7b2c 100644 --- a/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp +++ b/src/ObjLoading/Game/T6/BSP/BSPCreator.cpp @@ -1,6 +1,7 @@ #include "BSPCreator.h" #include "BSPUtil.h" +#include "Utils/StringUtils.h" #include "XModel/Gltf/GltfBinInput.h" #include "XModel/Gltf/GltfTextInput.h" #include "XModel/Gltf/Internal/GltfAccessor.h" @@ -607,6 +608,78 @@ namespace return rootNodes; } + void setMaterialFlags(BSPMaterial& material, const JsonMaterial& jsMaterial) + { + if (!jsMaterial.extras) + { + material.surfaceFlags = 1; + material.contentFlags = 1; + return; + } + if (!jsMaterial.extras->flags && !jsMaterial.extras->type) + { + material.surfaceFlags = 1; + material.contentFlags = 1; + return; + } + + material.surfaceFlags = 0; + material.contentFlags = 0; + if (jsMaterial.extras->type) + { + std::string typeStr = *jsMaterial.extras->type; + + size_t typeNameCount = std::extent::value; + for (size_t typeIdx = 0; typeIdx < typeNameCount; typeIdx++) + { + BSPFlags::SurfaceType surfType = BSPFlags::materialTypes[typeIdx]; + if (!typeStr.compare(BSPFlags::surfaceTypeToNameMap[surfType])) + { + BSPFlags::s_SurfaceTypeFlags flags = BSPFlags::surfaceTypeToFlagMap[surfType]; + material.surfaceFlags = flags.surfaceFlags; + material.contentFlags = flags.contentFlags; + break; + } + } + } + if (material.surfaceFlags == 0 && material.contentFlags == 0) + con::warn("invalid material {} type name: {}", material.materialName, *jsMaterial.extras->type); + + if (jsMaterial.extras->flags) + { + std::string flagsStr = *jsMaterial.extras->flags; + + std::vector flagStrVec = utils::StringSplit(flagsStr, ','); + for (std::string& flag : flagStrVec) + { + bool foundMatchingName = false; + utils::MakeStringLowerCase(flag); + utils::StringTrim(flag); + size_t typeNameCount = std::extent::value; + for (size_t typeIdx = 0; typeIdx < typeNameCount; typeIdx++) + { + BSPFlags::SurfaceType surfType = BSPFlags::materialFlags[typeIdx]; + if (!flag.compare(BSPFlags::surfaceTypeToNameMap[surfType])) + { + BSPFlags::s_SurfaceTypeFlags flags = BSPFlags::surfaceTypeToFlagMap[surfType]; + material.surfaceFlags |= flags.surfaceFlags; + material.contentFlags |= flags.contentFlags; + foundMatchingName = true; + break; + } + } + if (!foundMatchingName) + con::warn("invalid material {} flag name: {}", material.materialName, flag); + } + } + + // the first content flag bit must be set to 1 for the surface to have collision + if ((material.surfaceFlags & BSPFlags::surfaceTypeToFlagMap[BSPFlags::SURF_TYPE_NONSOLID].surfaceFlags) != 0) + material.contentFlags &= 0xFFFFFFFE; + else + material.contentFlags |= 1; + } + void LoadMaterials(const JsonRoot& jRoot) { if (jRoot.materials) @@ -653,6 +726,8 @@ namespace material.materialColour.w = 1.0f; } + setMaterialFlags(material, jsMaterial); + m_curr_bsp_world->materials.emplace_back(material); } } @@ -660,6 +735,8 @@ namespace // last material is used when a primitve has no material/colour data BSPMaterial colorMaterial; colorMaterial.materialType = MATERIAL_TYPE_COLOUR; + colorMaterial.surfaceFlags = 1; + colorMaterial.contentFlags = 1; colorMaterial.materialName = ""; colorMaterial.materialColour.x = 1.0f; colorMaterial.materialColour.y = 1.0f; diff --git a/src/ObjLoading/Game/T6/BSP/BSPFlags.h b/src/ObjLoading/Game/T6/BSP/BSPFlags.h new file mode 100644 index 00000000..936c1863 --- /dev/null +++ b/src/ObjLoading/Game/T6/BSP/BSPFlags.h @@ -0,0 +1,263 @@ +#pragma once + +namespace BSPFlags +{ + enum SurfaceType + { + SURF_TYPE_BARK, + SURF_TYPE_BRICK, + SURF_TYPE_CARPET, + SURF_TYPE_CLOTH, + SURF_TYPE_CONCRETE, + SURF_TYPE_DIRT, + SURF_TYPE_FLESH, + SURF_TYPE_FOLIAGE, + SURF_TYPE_GLASS, + SURF_TYPE_GRASS, + SURF_TYPE_GRAVEL, + SURF_TYPE_ICE, + SURF_TYPE_METAL, + SURF_TYPE_MUD, + SURF_TYPE_PAPER, + SURF_TYPE_PLASTER, + SURF_TYPE_ROCK, + SURF_TYPE_SAND, + SURF_TYPE_SNOW, + SURF_TYPE_WATER, + SURF_TYPE_WOOD, + SURF_TYPE_ASPHALT, + SURF_TYPE_CERAMIC, + SURF_TYPE_PLASTIC, + SURF_TYPE_RUBBER, + SURF_TYPE_CUSHION, + SURF_TYPE_FRUIT, + SURF_TYPE_PAINTEDMETAL, + SURF_TYPE_PLAYER, + SURF_TYPE_TALLGRASS, + SURF_TYPE_RIOTSHIELD, + SURF_TYPE_OPAQUEGLASS, + SURF_TYPE_CLIPMISSILE, + SURF_TYPE_AI_NOSIGHT, + SURF_TYPE_CLIPSHOT, + SURF_TYPE_PLAYERCLIP, + SURF_TYPE_MONSTERCLIP, + SURF_TYPE_VEHICLECLIP, + SURF_TYPE_ITEMCLIP, + SURF_TYPE_NODROP, + SURF_TYPE_NONSOLID, + SURF_TYPE_DETAIL, + SURF_TYPE_STRUCTURAL, + SURF_TYPE_PORTAL, + SURF_TYPE_CANSHOOTCLIP, + SURF_TYPE_ORIGIN, + SURF_TYPE_SKY, + SURF_TYPE_NOCASTSHADOW, + SURF_TYPE_ONLYCASTSHADOW, + SURF_TYPE_PHYSICSGEOM, + SURF_TYPE_LIGHTPORTAL, + SURF_TYPE_CAULK, + SURF_TYPE_AREALIGHT, + SURF_TYPE_SLICK, + SURF_TYPE_NOIMPACT, + SURF_TYPE_NOMARKS, + SURF_TYPE_NOPENETRATE, + SURF_TYPE_LADDER, + SURF_TYPE_NODAMAGE, + SURF_TYPE_MANTLEON, + SURF_TYPE_MANTLEOVER, + SURF_TYPE_MOUNT, + SURF_TYPE_NOSTEPS, + SURF_TYPE_NODRAW, + SURF_TYPE_NORECEIVEDYNAMICSHADOW, + SURF_TYPE_NODLIGHT, + SURF_TYPE_NONE, // Custom value + SURF_TYPE_COUNT + }; + + struct s_SurfaceTypeFlags + { + unsigned int surfaceFlags; + unsigned int contentFlags; + }; + + constexpr s_SurfaceTypeFlags surfaceTypeToFlagMap[SURF_TYPE_COUNT] = { + {0x100000, 0 }, // bark + {0x200000, 0 }, // brick + {0x300000, 0 }, // carpet + {0x400000, 0 }, // cloth + {0x500000, 0 }, // concrete + {0x600000, 0 }, // dirt + {0x700000, 0 }, // flesh + {0x800000, 2 }, // foliage + {0x900000, 0x10 }, // glass + {0x0A00000, 0 }, // grass + {0x0B00000, 0 }, // gravel + {0x0C00000, 0 }, // ice + {0x0D00000, 0 }, // metal + {0x0E00000, 0 }, // mud + {0x0F00000, 0 }, // paper + {0x1000000, 0 }, // plaster + {0x1100000, 0 }, // rock + {0x1200000, 0 }, // sand + {0x1300000, 0 }, // snow + {0x1400000, 0x20 }, // water + {0x1500000, 0 }, // wood + {0x1600000, 0 }, // asphalt + {0x1700000, 0 }, // ceramic + {0x1800000, 0 }, // plastic + {0x1900000, 0 }, // rubber + {0x1A00000, 0 }, // cushion + {0x1B00000, 0 }, // fruit + {0x1C00000, 0 }, // paintedmetal + {0x1D00000, 0 }, // player + {0x1E00000, 0 }, // tallgrass + {0x1F00000, 0 }, // riotshield + {0x900000, 0 }, // opaqueglass + {0, 0x80 }, // clipmissile + {0, 0x1000 }, // ai_nosight + {0, 0x2000 }, // clipshot + {0, 0x10000 }, // playerclip + {0, 0x20000 }, // monsterclip + {0, 0x200 }, // vehicleclip + {0, 0x400 }, // itemclip + {0, 0x80000000}, // noDrop + {0x4000, 0 }, // nonSolid + {0, 0x8000000 }, // detail + {0, 0x10000000}, // structural + {0x80000000, 0 }, // portal + {0, 0x40 }, // canShootClip + {0, 0 }, // origin + {4, 0x800 }, // sky + {0x40000, 0 }, // noCastShadow + {0x80000, 0 }, // onlyCastShadow + {0, 0 }, // physicsGeom + {0, 0 }, // lightPortal + {0x1000, 0 }, // caulk + {0x8000, 0 }, // areaLight + {2, 0 }, // slick + {0x10, 0 }, // noImpact + {0x20, 0 }, // noMarks + {0x100, 0 }, // noPenetrate + {8, 0 }, // ladder + {1, 0 }, // noDamage + {0x4000000, 0x1000000 }, // mantleOn + {0x8000000, 0x1000000 }, // mantleOver + {0x10000000, 0x1000000 }, // mount + {0x2000, 0 }, // noSteps + {0x80, 0 }, // noDraw + {0x800, 0 }, // noReceiveDynamicShadow + {0x20000, 0 }, // noDlight + {0, 0 } // none + }; + + constexpr SurfaceType materialTypes[] = { + SURF_TYPE_NONE, SURF_TYPE_BARK, SURF_TYPE_BRICK, SURF_TYPE_CARPET, SURF_TYPE_CLOTH, SURF_TYPE_CONCRETE, SURF_TYPE_DIRT, + SURF_TYPE_FLESH, SURF_TYPE_FOLIAGE, SURF_TYPE_GLASS, SURF_TYPE_GRASS, SURF_TYPE_GRAVEL, SURF_TYPE_ICE, SURF_TYPE_METAL, + SURF_TYPE_MUD, SURF_TYPE_PAPER, SURF_TYPE_PLASTER, SURF_TYPE_ROCK, SURF_TYPE_SAND, SURF_TYPE_SNOW, SURF_TYPE_WATER, + SURF_TYPE_WOOD, SURF_TYPE_ASPHALT, SURF_TYPE_CERAMIC, SURF_TYPE_PLASTIC, SURF_TYPE_RUBBER, SURF_TYPE_CUSHION, SURF_TYPE_FRUIT, + SURF_TYPE_PAINTEDMETAL, SURF_TYPE_PLAYER, SURF_TYPE_TALLGRASS, SURF_TYPE_RIOTSHIELD, SURF_TYPE_OPAQUEGLASS, + }; + + constexpr SurfaceType materialFlags[] = { + SURF_TYPE_NONE, + SURF_TYPE_CLIPMISSILE, + SURF_TYPE_AI_NOSIGHT, + SURF_TYPE_CLIPSHOT, + SURF_TYPE_PLAYERCLIP, + SURF_TYPE_MONSTERCLIP, + SURF_TYPE_VEHICLECLIP, + SURF_TYPE_ITEMCLIP, + SURF_TYPE_NODROP, + SURF_TYPE_NONSOLID, + SURF_TYPE_DETAIL, + SURF_TYPE_STRUCTURAL, + SURF_TYPE_PORTAL, + SURF_TYPE_CANSHOOTCLIP, + SURF_TYPE_SKY, + SURF_TYPE_NOCASTSHADOW, + SURF_TYPE_ONLYCASTSHADOW, + SURF_TYPE_CAULK, + SURF_TYPE_AREALIGHT, + SURF_TYPE_SLICK, + SURF_TYPE_NOIMPACT, + SURF_TYPE_NOMARKS, + SURF_TYPE_NOPENETRATE, + SURF_TYPE_LADDER, + SURF_TYPE_NODAMAGE, + SURF_TYPE_MANTLEON, + SURF_TYPE_MANTLEOVER, + SURF_TYPE_MOUNT, + SURF_TYPE_NOSTEPS, + SURF_TYPE_NODRAW, + SURF_TYPE_NORECEIVEDYNAMICSHADOW, + SURF_TYPE_NODLIGHT, + }; + + constexpr const char* surfaceTypeToNameMap[SURF_TYPE_COUNT] = {"bark", + "brick", + "carpet", + "cloth", + "concrete", + "dirt", + "flesh", + "foliage", + "glass", + "grass", + "gravel", + "ice", + "metal", + "mud", + "paper", + "plaster", + "rock", + "sand", + "snow", + "water", + "wood", + "asphalt", + "ceramic", + "plastic", + "rubber", + "cushion", + "fruit", + "paintedmetal", + "player", + "tallgrass", + "riotshield", + "opaqueglass", + "clipmissile", + "ai_nosight", + "clipshot", + "playerclip", + "monsterclip", + "vehicleclip", + "itemclip", + "nodrop", + "nonsolid", + "detail", + "structural", + "portal", + "canshootclip", + "origin", + "sky", + "nocastshadow", + "onlycastshadow", + "physicsgeom", + "lightportal", + "caulk", + "arealight", + "slick", + "noimpact", + "nomarks", + "nopenetrate", + "ladder", + "nodamage", + "mantleon", + "mantleover", + "mount", + "nosteps", + "nodraw", + "noreceivedynamicshadow", + "nodlight", + "none"}; +} // namespace BSPFlags diff --git a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp index fe5fe97c..1bc0d790 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp +++ b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.cpp @@ -184,9 +184,11 @@ namespace BSP currModel->origin.y = bspModel.origin.y; currModel->origin.z = bspModel.origin.z; + // tracing only checks if this is equal to 0 or not + currModel->contents = 1; + if (!xModelAsset->IsReference()) { - currModel->contents = currModel->xmodel->contents; BSPUtil::calculateXmodelBounds(currModel->xmodel, xmodelAxis, currModel->absmin, currModel->absmax); currModel->absmin.x = (currModel->absmin.x * bspModel.scale) + bspModel.origin.x; currModel->absmin.y = (currModel->absmin.y * bspModel.scale) + bspModel.origin.y; @@ -200,7 +202,6 @@ namespace BSP } else { - currModel->contents = 1; if (bspModel.areBoundsValid) { currModel->absmin = bspModel.mins; @@ -260,7 +261,7 @@ namespace BSP std::vector objectIndexes; }; - void ClipMapLinker::addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex) + void ClipMapLinker::addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex, int* out_treeContents) { assert(tree->isLeaf); BSPLeaf* bspLeaf = tree->leaf.get(); @@ -376,6 +377,9 @@ namespace BSP parentAABBArrayIndex += parentCount; } + + for (auto& matData : uniqueMaterials) + *out_treeContents |= clipMap->info.materials[matData.materialIndex].contentFlags; } constexpr vec3_t normalX = {1.0f, 0.0f, 0.0f}; @@ -404,19 +408,21 @@ namespace BSP leaf.maxs.z = 0.0f; leaf.leafBrushNode = 0; - leaf.terrainContents = 1; // todo: use correct contents if (tree->leaf->getObjectCount() > 0) { size_t parentCount = 0; size_t parentStartIndex = 0; - addAABBTreeFromLeaf(clipMap, tree, &parentCount, &parentStartIndex); + int treeContents; + addAABBTreeFromLeaf(clipMap, tree, &parentCount, &parentStartIndex, &treeContents); leaf.collAabbCount = static_cast(parentCount); leaf.firstCollAabbIndex = static_cast(parentStartIndex); + leaf.terrainContents = treeContents; } else { leaf.firstCollAabbIndex = 0; leaf.collAabbCount = 0; + leaf.terrainContents = 0; } uint16_t leafIndex = static_cast(leafVec.size()); @@ -693,8 +699,8 @@ namespace BSP BSPMaterial bspMat = bsp->colWorld.materials.at(matIdx); clipMat->name = m_memory.Dup(bspMat.materialName.c_str()); - clipMat->contentFlags = BSPEditableConstants::MATERIAL_CONTENT_FLAGS; - clipMat->surfaceFlags = BSPEditableConstants::MATERIAL_SURFACE_FLAGS; + clipMat->contentFlags = bspMat.contentFlags; + clipMat->surfaceFlags = bspMat.surfaceFlags; } return true; @@ -728,7 +734,7 @@ namespace BSP if (!loadMaterials(clipMap, bsp)) return nullptr; - if (!loadWorldCollision(clipMap, bsp)) + if (!loadWorldCollision(clipMap, bsp)) // requires materials return nullptr; loadSubModelCollision(clipMap, bsp); // requires tri verts diff --git a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.h b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.h index 38580075..65328a04 100644 --- a/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.h +++ b/src/ObjLoading/Game/T6/BSP/Linker/ClipMapLinker.h @@ -32,7 +32,7 @@ namespace BSP std::vector AABBTreeVec; size_t highestLeafObjectCount = 0; std::vector partitionToMaterialMap; - void addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex); + void addAABBTreeFromLeaf(clipMap_t* clipMap, BSPTree* tree, size_t* out_parentCount, size_t* out_parentStartIndex, int* out_treeContents); int16_t loadBSPNode(clipMap_t* clipMap, BSPTree* tree); bool loadBSPTree(clipMap_t* clipMap, BSPData* bsp); bool loadPartitions(clipMap_t* clipMap, BSPData* bsp);