gltfpack: obj material color
kzhsw opened this issue · 1 comments
Motivation:
In obj material (.mtl) files, colors and other options could be defined, but output glb model does not contain these information.
Example:
obj and mtl file:
input_obj.zip
converted glb file:
glb.zip
expected: a red cube
actual: a white cube
related code:
meshoptimizer/gltf/parseobj.cpp
Lines 59 to 86 in fd0b723
see also this for mapping from obj material to gltf material:
https://github.com/CesiumGS/obj2gltf/blob/a1709ac1fafa5546f592d232bde0a9f64b3bbd57/lib/loadMtl.js#L119-L159
quick and incomplete patch
Note this does not contains the pbr texture conversion code here
diff --git a/gltf/parseobj.cpp b/gltf/parseobj.cpp
index 14228d0..e38a885 100644
--- a/gltf/parseobj.cpp
+++ b/gltf/parseobj.cpp
@@ -62,12 +62,33 @@ static cgltf_data* parseSceneObj(fastObjMesh* obj)
fastObjMaterial& om = obj->materials[mi];
gm.has_pbr_metallic_roughness = true;
- gm.pbr_metallic_roughness.base_color_factor[0] = 1.0f;
- gm.pbr_metallic_roughness.base_color_factor[1] = 1.0f;
- gm.pbr_metallic_roughness.base_color_factor[2] = 1.0f;
+ // baseColorFactor = material.diffuseColor;
+ gm.pbr_metallic_roughness.base_color_factor[0] = om.Kd[0];
+ gm.pbr_metallic_roughness.base_color_factor[1] = om.Kd[1];
+ gm.pbr_metallic_roughness.base_color_factor[2] = om.Kd[2];
gm.pbr_metallic_roughness.base_color_factor[3] = 1.0f;
- gm.pbr_metallic_roughness.metallic_factor = 0.0f;
- gm.pbr_metallic_roughness.roughness_factor = 1.0f;
+ // emissiveFactor = material.emissiveColor
+ gm.emissive_factor[0] = om.Ke[0];
+ gm.emissive_factor[1] = om.Ke[1];
+ gm.emissive_factor[2] = om.Ke[2];
+ // Translate the blinn-phong model to the pbr metallic-roughness model
+ // Roughness factor is a combination of specular intensity and shininess
+ // Metallic factor is 0.0
+ // Textures are not converted for now
+ float specularIntensity = om.Ks[0] * 0.2125f + om.Ks[1] * 0.7154f + om.Ks[2] * 0.0721f;
+
+ // metallicFactor = material.specularColor[0]
+ gm.pbr_metallic_roughness.metallic_factor = 0.f;
+ // roughnessFactor = material.specularShininess
+ gm.pbr_metallic_roughness.roughness_factor = std::max(0.f, std::min(1.f - (om.Ns / 1000.f), 1.f));
+ // Low specular intensity values should produce a rough material even if shininess is high.
+ if (specularIntensity < 0.1) {
+ gm.pbr_metallic_roughness.roughness_factor *= 1.0 - specularIntensity;
+ }
+ bool transparent = false;
+ if (om.d < 1.0f) {
+ transparent = true;
+ }
gm.alpha_cutoff = 0.5f;
@@ -77,6 +98,10 @@ static cgltf_data* parseSceneObj(fastObjMesh* obj)
gm.pbr_metallic_roughness.base_color_texture.scale = 1.0f;
gm.alpha_mode = (om.illum == 4 || om.illum == 6 || om.illum == 7 || om.illum == 9) ? cgltf_alpha_mode_mask : cgltf_alpha_mode_opaque;
+ } else {
+ gm.pbr_metallic_roughness.base_color_factor[3] = om.d;
+ gm.alpha_mode = transparent ? cgltf_alpha_mode_blend : cgltf_alpha_mode_opaque;
+ gm.double_sided = transparent;
}
if (om.map_d.name)
Yeah this should be pretty easy to fix, I'll do this tomorrow. Thanks for the link - this will be helpful as a reference; I believe that code is not converting to the glTF materials strictly speaking (maybe they have a richer material model internally, or this includes glTF 1.0 and some other extensions?) as some .mtl features aren't really representable with glTF 2.0 + KHR extensions - for example separate alpha texture - but definitely at least basics like color should be covered.