diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 1089bab..b61702d 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -19,7 +19,7 @@ #include #include -#include "FBX2glTF.h" +#include "gltf/Raw2Gltf.hpp" #include "utils/File_Utils.hpp" #include "utils/String_Utils.hpp" @@ -382,6 +382,95 @@ static void ReadCamera(RawModel &raw, FbxScene *pScene, FbxNode *pNode) } } +static void ReadNodeProperty(RawModel &raw, FbxNode *pNode, FbxProperty &prop) +{ + using fbxsdk::EFbxType; + int nodeId = raw.GetNodeById(pNode->GetUniqueID()); + if (nodeId < 0) + return; + + std::string ename; + // Convert property type + switch (prop.GetPropertyDataType().GetType()) { + case eFbxBool: ename = "eFbxBool"; break; + case eFbxChar: ename = "eFbxChar"; break; + case eFbxUChar: ename = "eFbxUChar"; break; + case eFbxShort: ename = "eFbxShort"; break; + case eFbxUShort: ename = "eFbxUShort"; break; + case eFbxInt: ename = "eFbxInt"; break; + case eFbxUInt: ename = "eFbxUint"; break; + case eFbxLongLong: ename = "eFbxLongLong"; break; + case eFbxULongLong: ename = "eFbxULongLong"; break; + case eFbxFloat: ename = "eFbxFloat"; break; + case eFbxHalfFloat: ename = "eFbxHalfFloat"; break; + case eFbxDouble: ename = "eFbxDouble"; break; + case eFbxDouble2: ename = "eFbxDouble2"; break; + case eFbxDouble3: ename = "eFbxDouble3"; break; + case eFbxDouble4: ename = "eFbxDouble4"; break; + case eFbxString: ename = "eFbxString"; break; + + // Use this as fallback because it does not give very descriptive names + default: ename = prop.GetPropertyDataType().GetName(); break; + } + + json p; + p["type"] = ename; + + // Convert property value + switch (prop.GetPropertyDataType().GetType()) { + case eFbxBool: + case eFbxChar: + case eFbxUChar: + case eFbxShort: + case eFbxUShort: + case eFbxInt: + case eFbxUInt: + case eFbxLongLong: { + p["value"] = prop.EvaluateValue(FBXSDK_TIME_INFINITE); + break; + } + case eFbxULongLong: { + p["value"] = prop.EvaluateValue(FBXSDK_TIME_INFINITE); + break; + } + case eFbxFloat: + case eFbxHalfFloat: + case eFbxDouble: { + p["value"] = prop.EvaluateValue(FBXSDK_TIME_INFINITE); + break; + } + case eFbxDouble2: { + auto v = prop.EvaluateValue(FBXSDK_TIME_INFINITE); + p["value"] = {v[0], v[1]}; + break; + } + case eFbxDouble3: { + auto v = prop.EvaluateValue(FBXSDK_TIME_INFINITE); + p["value"] = {v[0], v[1], v[2]}; + break; + } + case eFbxDouble4: { + auto v = prop.EvaluateValue(FBXSDK_TIME_INFINITE); + p["value"] = {v[0], v[1], v[2], v[3]}; + break; + } + case eFbxString: { + p["value"] = std::string{prop.Get()}; + break; + } + default: { + p["value"] = "UNSUPPORTED_VALUE_TYPE"; + break; + } + } + + json n; + n[prop.GetNameAsCStr()] = p; + + RawNode &node = raw.GetNode(nodeId); + node.userProperties.push_back(n.dump()); +} + static void ReadNodeAttributes( RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std::map &textureLocations) { @@ -389,6 +478,17 @@ static void ReadNodeAttributes( return; } + // Only support non-animated user defined properties for now + FbxProperty objectProperty = pNode->GetFirstProperty(); + while (objectProperty.IsValid()) + { + if (objectProperty.GetFlag(FbxPropertyFlags::eUserDefined)) { + ReadNodeProperty(raw, pNode, objectProperty); + } + + objectProperty = pNode->GetNextProperty(objectProperty); + } + FbxNodeAttribute *pNodeAttribute = pNode->GetNodeAttribute(); if (pNodeAttribute != nullptr) { const FbxNodeAttribute::EType attributeType = pNodeAttribute->GetAttributeType(); diff --git a/src/gltf/Raw2Gltf.cpp b/src/gltf/Raw2Gltf.cpp index 17f4309..b18fb9f 100644 --- a/src/gltf/Raw2Gltf.cpp +++ b/src/gltf/Raw2Gltf.cpp @@ -335,6 +335,8 @@ ModelData *Raw2Gltf( auto nodeData = gltf->nodes.hold( new NodeData(node.name, node.translation, node.rotation, node.scale, node.isJoint)); + nodeData->userProperties = node.userProperties; + for (const auto &childId : node.childIds) { int childIx = raw.GetNodeById(childId); assert(childIx >= 0); diff --git a/src/gltf/properties/NodeData.cpp b/src/gltf/properties/NodeData.cpp index cba9e77..8ee0f10 100644 --- a/src/gltf/properties/NodeData.cpp +++ b/src/gltf/properties/NodeData.cpp @@ -85,5 +85,17 @@ json NodeData::serialize() const result["camera"] = camera; } } + + for (const auto& i : userProperties) + { + auto& prop_map = result["extras"]["fromFBX"]["userProperties"]; + + json j = json::parse(i); + for (const auto& k : json::iterator_wrapper(j)) + { + prop_map[k.key()] = k.value(); + } + } + return result; } diff --git a/src/gltf/properties/NodeData.hpp b/src/gltf/properties/NodeData.hpp index fb350fa..c976e66 100644 --- a/src/gltf/properties/NodeData.hpp +++ b/src/gltf/properties/NodeData.hpp @@ -32,4 +32,5 @@ struct NodeData : Holdable int32_t camera; int32_t skin; std::vector skeletons; + std::vector userProperties; }; diff --git a/src/raw/RawModel.hpp b/src/raw/RawModel.hpp index 61c6797..e895870 100644 --- a/src/raw/RawModel.hpp +++ b/src/raw/RawModel.hpp @@ -404,6 +404,7 @@ struct RawNode Quatf rotation; Vec3f scale; long surfaceId; + std::vector userProperties; }; class RawModel