in src/fbx/materials/3dsMaxPhysicalMaterial.cpp [11:171]
std::unique_ptr<FbxRoughMetMaterialInfo> Fbx3dsMaxPhysicalMaterialResolver::resolve() const {
const FbxProperty topProp = fbxMaterial->FindProperty("3dsMax", false);
if (topProp.GetPropertyDataType() != FbxCompoundDT) {
return nullptr;
}
const FbxProperty props = topProp.Find("Parameters", false);
if (!props.IsValid()) {
return nullptr;
}
FbxString shadingModel = fbxMaterial->ShadingModel.Get();
if (!shadingModel.IsEmpty() && shadingModel != "unknown") {
::fmt::printf(
"Warning: Material %s has surprising shading model: %s\n",
fbxMaterial->GetName(),
shadingModel);
}
auto getTex = [&](std::string propName) -> const FbxFileTexture* {
const FbxFileTexture* ptr = nullptr;
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;
}
}
return ptr;
};
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));
const auto* baseTex = getTex("base_color");
double emissiveWeight = getValue(props, "emission", 0.0);
const auto* emissiveWeightMap = getTex("emission");
FbxDouble4 emissiveColor = getValue(props, "emit_color", FbxDouble4(1, 1, 1, 1));
const auto* emissiveColorMap = getTex("emit_color");
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: we need this to affect roughness map, too.
bool invertRoughness = getValue(props, "inv_roughness", false);
if (invertRoughness) {
roughness = 1.0f - roughness;
}
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");
}
// 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");
// }
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");
}
double coating = getValue(props, "coating", 0.0);
if (coating != 0.0) {
addUnsupported("coating");
}
double diffuseRoughness = getValue(props, "diff_roughness", 0.0);
if (diffuseRoughness != 0.0) {
addUnsupported("diffuse roughness");
}
bool isBrdfMode = getValue(props, "brdf_mode", false);
if (isBrdfMode) {
addUnsupported("advanced reflectance custom curve");
}
double anisotropy = getValue(props, "anisotropy", 1.0);
if (anisotropy != 1.0) {
addUnsupported("anisotropy");
}
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->GetUniqueID(),
fbxMaterial->GetName(),
FbxRoughMetMaterialInfo::FBX_SHADER_METROUGH,
baseCol,
metalness,
roughness));
res->texBaseColor = baseTex;
res->baseWeight = baseWeight;
res->texBaseWeight = baseWeightMap;
res->texMetallic = metalnessMap;
res->texRoughness = roughnessMap;
res->invertRoughnessMap = invertRoughness;
res->emissive = emissiveColor;
res->emissiveIntensity = emissiveWeight;
res->texEmissive = emissiveColorMap;
res->texEmissiveWeight = emissiveWeightMap;
return res;
}