FBX2glTF/src/gltf/properties/MaterialData.cpp

134 lines
4.3 KiB
C++

/**
* Copyright (c) Facebook, Inc. and its affiliates.
* 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.
*/
#include "MaterialData.hpp"
#include "TextureData.hpp"
// TODO: retrieve & pass in correct UV set from FBX
std::unique_ptr<Tex> Tex::ref(const TextureData* tex, uint32_t texCoord) {
return std::unique_ptr<Tex>{(tex != nullptr) ? new Tex(tex->ix, texCoord) : nullptr};
}
Tex::Tex(uint32_t texRef, uint32_t texCoord) : texRef(texRef), texCoord(texCoord) {}
void to_json(json& j, const Tex& data) {
j = json{{"index", data.texRef}, {"texCoord", data.texCoord}};
}
KHRCmnUnlitMaterial::KHRCmnUnlitMaterial() {}
void to_json(json& j, const KHRCmnUnlitMaterial& d) {
j = json({});
}
inline float clamp(float d, float bottom = 0, float top = 1) {
return std::max(bottom, std::min(top, d));
}
inline Vec3f
clamp(const Vec3f& vec, const Vec3f& bottom = VEC3F_ZERO, const Vec3f& top = VEC3F_ONE) {
return Vec3f::Max(bottom, Vec3f::Min(top, vec));
}
inline Vec4f
clamp(const Vec4f& vec, const Vec4f& bottom = VEC4F_ZERO, const Vec4f& top = VEC4F_ONE) {
return Vec4f::Max(bottom, Vec4f::Min(top, vec));
}
PBRMetallicRoughness::PBRMetallicRoughness(
const TextureData* baseColorTexture,
const TextureData* metRoughTexture,
const Vec4f& baseColorFactor,
float metallic,
float roughness)
: baseColorTexture(Tex::ref(baseColorTexture)),
metRoughTexture(Tex::ref(metRoughTexture)),
baseColorFactor(clamp(baseColorFactor)),
metallic(clamp(metallic)),
roughness(clamp(roughness)) {}
void to_json(json& j, const PBRMetallicRoughness& d) {
j = {};
if (d.baseColorTexture != nullptr) {
j["baseColorTexture"] = *d.baseColorTexture;
}
if (d.baseColorFactor.LengthSquared() > 0) {
j["baseColorFactor"] = toStdVec(d.baseColorFactor);
}
if (d.metRoughTexture != nullptr) {
j["metallicRoughnessTexture"] = *d.metRoughTexture;
// if a texture is provided, throw away metallic/roughness values
j["roughnessFactor"] = 1.0f;
j["metallicFactor"] = 1.0f;
} else {
// without a texture, however, use metallic/roughness as constants
j["metallicFactor"] = d.metallic;
j["roughnessFactor"] = d.roughness;
}
}
MaterialData::MaterialData(
std::string name,
bool isTransparent,
const RawShadingModel shadingModel,
const TextureData* normalTexture,
const TextureData* occlusionTexture,
const TextureData* emissiveTexture,
const Vec3f& emissiveFactor,
std::shared_ptr<KHRCmnUnlitMaterial> const khrCmnConstantMaterial,
std::shared_ptr<PBRMetallicRoughness> const pbrMetallicRoughness)
: Holdable(),
name(std::move(name)),
shadingModel(shadingModel),
isTransparent(isTransparent),
normalTexture(Tex::ref(normalTexture)),
occlusionTexture(Tex::ref(occlusionTexture)),
emissiveTexture(Tex::ref(emissiveTexture)),
emissiveFactor(clamp(emissiveFactor)),
khrCmnConstantMaterial(khrCmnConstantMaterial),
pbrMetallicRoughness(pbrMetallicRoughness) {}
json MaterialData::serialize() const {
json result = {{"name", name},
{"alphaMode", isTransparent ? "BLEND" : "OPAQUE"},
{"extras",
{{"fromFBX",
{{"shadingModel", Describe(shadingModel)},
{"isTruePBR", shadingModel == RAW_SHADING_MODEL_PBR_MET_ROUGH}}}}}};
if (normalTexture != nullptr) {
result["normalTexture"] = *normalTexture;
}
if (occlusionTexture != nullptr) {
result["occlusionTexture"] = *occlusionTexture;
}
if (emissiveTexture != nullptr) {
result["emissiveTexture"] = *emissiveTexture;
}
if (emissiveFactor.LengthSquared() > 0) {
result["emissiveFactor"] = toStdVec(emissiveFactor);
}
if (pbrMetallicRoughness != nullptr) {
result["pbrMetallicRoughness"] = *pbrMetallicRoughness;
}
if (khrCmnConstantMaterial != nullptr) {
json extensions = {};
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;
}