• 13
• 18
• 19
• 27
• 9

# Skin deformation problem (rotations)

This topic is 4786 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've been trying to write an application to rescale/rotate robe model files for the game neverwinter nights (well, modify and existing app to do this, but the problem relates to things I've added, so it's definatley a problem with what I'm doing). Neverwinter Nights, as far as I can tell, uses a skeletal animation system for its robe models. In the file are a pile of "gizmos" (I think these are equivilent to bones in most descriptions of skeletal animation), and a seperate skin, which comprises of vertices and weights. I've worked out how to scale and rotate the gizmos, and how to scale the skin correctly, but am having big problems rotating the skin. How I understand this should work, and what I think I'm doing, is this: For each gizmo that contributes to the vertex (ie, has a weight) Start with an identity matrix, then rotate the matrix around each pivot up to and including the gizmo that is being rotated , starting with the root pivot. Then starting with a zero matrix, add (the skin vertex * the rotation matrix calculated above * the weight for this matrix) for each gizmo with a weight. I was using this as the result for the new position, but the finished skin is very wrong. To rotate around a pivot I am doing the following: Create a matrix based on the position of the pivot(Pos): |1 0 0 Px| |0 1 0 Py| |0 0 1 Pz| |0 0 0 1 | And another which should translate back the way we came (PosRev) |1 0 0 -Px| |0 1 0 -Py| |0 0 1 -Pz| |0 0 0 1 | And then calculating Pos*rotation matrix (this doesn't have the translation for the pivot in it...) * PosRev. The actual matrix calculation (ie, doing the multiplication) is done by a class which is part of the app I am modifying, and has been used elsewhere in the program a lot, so I'm fairly certain it's can't be that. I've tried removing any code to do pivots except the [leaf pivot?] and only using a rotation at the leaf pivot on the model, which also messes up (the picture below is of it set up like this), so I think I must be misunderstanding how the system is ment to work (I think I'm probably tripping on how the weighting is handled?) Can anyone spot something that I'm doing wrong (or lots of things...)? I've tried looking on google, and read quite a bit about skeletal animation, but haven't had any luck getting this to work (my method above is what I thought http://wscg.zcu.cz/wscg2003/Papers_2003/G61.pdf ment). Here is a before and after picture of a (45,0,0) rotation of the left forearm, the models are the same size, and only the forearm has changed rotation, the difference in angle and size is due to my screenshotting :/ I made the skin transparent on the after shot so it is more obvious how wrong I am. Sorry if these are red X-ing later this evening, the pictures are hosted on my PC so will disappear when I go to bed. ? [Edited by - Flax on February 8, 2005 3:32:11 PM]

##### Share on other sites
Here is the code I'm using for the rotation:
CMatrix Pos(4,4), PosRev(4,4), PosTotal(4,4);// identify4 sets a matrix to the identity matrixidentity4(Pos);identity4(PosRev);identity4(PosTotal);// This reads the position of the pivotCString pos = *posPtr;double x,y,z;pos.TrimLeft(_T(" \t"));sscanf(pos,"position %lf %lf %lf", &x, &y, &z);Pos.SetElement(0,3,x);Pos.SetElement(1,3,y);Pos.SetElement(2,3,z);Pos.SetElement(3,3,1.0f);PosRev.SetElement(0,3,-x);PosRev.SetElement(1,3,-y);PosRev.SetElement(2,3,-z);PosRev.SetElement(3,3,1.0f);PosTotal = Pos;PosTotal *= transform.GetRotTransform();PosTotal *= PosRev;// rot is a CMatrix reference passed to this functionrot = PosTotal;

and this is then used like so:
CMatrix vF(4,1);// This loop reads the values for the weights// which are stored, eg: lforearm_g 0.5 lbicep_g 0.5while (token != ""){CMatrix rotThis(4,4);identity4(rotThis);part = token;token = CSTokenize(weights, _T(" \t"), curPos);weight = atof(token);// calls the code in the  box aboveroot.SkinTransform(part, weight, transThis, rotThis);vF += v * (rotThis * weight);			token = CSTokenize(weights, _T(" \t"), curPos);

vF is then used in place of v(the original skin vertex) as the skin vertex.