simnalamburt / obj-rs

:shipit: Wavefront obj parser for Rust

Home Page:https://docs.rs/obj-rs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Document `RawObj` in detail, Support higher order surfaces

virtualritz opened this issue · comments

Many OBJ files are not made out of triangles and this is a feature. If I load an OBJ to send to an high end offline renderer, the last thing I want is probably triangles (so I also do not want the reader to convert the OBJ to triangles, on-the-fly).

To support this, a third array is needed that has one integer, listing the number of vertices per each face. So you would have:

// Do whatever you want
model.vertices;
model.vertices_per_face;
model.indices;

This is an implicit part of the TODO 'support full OBJ/MTL spec'.

Which is actually a lot of work because then you also need to support higher order surfaces, e.g. NURBS, trim curves, bicubic patches etc. OBJ can store all of these and some apps (e.g. Maya) will also read and write such OBJs.

I quickly made a file in Wings3D – this is an all quad model. Feel free to use however you want.

knotty02.zip

Hi @virtualritz! Thanks for using obj-rs and giving me a good idea!

obj-rs have two types. One is obj_rs::raw::RawObj. RawObj is one-to-one mapping of Wavefront OBJ types and Rust. And the other is obj_rs::Obj. Obj is transformed RawObj so that can be easily rendered to screen with OpenGL, Direct3D, Metal, or Vulkan.

I may have not tested all corner cases but AFAIK RawObj does support n-gons. And Obj cannot support n-gons since it's a format which should be rendered directly to the screen.

Maybe I can make some "n-gon Mesh to triangle Mesh" transformer as a separate crate but looks like it's not a trivial work.

About higher order surfaces... yes you are right. They are part of the spec of Wavefront OBJ and obj-rs currently do not support it. I definitely need to implement it.

TLDR;
If the crate is this specific, make it apparent in the description so people don't waste time with it when they need other features.

I would suggest to rename Obj to ObjAsTriangles or something like this to make it apparent that this is triangles only. Because this is not apparent. Nowhere in your crate description does it say "This crate is for reading OBJs for rendering on screenif the object is not made out of triangles it can not be read."

This is a new problem btw. If you had any library to read OBJs 10-20 years ago, it would always read the data as-is. I btw. predict that soon graphics cards will support subdivision surfaces. And then all the tools have to support quads and n-gons anyway. :)

RawObj seems to have what I need but then I have to write another bunch of code on top to get the data extracted nicely from that. It would still be great to have a simple API as the current one which does not convert to triangles and gives you an vertices_per_face vector/array.

At them moment I use the tobj crate. It has the same problem but it does read n-gons and converts them on the fly. Not ideal for me but I don't have to write code at least. :P

This is what I am using this for: https://github.com/virtualritz/rust-diffusion-limited-aggregation

If obj-rs ever supports n-gons I will switch to your crate.

I've changed the title to make this issue more clear! Thanks for your comment :)

Cool. If you support higher order surfaces, your lib will be outstanding. The only DCC apps that can read & write OBJs with NURBS or patches are Rhino3D and Maya, afaik.

Oh, and Blender, apparently!

5 years ago, I thought that hiding the low level RawObj type and presenting Obj type in the front page would be better. Since I thought that no one will want to mess around with the details of Obj type.

But now, I think it would be better to show the RawObj type to the front, and to show the Obj types separately as a helper. Wavefront OBJ is too complex format and there are so many corner cases that can't be abstracted with simple Obj type. And anyway, it's almost impossible to fully abstract the Wavefront OBJ type because of the MTL specification.

How do you think?