Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental support for materials in wavefront obj files #95

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

ffreyer
Copy link
Collaborator

@ffreyer ffreyer commented Jul 14, 2024

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 a material id => material name mapping and also loads the attached mtl file via MeshIO._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

Screenshot 2024-07-14 133931

Copy link

codecov bot commented Jul 14, 2024

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).

Files Patch % Lines
src/io/obj.jl 16.84% 153 Missing ⚠️
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     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ffreyer
Copy link
Collaborator Author

ffreyer commented Jul 14, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant