From a2d5c7d87b1b61572d2ea40afe9575075276cbb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C3=81vila?= Date: Wed, 6 Dec 2017 19:43:18 +0100 Subject: [PATCH] Fix duplicate name issues (#51) Fix the naming issues. Now the nodes are identified by pNode->GetUniqueID(), instead of its name. All dictionaries and references to nodes are replaced by its id, instead of its name. --- src/Fbx2Raw.cpp | 51 ++++++++++++++++++++++++------------------------ src/Raw2Gltf.cpp | 28 +++++++++++++------------- src/RawModel.cpp | 29 ++++++++++++++------------- src/RawModel.h | 25 ++++++++++++------------ 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/Fbx2Raw.cpp b/src/Fbx2Raw.cpp index 61b241f..d8fafc7 100644 --- a/src/Fbx2Raw.cpp +++ b/src/Fbx2Raw.cpp @@ -424,7 +424,7 @@ public: inverseBindMatrices.emplace_back(globalBindposeInverseMatrix); jointNodes.push_back(cluster->GetLink()); - jointNames.push_back(*cluster->GetLink()->GetName() != '\0' ? cluster->GetLink()->GetName() : cluster->GetName()); + jointIds.push_back(cluster->GetLink()->GetUniqueID()); const FbxAMatrix globalNodeTransform = cluster->GetLink()->EvaluateGlobalTransform(); jointSkinningTransforms.push_back(FbxMatrix(globalNodeTransform * globalBindposeInverseMatrix)); @@ -486,9 +486,9 @@ public: return jointNodes[jointIndex]; } - const char *GetJointName(const int jointIndex) const + const long GetJointId(const int jointIndex) const { - return jointNames[jointIndex].c_str(); + return jointIds[jointIndex]; } const FbxMatrix &GetJointSkinningTransform(const int jointIndex) const @@ -501,10 +501,10 @@ public: return jointInverseGlobalTransforms[jointIndex]; } - const char *GetRootNode() const + const long GetRootNode() const { assert(rootIndex != -1); - return jointNames[rootIndex].c_str(); + return jointIds[rootIndex]; } const FbxAMatrix &GetInverseBindMatrix(const int jointIndex) const @@ -526,7 +526,7 @@ public: private: int rootIndex; - std::vector jointNames; + std::vector jointIds; std::vector jointNodes; std::vector jointSkinningTransforms; std::vector jointInverseGlobalTransforms; @@ -697,7 +697,7 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: const long surfaceId = pMesh->GetUniqueID(); // Associate the node to this surface - int nodeId = raw.GetNodeByName(pNode->GetName()); + int nodeId = raw.GetNodeById(pNode->GetUniqueID()); if (nodeId >= 0) { RawNode &node = raw.GetNode(nodeId); node.surfaceId = surfaceId; @@ -725,7 +725,7 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: if (verboseOutput) { fmt::printf( "mesh %d: %s (skinned: %s)\n", rawSurfaceIndex, meshName, - skinning.IsSkinned() ? skinning.GetRootNode() : "NO"); + skinning.IsSkinned() ? raw.GetNode(raw.GetNodeById(skinning.GetRootNode())).name.c_str() : "NO"); } // The FbxNode geometric transformation describes how a FbxNodeAttribute is offset from @@ -758,12 +758,12 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: RawSurface &rawSurface = raw.GetSurface(rawSurfaceIndex); - rawSurface.skeletonRootName = (skinning.IsSkinned()) ? skinning.GetRootNode() : pNode->GetName(); + rawSurface.skeletonRootId = (skinning.IsSkinned()) ? skinning.GetRootNode() : pNode->GetUniqueID(); for (int jointIndex = 0; jointIndex < skinning.GetNodeCount(); jointIndex++) { - const char *jointName = skinning.GetJointName(jointIndex); - raw.GetNode(raw.GetNodeByName(jointName)).isJoint = true; + const long jointId = skinning.GetJointId(jointIndex); + raw.GetNode(raw.GetNodeById(jointId)).isJoint = true; - rawSurface.jointNames.emplace_back(jointName); + rawSurface.jointIds.emplace_back(jointId); rawSurface.inverseBindMatrices.push_back(toMat4f(skinning.GetInverseBindMatrix(jointIndex))); rawSurface.jointGeometryMins.emplace_back(FLT_MAX, FLT_MAX, FLT_MAX); rawSurface.jointGeometryMaxs.emplace_back(-FLT_MAX, -FLT_MAX, -FLT_MAX); @@ -988,12 +988,12 @@ static void ReadCamera(RawModel &raw, FbxScene *pScene, FbxNode *pNode) const FbxCamera *pCamera = pNode->GetCamera(); if (pCamera->ProjectionType.Get() == FbxCamera::EProjectionType::ePerspective) { raw.AddCameraPerspective( - "", pNode->GetName(), (float) pCamera->FilmAspectRatio, + "", pNode->GetUniqueID(), (float) pCamera->FilmAspectRatio, (float) pCamera->FieldOfViewX, (float) pCamera->FieldOfViewX, (float) pCamera->NearPlane, (float) pCamera->FarPlane); } else { raw.AddCameraOrthographic( - "", pNode->GetName(), + "", pNode->GetUniqueID(), (float) pCamera->OrthoZoom, (float) pCamera->OrthoZoom, (float) pCamera->FarPlane, (float) pCamera->NearPlane); } @@ -1069,10 +1069,11 @@ static FbxVector4 computeLocalScale(FbxNode *pNode, FbxTime pTime = FBXSDK_TIME_ static void ReadNodeHierarchy( RawModel &raw, FbxScene *pScene, FbxNode *pNode, - const std::string &parentName, const std::string &path) + const long parentId, const std::string &path) { + const FbxUInt64 nodeId = pNode->GetUniqueID(); const char *nodeName = pNode->GetName(); - const int nodeIndex = raw.AddNode(nodeName, parentName.c_str()); + const int nodeIndex = raw.AddNode(nodeId, nodeName, parentId); RawNode &node = raw.GetNode(nodeIndex); FbxTransform::EInheritType lInheritType; @@ -1085,7 +1086,7 @@ static void ReadNodeHierarchy( static int warnRrSsCount = 0; static int warnRrsCount = 0; - if (lInheritType == FbxTransform::eInheritRrSs && !parentName.empty()) { + if (lInheritType == FbxTransform::eInheritRrSs && parentId) { if (++warnRrSsCount == 1) { fmt::printf("Warning: node %s uses unsupported transform inheritance type 'eInheritRrSs'.\n", newPath); fmt::printf(" (Further warnings of this type squelched.)\n"); @@ -1112,19 +1113,19 @@ static void ReadNodeHierarchy( node.rotation = toQuatf(localRotation); node.scale = toVec3f(localScaling); - if (parentName.size() > 0) { - RawNode &parentNode = raw.GetNode(raw.GetNodeByName(parentName.c_str())); + if (parentId) { + RawNode &parentNode = raw.GetNode(raw.GetNodeById(parentId)); // Add unique child name to the parent node. - if (std::find(parentNode.childNames.begin(), parentNode.childNames.end(), nodeName) == parentNode.childNames.end()) { - parentNode.childNames.push_back(nodeName); + if (std::find(parentNode.childIds.begin(), parentNode.childIds.end(), nodeId) == parentNode.childIds.end()) { + parentNode.childIds.push_back(nodeId); } } else { // If there is no parent then this is the root node. - raw.SetRootNode(nodeName); + raw.SetRootNode(nodeId); } for (int child = 0; child < pNode->GetChildCount(); child++) { - ReadNodeHierarchy(raw, pScene, pNode->GetChild(child), nodeName, newPath); + ReadNodeHierarchy(raw, pScene, pNode->GetChild(child), nodeId, newPath); } } @@ -1180,7 +1181,7 @@ static void ReadAnimations(RawModel &raw, FbxScene *pScene) bool hasMorphs = false; RawChannel channel; - channel.nodeIndex = raw.GetNodeByName(pNode->GetName()); + channel.nodeIndex = raw.GetNodeById(pNode->GetUniqueID()); for (FbxLongLong frameIndex = firstFrameIndex; frameIndex <= lastFrameIndex; frameIndex++) { FbxTime pTime; @@ -1423,7 +1424,7 @@ bool LoadFBXFile(RawModel &raw, const char *fbxFileName, const char *textureExte FbxSystemUnit::m.ConvertScene(pScene); } - ReadNodeHierarchy(raw, pScene, pScene->GetRootNode(), "", ""); + ReadNodeHierarchy(raw, pScene, pScene->GetRootNode(), 0, ""); ReadNodeAttributes(raw, pScene, pScene->GetRootNode(), textureLocations); ReadAnimations(raw, pScene); diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index 943cc88..eaa034d 100644 --- a/src/Raw2Gltf.cpp +++ b/src/Raw2Gltf.cpp @@ -304,7 +304,7 @@ ModelData *Raw2Gltf( std::unique_ptr gltf(new GLTFData(options.outputBinary)); - std::map> nodesByName; + std::map> nodesById; std::map> materialsByName; std::map> textureByIndicesKey; std::map> meshBySurfaceId; @@ -326,13 +326,13 @@ ModelData *Raw2Gltf( auto nodeData = gltf->nodes.hold( new NodeData(node.name, node.translation, node.rotation, node.scale, node.isJoint)); - for (const auto &childName : node.childNames) { - int childIx = raw.GetNodeByName(childName.c_str()); + for (const auto &childId : node.childIds) { + int childIx = raw.GetNodeById(childId); assert(childIx >= 0); nodeData->AddChildNode(childIx); } - assert(nodesByName.find(nodeData->name) == nodesByName.end()); - nodesByName.insert(std::make_pair(nodeData->name, nodeData)); + + nodesById.insert(std::make_pair(node.id, nodeData)); } // @@ -367,7 +367,7 @@ ModelData *Raw2Gltf( channel.scales.size(), channel.weights.size()); } - NodeData &nDat = require(nodesByName, node.name); + NodeData &nDat = require(nodesById, node.id); if (!channel.translations.empty()) { aDat.AddNodeChannel(nDat, *gltf->AddAccessorAndView(buffer, GLT_VEC3F, channel.translations), "translation"); } @@ -1081,7 +1081,7 @@ ModelData *Raw2Gltf( // // surface skin // - if (!rawSurface.jointNames.empty()) { + if (!rawSurface.jointIds.empty()) { if (nodeData->skin == -1) { // glTF uses column-major matrices std::vector inverseBindMatrices; @@ -1090,14 +1090,14 @@ ModelData *Raw2Gltf( } std::vector jointIndexes; - for (const auto &jointName : rawSurface.jointNames) { - jointIndexes.push_back(require(nodesByName, jointName).ix); + for (const auto &jointId : rawSurface.jointIds) { + jointIndexes.push_back(require(nodesById, jointId).ix); } // Write out inverseBindMatrices auto accIBM = gltf->AddAccessorAndView(buffer, GLT_MAT4F, inverseBindMatrices); - auto skeletonRoot = require(nodesByName, rawSurface.skeletonRootName); + auto skeletonRoot = require(nodesById, rawSurface.skeletonRootId); auto skin = *gltf->skins.hold(new SkinData(jointIndexes, *accIBM, skeletonRoot)); nodeData->SetSkin(skin.ix); } @@ -1129,16 +1129,16 @@ ModelData *Raw2Gltf( } // Add the camera to the node hierarchy. - auto iter = nodesByName.find(cam.nodeName); - if (iter == nodesByName.end()) { - fmt::printf("Warning: Camera node name %s does not exist.\n", cam.nodeName); + auto iter = nodesById.find(cam.nodeId); + if (iter == nodesById.end()) { + fmt::printf("Warning: Camera node id %s does not exist.\n", cam.nodeId); continue; } iter->second->SetCamera(camera.ix); } } - NodeData &rootNode = require(nodesByName, "RootNode"); + NodeData &rootNode = require(nodesById, raw.GetRootNode()); const SceneData &rootScene = *gltf->scenes.hold(new SceneData(defaultSceneName, rootNode)); if (options.outputBinary) { diff --git a/src/RawModel.cpp b/src/RawModel.cpp index 712c799..98eb337 100644 --- a/src/RawModel.cpp +++ b/src/RawModel.cpp @@ -193,8 +193,8 @@ int RawModel::AddAnimation(const RawAnimation &animation) int RawModel::AddNode(const RawNode &node) { for (size_t i = 0; i < nodes.size(); i++) { - if (Gltf::StringUtils::CompareNoCase(nodes[i].name.c_str(), node.name) == 0) { - return (int) i; + if (nodes[i].id == node.id) { + return (int)i; } } @@ -203,12 +203,12 @@ int RawModel::AddNode(const RawNode &node) } int RawModel::AddCameraPerspective( - const char *name, const char *nodeName, const float aspectRatio, const float fovDegreesX, const float fovDegreesY, const float nearZ, + const char *name, const long nodeId, const float aspectRatio, const float fovDegreesX, const float fovDegreesY, const float nearZ, const float farZ) { RawCamera camera; camera.name = name; - camera.nodeName = nodeName; + camera.nodeId = nodeId; camera.mode = RawCamera::CAMERA_MODE_PERSPECTIVE; camera.perspective.aspectRatio = aspectRatio; camera.perspective.fovDegreesX = fovDegreesX; @@ -220,11 +220,11 @@ int RawModel::AddCameraPerspective( } int RawModel::AddCameraOrthographic( - const char *name, const char *nodeName, const float magX, const float magY, const float nearZ, const float farZ) + const char *name, const long nodeId, const float magX, const float magY, const float nearZ, const float farZ) { RawCamera camera; camera.name = name; - camera.nodeName = nodeName; + camera.nodeId = nodeId; camera.mode = RawCamera::CAMERA_MODE_ORTHOGRAPHIC; camera.orthographic.magX = magX; camera.orthographic.magY = magY; @@ -234,20 +234,21 @@ int RawModel::AddCameraOrthographic( return (int) cameras.size() - 1; } -int RawModel::AddNode(const char *name, const char *parentName) +int RawModel::AddNode(const long id, const char *name, const long parentId) { assert(name[0] != '\0'); for (size_t i = 0; i < nodes.size(); i++) { - if (Gltf::StringUtils::CompareNoCase(nodes[i].name, name) == 0) { + if (nodes[i].id == id ) { return (int) i; } } RawNode joint; joint.isJoint = false; + joint.id = id; joint.name = name; - joint.parentName = parentName; + joint.parentId = parentId; joint.surfaceId = 0; joint.translation = Vec3f(0, 0, 0); joint.rotation = Quatf(0, 0, 0, 1); @@ -455,9 +456,9 @@ void RawModel::CreateMaterialModels( RawSurface &rawSurface = model->GetSurface(surfaceIndex); if (model->GetSurfaceCount() > prevSurfaceCount) { - const std::vector &jointNames = surfaces[sortedTriangles[i].surfaceIndex].jointNames; - for (const auto &jointName : jointNames) { - const int nodeIndex = GetNodeByName(jointName.c_str()); + const std::vector &jointIds = surfaces[sortedTriangles[i].surfaceIndex].jointIds; + for (const auto &jointId : jointIds) { + const int nodeIndex = GetNodeById(jointId); assert(nodeIndex != -1); model->AddNode(GetNode(nodeIndex)); } @@ -515,10 +516,10 @@ void RawModel::CreateMaterialModels( } } -int RawModel::GetNodeByName(const char *name) const +int RawModel::GetNodeById(const long nodeId) const { for (size_t i = 0; i < nodes.size(); i++) { - if (nodes[i].name == name) { + if (nodes[i].id == nodeId) { return (int) i; } } diff --git a/src/RawModel.h b/src/RawModel.h index f729b6f..1a2c6c4 100644 --- a/src/RawModel.h +++ b/src/RawModel.h @@ -277,9 +277,9 @@ struct RawSurface { long id; std::string name; // The name of this surface - std::string skeletonRootName; // The name of the root of the skeleton. + long skeletonRootId; // The id of the root node of the skeleton. Bounds bounds; - std::vector jointNames; + std::vector jointIds; std::vector jointGeometryMins; std::vector jointGeometryMaxs; std::vector inverseBindMatrices; @@ -306,7 +306,7 @@ struct RawAnimation struct RawCamera { std::string name; - std::string nodeName; + long nodeId; enum { @@ -335,9 +335,10 @@ struct RawCamera struct RawNode { bool isJoint; + long id; std::string name; - std::string parentName; - std::vector childNames; + long parentId; + std::vector childIds; Vec3f translation; Quatf rotation; Vec3f scale; @@ -362,14 +363,14 @@ public: int AddSurface(const char *name, long surfaceId); int AddAnimation(const RawAnimation &animation); int AddCameraPerspective( - const char *name, const char *nodeName, const float aspectRatio, const float fovDegreesX, const float fovDegreesY, + const char *name, const long nodeId, const float aspectRatio, const float fovDegreesX, const float fovDegreesY, const float nearZ, const float farZ); int - AddCameraOrthographic(const char *name, const char *nodeName, const float magX, const float magY, const float nearZ, const float farZ); + AddCameraOrthographic(const char *name, const long nodeId, const float magX, const float magY, const float nearZ, const float farZ); int AddNode(const RawNode &node); - int AddNode(const char *name, const char *parentName); - void SetRootNode(const char *name) { rootNodeName = name; } - const char *GetRootNode() const { return rootNodeName.c_str(); } + int AddNode(const long id, const char *name, const long parentId); + void SetRootNode(const long nodeId) { rootNodeId = nodeId; } + const long GetRootNode() const { return rootNodeId; } // Remove unused vertices, textures or materials after removing vertex attributes, textures, materials or surfaces. void Condense(); @@ -413,7 +414,7 @@ public: int GetNodeCount() const { return (int) nodes.size(); } const RawNode &GetNode(const int index) const { return nodes[index]; } RawNode &GetNode(const int index) { return nodes[index]; } - int GetNodeByName(const char *name) const; + int GetNodeById(const long nodeId) const; // Create individual attribute arrays. // Returns true if the vertices store the particular attribute. @@ -427,7 +428,7 @@ public: std::vector &materialModels, const int maxModelVertices, const int keepAttribs, const bool forceDiscrete) const; private: - std::string rootNodeName; + long rootNodeId; int vertexAttributes; std::unordered_map vertexHash; std::vector vertices;