2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 08:42:35 +00:00

feat: moved surface type to material extras, and surface flags to the node extras

This commit is contained in:
LJW-Dev
2026-03-22 16:25:28 +08:00
committed by Jan Laupetin
parent 3a2d332d0c
commit 2039658737
2 changed files with 109 additions and 92 deletions
+4 -3
View File
@@ -91,9 +91,11 @@ namespace gltf
public: public:
std::optional<std::string> xmodel; std::optional<std::string> xmodel;
std::optional<std::string> spawnpoint; std::optional<std::string> spawnpoint;
std::optional<std::string> flags;
}; };
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonNodeExtras, xmodel, spawnpoint); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonNodeExtras, xmodel, spawnpoint, flags);
class JsonNode class JsonNode
{ {
@@ -305,10 +307,9 @@ namespace gltf
{ {
public: public:
std::optional<std::string> type; std::optional<std::string> type;
std::optional<std::string> flags;
}; };
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterialExtras, type, flags); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonMaterialExtras, type);
class JsonMaterial class JsonMaterial
{ {
+105 -89
View File
@@ -22,6 +22,8 @@
#include <numbers> #include <numbers>
#include <string> #include <string>
using namespace BSPFlags;
namespace namespace
{ {
struct AccessorsForVertex struct AccessorsForVertex
@@ -95,6 +97,7 @@ namespace
BSPData* m_bsp; BSPData* m_bsp;
BSPWorld* m_curr_bsp_world; BSPWorld* m_curr_bsp_world;
bool m_is_world_gfx; bool m_is_world_gfx;
size_t m_emptyMaterialIndex;
std::vector<std::unique_ptr<Accessor>> m_accessors; std::vector<std::unique_ptr<Accessor>> m_accessors;
std::vector<std::unique_ptr<BufferView>> m_buffer_views; std::vector<std::unique_ptr<BufferView>> m_buffer_views;
@@ -362,6 +365,53 @@ namespace
return true; return true;
} }
size_t createMaterialWithFlags(size_t originalMaterialIdx, const std::string& flags, bool& isNoDrawFlagSet)
{
BSPMaterial newMaterial = m_curr_bsp_world->materials.at(originalMaterialIdx);
bool matchedAnyFlag = false;
std::vector<std::string> flagStrVec = utils::StringSplit(flags, ',');
for (std::string& flag : flagStrVec)
{
bool foundMatchingName = false;
utils::MakeStringLowerCase(flag);
utils::StringTrim(flag);
size_t typeNameCount = std::extent<decltype(BSPFlags::materialFlags)>::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];
newMaterial.surfaceFlags |= flags.surfaceFlags;
newMaterial.contentFlags |= flags.contentFlags;
foundMatchingName = true;
matchedAnyFlag = true;
break;
}
}
if (!foundMatchingName)
con::warn("invalid surface using material {} flag name: {}", newMaterial.materialName, flag);
}
if (!matchedAnyFlag)
return originalMaterialIdx;
// the first content flag bit must be set to 1 for the surface to have collision
if ((newMaterial.surfaceFlags & BSPFlags::surfaceTypeToFlagMap[BSPFlags::SURF_TYPE_NONSOLID].surfaceFlags) != 0)
newMaterial.contentFlags &= 0xFFFFFFFE;
else
newMaterial.contentFlags |= 1;
if ((newMaterial.surfaceFlags & BSPFlags::surfaceTypeToFlagMap[BSPFlags::SURF_TYPE_NODRAW].surfaceFlags) != 0)
isNoDrawFlagSet = true;
else
isNoDrawFlagSet = false;
size_t newMaterialIndex = m_curr_bsp_world->materials.size();
m_curr_bsp_world->materials.emplace_back(newMaterial);
return newMaterialIndex;
}
bool addMeshNode(const JsonRoot& jRoot, const gltf::JsonNode& node) bool addMeshNode(const JsonRoot& jRoot, const gltf::JsonNode& node)
{ {
assert(node.mesh); assert(node.mesh);
@@ -389,11 +439,25 @@ namespace
.m_index_accessor = *primitive.indices, .m_index_accessor = *primitive.indices,
}; };
BSPSurface surface; size_t materialIndex;
if (primitive.material) if (primitive.material)
surface.materialIndex = *primitive.material; {
size_t originalMaterialIdx = *primitive.material;
if (node.extras && node.extras->flags)
{
bool isNoDrawFlagSet = false;
materialIndex = createMaterialWithFlags(originalMaterialIdx, *node.extras->flags, isNoDrawFlagSet);
if (isNoDrawFlagSet && m_is_world_gfx)
continue; // noDraw flag doesn't work, so remove the surface from the graphics data instead
}
else
materialIndex = originalMaterialIdx;
}
else else
surface.materialIndex = m_curr_bsp_world->materials.size() - 1; // last material is used for colour only meshes materialIndex = m_emptyMaterialIndex;
BSPSurface surface;
surface.materialIndex = materialIndex;
vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour; vec4_t vertexColour = m_curr_bsp_world->materials.at(surface.materialIndex).materialColour;
CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour); CreateVertices(accessorsForVertex, nodeMatrix, surface, vertexColour);
@@ -608,78 +672,6 @@ namespace
return rootNodes; 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<decltype(BSPFlags::materialTypes)>::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<std::string> flagStrVec = utils::StringSplit(flagsStr, ',');
for (std::string& flag : flagStrVec)
{
bool foundMatchingName = false;
utils::MakeStringLowerCase(flag);
utils::StringTrim(flag);
size_t typeNameCount = std::extent<decltype(BSPFlags::materialFlags)>::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) void LoadMaterials(const JsonRoot& jRoot)
{ {
if (jRoot.materials) if (jRoot.materials)
@@ -726,23 +718,43 @@ namespace
material.materialColour.w = 1.0f; material.materialColour.w = 1.0f;
} }
setMaterialFlags(material, jsMaterial); material.surfaceFlags = 0;
material.contentFlags = 1;
if (jsMaterial.extras && jsMaterial.extras->type)
{
bool foundType = false;
size_t typeNameCount = std::extent<decltype(BSPFlags::materialTypes)>::value;
for (size_t typeIdx = 0; typeIdx < typeNameCount; typeIdx++)
{
BSPFlags::SurfaceType surfType = BSPFlags::materialTypes[typeIdx];
if (!jsMaterial.extras->type->compare(BSPFlags::surfaceTypeToNameMap[surfType]))
{
BSPFlags::s_SurfaceTypeFlags flags = BSPFlags::surfaceTypeToFlagMap[surfType];
material.surfaceFlags |= flags.surfaceFlags;
material.contentFlags |= flags.contentFlags;
foundType = true;
break;
}
}
if (!foundType)
con::warn("invalid material {} type name: {}", material.materialName, *jsMaterial.extras->type);
}
m_curr_bsp_world->materials.emplace_back(material); m_curr_bsp_world->materials.emplace_back(material);
} }
} }
// last material is used when a primitve has no material/colour data m_emptyMaterialIndex = m_curr_bsp_world->materials.size();
BSPMaterial colorMaterial; BSPMaterial emptyMaterial;
colorMaterial.materialType = MATERIAL_TYPE_COLOUR; emptyMaterial.materialType = MATERIAL_TYPE_COLOUR;
colorMaterial.surfaceFlags = 1; emptyMaterial.surfaceFlags = 0;
colorMaterial.contentFlags = 1; emptyMaterial.contentFlags = 1;
colorMaterial.materialName = ""; emptyMaterial.materialName = "";
colorMaterial.materialColour.x = 1.0f; emptyMaterial.materialColour.x = 1.0f;
colorMaterial.materialColour.y = 1.0f; emptyMaterial.materialColour.y = 1.0f;
colorMaterial.materialColour.z = 1.0f; emptyMaterial.materialColour.z = 1.0f;
colorMaterial.materialColour.w = 1.0f; emptyMaterial.materialColour.w = 1.0f;
m_curr_bsp_world->materials.emplace_back(colorMaterial); m_curr_bsp_world->materials.emplace_back(emptyMaterial);
} }
void LoadLights(const JsonRoot& jRoot) void LoadLights(const JsonRoot& jRoot)
@@ -1037,6 +1049,9 @@ namespace BSP
return nullptr; return nullptr;
if (!loader.addGLTFDataToBSP(input, true)) if (!loader.addGLTFDataToBSP(input, true))
return nullptr; return nullptr;
if (!seperateColFile)
if (!loader.addGLTFDataToBSP(input, false))
return nullptr;
} }
else else
{ {
@@ -1045,6 +1060,9 @@ namespace BSP
return nullptr; return nullptr;
if (!loader.addGLTFDataToBSP(input, true)) if (!loader.addGLTFDataToBSP(input, true))
return nullptr; return nullptr;
if (!seperateColFile)
if (!loader.addGLTFDataToBSP(input, false))
return nullptr;
} }
if (seperateColFile) if (seperateColFile)
@@ -1066,8 +1084,6 @@ namespace BSP
return nullptr; return nullptr;
} }
} }
else
bsp->colWorld = bsp->gfxWorld;
return bsp; return bsp;
} }