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

node.meshes vs mesh.primitives #821

Closed
lexaknyazev opened this issue Jan 22, 2017 · 11 comments
Closed

node.meshes vs mesh.primitives #821

lexaknyazev opened this issue Jan 22, 2017 · 11 comments

Comments

@lexaknyazev
Copy link
Member

While re-editing skinning part of specification, I've found that spec requires that node can contain only one skinned mesh, however number of mesh.primitives isn't limited.

So the question is, why exactly do we have two ways of specifying the same geometry layout?

node
|----meshes
     |------meshA
            |-----primitives
                  |----------primitiveA
                  |----------primitiveB

and

node
|----meshes
     |------meshA
            |-----primitives
                  |----------primitiveA
     |------meshB
            |-----primitives
                  |----------primitiveB

CC @pjcozzi @tparisi @javagl

@lexaknyazev
Copy link
Member Author

Related: #744, CC @mre4ce

@lexaknyazev
Copy link
Member Author

From skinning perspective, this means that all primitives of the same mesh share the same joints/bones scope (because skin is defined per-node).
On the other hand, each primitive could have different set of attributes, material and even use different program.
Was such usage intended?

@javagl
Copy link
Contributor

javagl commented Jan 23, 2017

It's hard to tell "THE" reason for certain decisions. Particularly for me, because I've not been involved in many of the early discussions. So to be taken with a grain of salt:

From looking at the git history, the mesh.primitives have been there since the beginning of time (~2012). I can't imagine that they have never been questioned before. But during my search, I did not find a clear reason of why they exist at all. They might stem from a time where the mesh basically contained attribute objects, and each primitive combined some of these attributes. But this is just a guess based on the examples in #71 . (Obviously, the attribute objects have been moved up and became accessor objects)

There are some issues and comments related to the interplay of mesh/ mesh.primitives, and skin. These mainly seem to be about how to cope with the given structures, and less about why they exist (e.g. #442). However, one of these issues mentions a few points in #100 (comment) that might be relevant here - mainly, the case where a single mesh had to be split into multiple parts due to the 64k indices limit.

So I can't give a profound answer here. I think that at least the 64k-splitting-case may be a justification to have the primitives. Beyond that, I don't see why they should strictly be necessary, but it's easy to overlook some border case or application pattern that may be a justification for the current state.

@lexaknyazev
Copy link
Member Author

the case where a single mesh had to be split into multiple parts due to the 64k indices limit

This sounds reasonable, but I'm sure it doesn't apply anymore. Right now all desktop and almost all mobile WebGL 1.0 implementations support 32-bit indices. I think that mesh.primitives originates from the lack of universal 32-bit indices support at the time when collada2gltf was written.

What bothers me most is that such layout inevitably complicates state management, in worst case: different attributes layout of primitives of the same mesh - skinning/morphing issues, different drawing modes from different index buffers, different materials - possible program switching, etc.

Of course, runtime could workaround most of that stuff (reorder objects, build caches, etc) but, maybe, we could sacrifice 5% of use cases in favor of simplifying other 95%?

@lexaknyazev
Copy link
Member Author

If the only purpose of having several mesh.primitives is to allow mesh "splitting" (to workaround indices limit), wouldn't it be better to move material out of array and require that all primitives must have the same set of attributes (so skinning/morphing would be more predictable)?
Otherwise, I can't see any reason why same mesh parts couldn't be represented as separate "meshes".

@javagl
Copy link
Contributor

javagl commented Jan 24, 2017

Maybe an @fabrobinet may be appropriate, in view of #161 , where the concept of accessor objects was introduced. Again, that was before I started tracking glTF more actively, so just the question: Could it be that the main justifications for having the mesh.primitives became obsolete when the attribute objects have been replaced with accessor objects, but this potential simplification remained unnoticed?

Otherwise, the role of the mesh now only is that it is used for "grouping" several mesh.primitives. Considering the questions about skinning that arise from that, a simplification or additional constraints may be reasonable, but I'm still not sure whether I'm overlooking something.

@pjcozzi
Copy link
Member

pjcozzi commented Jan 25, 2017

mesh.primitives is there to allow converters and exporters to preserve their semantic hierarchy of objects in the scene. I definitely questioned it years ago myself and I'm pretty sure it is required if, for example, you want to have a clean conversions from COLLADA.

@pjcozzi pjcozzi added the 2.0 label Jan 25, 2017
@xelatihy
Copy link
Contributor

My 2cents.

  1. Mesh primitives may help with the semantic of some scenes, but combined with the use of accessors require quite a bit of indirections to render
  2. Most graphics file format have a concept of per-vertex or per-face attributes (OBJ, Blender, Renderman, all subdivision surface stuff) . Mesh primitives add complexity but disallow any kind of per-face attribute.
  3. In my opinion, and this is just an opinion, all application will likely convert a glTf model to their own data layout anyway, so the added complexity is unclear.
  4. I also considered using Mesh to enable instancing for raytracing/GL. But in their current form, the instancing would neither by flexible nor optimal.

In light of these observation, I would suggest the following things.

a. Either remove mesh entirely or maybe add a "groupname" property for nodes.
b. If there is interest, create an extension that preserve better topolgy information and per-face attributes to help data exchange for editing application. This would allow lossless conversion between glTF and OBJ, which in turn might help a lot with adoption. Not the conversion OBJ->glTF change entirely mesh topolgy. One way to do this is to look at the RIB API and OpenSubdiv. I plan to support one for our research efforts in yocto_gltf.

This is just me, but since glTF 2 is backward incompatible, trying to simplify some of its indirections might be helpful for adoption.

@pjcozzi
Copy link
Member

pjcozzi commented Jan 27, 2017

Looking into this more with @lasalvavida, it is likely that node.meshes could go from an array to just one property: node.mesh, or maybe even make it an array of Primitives (and rename Primitive to Mesh, and remove the current Mesh). Let me confirm with a few more users.

@xelatihy the extension could have potential once someone has the bandwidth to investigate.

@xelatihy
Copy link
Contributor

Sounds good. I think if Mesh is kept, than an additional extension cab certainly by done to add in topology preseving meshes and subdivs.

@lexaknyazev
Copy link
Member Author

From offline WG discussions:

  • mesh.primitives exist to allow having multiple materials per-"object" (this also allows vertex data re-usage), and splitting big meshes for platforms without 32-bit indices.

  • A node with multiple meshes could be easily replaced with multiple nodes having the same parent. This should simplify asset loading in general, and especially skinning / morphing bindings.

zellski referenced this issue in mrdoob/three.js Aug 8, 2017
Includes changes necessary to support the upcoming Draco extension, and more glTF primitive types.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants