KhronosGroup / glTF-Blender-IO

Blender glTF 2.0 importer and exporter
https://docs.blender.org/manual/en/latest/addons/import_export/scene_gltf2.html
Apache License 2.0
1.5k stars 319 forks source link

Export Vertex Groups #1232

Open canadaduane opened 4 years ago

canadaduane commented 4 years ago

Is your feature request related to a problem? Please describe. In a three.js game, we would like to be able to tell the "hair vertices" from the "skin vertices" of an avatar (as well as clothing, shoes, etc.) so that we can modify the colors of the vertices in-game. To accomplish this, we'd like to be able to see the vertex groups as they exist in Blender; however, it appears vertex groups are not currently exported.

Describe the solution you'd like When an object's vertices are grouped via Object Data Properties -> Add Vertex Group, we would like to see these vertex groups in the exported glTF file:

image

Describe alternatives you've considered Multiple UV maps. Dead end due to the way three.js uses UV maps.

Additional context This file has a vertex group called "vertexgroup" and when exported as a glTF, the vertex group is not present:

vertexgroup.blend.zip

scurest commented 4 years ago

How do you want to see it in the glTF?

canadaduane commented 4 years ago

I'm open to just about anything, but one way that seems congruent with a previous blender/three.js exporter is to export as an array attribute:

https://github.com/repsac/io_three/blob/56b2f35b7d56aab6df131c7a3aecb43cda915ca3/addons/io_three/exporter/geometry.py#L409

(extra_vertex_groups defined here: https://github.com/repsac/io_three/blob/master/addons/io_three/exporter/api/mesh.py#L182)

(See also a long ago discussion at https://stackoverflow.com/questions/38451346/blender-buffergeometry-access-vertices-from-vertex-group)

It was a long time ago though (5 years). Does that seem reasonable today?

scurest commented 4 years ago

This branch should export a SCALAR attribute array for every non-skinning vertex group.

canadaduane commented 4 years ago

Wow, that was quick! I'm unfamiliar with testing glTF-Blender-IO but I will give it a shot and report back. Thanks!

canadaduane commented 4 years ago

Thanks again for this addition @scurest!

After looking at the output, I think the export could be used in its current state. However, is it exporting data in a format that uses more memory than it needs to?

For example, here is a blender file with two exported vertex groups. Each vertex group is comprised of 4 selected vertices (at least, visually in Blender) so I would expect to see 4 vertices 3 dimensions = 12 values in each group. On the output, however, there are 24 data points, which matches the total number of vertices in the mesh (8 vertices 3 dimensions = 24). twovertexgroups.blend.zip

Here, I'm using Don McCurdy's gltfviewer to see the glTF, with the JS console open on the right showing "_group" (the first vertex group). Vertices in this group are highlighted RED: gltf-export1

Here is the second vertex group, "_group2", also with vertices highlighted RED: gltf-export2

It looks like there is redundant data in three ways:

  1. It appears we're using a Float32Array for what amounts to binary set inclusion: 0s for "not in the vertex group" and 1s for "in the vertex group".
  2. The set inclusivity data (binary 1 or 0) is repeated for each XYZ dimension.
  3. The entire mesh's vertices are being mapped--could we perhaps employ just a list of indices of vertices in the group? This would amount to 4 data points in my case.

Would it make sense to compress this data/remove redundancies in some way?

scurest commented 4 years ago

could we perhaps employ just a list of indices of vertices in the group

There's nothing like that in glTF but you can modify the exporter to stuff the indices into extensions/extras or something.

canadaduane commented 4 years ago

There's nothing like that in glTF but you can modifier the exporter to stuff the indices into extensions/extras or something.

Ok, well, I think it would be more useful to people if it's more or less the "standard" way.

What do you think about reducing redundant data (numbers 1 and 2 in the list above)?

Thanks again for your help--I wouldn't have known where to even start :)

scurest commented 4 years ago

As long as the data is stored as an attribute array, I think it's already as small as possible based on the fact all attribute arrays in a primitive have to have to same count, and the elements must align to four byte values.

re 1: The _Group array contains the weight each vertex was assigned in Group, so it isn't just set inclusion. But even if you wanted to store something smaller than a float, the alignment requirements (accessor.byteOffset and bufferView.byteStride must be multiples of 4) make it so you'd have to pad to 4 bytes anyway.

re 2: I don't understand what you mean by "repeated for each XYZ dimension". If you mean there are 24 vertices in glTF, rather than the 8 you see in Blender, that's because we need three verts (with three different normals) for each single corner of the cube. If you turn off export of normals/UVs you'll get the same 8 verts as Blender. It doesn't have anything to do with vertex groups.

canadaduane commented 4 years ago

I see. Thank you for the clarifications! It looks like it's working as intended & to spec.

donmccurdy commented 4 years ago

@scurest am I understanding correctly that if the mesh has three vertex groups, A, B, and C, each with optional weights, the branch would write custom vertex attributes to the mesh named _A, _B, and _C, each with values derived from the weights (or zero if the vertex is not in that group)? If so, then for my $0.02, I closed https://github.com/KhronosGroup/glTF-Blender-IO/pull/807 because I thought the approach you've taken here would be better, but I never found time to implement it.

I think it should probably be behind an export option, but would you want to open a PR?

scurest commented 4 years ago

@donmccurdy That's correct. I'm not interested in doing a PR for this.

Queatz commented 3 years ago

Looking for this!

donmccurdy commented 3 years ago

@Queatz could you say a bit more about how you'd like to use vertex groups in an exported glTF? Other software does not have a concept of vertex groups, and the only concrete proposal here is https://github.com/KhronosGroup/glTF-Blender-IO/issues/1232#issuecomment-704311864, which would preserve the weights from vertex groups, but not really preserve the groups themselves.

Queatz commented 3 years ago

@donmccurdy I want to use Vertex Groups to paint where grass will be spawned on my terrain. I ended up making it work using Vertex Colors, however it would still be nice to be able to use Vertex Groups since that's how it's normally done (in Blender at least.)

donmccurdy commented 3 years ago

Ok, thanks — I believe @scurest's suggestion https://github.com/KhronosGroup/glTF-Blender-IO/compare/master...scurest:custom-data would handle that case well.

scurest commented 3 years ago

(Sorta OT)

It occurred to me if the custom data accessors are mostly zero it would be better to write a sparse accessor, so I pushed a commit to the custom-data branch that calculates when a sparse accessor would be smaller and writes that instead. I haven't tested it extensively though.

@canadaduane This can serve as a partial response to your question about "employing just a list of indices of vertices in the group".

canadaduane commented 3 years ago

Nice! Yes, that would improve our use case as well (needing access to vertices that make up the "hair" part of a character, for example, which is a small number of vertices compared to all vertices in the character).

On Sun, Jan 10, 2021 at 1:45 PM scurest notifications@github.com wrote:

(Sorta OT)

It occurred to me if the custom data accessors are mostly zero it would be better to write a sparse accessor, so I pushed a commit to the custom-data https://github.com/scurest/glTF-Blender-IO/tree/custom-data branch that calculates when a sparse accessor would be smaller and writes that instead. I haven't tested it extensively though.

@canadaduane https://github.com/canadaduane This can serve as a partial response to your question about "employing just a list of indices of vertices in the group".

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/KhronosGroup/glTF-Blender-IO/issues/1232#issuecomment-757541183, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAABAP4PQI4PAXFJI4VOYDSZIGV3ANCNFSM4SFJQH3Q .

canadaduane commented 3 years ago

I have @donmccurdy's GLTF viewer working with vertex groups:

image

Code at https://github.com/canadaduane/three-gltf-viewer/commit/27354979166da0d68b7f19593ffcd4acd34653bd

This capability is exactly what we were looking for. Thanks @scurest!

canadaduane commented 3 years ago

@scurest I'm curious how difficult it would be to export Face Maps as well. I recently learned about this feature (Blender 2.8+, apparently). It's even more ideal than vertex groups for our use case, since it means we would not need to double up on certain vertices to get a "clean edge" when coloring based on vertex.

scurest commented 3 years ago

Here is a branch that should export facemaps.

canadaduane commented 3 years ago

Thanks @scurest! I combined both of your excellent contributions, so that one may export both vertex groups & facemaps if desired:

https://github.com/canadaduane/glTF-Blender-IO/tree/custom-data

NOTE: I changed the _FACEMAPS attribute to FACEMAPS so that the underscore prefix can continue to have special meaning, i.e. to flag mesh attributes as named vertex groups.

scurest commented 3 years ago

I changed the _FACEMAPS attribute to FACEMAPS so that the underscore prefix can continue to have special meaning, i.e. to flag mesh attributes as named vertex groups.

The underscore is because the spec requires that "application-specific semantics must start with an underscore, e.g., _TEMPERATURE". The validator will reject an attribute named FACEMAPS.

canadaduane commented 3 years ago

Oh, hmmm. That makes sense, but then someone could name a vertex group as "facemap" and it would potentially wipe out the legit "_facemap" attribute, right?

Maybe we need a special prefix, such as "vg*", for vertex groups...

On Fri, Mar 12, 2021, 11:48 PM scurest @.***> wrote:

I changed the _FACEMAPS attribute to FACEMAPS so that the underscore prefix can continue to have special meaning, i.e. to flag mesh attributes as named vertex groups.

The underscore is because the spec requires that "application-specific semantics must start with an underscore, e.g., _TEMPERATURE". The validator will reject an attribute named FACEMAPS.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/KhronosGroup/glTF-Blender-IO/issues/1232#issuecomment-797878706, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAABANJ6TVDZ37WADYXTSDTDL4EHANCNFSM4SFJQH3Q .

canadaduane commented 3 years ago

I added the _vg_* prefix and restored the _ prefix to _facemaps. (Thanks!)

fknfilewalker commented 3 years ago

are there plans to merge this into the official exporter?

donmccurdy commented 3 years ago

We'd be happy to review PRs for either Face Maps or Vertex Groups — ideally with added unit tests since this is a less common case and it would be easy to miss regressions.

julienduroure commented 1 year ago

Facemaps are now longer part of Blender (removed for 4.0) See https://projects.blender.org/blender/blender/commit/46cf09327001331c77bcd54ceab73404a1733172

globglob3D commented 5 months ago

+1 for vertex group export. We need a way to tag parts of a mesh in a Blender for later manipulation in threejs. This would open a lot of possibilities for parametric modeling and is less cumbersome than a full armature rig.

If not vertex groups then having the ability to export custom attributes on mesh components would be great. But I guess that can already be done with vertex color?

canadaduane commented 5 months ago

It can be done with vertex color, if you don't care about coloring vertices :) In our case (Relm) we wanted both.

ToonKru3 commented 1 month ago

+1 for export GLTF/GLB file with vertex group, This could make the feature more editable on the geometry 3D model

jonnytest1 commented 3 weeks ago

+1