kvark / obj

Basic Wavefront OBJ loader
Apache License 2.0
29 stars 12 forks source link

Invalid groups when loading object #31

Open agorgl opened 3 years ago

agorgl commented 3 years ago

Using CornellBox-Original.obj from https://casual-effects.com/data/ the following snippet:

        let meshes = obj
            .data
            .objects
            .iter()
            .flat_map(|o| &o.groups)
            .map(|g| {
                println!("{}: {}", g.name, g.polys.len());
                let mut vertices = vec![];
                let mut indexer = LruIndexer::new(16, |_, t: IndexTuple| {
                    let pos = obj.data.position[t.0];
                    let vtx = Vertex::new(pos.into());
                    vertices.push(vtx)
                });
                let indices = g
                    .polys
                    .iter()
                    .cloned()
                    .map(|p| p.into_genmesh())
                    .triangulate()
                    .vertices()
                    .map(|v| indexer.index(v) as _)
                    .collect::<Vec<_>>();

                Mesh { vertices, indices }
            })
            .collect::<Vec<_>>();

shows:

floor: 1
ceiling: 1
backWall: 1
rightWall: 1
leftWall: 1
leftWall: 6
shortBox: 0
shortBox: 6
tallBox: 0
light: 1
elrnv commented 2 years ago

I assume the desired output is:

floor: 1
ceiling: 1
backWall: 1
rightWall: 1
leftWall: 1
shortBox: 6
tallBox: 6
light: 1

It seems that the problem then is that the cornell box obj file has multiple "usemtl" calls with the same name. It's not clear what the right behaviour is then. From the spec I believe calling usemtl specifies the material name for the element following it, so doing something like:

usemtl shortBox
f ...
f ...
...
f ...
g shortBox
usemtl shortBox
usemtl tallBox

should in theory create a second empty group set to material shortBox because of the second usemtl shortBox command.

I think there are two sane options here:

  1. Don't parse empty groups (second usemtl shortBox command is wiped by the following usemtl tallBox command) or
  2. Ignore subsequent usemtl commands with the same name.

I think either of the options would parse the cornell box in the way we expect above, The other problem with that file is that the g command is sometimes after the faces are determined, which doesn't follow the obj spec, but suggests that we should treat usemtl as setting a new group (which I think we've been doing already).

Any suggestions?

kvark commented 2 years ago

No suggestions from me.