浏览代码

Transcribe FBX Custom Properties

Michael Ranieri 7 年之前
父节点
当前提交
2e03a3cdea
共有 5 个文件被更改,包括 117 次插入1 次删除
  1. 101 1
      src/fbx/Fbx2Raw.cpp
  2. 2 0
      src/gltf/Raw2Gltf.cpp
  3. 12 0
      src/gltf/properties/NodeData.cpp
  4. 1 0
      src/gltf/properties/NodeData.hpp
  5. 1 0
      src/raw/RawModel.hpp

+ 101 - 1
src/fbx/Fbx2Raw.cpp

@@ -19,7 +19,7 @@
 #include <cassert>
 #include <cmath>
 
-#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<long long>(FBXSDK_TIME_INFINITE);
+            break;
+        }
+        case eFbxULongLong: {
+            p["value"] = prop.EvaluateValue<unsigned long long>(FBXSDK_TIME_INFINITE);
+            break;
+        }
+        case eFbxFloat:
+        case eFbxHalfFloat:
+        case eFbxDouble: {
+            p["value"] = prop.EvaluateValue<double>(FBXSDK_TIME_INFINITE);
+            break;
+        }
+        case eFbxDouble2: {
+            auto v = prop.EvaluateValue<FbxDouble2>(FBXSDK_TIME_INFINITE);
+            p["value"] = {v[0], v[1]};
+            break;
+        }
+        case eFbxDouble3: {
+            auto v = prop.EvaluateValue<FbxDouble3>(FBXSDK_TIME_INFINITE);
+            p["value"] = {v[0], v[1], v[2]};
+            break;
+        }
+        case eFbxDouble4: {
+            auto v = prop.EvaluateValue<FbxDouble4>(FBXSDK_TIME_INFINITE);
+            p["value"] = {v[0], v[1], v[2], v[3]};
+            break;
+        }
+        case eFbxString: {
+            p["value"] = std::string{prop.Get<FbxString>()};
+            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<const FbxTexture *, FbxString> &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();

+ 2 - 0
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);

+ 12 - 0
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;
 }

+ 1 - 0
src/gltf/properties/NodeData.hpp

@@ -32,4 +32,5 @@ struct NodeData : Holdable
     int32_t                  camera;
     int32_t                  skin;
     std::vector<std::string> skeletons;
+    std::vector<std::string> userProperties;
 };

+ 1 - 0
src/raw/RawModel.hpp

@@ -404,6 +404,7 @@ struct RawNode
     Quatf                    rotation;
     Vec3f                    scale;
     long                     surfaceId;
+    std::vector<std::string> userProperties;
 };
 
 class RawModel