Archived

This topic is now archived and is closed to further replies.

Art of Rotation

Recommended Posts

Chaoz    122
Ok.. I have turned my head around a couple of times to try to figure this problem out. I know it is a simple math problem and I have scanned the forum here the past two days to figure out how to solve this. The short version: I want to make my unit follow the terrain on my map. Ok..so the detailed version: I have my little triangle (plane). I have the normal to this triangle. So.. from what I can figure out you are using a nice formula to figure out the angle between the direction vector and the normal of my plane, to figure out how many degrees I should rotate my unit to make it look like it is actually standing on the ground. I have tried this formula: a dot b = |a||b|cos@ (where @ = angle) But the trick is.. how do I do this to find each of the angles for each axis I want to rotate?? I tried to use A as forward vector (1,0,0) and then B as the normal to the triangle/plane to find the angle I should rotate around the x-axis, but this doesnt seem to work :\ Might be that I am totally off here - So pleeease help before I go insaine --------------------------------------- Sex is like hacking. You get in, you get out,and you hope you didn''''t leave something behind that can be traced back to you. Sex is like hacking. You get in, you get out,and you hope you didn''''t leave something behind that can be traced back to you.

Share on other sites
johnb    351
> a dot b = |a||b|cos@ (where @ = angle)

That's right, but use the up direction and normal to get the angle, which is the steepness of the slope. The axis of rotation is perpendicular to both these vectors, and is given by the normalised outer/cross product of them.

This rotates your charater to stand on the plane. Combine this with a similar rotation about the up axis through the bearing/orientation of the character to face the character in the correct direction. E.g. to do this with quaternions calculate two quaternions from the angle-axis information for the two rotations about the two axes described above then multiply the quaternions to give the total rotation. The order of multiplication depends on how your API handles quaternions: easiest to try both to see which works.

[edited by - johnb on June 6, 2002 11:08:19 AM]

Share on other sites
Chaoz    122
But I am still a bit confused.

Here is a short copy&paste from my source:

// My upvector
D3DXVECTOR3 vUp = D3DXVECTOR3(0,1,0);

// Normal to the plane
D3DXVECTOR3 vNorm = D3DXVECTOR3(0.21070,0.78583,0.58144);

// The orientation vector for the unit
D3DXVECTOR3 vRotate;

// a dot b
float adotb = vUp.x*vNorm.x + vUp.y*vNorm.y + vUp.z*vNorm.z;

// |a|
float uA=sqrtf(vUp.x*vUp.x + vUp.y*vUp.y + vUp.z*vUp.z);

// |b|
float uB=sqrtf(vNorm.x*vNorm.x + vNorm.y*vNorm.y + vNorm.z*vNorm.z);

// My angle between upvector and normal
float angle = acosf(adotb / (uA*uB));

So..now I want set the rotate values for vRotate.x and vRotate.z
(tilt forward and roll to the right to match the ground
and the rotation angle for x and z are ofcourse not the same, so how do I get them from the angle I calculated?

(Or do I have to calculate each angle individually with some magic trick

Share on other sites
johnb    351
It sounds like your rotation angles are just Euler angles. I avoid them as they are far more complex to work with. It''s still easiest to work out the quaternion and then convert it to Euler angles as a last step. Even better just use quaternions or matrices throughout: if you convert to Euler angles your just doing extra work as they have to be converted to matrices at some point to do the transformations.

Share on other sites
Chaoz    122

I have now skipped using the Eular angles and YawRollPitch thing, and got my hands dirty on matrices instead.
I have used the tutorial I found on http://www.makegames.com/3drotation but I know I am messing up something here. :-)

Here is the source:
(I have just hardcoded the normal for the triangle for now.. to see if it really works

    D3DXMATRIX CDFMap :: getPlaneAngle(D3DXMATRIX m,float mx,float my){	D3DXMATRIX m;	D3DXVECTOR3 vUpw        = D3DXVECTOR3(0,1,0);	D3DXVECTOR3 vNorm       = D3DXVECTOR3(0.21070f,0.78583f,0.58144f);	D3DXVECTOR3 vOut,vUp,vRight;	//	// 1. We have the up vector (since this is the normal to the plane)	//	float xx = vNorm.x;	float yy = vNorm.y;	float zz = vNorm.z;	// Project vUp	vUp.x = xx / sqrtf(xx*xx + yy*yy + zz*zz);	vUp.y = yy / sqrtf(xx*xx + yy*yy + zz*zz);	vUp.z = zz / sqrtf(xx*xx + yy*yy + zz*zz);	//	// 2. Get the vOut vector (forward) by projecting the up vector	//    into the zx plane	//	float d = vNorm.x*vUpw.x + vNorm.y*vUpw.y + vNorm.z*vUpw.z;	vOut.x = vUpw.x - d*vNorm.x;	vOut.y = vUpw.y - d*vNorm.y;	vOut.z = vUpw.z - d*vNorm.z;	// Normalize the vOut	vOut = vOut / sqrtf(vOut.x*vOut.x + vOut.y*vOut.y + vOut.z*vOut.z);	//	// 3. Getting vRight (cross product of vUp and vOut)	//	vRight.x = vUp.y * vOut.z - vUp.z * vOut.y;	vRight.y = vUp.z * vOut.x - vUp.x * vOut.z;	vRight.z = vUp.x * vOut.y - vUp.y * vOut.x;	//	// Building Rotation Matrix	// 	m._11 = vRight.x; m._12 = vRight.y; m._13 = vRight.z; m._14 = 0; // Right	m._21 = vUp.x;  m._22 = vUp.y;  m._23 = vUp.z;  m._24 = 0; // Up	m._31 = vOut.x;  m._32 = vOut.y;  m._33 = vOut.z;  m._34 = 0; // Out	m._41 = 0;   m._42 = 0;   m._43 = 0;   m._44 = 1;                return m;}  vUpw is the World Up vector (0,1,0). and the vNorm is the Normal to my triangle/plane.This is called by:      	D3DXMatrixIdentity(&matTemp);	D3DXMatrixIdentity(&matWorld);	matTemp = getPlaneAngle(matTemp,UnitsOnMap[i].travelposition.x,UnitsOnMap[i].travelposition.z,D3DXVECTOR3(0,0,0));	D3DXMatrixMultiply(&matWorld, &m_matWorld, &matTemp);	D3DXMatrixTranslation( &matTemp, UnitsOnMap[i].position.x,UnitsOnMap[i].position.y,UnitsOnMap[i].position.z ); // X,Y,Z	D3DXMatrixMultiply( &matWorld, &matWorld, &matTemp );	m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

Hum..so any obvious bugs, or am I totally off here?

[edited by - chaoz on June 7, 2002 6:15:16 AM]

[edited by - chaoz on June 7, 2002 6:20:28 AM]