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

feat: heirarchical transforms are now implemented

This commit is contained in:
LJW-Dev
2026-04-18 13:41:01 +08:00
committed by Jan Laupetin
parent e5748a59fa
commit 1d109d5e35
+35 -45
View File
@@ -359,14 +359,12 @@ namespace
return vertexOffset; return vertexOffset;
} }
bool addLightNode(const gltf::JsonNode& node) bool addLightNode(const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(m_is_world_gfx); assert(m_is_world_gfx);
assert(node.extensions); assert(node.extensions);
assert(node.extensions->KHR_lights_punctual); assert(node.extensions->KHR_lights_punctual);
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
int lightIndex = node.extensions->KHR_lights_punctual->light; int lightIndex = node.extensions->KHR_lights_punctual->light;
assert(lightIndex >= 0); assert(lightIndex >= 0);
@@ -438,13 +436,11 @@ namespace
return newMaterialIndex; return newMaterialIndex;
} }
bool addMeshNode(const JsonRoot& jRoot, const gltf::JsonNode& node) bool addMeshNode(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(node.mesh); assert(node.mesh);
assert(jRoot.meshes); assert(jRoot.meshes);
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
const auto& mesh = jRoot.meshes.value()[node.mesh.value()]; const auto& mesh = jRoot.meshes.value()[node.mesh.value()];
for (const auto& primitive : mesh.primitives) for (const auto& primitive : mesh.primitives)
{ {
@@ -559,12 +555,11 @@ namespace
} }
} }
bool addXModelNode(const JsonRoot& jRoot, const gltf::JsonNode& node) bool addXModelNode(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(node.extras); assert(node.extras);
assert(node.extras->contains("xmodel")); assert(node.extras->contains("xmodel"));
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
BSPXModel xmodel; BSPXModel xmodel;
xmodel.name = node.extras->at("xmodel"); xmodel.name = node.extras->at("xmodel");
@@ -607,13 +602,11 @@ namespace
return true; return true;
} }
bool addSpawnPointNode(const gltf::JsonNode& node) bool addSpawnPointNode(const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(node.extras); assert(node.extras);
assert(node.extras->contains("spawnpoint")); assert(node.extras->contains("spawnpoint"));
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
Eigen::Vector4f position(0, 0, 0, 1.0f); Eigen::Vector4f position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position; Eigen::Vector4f transformedPosition = nodeMatrix * position;
vec3_t origin; vec3_t origin;
@@ -650,12 +643,11 @@ namespace
return true; return true;
} }
size_t addScriptBrushModel(const JsonRoot& jRoot, const gltf::JsonNode& node) size_t addScriptBrushModel(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
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");
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
const auto& mesh = jRoot.meshes.value()[node.mesh.value()]; const auto& mesh = jRoot.meshes.value()[node.mesh.value()];
if (mesh.primitives.size() == 0) if (mesh.primitives.size() == 0)
@@ -737,12 +729,11 @@ namespace
return m_bsp->models.size(); // script model index starts at 1 return m_bsp->models.size(); // script model index starts at 1
} }
size_t addScriptTerrainModel(const JsonRoot& jRoot, const gltf::JsonNode& node) size_t addScriptTerrainModel(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
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");
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
const auto& mesh = jRoot.meshes.value()[node.mesh.value()]; const auto& mesh = jRoot.meshes.value()[node.mesh.value()];
if (mesh.primitives.size() == 0) if (mesh.primitives.size() == 0)
@@ -798,7 +789,7 @@ namespace
return m_bsp->models.size(); // script model index starts at 1 return m_bsp->models.size(); // script model index starts at 1
} }
bool addZoneNode(const JsonRoot& jRoot, const gltf::JsonNode& node) bool addZoneNode(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(node.extras); assert(node.extras);
assert(node.extras->contains("zone")); assert(node.extras->contains("zone"));
@@ -809,8 +800,6 @@ namespace
return false; return false;
} }
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
Eigen::Vector4f position(0, 0, 0, 1.0f); Eigen::Vector4f position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position; Eigen::Vector4f transformedPosition = nodeMatrix * position;
vec3_t origin; vec3_t origin;
@@ -824,19 +813,17 @@ namespace
zone.zoneName = node.extras->at("zone"); zone.zoneName = node.extras->at("zone");
zone.spawnerGroupName = node.extras->at("spawner_group"); zone.spawnerGroupName = node.extras->at("spawner_group");
zone.spawnpointGroupName = node.extras->at("spawnpoint_group"); zone.spawnpointGroupName = node.extras->at("spawnpoint_group");
zone.modelIndex = addScriptBrushModel(jRoot, node); zone.modelIndex = addScriptBrushModel(jRoot, node, nodeMatrix);
m_bsp->zm_zones.emplace_back(zone); m_bsp->zm_zones.emplace_back(zone);
return true; return true;
} }
bool addZSpawnerNode(const gltf::JsonNode& node) bool addZSpawnerNode(const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(node.extras); assert(node.extras);
assert(node.extras->contains("spawner")); assert(node.extras->contains("spawner"));
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
Eigen::Vector4f position(0, 0, 0, 1.0f); Eigen::Vector4f position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position; Eigen::Vector4f transformedPosition = nodeMatrix * position;
vec3_t origin; vec3_t origin;
@@ -866,7 +853,7 @@ namespace
return true; return true;
} }
bool addClassNode(const JsonRoot& jRoot, const gltf::JsonNode& node) bool addClassNode(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
assert(node.extras); assert(node.extras);
assert(node.extras->contains("classname")); assert(node.extras->contains("classname"));
@@ -891,15 +878,13 @@ namespace
if (node.mesh && !doesClassContainModel) if (node.mesh && !doesClassContainModel)
{ {
if (m_is_world_gfx) if (m_is_world_gfx)
entity.modelIndex = addScriptTerrainModel(jRoot, node); entity.modelIndex = addScriptTerrainModel(jRoot, node, nodeMatrix);
else else
entity.modelIndex = addScriptBrushModel(jRoot, node); entity.modelIndex = addScriptBrushModel(jRoot, node, nodeMatrix);
} }
else else
entity.modelIndex = 0; entity.modelIndex = 0;
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
Eigen::Vector4f position(0, 0, 0, 1.0f); Eigen::Vector4f position(0, 0, 0, 1.0f);
Eigen::Vector4f transformedPosition = nodeMatrix * position; Eigen::Vector4f transformedPosition = nodeMatrix * position;
entity.origin.x = transformedPosition.x(); entity.origin.x = transformedPosition.x();
@@ -920,37 +905,37 @@ namespace
return true; return true;
} }
bool addNodeToBSP(const JsonRoot& jRoot, const gltf::JsonNode& node) bool addNodeToBSP(const JsonRoot& jRoot, const gltf::JsonNode& node, Eigen::Matrix4f& nodeMatrix)
{ {
if (m_is_world_gfx && node.extensions && node.extensions->KHR_lights_punctual) if (m_is_world_gfx && node.extensions && node.extensions->KHR_lights_punctual)
return addLightNode(node); return addLightNode(node, nodeMatrix);
if (node.extras) if (node.extras)
{ {
if (!m_is_world_gfx) if (!m_is_world_gfx)
{ {
if (node.extras->contains("classname")) if (node.extras->contains("classname"))
return addClassNode(jRoot, node); return addClassNode(jRoot, node, nodeMatrix);
if (node.extras->contains("spawnpoint")) if (node.extras->contains("spawnpoint"))
return addSpawnPointNode(node); return addSpawnPointNode(node, nodeMatrix);
if (m_bsp->isZombiesMap) if (m_bsp->isZombiesMap)
{ {
if (node.extras->contains("zone")) if (node.extras->contains("zone"))
return addZoneNode(jRoot, node); return addZoneNode(jRoot, node, nodeMatrix);
if (node.extras->contains("spawner")) if (node.extras->contains("spawner"))
return addZSpawnerNode(node); return addZSpawnerNode(node, nodeMatrix);
} }
} }
if (node.extras->contains("xmodel")) if (node.extras->contains("xmodel"))
return addXModelNode(jRoot, node); return addXModelNode(jRoot, node, nodeMatrix);
} }
if (node.mesh) if (node.mesh)
return addMeshNode(jRoot, node); return addMeshNode(jRoot, node, nodeMatrix);
return false; return false;
} }
@@ -1155,27 +1140,32 @@ namespace
if (!jRoot.nodes || jRoot.nodes->empty()) if (!jRoot.nodes || jRoot.nodes->empty())
return; return;
std::deque<unsigned> nodeQueue; struct s_nodes
const std::vector<unsigned> rootNodes = GetRootNodes(jRoot); {
unsigned int nodeIndex;
Eigen::Matrix4f parentNodeMatrix;
};
for (const auto rootNode : rootNodes) std::deque<s_nodes> nodeQueue;
nodeQueue.emplace_back(rootNode); for (const auto rootNode : GetRootNodes(jRoot))
nodeQueue.emplace_back(s_nodes{rootNode, Eigen::Matrix4f::Identity()});
while (!nodeQueue.empty()) while (!nodeQueue.empty())
{ {
const auto& node = jRoot.nodes.value()[nodeQueue.front()]; const auto& node = jRoot.nodes.value()[nodeQueue.front().nodeIndex];
Eigen::Matrix4f parentNodeMatrix = nodeQueue.front().parentNodeMatrix;
nodeQueue.pop_front(); nodeQueue.pop_front();
Eigen::Matrix4f nodeMatrix = createNodeMatrix(node);
Eigen::Matrix4f transformedNodeMatrix = parentNodeMatrix * nodeMatrix;
if (node.children) if (node.children)
{ {
for (const auto childIndex : *node.children) for (const auto childIndex : *node.children)
nodeQueue.emplace_back(childIndex); nodeQueue.emplace_back(s_nodes{childIndex, transformedNodeMatrix});
if (node.matrix || node.translation || node.rotation || node.scale)
con::warn("Parent node has position data that won't be used");
} }
if (!addNodeToBSP(jRoot, node)) if (!addNodeToBSP(jRoot, node, transformedNodeMatrix))
con::warn("({}) Ignoring node: {}", getWorldTypeName(), node.name.value_or("unnamed node")); con::warn("({}) Ignoring node: {}", getWorldTypeName(), node.name.value_or("unnamed node"));
} }
} }