Add experimental support for materials in wavefront obj files
This adds a couple of things:
- the main
load("filename.obj")now also reads "usemtl" commands and treats them like a vertex attribute. I.e. it maps the related material names to indices and generates faces for them so that a mesh can later be split into submeshes based on materials -
MeshIO.split_mesh(mesh)does the splitting based on material indices. It's not exported as I see it as an experimental feature. It's hard-coded to assume a mesh has normals, uvs and material ids for now. It returns a Dict mapping material ids to sub meshes. -
MeshIO.load_materials("filename.obj")repeats some of the work of the main load function to provide amaterial id => material namemapping and also loads the attached mtl file viaMeshIO._load_mtl("filename.mtl"). I consider those experimental as well so they're not exported. The output is a nested Dict of the information in the mtl file.
For example you can use this to load https://free3d.com/3d-model/girl-blind-703979.html. (This isn't using all the material settings specified in the mtl file so the shading doesn't match exactly. )
using FileIO, MeshIO, GeometryBasics
path = "D:/data/Julia/"
filepath = joinpath(path, "14-girl-obj/girl OBJ.obj")
mesh = load(filepath)
meshes = MeshIO.split_mesh(mesh)
materials = MeshIO.load_materials(filepath)
# filename incorrect in mtl file...?
materials["FACE"]["diffuse map"]["filename"] = "D:/data/Julia/14-girl-obj/tEXTURE/FACE Base Color apha.png"
using GLMakie
begin
fig = Figure()
ax = LScene(fig[1, 1])
for (id, m) in meshes
# get material associated with a submesh
material_name = materials["id to material"][id]
material = materials[material_name]
# load texture from filename specified in .mtl file
texture = if haskey(material, "diffuse map") && haskey(material["diffuse map"], "filename")
load(material["diffuse map"]["filename"])
else
RGBf(0,1,0)
end
# texture uses white as transparent for some reason...
if material_name == "FACE"
texture = map(texture) do c
RGBAf(c.r, c.g, c.b, 1 - c.r)
end
end
# render mesh with specified material properties if specified
mesh!(ax, m, color = texture,
diffuse = get(material, "diffuse", Vec3f(1)),
specular = get(material, "specular", Vec3f(0.2)),
shininess = get(material, "shininess", 32f0),
)
end
fig
end
Codecov Report
Attention: Patch coverage is 16.84783% with 153 lines in your changes missing coverage. Please review.
Project coverage is 62.15%. Comparing base (
cb8e494) to head (fd36a88). Report is 11 commits behind head on master.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| src/io/obj.jl | 16.84% | 153 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## master #95 +/- ##
===========================================
- Coverage 77.08% 62.15% -14.94%
===========================================
Files 11 11
Lines 576 753 +177
===========================================
+ Hits 444 468 +24
- Misses 132 285 +153
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
🚨 Try these New Features:
- Flaky Tests Detection - Detect and resolve failed and flaky tests
- JS Bundle Analysis - Avoid shipping oversized bundles
This adds experimental support for #94. To cleanly support this we need changes in GeometryBasics to attach metadata to meshes that's not per vertex.