Merge remote-tracking branch 'upstream/master' into feat/mocha-tests
This commit is contained in:
commit
d686d8eca7
|
@ -154,20 +154,20 @@ endif()
|
|||
|
||||
set(LIB_SOURCE_FILES
|
||||
src/FBX2glTF.h
|
||||
src/fbx/materials/3dsMaxPhysicalMaterial.cpp
|
||||
src/fbx/materials/FbxMaterials.cpp
|
||||
src/fbx/materials/FbxMaterials.hpp
|
||||
src/fbx/materials/RoughnessMetallicMaterials.hpp
|
||||
src/fbx/materials/StingrayPBSMaterial.cpp
|
||||
src/fbx/materials/TraditionalMaterials.cpp
|
||||
src/fbx/materials/TraditionalMaterials.hpp
|
||||
src/fbx/Fbx2Raw.cpp
|
||||
src/fbx/Fbx2Raw.hpp
|
||||
src/fbx/FbxBlendShapesAccess.cpp
|
||||
src/fbx/FbxBlendShapesAccess.hpp
|
||||
src/fbx/FbxLayerElementAccess.hpp
|
||||
src/fbx/FbxMaterialInfo.hpp
|
||||
src/fbx/FbxMaterialsAccess.cpp
|
||||
src/fbx/FbxMaterialsAccess.hpp
|
||||
src/fbx/FbxRoughMetMaterialInfo.cpp
|
||||
src/fbx/FbxRoughMetMaterialInfo.hpp
|
||||
src/fbx/FbxSkinningAccess.cpp
|
||||
src/fbx/FbxSkinningAccess.hpp
|
||||
src/fbx/FbxTraditionalMaterialInfo.cpp
|
||||
src/fbx/FbxTraditionalMaterialInfo.hpp
|
||||
src/gltf/Raw2Gltf.cpp
|
||||
src/gltf/Raw2Gltf.hpp
|
||||
src/gltf/GltfModel.cpp
|
||||
|
|
|
@ -103,33 +103,10 @@ int main(int argc, char* argv[]) {
|
|||
"When to compute vertex normals from mesh geometry.")
|
||||
->type_name("(never|broken|missing|always)");
|
||||
|
||||
std::vector<std::function<Vec2f(Vec2f)>> texturesTransforms;
|
||||
app.add_flag_function(
|
||||
"--flip-u",
|
||||
[&](size_t count) {
|
||||
if (count > 0) {
|
||||
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0f - uv[0], uv[1]); });
|
||||
if (verboseOutput) {
|
||||
fmt::printf("Flipping texture coordinates in the 'U' dimension.\n");
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flip all U texture coordinates.");
|
||||
|
||||
app.add_flag("--no-flip-u", "Don't flip U texture coordinates.")->excludes("--flip-u");
|
||||
|
||||
app.add_flag_function(
|
||||
"--no-flip-v",
|
||||
[&](size_t count) {
|
||||
if (count > 0) {
|
||||
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0f - uv[1]); });
|
||||
if (verboseOutput) {
|
||||
fmt::printf("NOT flipping texture coordinates in the 'V' dimension.\n");
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flip all V texture coordinates.");
|
||||
app.add_flag("--flip-v", "Don't flip U texture coordinates.")->excludes("--no-flip-v");
|
||||
const auto opt_flip_u = app.add_flag("--flip-u", "Flip all U texture coordinates.");
|
||||
const auto opt_no_flip_u = app.add_flag("--no-flip-u", "Don't flip U texture coordinates.");
|
||||
const auto opt_flip_v = app.add_flag("--flip-v", "Flip all V texture coordinates.");
|
||||
const auto opt_no_flip_v = app.add_flag("--no-flip-v", "Don't flip V texture coordinates.");
|
||||
|
||||
app.add_flag(
|
||||
"--pbr-metallic-rougnness",
|
||||
|
@ -250,6 +227,32 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
bool do_flip_u = false;
|
||||
bool do_flip_v = true;
|
||||
// somewhat tedious way to resolve --flag vs --no-flag in order provided
|
||||
for (const auto opt : app.parse_order()) {
|
||||
do_flip_u = (do_flip_u || (opt == opt_flip_u)) && (opt != opt_no_flip_u);
|
||||
do_flip_v = (do_flip_v || (opt == opt_flip_v)) && (opt != opt_no_flip_v);
|
||||
}
|
||||
std::vector<std::function<Vec2f(Vec2f)>> texturesTransforms;
|
||||
if (do_flip_u || do_flip_v) {
|
||||
if (do_flip_u && do_flip_v) {
|
||||
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], 1.0 - uv[1]); });
|
||||
} else if (do_flip_u) {
|
||||
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(1.0 - uv[0], uv[1]); });
|
||||
} else {
|
||||
texturesTransforms.emplace_back([](Vec2f uv) { return Vec2f(uv[0], 1.0 - uv[1]); });
|
||||
}
|
||||
}
|
||||
if (verboseOutput) {
|
||||
if (do_flip_u) {
|
||||
fmt::printf("Flipping texture coordinates in the 'U' dimension.\n");
|
||||
}
|
||||
if (!do_flip_v) {
|
||||
fmt::printf("NOT flipping texture coordinates in the 'V' dimension.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (inputPath.empty()) {
|
||||
fmt::printf("You must supply a FBX file to convert.\n");
|
||||
exit(1);
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
|
||||
#include "FbxBlendShapesAccess.hpp"
|
||||
#include "FbxLayerElementAccess.hpp"
|
||||
#include "FbxMaterialsAccess.hpp"
|
||||
#include "FbxSkinningAccess.hpp"
|
||||
#include "materials/RoughnessMetallicMaterials.hpp"
|
||||
#include "materials/TraditionalMaterials.hpp"
|
||||
|
||||
float scaleFactor;
|
||||
|
||||
|
@ -236,7 +237,7 @@ static void ReadMesh(
|
|||
FbxRoughMetMaterialInfo* fbxMatInfo =
|
||||
static_cast<FbxRoughMetMaterialInfo*>(fbxMaterial.get());
|
||||
|
||||
maybeAddTexture(fbxMatInfo->texColor, RAW_TEXTURE_USAGE_ALBEDO);
|
||||
maybeAddTexture(fbxMatInfo->texBaseColor, RAW_TEXTURE_USAGE_ALBEDO);
|
||||
maybeAddTexture(fbxMatInfo->texNormal, RAW_TEXTURE_USAGE_NORMAL);
|
||||
maybeAddTexture(fbxMatInfo->texEmissive, RAW_TEXTURE_USAGE_EMISSIVE);
|
||||
maybeAddTexture(fbxMatInfo->texRoughness, RAW_TEXTURE_USAGE_ROUGHNESS);
|
||||
|
@ -244,11 +245,12 @@ static void ReadMesh(
|
|||
maybeAddTexture(fbxMatInfo->texAmbientOcclusion, RAW_TEXTURE_USAGE_OCCLUSION);
|
||||
rawMatProps.reset(new RawMetRoughMatProps(
|
||||
RAW_SHADING_MODEL_PBR_MET_ROUGH,
|
||||
toVec4f(fbxMatInfo->colBase),
|
||||
toVec3f(fbxMatInfo->colEmissive),
|
||||
toVec4f(fbxMatInfo->baseColor),
|
||||
toVec3f(fbxMatInfo->emissive),
|
||||
fbxMatInfo->emissiveIntensity,
|
||||
fbxMatInfo->metallic,
|
||||
fbxMatInfo->roughness));
|
||||
fbxMatInfo->roughness,
|
||||
fbxMatInfo->invertRoughnessMap));
|
||||
} else {
|
||||
FbxTraditionalMaterialInfo* fbxMatInfo =
|
||||
static_cast<FbxTraditionalMaterialInfo*>(fbxMaterial.get());
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FBX2glTF.h"
|
||||
|
||||
class FbxMaterialInfo {
|
||||
public:
|
||||
FbxMaterialInfo(const FbxString& name, const FbxString& shadingModel)
|
||||
: name(name), shadingModel(shadingModel) {}
|
||||
|
||||
const FbxString name;
|
||||
const FbxString shadingModel;
|
||||
};
|
|
@ -1,104 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include "FbxMaterialsAccess.hpp"
|
||||
#include "Fbx2Raw.hpp"
|
||||
|
||||
FbxMaterialsAccess::FbxMaterialsAccess(
|
||||
const FbxMesh* pMesh,
|
||||
const std::map<const FbxTexture*, FbxString>& textureLocations)
|
||||
: mappingMode(FbxGeometryElement::eNone), mesh(nullptr), indices(nullptr) {
|
||||
if (pMesh->GetElementMaterialCount() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FbxGeometryElement::EMappingMode materialMappingMode =
|
||||
pMesh->GetElementMaterial()->GetMappingMode();
|
||||
if (materialMappingMode != FbxGeometryElement::eByPolygon &&
|
||||
materialMappingMode != FbxGeometryElement::eAllSame) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FbxGeometryElement::EReferenceMode materialReferenceMode =
|
||||
pMesh->GetElementMaterial()->GetReferenceMode();
|
||||
if (materialReferenceMode != FbxGeometryElement::eIndexToDirect) {
|
||||
return;
|
||||
}
|
||||
|
||||
mappingMode = materialMappingMode;
|
||||
mesh = pMesh;
|
||||
indices = &pMesh->GetElementMaterial()->GetIndexArray();
|
||||
|
||||
for (int ii = 0; ii < indices->GetCount(); ii++) {
|
||||
int materialNum = indices->GetAt(ii);
|
||||
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(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)) {
|
||||
userProperties[materialNum].push_back(TranscribeProperty(objectProperty).dump());
|
||||
}
|
||||
objectProperty = surfaceMaterial->GetNextProperty(objectProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::shared_ptr<FbxMaterialInfo> FbxMaterialsAccess::GetMaterial(
|
||||
const int polygonIndex) const {
|
||||
if (mappingMode != FbxGeometryElement::eNone) {
|
||||
const int materialNum =
|
||||
indices->GetAt((mappingMode == FbxGeometryElement::eByPolygon) ? polygonIndex : 0);
|
||||
if (materialNum < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return summaries.at((unsigned long)materialNum);
|
||||
}
|
||||
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) {
|
||||
std::unique_ptr<FbxMaterialInfo> res;
|
||||
res = FbxRoughMetMaterialInfo::From(material, textureLocations);
|
||||
if (!res) {
|
||||
res = FbxTraditionalMaterialInfo::From(material, textureLocations);
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Fbx2Raw.hpp"
|
||||
#include "FbxMaterialInfo.hpp"
|
||||
#include "FbxRoughMetMaterialInfo.hpp"
|
||||
#include "FbxTraditionalMaterialInfo.hpp"
|
||||
|
||||
class FbxMaterialsAccess {
|
||||
public:
|
||||
FbxMaterialsAccess(
|
||||
const FbxMesh* pMesh,
|
||||
const std::map<const FbxTexture*, FbxString>& textureLocations);
|
||||
|
||||
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;
|
||||
};
|
|
@ -1,73 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include "FbxRoughMetMaterialInfo.hpp"
|
||||
|
||||
std::unique_ptr<FbxRoughMetMaterialInfo> FbxRoughMetMaterialInfo::From(
|
||||
FbxSurfaceMaterial* fbxMaterial,
|
||||
const std::map<const FbxTexture*, FbxString>& textureLocations) {
|
||||
std::unique_ptr<FbxRoughMetMaterialInfo> res(
|
||||
new FbxRoughMetMaterialInfo(fbxMaterial->GetName(), FBX_SHADER_METROUGH));
|
||||
|
||||
const FbxProperty mayaProp = fbxMaterial->FindProperty("Maya");
|
||||
if (mayaProp.GetPropertyDataType() != FbxCompoundDT) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!fbxMaterial->ShadingModel.Get().IsEmpty()) {
|
||||
::fmt::printf(
|
||||
"Warning: Material %s has surprising shading model: %s\n",
|
||||
fbxMaterial->GetName(),
|
||||
fbxMaterial->ShadingModel.Get());
|
||||
}
|
||||
|
||||
auto getTex = [&](std::string propName) {
|
||||
const FbxFileTexture* ptr = nullptr;
|
||||
|
||||
const FbxProperty useProp = mayaProp.FindHierarchical(("use_" + propName + "_map").c_str());
|
||||
if (useProp.IsValid() && useProp.Get<bool>()) {
|
||||
const FbxProperty texProp = mayaProp.FindHierarchical(("TEX_" + propName + "_map").c_str());
|
||||
if (texProp.IsValid()) {
|
||||
ptr = texProp.GetSrcObject<FbxFileTexture>();
|
||||
if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
}
|
||||
} else if (verboseOutput && useProp.IsValid()) {
|
||||
fmt::printf(
|
||||
"Note: Property '%s' of material '%s' exists, but is flagged as 'do not use'.\n",
|
||||
propName,
|
||||
fbxMaterial->GetName());
|
||||
}
|
||||
return ptr;
|
||||
};
|
||||
|
||||
auto getVec = [&](std::string propName) -> FbxDouble3 {
|
||||
const FbxProperty vecProp = mayaProp.FindHierarchical(propName.c_str());
|
||||
return vecProp.IsValid() ? vecProp.Get<FbxDouble3>() : FbxDouble3(1, 1, 1);
|
||||
};
|
||||
|
||||
auto getVal = [&](std::string propName) -> FbxDouble {
|
||||
const FbxProperty vecProp = mayaProp.FindHierarchical(propName.c_str());
|
||||
return vecProp.IsValid() ? vecProp.Get<FbxDouble>() : 0;
|
||||
};
|
||||
|
||||
res->texNormal = getTex("normal");
|
||||
res->texColor = getTex("color");
|
||||
res->colBase = getVec("base_color");
|
||||
res->texAmbientOcclusion = getTex("ao");
|
||||
res->texEmissive = getTex("emissive");
|
||||
res->colEmissive = getVec("emissive");
|
||||
res->emissiveIntensity = getVal("emissive_intensity");
|
||||
res->texMetallic = getTex("metallic");
|
||||
res->metallic = getVal("metallic");
|
||||
res->texRoughness = getTex("roughness");
|
||||
res->roughness = getVal("roughness");
|
||||
|
||||
return res;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "FbxMaterialInfo.hpp"
|
||||
|
||||
struct FbxRoughMetMaterialInfo : FbxMaterialInfo {
|
||||
static constexpr const char* FBX_SHADER_METROUGH = "MetallicRoughness";
|
||||
|
||||
static std::unique_ptr<FbxRoughMetMaterialInfo> From(
|
||||
FbxSurfaceMaterial* fbxMaterial,
|
||||
const std::map<const FbxTexture*, FbxString>& textureLocations);
|
||||
|
||||
FbxRoughMetMaterialInfo(const FbxString& name, const FbxString& shadingModel)
|
||||
: FbxMaterialInfo(name, shadingModel) {}
|
||||
|
||||
const FbxFileTexture* texColor{};
|
||||
FbxVector4 colBase{};
|
||||
const FbxFileTexture* texNormal{};
|
||||
const FbxFileTexture* texMetallic{};
|
||||
FbxDouble metallic{};
|
||||
const FbxFileTexture* texRoughness{};
|
||||
FbxDouble roughness{};
|
||||
const FbxFileTexture* texEmissive{};
|
||||
FbxVector4 colEmissive{};
|
||||
FbxDouble emissiveIntensity{};
|
||||
const FbxFileTexture* texAmbientOcclusion{};
|
||||
};
|
|
@ -1,137 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include "FbxTraditionalMaterialInfo.hpp"
|
||||
|
||||
std::unique_ptr<FbxTraditionalMaterialInfo> FbxTraditionalMaterialInfo::From(
|
||||
FbxSurfaceMaterial* fbxMaterial,
|
||||
const std::map<const FbxTexture*, FbxString>& textureLocations) {
|
||||
auto getSurfaceScalar = [&](const char* propName) -> std::tuple<FbxDouble, FbxFileTexture*> {
|
||||
const FbxProperty prop = fbxMaterial->FindProperty(propName);
|
||||
|
||||
FbxDouble val(0);
|
||||
FbxFileTexture* tex = prop.GetSrcObject<FbxFileTexture>();
|
||||
if (tex != nullptr && textureLocations.find(tex) == textureLocations.end()) {
|
||||
tex = nullptr;
|
||||
}
|
||||
if (tex == nullptr && prop.IsValid()) {
|
||||
val = prop.Get<FbxDouble>();
|
||||
}
|
||||
return std::make_tuple(val, tex);
|
||||
};
|
||||
|
||||
auto getSurfaceVector = [&](const char* propName) -> std::tuple<FbxDouble3, FbxFileTexture*> {
|
||||
const FbxProperty prop = fbxMaterial->FindProperty(propName);
|
||||
|
||||
FbxDouble3 val(1, 1, 1);
|
||||
FbxFileTexture* tex = prop.GetSrcObject<FbxFileTexture>();
|
||||
if (tex != nullptr && textureLocations.find(tex) == textureLocations.end()) {
|
||||
tex = nullptr;
|
||||
}
|
||||
if (tex == nullptr && prop.IsValid()) {
|
||||
val = prop.Get<FbxDouble3>();
|
||||
}
|
||||
return std::make_tuple(val, tex);
|
||||
};
|
||||
|
||||
auto getSurfaceValues =
|
||||
[&](const char* colName,
|
||||
const char* facName) -> std::tuple<FbxVector4, FbxFileTexture*, FbxFileTexture*> {
|
||||
const FbxProperty colProp = fbxMaterial->FindProperty(colName);
|
||||
const FbxProperty facProp = fbxMaterial->FindProperty(facName);
|
||||
|
||||
FbxDouble3 colorVal(1, 1, 1);
|
||||
FbxDouble factorVal(1);
|
||||
|
||||
FbxFileTexture* colTex = colProp.GetSrcObject<FbxFileTexture>();
|
||||
if (colTex != nullptr && textureLocations.find(colTex) == textureLocations.end()) {
|
||||
colTex = nullptr;
|
||||
}
|
||||
if (colTex == nullptr && colProp.IsValid()) {
|
||||
colorVal = colProp.Get<FbxDouble3>();
|
||||
}
|
||||
FbxFileTexture* facTex = facProp.GetSrcObject<FbxFileTexture>();
|
||||
if (facTex != nullptr && textureLocations.find(facTex) == textureLocations.end()) {
|
||||
facTex = nullptr;
|
||||
}
|
||||
if (facTex == nullptr && facProp.IsValid()) {
|
||||
factorVal = facProp.Get<FbxDouble>();
|
||||
}
|
||||
|
||||
auto val = FbxVector4(
|
||||
colorVal[0] * factorVal, colorVal[1] * factorVal, colorVal[2] * factorVal, factorVal);
|
||||
return std::make_tuple(val, colTex, facTex);
|
||||
};
|
||||
|
||||
std::string name = fbxMaterial->GetName();
|
||||
std::unique_ptr<FbxTraditionalMaterialInfo> res(
|
||||
new FbxTraditionalMaterialInfo(name.c_str(), fbxMaterial->ShadingModel.Get()));
|
||||
|
||||
// four properties are on the same structure and follow the same rules
|
||||
auto handleBasicProperty = [&](const char* colName,
|
||||
const char* facName) -> std::tuple<FbxVector4, FbxFileTexture*> {
|
||||
FbxFileTexture *colTex, *facTex;
|
||||
FbxVector4 vec;
|
||||
|
||||
std::tie(vec, colTex, facTex) = getSurfaceValues(colName, facName);
|
||||
if (colTex) {
|
||||
if (facTex) {
|
||||
fmt::printf(
|
||||
"Warning: Mat [%s]: Can't handle both %s and %s textures; discarding %s.\n",
|
||||
name,
|
||||
colName,
|
||||
facName,
|
||||
facName);
|
||||
}
|
||||
return std::make_tuple(vec, colTex);
|
||||
}
|
||||
return std::make_tuple(vec, facTex);
|
||||
};
|
||||
|
||||
std::tie(res->colAmbient, res->texAmbient) =
|
||||
handleBasicProperty(FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor);
|
||||
std::tie(res->colSpecular, res->texSpecular) =
|
||||
handleBasicProperty(FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor);
|
||||
std::tie(res->colDiffuse, res->texDiffuse) =
|
||||
handleBasicProperty(FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor);
|
||||
std::tie(res->colEmissive, res->texEmissive) =
|
||||
handleBasicProperty(FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor);
|
||||
|
||||
// the normal map can only ever be a map, ignore everything else
|
||||
tie(std::ignore, res->texNormal) = getSurfaceVector(FbxSurfaceMaterial::sNormalMap);
|
||||
|
||||
// shininess can be a map or a factor; afaict the map is always 'ShininessExponent' and the
|
||||
// value is always found in 'Shininess' but only sometimes in 'ShininessExponent'.
|
||||
tie(std::ignore, res->texShininess) = getSurfaceScalar("ShininessExponent");
|
||||
tie(res->shininess, std::ignore) = getSurfaceScalar("Shininess");
|
||||
|
||||
// for transparency we just want a constant vector value;
|
||||
FbxVector4 transparency;
|
||||
// extract any existing textures only so we can warn that we're throwing them away
|
||||
FbxFileTexture *colTex, *facTex;
|
||||
std::tie(transparency, colTex, facTex) = getSurfaceValues(
|
||||
FbxSurfaceMaterial::sTransparentColor, FbxSurfaceMaterial::sTransparencyFactor);
|
||||
if (colTex) {
|
||||
fmt::printf(
|
||||
"Warning: Mat [%s]: Can't handle texture for %s; discarding.\n",
|
||||
name,
|
||||
FbxSurfaceMaterial::sTransparentColor);
|
||||
}
|
||||
if (facTex) {
|
||||
fmt::printf(
|
||||
"Warning: Mat [%s]: Can't handle texture for %s; discarding.\n",
|
||||
name,
|
||||
FbxSurfaceMaterial::sTransparencyFactor);
|
||||
}
|
||||
// FBX color is RGB, so we calculate the A channel as the average of the FBX transparency color
|
||||
// vector
|
||||
res->colDiffuse[3] = 1.0 - (transparency[0] + transparency[1] + transparency[2]) / 3.0;
|
||||
|
||||
return res;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "FbxMaterialInfo.hpp"
|
||||
|
||||
struct FbxTraditionalMaterialInfo : FbxMaterialInfo {
|
||||
static constexpr const char* FBX_SHADER_LAMBERT = "Lambert";
|
||||
static constexpr const char* FBX_SHADER_BLINN = "Blinn";
|
||||
static constexpr const char* FBX_SHADER_PHONG = "Phong";
|
||||
|
||||
FbxTraditionalMaterialInfo(const FbxString& name, const FbxString& shadingModel)
|
||||
: FbxMaterialInfo(name, shadingModel) {}
|
||||
|
||||
FbxFileTexture* texAmbient{};
|
||||
FbxVector4 colAmbient{};
|
||||
FbxFileTexture* texSpecular{};
|
||||
FbxVector4 colSpecular{};
|
||||
FbxFileTexture* texDiffuse{};
|
||||
FbxVector4 colDiffuse{};
|
||||
FbxFileTexture* texEmissive{};
|
||||
FbxVector4 colEmissive{};
|
||||
FbxFileTexture* texNormal{};
|
||||
FbxFileTexture* texShininess{};
|
||||
FbxDouble shininess{};
|
||||
|
||||
static std::unique_ptr<FbxTraditionalMaterialInfo> From(
|
||||
FbxSurfaceMaterial* fbxMaterial,
|
||||
const std::map<const FbxTexture*, FbxString>& textureLocations);
|
||||
};
|
|
@ -10,11 +10,14 @@
|
|||
#include "RoughnessMetallicMaterials.hpp"
|
||||
|
||||
std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::resolve() const {
|
||||
const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax");
|
||||
const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax", false);
|
||||
if (topProp.GetPropertyDataType() != FbxCompoundDT) {
|
||||
return nullptr;
|
||||
}
|
||||
const FbxProperty props = fbxMaterial->FindProperty("Parameters");
|
||||
const FbxProperty props = topProp.Find("Parameters", false);
|
||||
if (!props.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FbxString shadingModel = fbxMaterial->ShadingModel.Get();
|
||||
if (!shadingModel.IsEmpty() && shadingModel != "unknown") {
|
||||
|
@ -26,29 +29,21 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
|||
|
||||
auto getTex = [&](std::string propName) -> const FbxFileTexture* {
|
||||
const FbxFileTexture* ptr = nullptr;
|
||||
|
||||
const FbxProperty useProp = props.FindHierarchical((propName + "_map_on").c_str());
|
||||
if (useProp.IsValid() && useProp.Get<bool>()) {
|
||||
const FbxProperty texProp = useProp.FindHierarchical((propName + "_map").c_str());
|
||||
const FbxProperty texProp = props.Find((propName + "_map").c_str(), false);
|
||||
if (texProp.IsValid()) {
|
||||
const FbxProperty useProp = props.Find((propName + "_map_on").c_str(), false);
|
||||
if (useProp.IsValid() && !useProp.Get<FbxBool>()) {
|
||||
// skip this texture if the _on property exists *and* is explicitly false
|
||||
return nullptr;
|
||||
}
|
||||
ptr = texProp.GetSrcObject<FbxFileTexture>();
|
||||
if (ptr != nullptr && textureLocations.find(ptr) == textureLocations.end()) {
|
||||
ptr = nullptr;
|
||||
}
|
||||
}
|
||||
} else if (verboseOutput && useProp.IsValid()) {
|
||||
fmt::printf(
|
||||
"Note: property '%s' of 3dsMax Physical material '%s' exists, but is flagged as 'off'.\n",
|
||||
propName,
|
||||
fbxMaterial->GetName());
|
||||
}
|
||||
return ptr;
|
||||
};
|
||||
|
||||
int materialMode = getValue(props, "material_mode", 0);
|
||||
fmt::printf("Note: 3dsMax Physical material has material_mode = %d.\n", materialMode);
|
||||
|
||||
// baseWeight && baseColor
|
||||
FbxDouble baseWeight = getValue(props, "base_weight", 1.0);
|
||||
const auto* baseWeightMap = getTex("base_weight");
|
||||
FbxDouble4 baseCol = getValue(props, "base_color", FbxDouble4(0.5, 0.5, 0.5, 1.0));
|
||||
|
@ -58,49 +53,100 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
|||
const auto* emissiveWeightMap = getTex("emission");
|
||||
FbxDouble4 emissiveColor = getValue(props, "emit_color", FbxDouble4(1, 1, 1, 1));
|
||||
const auto* emissiveColorMap = getTex("emit_color");
|
||||
// TODO: emit_luminance, emit_kelvin?
|
||||
|
||||
// roughness & metalness: supported
|
||||
double roughness = getValue(props, "roughness", 0.0);
|
||||
const auto* roughnessMap = getTex("roughness");
|
||||
double metalness = getValue(props, "metalness", 0.0);
|
||||
const auto* metalnessMap = getTex("metalness");
|
||||
|
||||
// TODO: does invertRoughness affect roughness_map too?
|
||||
// TODO: we need this to affect roughness map, too.
|
||||
bool invertRoughness = getValue(props, "inv_roughness", false);
|
||||
if (invertRoughness) {
|
||||
roughness = 1.0f - roughness;
|
||||
}
|
||||
|
||||
// TODO: attempt to bake transparency > 0.0f into the alpha of baseColour?
|
||||
std::string unsupported;
|
||||
const auto addUnsupported = [&](const std::string bit) {
|
||||
if (!unsupported.empty()) {
|
||||
unsupported += ", ";
|
||||
}
|
||||
unsupported += bit;
|
||||
};
|
||||
|
||||
// TODO: turn this into a normal map through simple numerial differentiation
|
||||
const auto* bumpMap = getTex("bump");
|
||||
if (bumpMap != nullptr) {
|
||||
addUnsupported("bump map");
|
||||
}
|
||||
|
||||
// TODO: bake transparency > 0.0f into the alpha of baseColor?
|
||||
double transparency = getValue(props, "transparency", 0.0);
|
||||
const auto* transparencyMap = getTex("transparency");
|
||||
if (transparency != 0.0 || transparencyMap != nullptr) {
|
||||
addUnsupported("transparency");
|
||||
}
|
||||
|
||||
// SSS: not supported
|
||||
double scattering = getValue(props, "scattering", 0.0);
|
||||
const auto* scatteringMap = getTex("scattering");
|
||||
// TODO: if/when we bake transparency, we'll need this
|
||||
// double transparencyDepth = getValue(props, "trans_depth", 0.0);
|
||||
// if (transparencyDepth != 0.0) {
|
||||
// addUnsupported("transparency depth");
|
||||
// }
|
||||
// double transparencyColor = getValue(props, "trans_color", 0.0);
|
||||
// const auto* transparencyColorMap = getTex("trans_color");
|
||||
// if (transparencyColor != 0.0 || transparencyColorMap != nullptr) {
|
||||
// addUnsupported("transparency color");
|
||||
// }
|
||||
// double thinWalledTransparency = getValue(props, "thin_walled", false);
|
||||
// if (thinWalledTransparency) {
|
||||
// addUnsupported("thin-walled transparency");
|
||||
// }
|
||||
|
||||
// reflectivity: not supported
|
||||
double reflectivityWeight = getValue(props, "reflectivity", 1.);
|
||||
const auto* displacementMap = getTex("displacement");
|
||||
if (displacementMap != nullptr) {
|
||||
addUnsupported("displacement");
|
||||
}
|
||||
|
||||
double reflectivityWeight = getValue(props, "reflectivity", 1.0);
|
||||
const auto* reflectivityWeightMap = getTex("reflectivity");
|
||||
FbxDouble4 reflectivityColor = getValue(props, "refl_color", FbxDouble4(1, 1, 1, 1));
|
||||
const auto* reflectivityColorMap = getTex("refl_color");
|
||||
if (reflectivityWeight != 1.0 || reflectivityWeightMap != nullptr ||
|
||||
reflectivityColor != FbxDouble4(1, 1, 1, 1) || reflectivityColorMap != nullptr) {
|
||||
addUnsupported("reflectivity");
|
||||
}
|
||||
|
||||
double scattering = getValue(props, "scattering", 0.0);
|
||||
const auto* scatteringMap = getTex("scattering");
|
||||
if (scattering != 0.0 || scatteringMap != nullptr) {
|
||||
addUnsupported("sub-surface scattering");
|
||||
}
|
||||
|
||||
// coatings: not supported
|
||||
double coating = getValue(props, "coating", 0.0);
|
||||
if (coating != 0.0) {
|
||||
addUnsupported("coating");
|
||||
}
|
||||
|
||||
// diffuse roughness: not supported
|
||||
double diffuseRoughness = getValue(props, "diff_roughness", 0.);
|
||||
double diffuseRoughness = getValue(props, "diff_roughness", 0.0);
|
||||
if (diffuseRoughness != 0.0) {
|
||||
addUnsupported("diffuse roughness");
|
||||
}
|
||||
|
||||
// explicit brdf curve control: not supported
|
||||
bool isBrdfMode = getValue(props, "brdf_mode", false);
|
||||
if (isBrdfMode) {
|
||||
addUnsupported("advanced reflectance custom curve");
|
||||
}
|
||||
|
||||
// anisotrophy: not supported
|
||||
double anisotropy = getValue(props, "anisotropy", 1.0);
|
||||
if (anisotropy != 1.0) {
|
||||
addUnsupported("anisotropy");
|
||||
}
|
||||
|
||||
// TODO: how the heck do we combine these to generate a normal map?
|
||||
const auto* bumpMap = getTex("bump");
|
||||
const auto* displacementMap = getTex("displacement");
|
||||
if (verboseOutput && !unsupported.empty()) {
|
||||
fmt::printf(
|
||||
"Warning: 3dsMax Physical Material %s uses features glTF cannot express:\n %s\n",
|
||||
fbxMaterial->GetName(),
|
||||
unsupported);
|
||||
}
|
||||
|
||||
std::unique_ptr<FbxRoughMetMaterialInfo> res(new FbxRoughMetMaterialInfo(
|
||||
fbxMaterial->GetName(),
|
||||
|
@ -114,8 +160,7 @@ std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::reso
|
|||
|
||||
res->texMetallic = metalnessMap;
|
||||
res->texRoughness = roughnessMap;
|
||||
|
||||
res->texNormal = bumpMap; // TODO LOL NO NONO
|
||||
res->invertRoughnessMap = invertRoughness;
|
||||
|
||||
res->emissive = emissiveColor;
|
||||
res->emissiveIntensity = emissiveWeight;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include "fbx/Fbx2Raw.hpp"
|
||||
|
||||
#include "FbxMaterials.hpp"
|
||||
#include "RoughnessMetallicMaterials.hpp"
|
||||
#include "TraditionalMaterials.hpp"
|
||||
|
@ -41,13 +43,29 @@ FbxMaterialsAccess::FbxMaterialsAccess(
|
|||
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), textureLocations);
|
||||
summary = summaries[materialNum] = GetMaterialInfo(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)) {
|
||||
userProperties[materialNum].push_back(TranscribeProperty(objectProperty).dump());
|
||||
}
|
||||
objectProperty = surfaceMaterial->GetNextProperty(objectProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +83,18 @@ const std::shared_ptr<FbxMaterialInfo> FbxMaterialsAccess::GetMaterial(
|
|||
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) {
|
||||
|
|
|
@ -45,6 +45,8 @@ class FbxMaterialsAccess {
|
|||
|
||||
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);
|
||||
|
@ -52,6 +54,7 @@ class FbxMaterialsAccess {
|
|||
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;
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ struct FbxRoughMetMaterialInfo : FbxMaterialInfo {
|
|||
const FbxDouble metallic;
|
||||
const FbxDouble roughness;
|
||||
|
||||
FbxBool invertRoughnessMap = false;
|
||||
FbxDouble baseWeight = 1;
|
||||
FbxVector4 emissive = FbxVector4(0, 0, 0, 1);
|
||||
FbxDouble emissiveIntensity = 1;
|
||||
|
@ -70,8 +71,8 @@ class Fbx3dsMaxPhysicalMaterialResolver : FbxMaterialResolver<FbxRoughMetMateria
|
|||
|
||||
private:
|
||||
template <typename T>
|
||||
T getValue(const FbxProperty& props, std::string propName, const T& default) const {
|
||||
T getValue(const FbxProperty& props, std::string propName, const T& def) const {
|
||||
const FbxProperty prop = props.FindHierarchical(propName.c_str());
|
||||
return prop.IsValid() ? prop.Get<T>() : default;
|
||||
return prop.IsValid() ? prop.Get<T>() : def;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -276,7 +276,13 @@ ModelData* Raw2Gltf(
|
|||
},
|
||||
"ao_met_rough",
|
||||
[&](const std::vector<const TextureBuilder::pixel*> pixels) -> TextureBuilder::pixel {
|
||||
return {{(*pixels[0])[0], (*pixels[2])[0], (*pixels[1])[0], 1}};
|
||||
const float occlusion = (*pixels[0])[0];
|
||||
const float metallic = (*pixels[1])[0];
|
||||
const float roughness = (*pixels[2])[0];
|
||||
return {{occlusion,
|
||||
props->invertRoughnessMap ? 1.0f - roughness : roughness,
|
||||
metallic,
|
||||
1}};
|
||||
},
|
||||
false);
|
||||
|
||||
|
|
|
@ -100,7 +100,10 @@ int RawModel::AddTexture(
|
|||
return -1;
|
||||
}
|
||||
for (size_t i = 0; i < textures.size(); i++) {
|
||||
if (StringUtils::CompareNoCase(textures[i].name, name) == 0 && textures[i].usage == usage) {
|
||||
// we allocate the struct even if the implementing image file is missing
|
||||
if (textures[i].usage == usage &&
|
||||
StringUtils::CompareNoCase(textures[i].fileLocation, fileLocation) == 0 &&
|
||||
StringUtils::CompareNoCase(textures[i].name, name) == 0) {
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,18 +234,21 @@ struct RawMetRoughMatProps : RawMatProps {
|
|||
const Vec3f&& emissiveFactor,
|
||||
float emissiveIntensity,
|
||||
float metallic,
|
||||
float roughness)
|
||||
float roughness,
|
||||
bool invertRoughnessMap)
|
||||
: RawMatProps(shadingModel),
|
||||
diffuseFactor(diffuseFactor),
|
||||
emissiveFactor(emissiveFactor),
|
||||
emissiveIntensity(emissiveIntensity),
|
||||
metallic(metallic),
|
||||
roughness(roughness) {}
|
||||
roughness(roughness),
|
||||
invertRoughnessMap(invertRoughnessMap) {}
|
||||
const Vec4f diffuseFactor;
|
||||
const Vec3f emissiveFactor;
|
||||
const float emissiveIntensity;
|
||||
const float metallic;
|
||||
const float roughness;
|
||||
const bool invertRoughnessMap;
|
||||
|
||||
bool operator==(const RawMatProps& other) const override {
|
||||
if (RawMatProps::operator==(other)) {
|
||||
|
|
Loading…
Reference in New Issue