PDA

View Full Version : Major Mistake - Clarification needed asap



spiralsmile
03-28-2003, 10:56 AM
Right i fear that i have made a huge mistake in my understanding of what matrix Palette Skinning is.

I believed it was the same as nVidias openGL mesh skinning of the harley model in the effects browser was the same as the matrix palette skinning demo in directX also in the effects browser.

My question is however is it the case that you load all bones into the constant registers of a vertex program (this being the matrix palette) and then when a vertice is loaded it chooses then bones it needs by some means and then the vertex program outputs the vertex after its being affected.

I know thats not very clear but i am very confused about this issue.

Could someone possibily sppend a little time and explain to me _simply_ how matrix palette skinning is implmented, ie is it the same in OpenGL as it is when described by Benjamin Freidlin in the following article?

MSDN article by Benjamin Freidlin (http://msdn.microsoft.com/msdnmag/issues/01/06/matrix/default.aspx)

Thanks in advance

tony

jwatte
03-28-2003, 02:00 PM
Here's some simple code that shows how it's done:
http://www.mindcontrol.org/~hplus/graphics/vert_weighting.html

Your description seems mostly sound, but as it's lacking rigour, it's hard to tell for sure :-)

jwatte
03-29-2003, 08:55 AM
I got private e-mail, which I don't quite like, because if I take the time to explain something, I might as well put it where other people can find it:


The basic idea is that you bind, say, two extra data streams
to your vertex; one contains 4 indices (into the constant pool);
one contains 4 weights. Then you use the address register
addressing mode in the vertex program to transform the vertex
by the 4 separate matrices determined by the index values, and
add them together using the blend.

You probably only need to use 3 constant registers per available
bone, as the "w" is likely to always be 1.

Note: you can fit ~26 bones at a time into the constant pool,
which may be enough for an entire skeleton. If it isn't, then
you have to split your mesh, in such a way that you have enough
overlap to draw each vertex necessary for each triangle in each
piece. Only necessary if you have > 26 bones in your skeleton.

I suggest you get the nVIDIA developer SDK and look through it;
it contains all the samples you need. The DirectX SDK also
contains the same thing (with DirectX API, of course).

In NV_vertex_program, you use the ARL instruction with the A0 register from your vertex attribute, and then use c[A0] for addressing the bone data. In ARB_vertex_program, it's very similar (check section Section 2.14.4.2 of the extension spec).

spiralsmile
03-30-2003, 12:13 PM
another question about matrix palette skinning

Right assuming you are using vertex program version 1-1.
And that the code is optimised as it can be (feel free to correct me)

Is the maximum number of bones to be loaded into the const table ie the matrix palette 30?
i made this caculation by
assuming that you use 4 registers thru loading the modelview
matrice into c[0] thru c[3] and you use 2 registers loading a diffuse colour and light position into
registers c[4 and c[5] respectively

Is the maximum number bones that can be referenced by one vertex 13?
I made this calculation by
Using v[OPOS] as normal to store the vertex coords. Using v[NRML] to store the vertex normals. Using v[WGHT] and v[COL0] thru v[TEX0] to store the vertex weights. Using v[TEX1] thru v[TEX7] to store the bone (matrix) indices

Now remebering there is a limit of 128 instructions in this version (1-1) of vertex programs:
Each bone requires 9 instructions to process if i use a vertex program like this one




# Load the matrix index for mat0
ARL A0.x, v[TEX0].x;

# We transform the offset by bone one's tranform
DP4 R0.x, c[A0.x + 8], v[OPOS];
DP4 R0.y, c[A0.x + 9], v[OPOS];
DP4 R0.z, c[A0.x + 10], v[OPOS];
# We multiply the transformed offset by the weight
MUL R0.xyz, R0, v[WGHT].x;

# We transform the normal offset by bone one's tranform
DP3 R1.x, c[A0.x + 8], v[NRML];
DP3 R1.y, c[A0.x + 9], v[NRML];
DP3 R1.z, c[A0.x + 10], v[NRML];
# We multiply the transformed normal offset by the weight
MUL R1.xyz, R1, v[WGHT].x;

# Load the matrix index for mat1
ARL A0.x, v[TEX0].y;

# We transform the offset by bone two's tranform
DP4 R2.x, c[A0.x + 8], v[OPOS];
DP4 R2.y, c[A0.x + 9], v[OPOS];
DP4 R2.z, c[A0.x + 10], v[OPOS];
# We multiply the transformed offset by the weight
MAD R0.xyz, R2, v[WGHT].y, R0;

# We transform the normal offset by bone two's tranform
DP3 R3.x, c[A0.x + 8], v[NRML];
DP3 R3.y, c[A0.x + 9], v[NRML];
DP3 R3.z, c[A0.x + 10], v[NRML];
# We multiply the transformed normal offset by the weight
MAD R1.xyz, R3, v[WGHT].y, R1;

......... keep going for mat2 and mat3..........
then load up mat4.....

# Load the matrix index for mat1
ARL A0.x, v[TEX1].x;

# We transform the offset by bone two's tranform
DP4 R2.x, c[A0.x + 8], v[OPOS];
DP4 R2.y, c[A0.x + 9], v[OPOS];
DP4 R2.z, c[A0.x + 10], v[OPOS];
# We multiply the transformed offset by the weight
MAD R0.xyz, R2, v[COL0].x, R0;

# We transform the normal offset by bone two's tranform
DP3 R3.x, c[A0.x + 8], v[NRML];
DP3 R3.y, c[A0.x + 9], v[NRML];
DP3 R3.z, c[A0.x + 10], v[NRML];
# We multiply the transformed normal offset by the weight
MAD R1.xyz, R3, v[COL0].x, R1;

...and so on and so forth...until the last bone

# set the vertex w to 1.0
SGE R0.w, R1, R1;

# normalize(R1) -> R1
DP3 R1.w, R1, R1;
RSQ R1.w, R1.w;
MUL R1, R1, R1.w;

# Still needs to be projected...
DP4 o[HPOS].x, c[0], R0;
DP4 o[HPOS].y, c[1], R0;
DP4 o[HPOS].z, c[2], R0;
DP4 o[HPOS].w, c[3], R0;

DP3 R3, c[5], R1; # light position DOT normal
MUL o[COL0].xyz, R3, c[4];
END



Thanks
tony

[This message has been edited by spiralsmile (edited 03-30-2003).]

jwatte
03-30-2003, 01:35 PM
That seems about right, except you don't have space for your projection matrix in that register bank -- perhaps you meant putting MVP into c0-c3, and you're lighting in projected space?

EDIT: of course you're lighting in MODEL space, but your c0-c3 is still MVP.

[This message has been edited by jwatte (edited 03-30-2003).]

spiralsmile
04-01-2003, 02:27 AM
Originally posted by jwatte:
Note: you can fit ~26 bones at a time into the constant pool,
which may be enough for an entire skeleton. If it isn't, then
you have to split your mesh, in such a way that you have enough
overlap to draw each vertex necessary for each triangle in each
piece. Only necessary if you have > 26 bones in your skeleton.


Is there a visual explanation of what you describe here, ie about

"there being enough overlap to draw each vertex necessary for each triangle in each piece."

I dont understand what you mean.
thanks
tony




[This message has been edited by spiralsmile (edited 04-01-2003).]

jwatte
04-01-2003, 07:08 AM
Each vertex needs influences from some number of bones to draw.

All bones needed need to be in the constant pool for the vertex to be able to draw.

All vertices that go into a triangle need to be drawable for the triangle to draw.

Thus, you need to generate separate chunks of your mesh such that, for each chunk, all vertices of all triangles in the chunk only reference the same 26 (or less) bones. At the seams between chunks you may get triangles that reference bones that were part of the previous chunk -- this is normal, and to be expected; there will be a bit of overlap in what bones each chunk uses. I'd conservatively estimate another 12-18 new unique bones per extra chunk you add.