Skip to main content
GameDev.net gamedev.net
🔒 Locked

Finding new Normals?

Started by GamerSg Jan 9, 2004 at 9:26 AM 10 replies 1k views
Original Post
GamerSg
GamerSg
How do i find the new values of my normal after i have deformed my mesh using skeletal animation? Do i have to calculate a new matrix? Or can i just use the same matrix as i did to find the vertex positions? Im doing something like this now
if(temp.bone[u].parentPtr)
{
//rmat refers to the rotation matrix

//tmat originally refers to the inverse of the bones XYZ position to move the bone to the origin before doing rotation.

//fmat is a temporary matrix

//temp.bone[u].mat is the matrix where the final matrix to be used is stored


multMat(rmat,tmat,fmat);//translate to origin, followed by rotation

//find a new tmat which returns bone back to its position

tmat[12] = temp.bone[u].x;
tmat[13] = temp.bone[u].y;
tmat[14] = temp.bone[u].z;
//apply the tmat to the fmat to return the bone back

multMat(tmat,fmat,rmat);
//apply parents matrix after local is done

multMat(temp.bone[u].parentPtr->mat,rmat,temp.bone[u].mat);

}
[edited by - GamerSg on January 9, 2004 10:32:27 AM]
superpig
superpig
I believe you *can* use the same matrices as for regular vertex animation. However, it might require some preparation.

If you consider a normal as being a ''pin'' that sticks out of a vertex and has length 1, then you can find the position of the point at the end of it. You can rotate that point like a normal vertex. Then, find the vector from the vertex to the point again, and there''s your new normal.

There''s probably a way of doing it without needing to calculate these ''tip points'' but you''d have to ask someone else.

Richard "Superpig" Fine
- saving pigs from untimely fates, and when he''s not doing that, runs The Binary Refinery.
Enginuity1 | Enginuity2 | Enginuity3 | Enginuity4 | Enginuity5
ry. .ibu cy. .y''ybu. .abu ry. dy. "sy. .ubu py. .ebu ry. py. .ibu gy." fy. .ibu ny. .ebu
"Don''t document your code; code your documentation." -me
"I''m not a complete idiot; parts of me are missing." -}}i{{
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
Monder
Monder
When transforming normals, you have to use the transpose of the inverse of the matrix used to transform the verticies. However if the matrix you use to transform the verticies is orthogonal (as all matricies which are combinations of rotate and translate matricies are) then you can use the same matrix to transform the normals.

So simply if you've only changed the verticies in the mesh using rotate and translate matricies you can use the exact same matricies to translate the normals

[edit]It's the transpose of the inverse, not the inverse transpose [/edit]

[edited by - Monder on January 10, 2004 11:08:42 AM]
Trienco
Trienco
id agree that in most cases using the same matrices should work perfectly well, except that id set the translation part to 0. normals are just directions and rotating them should work, but you dont want to "move" them, because after that i guess they would be pretty skewed up (pun intended).

and im pretty sure the above is rather pointless as i would expect your fav 3d api to do it right. only if you need to calculate the new normals yourself (collision detection/response or whatever) it might be something to keep in mind ,-)
f@dzhttp://festini.device-zero.de
Monder
Monder
If you''re using proper homogenous vectors (i.e. with a w componant) translations should not effect vectors.
GameCat
GameCat
Small correction, a concatenation of rotations and translations is a 4x4 matrix and is not guaranteed to be orthogonal. However, you should only be interested in the rotation part, which indeed always will be orthogonal.
Monder
Monder
You''re right, but you can still multiply the normals by the same transformation matrix as the one used for verticies because translation doesn''t effect normals (if you''re using a homogenous coordinate system anyway, which you should be)
Namethatnobodyelsetook
Namethatnobodyelsetook
As was said, usually it''s fine to use the same matrix, without translation. If you introduce scale or shear operations then you may have trouble.

To use the same matrix for skinning, assuming you''re using a shader, do something like this:

dp4 r0.x, v0, c0
dp4 r0.y, v0, c1
dp4 r0.z, v0, c2
dp3 r1.x, v1, c0
dp3 r1.y, v1, c1
dp3 r1.z, v1, c2

Granted, you''ll probably be using bone indices, and weights. I''m just highlighting that you need a dp3 instead of a dp4. The has the effect of using the matrix without translation, rather than storing the matrix without translation in other constant registers. The mul, and mad operations for weighting work on normals just as well as position.
GamerSg
GamerSg
I am using the same matrix as for my vertices but i am not getting correct lighting.

Some of you refer to the homogenous system. My matrices are actually just a float[16].
Where does the W coordinate you talk about come into effect? In the matrices or in the vectors?

Both my vertices and normals are just 3 floats.
x y z
nx ny nz

Do i need to add an additional w component to it?

I am not using any scaling/skewing.

Trienco i think i agree with you, since normals are just directions. So that means i will have to calculate a matrix specially for normals?

But does that mean that normals rotated whose bones are at the origin and normals whose bones are somewhere like 100 100 100 will give the same results after rotation?

What about taking into account the parents rotation?
Trienco
Trienco
i think there a few confusing things in the way we think about vertices and normals. we think about the former as points and the latter as direction, but we represent them both as vectors.

sometimes you shouldnt think of a vertex as a point in space, but a vector or "line" from the origin to its position. if you translate that point this vector will be skewed (i think thats the term?).
same happens to a normal, so translation is a big no no (id expect opengl to simply not apply the translation, just like in the vertex shader above). also, normals dont have a position. of course when we visualize them we place them based on the face/plane it belongs to, but basically they all just create one hell of a mess around the origin, all with a length of 1 and on the same sphere (that alone should make it obvious: DONT translate).

next: you should really read up on those matrices and dont think of them as a magic blackbox that is created for you by opengl/directx and does something. its a simple collection of 4d vectors representing the "right", "up", "forward"-vectors and position of your object in world coords. the last component is w and usually its 0 for the three vectors and 1 for the position. theres no need to "calculate" a new matrix (except setting three values to 0 is what you meant with that, but if you do the matrix math yourself it would be easier to just not use that part).

little detail: i think vertex/fragment programs are reading matrices in a transposed fashion, so you can use them in the way above to multiply vectors by them without a lot of extra work. so in the example c0 would be all x components and not the "right"-vector. you dont need c3 as it would contain all w components (if you didnt do anything strange: 0 0 0 1) which shouldnt matter to you at this point.

about parent rotations: how you build your hierachy is up to (if every bone is storing its matrix relative to the world or its parent or both to save time), but the matrix for the normals is just the same as for the vertices, just without any translation.
f@dzhttp://festini.device-zero.de
Trienco
Trienco
ah, isnt it always nice if you finally figure out the obvious? finally making sense to what monder said (assuming a few things, so correct me if im wrong).

internally vertices and normals are transformed by the same modelview matrix. also, that requires them to be 4d so the w component will be added. that should be 1 for vertices and 0 for normals.
so (x y z 1) dot (m0 m4 m8 m12) will calculate the x coordinate (a simple dot3 with xyz and the x components of right/up/fwd) and add the x component of the position (1*m12).
for normals you get w=0, adding 0*position.

what all this means in the end: if you just set your matrix and then render all vertices that belong to this matrix/bone it should just work fine (nothing new here). so my statement is still true "only if you need to calculate the new normals yourself". addition: even in a custom shader you can do the same as with the position of the vertex, as the translation will automatically be cancelled out by w being 0.

if you just need them for lighting you shouldnt have to do anything at all (assuming your normals have been correct before applying any bonematrices).
f@dzhttp://festini.device-zero.de

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.