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

feat: proper implementation of GFX models and refactor of node ignore/allow

This commit is contained in:
LJW-Dev
2026-04-23 23:52:22 +08:00
committed by Jan Laupetin
parent 0bd1e29ccc
commit fa2a520eb4
+68 -39
View File
@@ -444,7 +444,30 @@ namespace
return true; return true;
} }
size_t createMaterialWithFlags(size_t originalMaterialIdx, const std::string& flags, bool& isNoDrawFlagSet) bool getSurfaceAndContentFlags(const std::string& flagStr, int& surfaceFlags, int& contentFlags)
{
bool matchedAnyFlag = false;
std::vector<std::string> flagStrVec = utils::StringSplit(flagStr, ',');
for (std::string& flag : flagStrVec)
{
utils::MakeStringLowerCase(flag);
utils::StringTrim(flag);
for (size_t typeIdx = 0; typeIdx < BSPFlags::SURF_TYPE_COUNT; typeIdx++)
{
if (!flag.compare(BSPFlags::surfaceTypeToNameMap[typeIdx]))
{
BSPFlags::s_SurfaceTypeFlags flags = BSPFlags::surfaceTypeToFlagMap[typeIdx];
surfaceFlags |= flags.surfaceFlags;
contentFlags |= flags.contentFlags;
matchedAnyFlag = true;
break;
}
}
}
return matchedAnyFlag;
}
size_t createMaterialWithFlags(size_t originalMaterialIdx, const std::string& flags)
{ {
BSPMaterial newMaterial = m_curr_bsp_world->materials.at(originalMaterialIdx); BSPMaterial newMaterial = m_curr_bsp_world->materials.at(originalMaterialIdx);
@@ -481,11 +504,6 @@ namespace
else else
newMaterial.contentFlags |= 1; 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(); size_t newMaterialIndex = m_curr_bsp_world->materials.size();
m_curr_bsp_world->materials.emplace_back(newMaterial); m_curr_bsp_world->materials.emplace_back(newMaterial);
return newMaterialIndex; return newMaterialIndex;
@@ -522,12 +540,7 @@ namespace
else else
materialIndex = m_emptyMaterialIndex; materialIndex = m_emptyMaterialIndex;
if (node.extras && node.extras->contains("flags")) if (node.extras && node.extras->contains("flags"))
{ materialIndex = createMaterialWithFlags(materialIndex, node.extras->at("flags"));
bool isNoDrawFlagSet = false;
materialIndex = createMaterialWithFlags(materialIndex, node.extras->at("flags"), isNoDrawFlagSet);
if (isNoDrawFlagSet && m_is_world_gfx)
continue; // noDraw flag doesn't work, so remove the surface from the graphics data instead
}
BSPSurface surface; BSPSurface surface;
CreateSurface(accessorsForVertex, nodeMatrix, materialIndex, false, surface); CreateSurface(accessorsForVertex, nodeMatrix, materialIndex, false, surface);
@@ -695,6 +708,8 @@ namespace
size_t addScriptBrushModel(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix) size_t addScriptBrushModel(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(!m_is_world_gfx);
if (!node.mesh || !jRoot.meshes) if (!node.mesh || !jRoot.meshes)
throw new GltfLoadException("Script model created with no mesh data"); throw new GltfLoadException("Script model created with no mesh data");
@@ -721,10 +736,7 @@ namespace
size_t materialIndex = m_emptyMaterialIndex; size_t materialIndex = m_emptyMaterialIndex;
if (node.extras && node.extras->contains("flags")) if (node.extras && node.extras->contains("flags"))
{ materialIndex = createMaterialWithFlags(materialIndex, node.extras->at("flags"));
bool isNoDrawFlagSet;
materialIndex = createMaterialWithFlags(materialIndex, node.extras->at("flags"), isNoDrawFlagSet);
}
BSPBoxBrush boxBrush; BSPBoxBrush boxBrush;
boxBrush.vertexIndex = m_curr_bsp_world->boxBrushVerts.size(); boxBrush.vertexIndex = m_curr_bsp_world->boxBrushVerts.size();
boxBrush.contentFlags = m_curr_bsp_world->materials.at(materialIndex).contentFlags; boxBrush.contentFlags = m_curr_bsp_world->materials.at(materialIndex).contentFlags;
@@ -818,10 +830,7 @@ namespace
{ {
size_t originalMaterialIdx = *primitive.material; size_t originalMaterialIdx = *primitive.material;
if (node.extras && node.extras->contains("flags")) if (node.extras && node.extras->contains("flags"))
{ materialIndex = createMaterialWithFlags(originalMaterialIdx, node.extras->at("flags"));
bool isNoDrawFlagSet;
materialIndex = createMaterialWithFlags(originalMaterialIdx, node.extras->at("flags"), isNoDrawFlagSet);
}
else else
materialIndex = originalMaterialIdx; materialIndex = originalMaterialIdx;
} }
@@ -906,32 +915,37 @@ namespace
assert(node.extras->contains("classname")); assert(node.extras->contains("classname"));
BSPEntity entity; BSPEntity entity;
std::string classname = node.extras->at("classname");
if (node.mesh && (classname.starts_with("trigger_") || !classname.compare("info_volume") || !classname.compare("script_brushmodel")))
{
if (node.extras->contains("model"))
{
con::error("Node {} cannot have a model property when its class is a trigger, info_volume or script_brushmodel");
return false;
}
if (m_is_world_gfx) std::string classname = node.extras->at("classname");
entity.modelIndex = addScriptTerrainModel(jRoot, node, nodeMatrix); if (!classname.compare("script_brushmodel_gfx") || !classname.compare("script_brushmodel_tris"))
else entity.modelIndex = addScriptTerrainModel(jRoot, node, nodeMatrix);
entity.modelIndex = addScriptBrushModel(jRoot, node, nodeMatrix); else if ((!classname.compare("script_brushmodel_box") || !classname.compare("script_brushmodel"))
} || (classname.starts_with("trigger_") || !classname.compare("info_volume")))
entity.modelIndex = addScriptBrushModel(jRoot, node, nodeMatrix);
else else
entity.modelIndex = 0; entity.modelIndex = 0;
if (entity.modelIndex != 0 && node.extras->contains("model"))
{
con::error("Node {} cannot have a model property when its class is a trigger, info_volume, script_brushmodel_gfx, script_brushmodel_tris, "
"script_brushmodel_box or script_brushmodel");
return false;
}
for (auto& element : node.extras->items()) for (auto& element : node.extras->items())
{ {
std::string key = element.key(); std::string key = element.key();
std::string value = element.value();
if (!key.compare("origin") || !key.compare("angles") || !key.compare("flags")) if (!key.compare("origin") || !key.compare("angles") || !key.compare("flags"))
continue; continue;
if (!key.compare("classname")
&& (!value.compare("script_brushmodel_gfx") || !value.compare("script_brushmodel_tris") || !value.compare("script_brushmodel_box")))
value = "script_brushmodel";
BSPEntityEntry entry; BSPEntityEntry entry;
entry.key = key; entry.key = key;
entry.value = element.value(); entry.value = value;
entity.entries.emplace_back(entry); entity.entries.emplace_back(entry);
} }
@@ -976,11 +990,17 @@ namespace
if (node.extras) if (node.extras)
{ {
if (node.extras->contains("classname"))
{
std::string classnameVal = node.extras->at("classname");
if ((m_is_world_gfx && !classnameVal.compare("script_brushmodel_gfx")) // make sure only GFX loads script_brushmodel_gfx
|| (!m_is_world_gfx && classnameVal.compare("script_brushmodel_gfx")))
return addClassNode(jRoot, node, nodeMatrix);
}
if (!m_is_world_gfx) if (!m_is_world_gfx)
{ {
if (node.extras->contains("classname"))
return addClassNode(jRoot, node, nodeMatrix);
if (node.extras->contains("spawnpoint")) if (node.extras->contains("spawnpoint"))
return addSpawnPointNode(node, nodeMatrix); return addSpawnPointNode(node, nodeMatrix);
@@ -999,7 +1019,16 @@ namespace
} }
if (node.mesh) if (node.mesh)
return addMeshNode(jRoot, node, nodeMatrix); {
int surfaceFlags = 0;
int contentFlags = 0;
if (node.extras && node.extras->contains("flags"))
getSurfaceAndContentFlags(node.extras->at("flags"), surfaceFlags, contentFlags);
if (!m_is_world_gfx
|| ((surfaceFlags & BSPFlags::surfaceTypeToFlagMap[BSPFlags::SURF_TYPE_NODRAW].surfaceFlags) == 0)) // ignore if gfx mesh has nodraw flag
return addMeshNode(jRoot, node, nodeMatrix);
}
return false; return false;
} }
@@ -1060,7 +1089,7 @@ namespace
material.materialColour.w = 1.0f; material.materialColour.w = 1.0f;
material.surfaceFlags = 0; material.surfaceFlags = 0;
material.contentFlags = 1; material.contentFlags = 0;
if (jsMaterial.extras && jsMaterial.extras->type) if (jsMaterial.extras && jsMaterial.extras->type)
{ {
bool foundType = false; bool foundType = false;