Implemented support for exporting user properties assigned to materials

This commit is contained in:
Graham Wihlidal 2018-11-29 11:57:48 +01:00 committed by Pär Winzell
parent 7374bcf34f
commit 8b081a5fc3
8 changed files with 145 additions and 5 deletions

View File

@ -173,6 +173,7 @@ static void ReadMesh(RawModel &raw, FbxScene *pScene, FbxNode *pNode, const std:
for (int polygonIndex = 0; polygonIndex < pMesh->GetPolygonCount(); polygonIndex++) { for (int polygonIndex = 0; polygonIndex < pMesh->GetPolygonCount(); polygonIndex++) {
FBX_ASSERT(pMesh->GetPolygonSize(polygonIndex) == 3); FBX_ASSERT(pMesh->GetPolygonSize(polygonIndex) == 3);
const std::shared_ptr<FbxMaterialInfo> fbxMaterial = materials.GetMaterial(polygonIndex); const std::shared_ptr<FbxMaterialInfo> fbxMaterial = materials.GetMaterial(polygonIndex);
const std::vector<std::string> userProperties = materials.GetUserProperties(polygonIndex);
int textures[RAW_TEXTURE_USAGE_MAX]; int textures[RAW_TEXTURE_USAGE_MAX];
std::fill_n(textures, (int) RAW_TEXTURE_USAGE_MAX, -1); 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 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); raw.AddTriangle(rawVertexIndices[0], rawVertexIndices[1], rawVertexIndices[2], rawMaterialIndex, rawSurfaceIndex);
} }

View File

@ -37,15 +37,110 @@ FbxMaterialsAccess::FbxMaterialsAccess(const FbxMesh *pMesh, const std::map<cons
if (materialNum < 0) { if (materialNum < 0) {
continue; continue;
} }
FbxSurfaceMaterial* surfaceMaterial = mesh->GetNode()->GetSrcObject<FbxSurfaceMaterial>(materialNum);
if (materialNum >= summaries.size()) { if (materialNum >= summaries.size()) {
summaries.resize(materialNum + 1); summaries.resize(materialNum + 1);
} }
auto summary = summaries[materialNum]; auto summary = summaries[materialNum];
if (summary == nullptr) { if (summary == nullptr) {
summary = summaries[materialNum] = GetMaterialInfo( summary = summaries[materialNum] = GetMaterialInfo(
mesh->GetNode()->GetSrcObject<FbxSurfaceMaterial>(materialNum), surfaceMaterial,
textureLocations); 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; 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> std::unique_ptr<FbxMaterialInfo>
FbxMaterialsAccess::GetMaterialInfo(FbxSurfaceMaterial *material, const std::map<const FbxTexture *, FbxString> &textureLocations) FbxMaterialsAccess::GetMaterialInfo(FbxSurfaceMaterial *material, const std::map<const FbxTexture *, FbxString> &textureLocations)
{ {

View File

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

View File

@ -362,6 +362,10 @@ ModelData *Raw2Gltf(
normalTexture, occlusionTexture, emissiveTexture, normalTexture, occlusionTexture, emissiveTexture,
emissiveFactor * emissiveIntensity, khrCmnUnlitMat, pbrMetRough)); emissiveFactor * emissiveIntensity, khrCmnUnlitMat, pbrMetRough));
materialsByName[materialHash(material)] = mData; materialsByName[materialHash(material)] = mData;
if (options.enableUserProperties) {
mData->userProperties = material.userProperties;
}
} }
for (const auto &surfaceModel : materialModels) { for (const auto &surfaceModel : materialModels) {

View File

@ -128,5 +128,17 @@ json MaterialData::serialize() const
extensions[KHR_MATERIALS_CMN_UNLIT] = *khrCmnConstantMaterial; extensions[KHR_MATERIALS_CMN_UNLIT] = *khrCmnConstantMaterial;
result["extensions"] = extensions; 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; return result;
} }

View File

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

View File

@ -113,14 +113,15 @@ int RawModel::AddTexture(const std::string &name, const std::string &fileName, c
int RawModel::AddMaterial(const RawMaterial &material) 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( int RawModel::AddMaterial(
const char *name, const char *name,
const RawMaterialType materialType, const RawMaterialType materialType,
const int textures[RAW_TEXTURE_USAGE_MAX], 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++) { for (size_t i = 0; i < materials.size(); i++) {
if (materials[i].name != name) { if (materials[i].name != name) {
@ -136,6 +137,14 @@ int RawModel::AddMaterial(
for (int j = 0; match && j < RAW_TEXTURE_USAGE_MAX; j++) { for (int j = 0; match && j < RAW_TEXTURE_USAGE_MAX; j++) {
match = match && (materials[i].textures[j] == textures[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) { if (match) {
return (int) i; return (int) i;
} }
@ -145,6 +154,7 @@ int RawModel::AddMaterial(
material.name = name; material.name = name;
material.type = materialType; material.type = materialType;
material.info = materialInfo; material.info = materialInfo;
material.userProperties = userProperties;
for (int i = 0; i < RAW_TEXTURE_USAGE_MAX; i++) { for (int i = 0; i < RAW_TEXTURE_USAGE_MAX; i++) {
material.textures[i] = textures[i]; material.textures[i] = textures[i];

View File

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