2
0
Эх сурвалжийг харах

Implemented support for exporting user properties assigned to materials

Graham Wihlidal 6 жил өмнө
parent
commit
8b081a5fc3

+ 2 - 1
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<FbxMaterialInfo> fbxMaterial = materials.GetMaterial(polygonIndex);
+		const std::vector<std::string> 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);
     }

+ 108 - 1
src/fbx/FbxMaterialsAccess.cpp

@@ -37,15 +37,110 @@ FbxMaterialsAccess::FbxMaterialsAccess(const FbxMesh *pMesh, const std::map<cons
         if (materialNum < 0) {
             continue;
         }
+
+		FbxSurfaceMaterial* surfaceMaterial = mesh->GetNode()->GetSrcObject<FbxSurfaceMaterial>(materialNum);
+		
         if (materialNum >= summaries.size()) {
             summaries.resize(materialNum + 1);
         }
         auto summary = summaries[materialNum];
         if (summary == nullptr) {
             summary = summaries[materialNum] = GetMaterialInfo(
-                mesh->GetNode()->GetSrcObject<FbxSurfaceMaterial>(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<long long>(FBXSDK_TIME_INFINITE);
+							break;
+						}
+						case eFbxULongLong: {
+							p["value"] = objectProperty.EvaluateValue<unsigned long long>(FBXSDK_TIME_INFINITE);
+							break;
+						}
+						case eFbxFloat:
+						case eFbxHalfFloat:
+						case eFbxDouble: {
+							p["value"] = objectProperty.EvaluateValue<double>(FBXSDK_TIME_INFINITE);
+							break;
+						}
+						case eFbxDouble2: {
+							auto v = objectProperty.EvaluateValue<FbxDouble2>(FBXSDK_TIME_INFINITE);
+							p["value"] = { v[0], v[1] };
+							break;
+						}
+						case eFbxDouble3: {
+							auto v = objectProperty.EvaluateValue<FbxDouble3>(FBXSDK_TIME_INFINITE);
+							p["value"] = { v[0], v[1], v[2] };
+							break;
+						}
+						case eFbxDouble4: {
+							auto v = objectProperty.EvaluateValue<FbxDouble4>(FBXSDK_TIME_INFINITE);
+							p["value"] = { v[0], v[1], v[2], v[3] };
+							break;
+						}
+						case eFbxString: {
+							p["value"] = std::string{ objectProperty.Get<FbxString>() };
+							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<FbxMaterialInfo> FbxMaterialsAccess::GetMaterial(const int
     return nullptr;
 }
 
+const std::vector<std::string> 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<std::string>();
+		}
+		return userProperties.at((unsigned long)materialNum);
+	}
+	return std::vector<std::string>();
+}
+
 std::unique_ptr<FbxMaterialInfo>
 FbxMaterialsAccess::GetMaterialInfo(FbxSurfaceMaterial *material, const std::map<const FbxTexture *, FbxString> &textureLocations)
 {

+ 3 - 0
src/fbx/FbxMaterialsAccess.hpp

@@ -21,12 +21,15 @@ public:
 
     const std::shared_ptr<FbxMaterialInfo> GetMaterial(const int polygonIndex) const;
 
+	const std::vector<std::string> GetUserProperties(const int polygonIndex) const;
+
     std::unique_ptr<FbxMaterialInfo>
     GetMaterialInfo(FbxSurfaceMaterial *material, const std::map<const FbxTexture *, FbxString> &textureLocations);
 
 private:
     FbxGeometryElement::EMappingMode              mappingMode;
     std::vector<std::shared_ptr<FbxMaterialInfo>> summaries {};
+	std::vector<std::vector<std::string>>         userProperties;
     const FbxMesh                                 *mesh;
     const FbxLayerElementArrayTemplate<int>       *indices;
 };

+ 4 - 0
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) {

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

+ 2 - 0
src/gltf/properties/MaterialData.hpp

@@ -61,6 +61,8 @@ struct MaterialData : Holdable
 
     const std::shared_ptr<const KHRCmnUnlitMaterial>    khrCmnConstantMaterial;
     const std::shared_ptr<const PBRMetallicRoughness>   pbrMetallicRoughness;
+
+	std::vector<std::string> userProperties;
 };
 
 void to_json(json &j, const Tex &data);

+ 12 - 2
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<RawMatProps> materialInfo)
+    std::shared_ptr<RawMatProps> materialInfo,
+	const std::vector<std::string>& 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];

+ 2 - 1
src/raw/RawModel.hpp

@@ -267,6 +267,7 @@ struct RawMaterial
     RawMaterialType              type;
     std::shared_ptr<RawMatProps> info;
     int                          textures[RAW_TEXTURE_USAGE_MAX];
+	std::vector<std::string>     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<RawMatProps> materialInfo);
+        std::shared_ptr<RawMatProps> materialInfo, const std::vector<std::string>& userProperties);
     int AddSurface(const RawSurface &suface);
     int AddSurface(const char *name, long surfaceId);
     int AddAnimation(const RawAnimation &animation);