diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 5db2faa..40a2cf3 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -688,10 +688,19 @@ static void ReadNodeHierarchy( FbxScene* pScene, FbxNode* pNode, const long parentId, - const std::string& path) { + const std::string& path, + int extraSkinIx) { const FbxUInt64 nodeId = pNode->GetUniqueID(); const char* nodeName = pNode->GetName(); - const int nodeIndex = raw.AddNode(nodeId, nodeName, parentId); + FbxSkeleton *skel = pNode->GetSkeleton(); + if (skel == nullptr) { + extraSkinIx = -1; + } else { + if (skel->IsSkeletonRoot()) { + extraSkinIx = raw.CreateExtraSkinIndex(); + } + } + const int nodeIndex = raw.AddNode(nodeId, nodeName, parentId, extraSkinIx); RawNode& node = raw.GetNode(nodeIndex); FbxTransform::EInheritType lInheritType; @@ -745,7 +754,7 @@ static void ReadNodeHierarchy( raw.SetRootNode(nodeId); } for (int child = 0; child < pNode->GetChildCount(); child++) { - ReadNodeHierarchy(raw, pScene, pNode->GetChild(child), nodeId, newPath); + ReadNodeHierarchy(raw, pScene, pNode->GetChild(child), nodeId, newPath, extraSkinIx); } } @@ -1174,7 +1183,7 @@ bool LoadFBXFile( // this is always 0.01, but let's opt for clarity. scaleFactor = FbxSystemUnit::m.GetConversionFactorFrom(FbxSystemUnit::cm); - ReadNodeHierarchy(raw, pScene, pScene->GetRootNode(), 0, ""); + ReadNodeHierarchy(raw, pScene, pScene->GetRootNode(), 0, "", -1); ReadNodeAttributes(raw, pScene, pScene->GetRootNode(), textureLocations); ReadAnimations(raw, pScene, options); diff --git a/src/gltf/Raw2Gltf.cpp b/src/gltf/Raw2Gltf.cpp index b6d3a32..30ff5a3 100644 --- a/src/gltf/Raw2Gltf.cpp +++ b/src/gltf/Raw2Gltf.cpp @@ -853,6 +853,18 @@ ModelData* Raw2Gltf( } } + std::vector> extraJointIndexes; + extraJointIndexes.resize(raw.GetExtraSkinCount()); + for (int i = 0; i < raw.GetNodeCount(); i++) { + const RawNode& node = raw.GetNode(i); + if (node.extraSkinIx >= 0) { + extraJointIndexes[node.extraSkinIx].push_back(i); + } + } + for (int i = 0; i < extraJointIndexes.size(); i++) { + gltf->skins.hold(new SkinData(extraJointIndexes[i], true)); + } + // // cameras // diff --git a/src/gltf/properties/SkinData.cpp b/src/gltf/properties/SkinData.cpp index d63acf3..ebaf093 100644 --- a/src/gltf/properties/SkinData.cpp +++ b/src/gltf/properties/SkinData.cpp @@ -18,9 +18,22 @@ SkinData::SkinData( : Holdable(), joints(joints), inverseBindMatrices(inverseBindMatricesAccessor.ix), - skeletonRootNode(skeletonRootNode.ix) {} + skeletonRootNode(skeletonRootNode.ix), + isExtraSkin(false) {} + +SkinData::SkinData( + const std::vector joints, + bool isExtraSkin) + : Holdable(), + joints(joints), + inverseBindMatrices(0), + skeletonRootNode(0), + isExtraSkin(true) {} json SkinData::serialize() const { + if (isExtraSkin) { + return {{"joints", joints}}; + } return { {"joints", joints}, {"inverseBindMatrices", inverseBindMatrices}, diff --git a/src/gltf/properties/SkinData.hpp b/src/gltf/properties/SkinData.hpp index 0a43306..5415fb3 100644 --- a/src/gltf/properties/SkinData.hpp +++ b/src/gltf/properties/SkinData.hpp @@ -16,9 +16,14 @@ struct SkinData : Holdable { const AccessorData& inverseBindMatricesAccessor, const NodeData& skeletonRootNode); + SkinData( + const std::vector joints, + bool isExtraSkin); + json serialize() const override; const std::vector joints; const uint32_t skeletonRootNode; const uint32_t inverseBindMatrices; + const bool isExtraSkin; }; diff --git a/src/raw/RawModel.cpp b/src/raw/RawModel.cpp index fa30079..2c0f51b 100644 --- a/src/raw/RawModel.cpp +++ b/src/raw/RawModel.cpp @@ -69,7 +69,7 @@ size_t RawVertex::Difference(const RawVertex& other) const { return attributes; } -RawModel::RawModel() : vertexAttributes(0) {} +RawModel::RawModel() : nextExtraSkinIx(0), rootNodeId(0), vertexAttributes(0), globalMaxWeights(0) {} void RawModel::AddVertexAttribute(const RawVertexAttribute attrib) { vertexAttributes |= attrib; @@ -311,7 +311,7 @@ int RawModel::AddCameraOrthographic( return (int)cameras.size() - 1; } -int RawModel::AddNode(const long id, const char* name, const long parentId) { +int RawModel::AddNode(const long id, const char* name, const long parentId, const int extraSkinIx) { assert(name[0] != '\0'); for (size_t i = 0; i < nodes.size(); i++) { @@ -330,6 +330,7 @@ int RawModel::AddNode(const long id, const char* name, const long parentId) { joint.translation = Vec3f(0, 0, 0); joint.rotation = Quatf(0, 0, 0, 1); joint.scale = Vec3f(1, 1, 1); + joint.extraSkinIx = extraSkinIx; nodes.emplace_back(joint); return (int)nodes.size() - 1; diff --git a/src/raw/RawModel.hpp b/src/raw/RawModel.hpp index 066e555..5f25231 100644 --- a/src/raw/RawModel.hpp +++ b/src/raw/RawModel.hpp @@ -355,6 +355,7 @@ struct RawNode { long surfaceId; long lightIx; std::vector userProperties; + int extraSkinIx; }; class RawModel { @@ -410,7 +411,7 @@ class RawModel { const float nearZ, const float farZ); int AddNode(const RawNode& node); - int AddNode(const long id, const char* name, const long parentId); + int AddNode(const long id, const char* name, const long parentId, const int extraSkinIx); void SetRootNode(const long nodeId) { rootNodeId = nodeId; } @@ -541,9 +542,19 @@ class RawModel { const int keepAttribs, const bool forceDiscrete) const; + int CreateExtraSkinIndex() { + int ret = nextExtraSkinIx; + nextExtraSkinIx++; + return ret; + } + int GetExtraSkinCount() const { + return nextExtraSkinIx; + } + private: Vec3f getFaceNormal(int verts[3]) const; + int nextExtraSkinIx; long rootNodeId; int vertexAttributes; int globalMaxWeights;