diff --git a/src/fbx/Fbx2Raw.cpp b/src/fbx/Fbx2Raw.cpp index 0872113..f53b2f5 100644 --- a/src/fbx/Fbx2Raw.cpp +++ b/src/fbx/Fbx2Raw.cpp @@ -173,6 +173,7 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: for (int polygonIndex = 0; polygonIndex < pMesh->GetPolygonCount(); polygonIndex++) { FBX_ASSERT(pMesh->GetPolygonSize(polygonIndex) == 3); const std::shared_ptr fbxMaterial = materials.GetMaterial(polygonIndex); + const std::vector userProperties = materials.GetUserProperties(polygonIndex); int textures[RAW_TEXTURE_USAGE_MAX]; std::fill_n(textures, (int) RAW_TEXTURE_USAGE_MAX, -1); @@ -361,7 +362,7 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std: } const RawMaterialType materialType = GetMaterialType(raw, textures, vertexTransparency, skinning.IsSkinned()); - const int rawMaterialIndex = raw.AddMaterial(materialName, materialType, textures, rawMatProps); + const int rawMaterialIndex = raw.AddMaterial(materialName, materialType, textures, rawMatProps, userProperties); raw.AddTriangle(rawVertexIndices[0], rawVertexIndices[1], rawVertexIndices[2], rawMaterialIndex, rawSurfaceIndex); } diff --git a/src/fbx/FbxMaterialsAccess.cpp b/src/fbx/FbxMaterialsAccess.cpp index f8b27ad..16122be 100644 --- a/src/fbx/FbxMaterialsAccess.cpp +++ b/src/fbx/FbxMaterialsAccess.cpp @@ -37,15 +37,110 @@ FbxMaterialsAccess::FbxMaterialsAccess(const FbxMesh *pMesh, const std::mapGetNode()->GetSrcObject(materialNum); + if (materialNum >= summaries.size()) { summaries.resize(materialNum + 1); } auto summary = summaries[materialNum]; if (summary == nullptr) { summary = summaries[materialNum] = GetMaterialInfo( - mesh->GetNode()->GetSrcObject(materialNum), + surfaceMaterial, textureLocations); } + + if (materialNum >= userProperties.size()) { + userProperties.resize(materialNum + 1); + } + if (userProperties[materialNum].empty()) { + FbxProperty objectProperty = surfaceMaterial->GetFirstProperty(); + while (objectProperty.IsValid()) + { + if (objectProperty.GetFlag(FbxPropertyFlags::eUserDefined)) { + std::string ename; + switch (objectProperty.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 = objectProperty.GetPropertyDataType().GetName(); break; + } + + json p; + p["type"] = ename; + + // Convert property value + switch (objectProperty.GetPropertyDataType().GetType()) { + case eFbxBool: + case eFbxChar: + case eFbxUChar: + case eFbxShort: + case eFbxUShort: + case eFbxInt: + case eFbxUInt: + case eFbxLongLong: { + p["value"] = objectProperty.EvaluateValue(FBXSDK_TIME_INFINITE); + break; + } + case eFbxULongLong: { + p["value"] = objectProperty.EvaluateValue(FBXSDK_TIME_INFINITE); + break; + } + case eFbxFloat: + case eFbxHalfFloat: + case eFbxDouble: { + p["value"] = objectProperty.EvaluateValue(FBXSDK_TIME_INFINITE); + break; + } + case eFbxDouble2: { + auto v = objectProperty.EvaluateValue(FBXSDK_TIME_INFINITE); + p["value"] = { v[0], v[1] }; + break; + } + case eFbxDouble3: { + auto v = objectProperty.EvaluateValue(FBXSDK_TIME_INFINITE); + p["value"] = { v[0], v[1], v[2] }; + break; + } + case eFbxDouble4: { + auto v = objectProperty.EvaluateValue(FBXSDK_TIME_INFINITE); + p["value"] = { v[0], v[1], v[2], v[3] }; + break; + } + case eFbxString: { + p["value"] = std::string{ objectProperty.Get() }; + break; + } + default: { + p["value"] = "UNSUPPORTED_VALUE_TYPE"; + break; + } + } + + json n; + n[objectProperty.GetNameAsCStr()] = p; + + userProperties[materialNum].push_back(n.dump()); + } + + objectProperty = surfaceMaterial->GetNextProperty(objectProperty); + } + } } } @@ -61,6 +156,18 @@ const std::shared_ptr FbxMaterialsAccess::GetMaterial(const int return nullptr; } +const std::vector FbxMaterialsAccess::GetUserProperties(const int polygonIndex) const +{ + if (mappingMode != FbxGeometryElement::eNone) { + const int materialNum = indices->GetAt((mappingMode == FbxGeometryElement::eByPolygon) ? polygonIndex : 0); + if (materialNum < 0) { + return std::vector(); + } + return userProperties.at((unsigned long)materialNum); + } + return std::vector(); +} + std::unique_ptr FbxMaterialsAccess::GetMaterialInfo(FbxSurfaceMaterial *material, const std::map &textureLocations) { diff --git a/src/fbx/FbxMaterialsAccess.hpp b/src/fbx/FbxMaterialsAccess.hpp index 33e6cf6..69c4aae 100644 --- a/src/fbx/FbxMaterialsAccess.hpp +++ b/src/fbx/FbxMaterialsAccess.hpp @@ -21,12 +21,15 @@ public: const std::shared_ptr GetMaterial(const int polygonIndex) const; + const std::vector GetUserProperties(const int polygonIndex) const; + std::unique_ptr GetMaterialInfo(FbxSurfaceMaterial *material, const std::map &textureLocations); private: FbxGeometryElement::EMappingMode mappingMode; std::vector> summaries {}; + std::vector> userProperties; const FbxMesh *mesh; const FbxLayerElementArrayTemplate *indices; }; diff --git a/src/gltf/Raw2Gltf.cpp b/src/gltf/Raw2Gltf.cpp index aa89c06..96fbc8f 100644 --- a/src/gltf/Raw2Gltf.cpp +++ b/src/gltf/Raw2Gltf.cpp @@ -362,6 +362,10 @@ ModelData *Raw2Gltf( normalTexture, occlusionTexture, emissiveTexture, emissiveFactor * emissiveIntensity, khrCmnUnlitMat, pbrMetRough)); materialsByName[materialHash(material)] = mData; + + if (options.enableUserProperties) { + mData->userProperties = material.userProperties; + } } for (const auto &surfaceModel : materialModels) { diff --git a/src/gltf/properties/MaterialData.cpp b/src/gltf/properties/MaterialData.cpp index f61ef12..1bb1a92 100644 --- a/src/gltf/properties/MaterialData.cpp +++ b/src/gltf/properties/MaterialData.cpp @@ -128,5 +128,17 @@ json MaterialData::serialize() const extensions[KHR_MATERIALS_CMN_UNLIT] = *khrCmnConstantMaterial; result["extensions"] = extensions; } + + 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/MaterialData.hpp b/src/gltf/properties/MaterialData.hpp index a168e5f..d38a532 100644 --- a/src/gltf/properties/MaterialData.hpp +++ b/src/gltf/properties/MaterialData.hpp @@ -61,6 +61,8 @@ struct MaterialData : Holdable const std::shared_ptr khrCmnConstantMaterial; const std::shared_ptr pbrMetallicRoughness; + + std::vector userProperties; }; void to_json(json &j, const Tex &data); diff --git a/src/raw/RawModel.cpp b/src/raw/RawModel.cpp index 26b6b9d..04d66b3 100644 --- a/src/raw/RawModel.cpp +++ b/src/raw/RawModel.cpp @@ -113,14 +113,15 @@ int RawModel::AddTexture(const std::string &name, const std::string &fileName, c int RawModel::AddMaterial(const RawMaterial &material) { - return AddMaterial(material.name.c_str(), material.type, material.textures, material.info); + return AddMaterial(material.name.c_str(), material.type, material.textures, material.info, material.userProperties); } int RawModel::AddMaterial( const char *name, const RawMaterialType materialType, const int textures[RAW_TEXTURE_USAGE_MAX], - std::shared_ptr materialInfo) + std::shared_ptr materialInfo, + const std::vector& userProperties) { for (size_t i = 0; i < materials.size(); i++) { if (materials[i].name != name) { @@ -136,6 +137,14 @@ int RawModel::AddMaterial( for (int j = 0; match && j < RAW_TEXTURE_USAGE_MAX; j++) { match = match && (materials[i].textures[j] == textures[j]); } + if (materials[i].userProperties.size() != userProperties.size()) { + match = false; + } + else { + for (int j = 0; match && j < userProperties.size(); j++) { + match = match && (materials[i].userProperties[j] == userProperties[j]); + } + } if (match) { return (int) i; } @@ -145,6 +154,7 @@ int RawModel::AddMaterial( material.name = name; material.type = materialType; material.info = materialInfo; + material.userProperties = userProperties; for (int i = 0; i < RAW_TEXTURE_USAGE_MAX; i++) { material.textures[i] = textures[i]; diff --git a/src/raw/RawModel.hpp b/src/raw/RawModel.hpp index 82ed269..5c9de5c 100644 --- a/src/raw/RawModel.hpp +++ b/src/raw/RawModel.hpp @@ -267,6 +267,7 @@ struct RawMaterial RawMaterialType type; std::shared_ptr info; int textures[RAW_TEXTURE_USAGE_MAX]; + std::vector userProperties; }; struct RawBlendChannel @@ -363,7 +364,7 @@ public: int AddMaterial(const RawMaterial &material); int AddMaterial( const char *name, const RawMaterialType materialType, const int textures[RAW_TEXTURE_USAGE_MAX], - std::shared_ptr materialInfo); + std::shared_ptr materialInfo, const std::vector& userProperties); int AddSurface(const RawSurface &suface); int AddSurface(const char *name, long surfaceId); int AddAnimation(const RawAnimation &animation);