PDA

View Full Version : Collada parsing: matching per-vertex weights and indices to other per-vertex data



naf1202
01-18-2018, 06:17 PM
Hi all,

I'm attempting to implement a simple skeletal animation system with data drawn from collada files.

I feel I must be missing something, because I'm having a hard time matching the geometry data to the per-vertex weights and joint indices.

As I understand it, the layout of geometry data in a collada file is more or less the following (for a model with only normals and positions):

positions array: [0, 1, 0, 0.7 ...]
normals array: [0, 1, 0.9, 0.8 ...]
indices: <p>[0, 0, 1, 0, 0, 3]</p>

where, for example, [0, 0] represents the first vertex of the model, with position (0, 1, 0) and normal (0, 1, 0.9).

If I've got this right, it seems obvious that a model should be composed of `length(indices) / number_of_vertex_attributes` vertices.

//

Separately, I understand the joint weights and indices to be stored in a <vertex_weights> node with a layout like this:

<vcount>1, 2, 1</vcount>
<v>3, 0, 3, 1 3, 2 ...</v>

where each element `i` in `vcount` indicates the number of bones that influence that vertex `i`.

Again, if I've got this right, it would seem that the number of elements in `vcount` should equal `length(indices) / number_of_vertex_attributes` -- but in my case, it does not.

I'm pretty sure there aren't any parse issues going on, because all of the relevant count attributes in the collada source match up to my array lengths -- there must be a conceptual thing I'm misunderstanding.

So what am I missing here?

Thanks in advance for any help!

Edit: Also, if I ignore the joint info and just render the geometry, all is well -- so I think the file parsing is ok.

GClements
01-19-2018, 12:12 AM
As I understand it, the layout of geometry data in a collada file is more or less the following

You can't really say anything about the layout of data in a collada file. Collada is designed to allow applications to "dump" their data without substantial restructuring then separately specify what that data actually means.



where, for example, [0, 0] represents the first vertex of the model, with position (0, 1, 0) and normal (0, 1, 0.9).

You can have one index per attribute, or one index per vertex (common to all attributes). You can have one array for positions and one for normals, or you can have both in the same array. You have to consider the attributes and children of the <source> node to make any sense of the data, as well as the attributes (specifically offset=) of the <input> nodes which use it.



Separately, I understand the joint weights and indices to be stored in a <vertex_weights> node with a layout like this:

<vcount>1, 2, 1</vcount>
<v>3, 0, 3, 1 3, 2 ...</v>

where each element `i` in `vcount` indicates the number of other vertices that influence that vertex `i`.

It's the number of bones which influence each vertex. Note that "bind pose position" is also considered a bone (with index -1).


Again, if I've got this right, it would seem that the number of elements in `vcount` should equal `length(indices) / number_of_vertex_attributes` -- but in my case, it does not.
It should equal the number of vertices in the base mesh (the mesh referenced by the source= attribute of the <skin> node).

naf1202
01-19-2018, 07:47 AM
Thank you for responding!

I skimmed over a couple of things in my original post for the sake of brevity.


You have to consider the attributes and children of the <source> node to make any sense of the data, as well as the attributes (specifically offset=) of the <input> nodes which use it.

The parse code does take the offsets and arrays from each input and corresponding source node. Generally, it seems the geometry side of things is working ok, since the model renders just fine.


It's the number of bones which influence each vertex.

I did mean bone here, and I've edited my original post for clarity :)


It should equal the number of vertices in the base mesh (the mesh referenced by the source= attribute of the <skin> node).

Here's where I'm tripping up somehow. In my example model, the <polylist> node in the <mesh> has a count attribute of 48. This matches well with the total number of faces in the model (i.e., the <vcount> node is an array of 3s of length 48), and means the model should have 48 * 3 (144) vertices. My simple model has only positions and normals for each vertex. Fittingly, the <p> node containing indices into the attribute arrays is an array of length 144 * 2.

BUT, in the <controller> linked to the above <mesh>, the <vertex_weights> node has a count attribute of 32 -- so I must be missing something else somewhere.

GClements
01-19-2018, 11:53 AM
Here's where I'm tripping up somehow. In my example model, the <polylist> node in the <mesh> has a count attribute of 48. This matches well with the total number of faces in the model (i.e., the <vcount> node is an array of 3s of length 48), and means the model should have 48 * 3 (144) vertices.

That doesn't follow. Unless the mesh consists of a "cloud" of disconnected triangles, most vertices will be used by several faces (for large triangle meshes, there are typically around twice as many faces as vertices).



My simple model has only positions and normals for each vertex. Fittingly, the <p> node containing indices into the attribute arrays is an array of length 144 * 2.

But how many unique indices are present in those arrays?



BUT, in the <controller> linked to the above <mesh>, the <vertex_weights> node has a count attribute of 32 -- so I must be missing something else somewhere.
Faces can (and usually do) share vertices. E.g. a "quad" made from two triangles sharing a common edge will have 4 vertices, but the <vcount> node will contain "3 3" and the <p> node will contain e.g. "0 1 2 2 3 0" (assuming that it's just positions).

naf1202
01-19-2018, 02:38 PM
But how many unique indices are present in those arrays?

Of course! I don't know why I hadn't considered this. Obviously, things match perfectly now. Thanks so much!