GltfSerializer: clamp roughnessFactor into the valid glTF range #8073

roughnessFactor was computed as 1/specularity. An IfcSpecularExponent of
0 produced infinity, which nlohmann::json serialises as null and makes
the glTF invalid; exponents below 1 produced values above 1, which glTF
also forbids. Map exponents <= 1 to full roughness and keep 1/exponent
above that, so the factor always lands in [0, 1].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Petru Conduraru
2026-07-05 18:31:02 +03:00
committed by Thomas Krijnen
parent 49de7dbcb1
commit 7322263a5e
+7 -3
View File
@@ -108,9 +108,13 @@ int GltfSerializer::writeMaterial(const ifcopenshell::geometry::taxonomy::style:
base[3] = 1. - style->transparency;
}
if (style->has_specularity())
json_["materials"].push_back({ {"name", style->name}, {"doubleSided", true}, {"pbrMetallicRoughness", {{"baseColorFactor", base}, {"metallicFactor", 0}, {"roughnessFactor", 1.0 / style->specularity}}}});
else
if (style->has_specularity()) {
// glTF requires roughnessFactor in [0, 1]. A specular exponent of 0
// previously produced 1/0 = inf, which nlohmann::json serialises as
// null and makes the file invalid; exponents below 1 exceeded 1. #8073
const double roughness = style->specularity > 1.0 ? 1.0 / style->specularity : 1.0;
json_["materials"].push_back({ {"name", style->name}, {"doubleSided", true}, {"pbrMetallicRoughness", {{"baseColorFactor", base}, {"metallicFactor", 0}, {"roughnessFactor", roughness}}}});
} else
json_["materials"].push_back({ {"name", style->name}, {"doubleSided", true}, {"pbrMetallicRoughness", {{"baseColorFactor", base}, {"metallicFactor", 0}}}});
if (style->transparency == style->transparency && style->transparency > 1.e-9) {