Sign in to follow this  
SiS-Shadowman

Rotating, again...

Recommended Posts

SiS-Shadowman    359
I have another question about rotation matrices. I'm trying to rotate a gun or any other item so that it always fits into a character's hand. If I take a gun for example, it needs to be oriented, that the barrel is pointing from the wrist to the index joint, but the grip should always point from the index to the other fingers' joints: Here's an illustration, to show you what I mean (please forgive my poor drawing qualities :D) I thought this should be similar to axial billboarding, I only would need to change the view vector, wich is not the vector from the camera to the billbord position, but from the fingers' joints to the index. I'm pretty shure I didn't make any mistake here, cause my axial billboarding code is working fine. But this time, the rotation matrix messes around with the scale of my object. For testing purposes, I'm using a wireframe box as a representation for the weapon. But this box's scale is complete messed up, once I calculate my rotation matrix like an axial billboarding matrix. Any ideas what might go wrong? *edit* I tried something on my own, but it isn't going well:
D3DXVECTOR3 barrel = index - hand;
D3DXVECTOR3 grip   = finger - index;

D3DXVECTOR3 barrely( barrel.x, 0, barrel.z );
D3DXVec3Normalize( &barrely, &barrely );

D3DXVECTOR3 tmp;
D3DXVec3Cross( &tmp, &D3DXVECTOR3( 1, 0, 0 ), &barrely );
float cosy = D3DXVec3Dot( &D3DXVECTOR3( 1, 0, 0 ), &barrely );
float siny = D3DXVec3Length( &tmp );
m_Rotation = D3DXMATRIX( cosy, 0, -siny, 0,
			 0,	   1, 0,     0,
			 siny, 0, cosy,  0,
			 0,    0, 0,     1 );


Basicly, I'm trying to get the sine and cosine of the angle between the barrel and the X-Axis. At first, I only want to rotate my gun around the Y-Axis, so I only want the angle between the Barrel(x, 0, z) Vector and the (1,0,0) Vector. However the dot- and crossproduct only return the right sign for half a circle, after that the sign seems to be wrong (when I rotate my character, the gun is rotating perfect for half a circle and the other half it is rotating the wrong way round). [Edited by - SiS-Shadowman on April 22, 2008 7:25:14 PM]

Share this post


Link to post
Share on other sites
SiS-Shadowman    359
*edit*

Ok, I read some more information about rotation matrices and I finally realized, that a normalized vector contains the sine and cosine of an angle. So I tried to construct the rotation matrix on my own:

D3DXVECTOR3 hand = pPlayer->GetJointPosition( BaseMonster::RightHand );
D3DXVECTOR3 index = pPlayer->GetJointPosition( BaseMonster::RightIndex3 );
D3DXVECTOR3 finger = pPlayer->GetJointPosition( BaseMonster::RightFinger2 );

D3DXVECTOR3 barrel = index - hand;
D3DXVECTOR3 grip = finger - index;

D3DXVec3Normalize( &barrel, &barrel );
D3DXVec3Normalize( &grip, &grip );

////////////////////////////
// Rotation around Y-Axis //
////////////////////////////

D3DXVECTOR3 angle( barrel.x, 0, barrel.z );
D3DXVec3Normalize( &angle, &angle );
D3DXMATRIX rotY;
lib::CreateRotYMatrix( &rotY, angle.x, angle.z );


////////////////////////////
// Rotation around X-Axis //
////////////////////////////

angle = D3DXVECTOR3( barrel.x, barrel.y, 0 );
D3DXVec3Normalize( &angle, &angle );
D3DXMATRIX rotX;
lib::CreateRotXMatrix( &rotX, angle.x, angle.y );


///////////////////////////////////
// Rotation around "barrel"-Axis //
///////////////////////////////////

angle = D3DXVECTOR3( 0, grip.y, grip.z );
D3DXVec3Normalize( &angle, &angle );
D3DXMATRIX rotAxis;
lib::CreateRotAxisMatrix( &rotAxis, &barrel, angle.z, angle.y );

// Final Rotation-Matrix
m_Rotation = m_pModelData->Rotation() * rotX * rotY * rotAxis;




// m_Rotation is the matrix, returned by m_pModelData->Rotation()

D3DXMATRIX tmp;
lib::CreateRotXMatrix( &tmp, sinf( fRotX * D3DX_PI / 180.0f ), cosf( fRotX * D3DX_PI / 180.0f ) );
m_Rotation = tmp;

lib::CreateRotYMatrix( &tmp, sinf( fRotY * D3DX_PI / 180.0f ), cosf( fRotY * D3DX_PI / 180.0f ) );
m_Rotation *= tmp;

lib::CreateRotZMatrix( &tmp, sinf( fRotZ * D3DX_PI / 180.0f ), cosf( fRotZ * D3DX_PI / 180.0f ) );
m_Rotation *= tmp;



I could finally solve my reorientation problem, but the gun is not always facing the right direction. I've prepared a video to show you my problem. Can anybody tell me how I can construct a rotation matrix with those 2 vectors mentioned in my first post?

[Edited by - SiS-Shadowman on April 23, 2008 1:26:51 PM]

Share this post


Link to post
Share on other sites
SiS-Shadowman    359
Is there anybody who can help me? I'm pretty much finished with the rotation code, but somehow, my calculations are not right. I think the problem is calculating the rotation around the barrel-axis. My code would work well, if the grip (index - finger) wasn't moving, but that is not the case. It's becoming visible in the running video, where the grip is moving from the front of the character to it's back. I've also tried to rotate the grip vector by the inverse rotX * rotY matrix, then normalize it. But this code didn't work well either.
There must be some math guru who knows the presumably easy answer :)

Share this post


Link to post
Share on other sites
haegarr    7372
Altough not a direct solution to your problem, I'd present a way to solve such grasping problems generally. This way would allows the modeller to define how a thing is grasped, and grasping would work with all kinds of things (in theory). However, it doesn't deal with each finger (as long as the modeller doesn't pay attention), and hence may not fulfil your needs.

The core components are 2 explicit co-ordinate frames, 1 being the handle and 1 being the grasper. The handle is defined inside the local frame of the thing to grasp, in your example the weapon. The grasper is defined inside the local frame of the PC; in fact in my case it is a kind of end-effector of the skeleton (if you use skeletons for animations).

Now, having the thing grasped means to match the handle's frame with the grasper's frame, and to link them together. Before grasping, the handle's frame H is transformed into global co-ordinates, e.g. like so (using row vectors since you're using D3D)
Hg := H * MT
where MT denotes the model matrix of the thing (i.e. weapon). Similarly, the frame G of the grasper is given as
Gg := G * MC
in global co-ordinates, where MC denotes the model matrix of the character. To let the handle's frame match the grapser's frame (in global space), a transformation T is to be applied, so that
Hg * Tg == Gg
<=>
Tg = Hg-1 * Gg

You could, of course, also go the other way and match the grasper with the handle, e.g. performing some IK to animate the skeleton grasping the handle. You could also combine both ways, e.g. using skeleton IK to match the positions, but let the handle magically re-orientate to match the grasper's orientation (would would make things somewhat easier).

As a side note, in the implementation I'd not use matrices at this point, but distinct position and orientation (a quaternion in fact). That makes interpolation things easier during animating the grasping. But the matrix writing is better to show the theory.

When the frames are matched, the handled thing is attached to the grasper, letting it follow the skeleton's animation without any furthur special handling. Problems like false orientations of the things during an animation are avoided simply due to using FK.

Share this post


Link to post
Share on other sites
SiS-Shadowman    359
Quote:
Original post by Aph3x
Is it possible for you to set the gun's matrix directly without piddling around with rotations?


I'm afraid not, at least my knowledge is not good enough to know a way how I can derive such an rotation matrix. I've rewritten some MD5 loader code to fit my needs, but I don't understand the core mathematics behind quaternions. So I thought that I could create a rotation matrix from the bones position of the skeleton. I also thought about later using some sort of additional bones, that I can use to position weapons, but the "normal" bones will work for now.

Quote:
Original post by haegarr
The core components are 2 explicit co-ordinate frames, 1 being the handle and 1 being the grasper. The handle is defined inside the local frame of the thing to grasp, in your example the weapon. The grasper is defined inside the local frame of the PC; in fact in my case it is a kind of end-effector of the skeleton (if you use skeletons for animations).


That's a good model. I will use it later in the process, but for now (I don't have any modelers yet) I'm using joint positions to get the basics done, an adjustement should be easy if it works properly.

Quote:

Now, having the thing grasped means to match the handle's frame with the grasper's frame, and to link them together. Before grasping, the handle's frame H is transformed into global co-ordinates, e.g. like so (using row vectors since you're using D3D)
Hg := H * MT
where MT denotes the model matrix of the thing (i.e. weapon). Similarly, the frame G of the grasper is given as
Gg := G * MC
in global co-ordinates, where MC denotes the model matrix of the character. To let the handle's frame match the grapser's frame (in global space), a transformation T is to be applied, so that
Hg * Tg == Gg
<=>
Tg = Hg-1 * Gg
is better to show the theory.

When the frames are matched, the handled thing is attached to the grasper, letting it follow the skeleton's animation without any furthur special handling. Problems like false orientations of the things during an animation are avoided simply due to using FK.


I think I understand your theory, but my problem is to just get the grasps orientation. The handlers orientation matrix is just an identity matrix (for now). But this is the reason I'm having trouble with my orientation code. I just can't construct a matrix for the grasper. My approach is somewhat similar to your's. I'm using a position (for now the index) and an orientation (presented as Vector(index - finger) plus Vector(index-hand)) to create the grasp orientation.
I'm not shure if I can get this information from the animation data itself. Currently I'm using Doom3 models for testing purposes, and they do have some ATTACHER bones in their skeleton data. But I don't know if I can retrieve the orientation data from that because of my poor quaternion knowledge (as mentioned earlier, I only rewrote a model loader, leaving the quaterion/rotation thing nearly untouched).

Share this post


Link to post
Share on other sites
Aph3x    288
Well maybe something as simple as this would work with your system:

vec axisX = Cross(index, fingers);
vec axisY = Cross(index, axisX);
gunOrientation = Matrix33(axisX, axisY, index);

Where the Matrix33 constructor forms an orientation matrix from the given basis vectors. (Note: assumes all vectors are normalised.) We basically make a matrix taking its Z axis (assuming Z = 'forwards') from the index finger vector.

Share this post


Link to post
Share on other sites
haegarr    7372
Quote:
Original post by SiS-Shadowman
...
I think I understand your theory, but my problem is to just get the grasps orientation. The handlers orientation matrix is just an identity matrix (for now). But this is the reason I'm having trouble with my orientation code. I just can't construct a matrix for the grasper. My approach is somewhat similar to your's. I'm using a position (for now the index) and an orientation (presented as Vector(index - finger) plus Vector(index-hand)) to create the grasp orientation.

Well, there is something you should know about rotation matrices since it makes your problem less, err, problematic ;) Aph3x has already hinted at this, but his post has some minor quirks (using position vectors for the cross products) and lacks for an explanation, so I will clarify it a bit w.r.t. my "theory post" above.

A matrix represents a pure rotation matrix if and only if (a) their row vectors are of unit length, and (b) their row vectors are pairwise perpendicular (instead of row vectors also column vectors can be used, but you're working with D3D so that row vectors is better suited in this situation). This is called an "ortho-normal basis". You can check this with the rotation matrix you build in the OP.

The above is introducing some constraints to rotation matrices. This is necessery because a 3x3 matrix has 9 values (i.e. the 3x3 affine part of a homogenous matrix), and hence has 9 degrees of freedom (DoFs). But a rotation in 3D space has only 3 DoFs. So 6 constraints are needed. In this case, "the 3 row vectors should be of unit length" makes up 3 constraints, and "the 3 row vectors have to be pairwiese perpendicular" makes up another 3 contraints.

Anyway, these constraints can be used to construct rotation matrices without computing any trigonometric function from angles. For the following to work, the vectors
b // barrel = index - hand
g // grip = fingers - hand ; note the difference to your approach here
must show a length greater than 0, and must not be parallel. Then you can understand the both vector to spread a plane (in which both vectors lie). The vector
n := b x g
where x means the cross product, will be perpendicular to the plane and hence also to b and g. You may have noticed that this goes into direction of pairwise perpendicular vectors. However, b and g itself are not (necessarily) perpendicular, so let's do the trick once again:
h := n x b
gives us a new vector that is perpendicular to n and b, and points "more or less" into the same direction as g. Notice please that the order of n and b are chosen accordingly so that the principla direction is the same.

What we now have are 3 vectors b, n, and h that are all pairwise perpendicular. The other 3 constraints are simple:
b' := b / | b |
n' := n / | n |
h' := h / | h |

So, using these 3 vectors as row vectors of a matrix gives us ... a rotation matrix! (See Aph3x post above.) The matrix is defined w.r.t. the same super-ordinated co-ordinate frame as the original position vectors of the index finger, the hand, and the "other" fingers are, of course. Assuming that those points are local to the model, then the above matrix is in fact what I've named G in my theory post above.

EDIT: Notice please that a x b == - b x a, so that the order of arguments of the cross-product plays a role. It may happen that the weapon will be orientated wrong, namely if the cross-products doesn't match the (until now) prescribed orientation of the handle in the gun.

Quote:
Original post by SiS-Shadowman
...
I'm not shure if I can get this information from the animation data itself. Currently I'm using Doom3 models for testing purposes, and they do have some ATTACHER bones in their skeleton data. But I don't know if I can retrieve the orientation data from that because of my poor quaternion knowledge (as mentioned earlier, I only rewrote a model loader, leaving the quaterion/rotation thing nearly untouched).

Unfortunately, I've no experience with Doom3 models, so I assume I can't help with this issue.

Share this post


Link to post
Share on other sites
Aph3x    288
Yes sorry there were a few holes in that reply... I tend to be brief nowadays... must be getting old :o
That's why Mr Haegarr has such a deservedly high rating!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this