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

Arbitrary Axis Rotation

Started by sdoherty55 Jun 14, 2002 at 8:47 PM 6 replies 700+ views
Original Post
sdoherty55
sdoherty55
The source below seems to work work most arbitrary axis rotation''s. However, it does not work for B2.z = -1.0? When B2.z = 1.0f or -1.0f all matrixes are the identitiy matrix except for R3 (it just rotates in the direction of theta)? I releize that there is a lot of additional code, but I am trying to get the code working prior to eliminating the additoinal code. Please help!!
  
	m_fPitch = m_fPitch + .01f;

	// Step 0

	D3DXVECTOR3 A2, B2;
	double theta = -m_fPitch;


	// Step 1.

	// Start of procedure

	A2.x = 0.0f; A2.y = 0.0f; A2.z = 0.0f;
	B2.x = 0.0f; B2.y = 0.0f; B2.z = -1.0f; 

	// Step 2

	D3DXMATRIX T;
	D3DXMatrixIdentity(&T);
	D3DXMatrixTranslation(&T, -A2.x, -A2.y, -A2.z);

	// Step 3

	D3DXMATRIX R1;
	float len1 = (float) sqrt(B2.x * B2.x + B2.z * B2.z);
	float costheta1, sintheta1;

	if (len1 > 0)
	{
		costheta1 = B2.z / len1;
		sintheta1 = B2.x / len1;

		// This, of course, is the matrix for rotation around the Y axis

		R1 = D3DXMATRIX( costheta1,  0, sintheta1,  0,
			                 0,  1,         0,  0,
				    -sintheta1,  0, costheta1,  0,
					         0,  0,         0,  1);
	}
	else
	{

		// Line is already parallel to Y-axis, and therefore already in

		// the YZ plane.  Make this rotation do nothing.  

		D3DXMatrixIdentity(&R1);
	}

	// Step 4

	D3DXMATRIX R2;
	float len2 = (float) sqrt(B2.y * B2.y + B2.z * B2.z);
	float costheta2, sintheta2;

	if (len2 > 0)
	{
	    costheta2 = B2.z / len2;
		sintheta2 = B2.y / len2;

		// This is the X-axis rotation matrix

		R2 = D3DXMATRIX(1,          0,          0,  0,
						0,  costheta2,  sintheta2,  0,                
						0, -sintheta2,  costheta2,  0,
						0,          0,          0,  1);
	}
	else
	{
	    // Should never happen

		D3DXMatrixIdentity(&R2);
	}

	// Step 5

	D3DXMATRIX R3 = D3DXMATRIX( cos(theta), sin(theta), 0, 0,
							    -sin(theta), cos(theta), 0, 0,
				                   0,          0, 1, 0,
					               0,          0, 0, 1);

	// Step 6

	D3DXMATRIX R2_inv;

	if (len2 > 0)
	{ 

	    R2_inv = D3DXMATRIX(1,          0,          0,  0,
							0,  costheta2, -sintheta2,  0,                
							0,  sintheta2,  costheta2,  0,
							0,          0,          0,  1);
	}
	else
	{


		// Obviously, if we skipped this rotation, don''t un-rotate.

		// However, as I stated before, this rotation should always

		// happen, so it would be bizarre indeed if control made it here.

		// Oh, well.

//		R2_inv = identity_matrix;

		D3DXMatrixIdentity(&R2_inv);
	}

	// Step 7

	D3DXMATRIX R1_inv;

	if (len1 > 0)
	{

	    R1_inv = D3DXMATRIX(costheta1,  0, -sintheta1,  0,
		                        0,  1,          0,  0,
			            sintheta1,  0,  costheta1,  0,
				                0,  0,          0,  1);
	}
	else
	{
		D3DXMatrixIdentity(&R1_inv);
	}


	// Step 8

	D3DXMATRIX T_inv = D3DXMATRIX(  1,   0,   0,  0,
							0,   1,   0,  0,
							0,   0,   1,  0,
							0.0f, 0.0f, 0.0f,  1);

	// Construct the final matrix...

	D3DXMATRIX M = T * R1 * R2 * R3 * R2_inv * R1_inv * T_inv;

	// Obviously, you can apply this same matrix to any number of points.

//	P = P * M;

	//b  Step 9


	D3DXMatrixIdentity(&m_matWorld);
//	D3DXMatrixTranslation(&m_matWorld, m_vPosition.x, m_vPosition.y, m_vPosition.z);

	D3DXMatrixTranslation(&m_matWorld, m_vLoc.x, m_vLoc.y, m_vLoc.z);
	D3DXMatrixMultiply( &m_matWorld, &M, &m_matWorld ); 
  
Fruny
Fruny
Gimbal Lock

Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]


[edited by - Fruny on June 14, 2002 9:50:45 PM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
sdoherty55
sdoherty55
Are you sure this is Gimbal lock? Under the conditions where B2.Z = 1.0f or -1.0f, only the R3 matrix is being created. I thought in order to get Gimbal lock, you had to perform multiple rotations where the second or third rotation ends up being in the same plane as a previous rotations. Since there is really only one rotation matrix being created and the rest of the matrices are just the identity matrix, I don't understand how this can be Gibmal Lock?

[edited by - sdoherty55 on June 15, 2002 8:24:38 AM]
sdoherty55
sdoherty55
If anyone is interested, here is the working code produced with alot of help from Nick from FlipCode.


    
float theta = m_fPitch;
float c = cos(theta);
float s = sin(theta);
float t = 1.0f - c;

float x = -vMove.z; // Camera is Rotated 90 Degrees making x the z.

float y = vMove.y;
float z = -vMove.x; // Camera is Rotated 90 Degress making z the x.


float mag = sqrt(x * x + y * y + z * z);

x = x / mag;
y = y / mag;
z = z / mag;


D3DXMATRIX R;
D3DXMatrixIdentity(&R);

R._11 = t * x * x + c;
R._12 = t * x * y + s * z;
R._13 = t * x * z - s * y;

R._21 = t * x * y - s * z;
R._22 = t * y * y + c;
R._23 = t * y * z + s * x;

R._31 = t * x * z + s * y;
R._32 = t * y * z - s * x;
R._33 = t * z * z + c;

R._41 = m_vLoc.x;
R._42 = m_vLoc.y;
R._43 = m_vLoc.z;

m_matWorld = R;


[edited by - sdoherty55 on June 16, 2002 9:37:54 AM]
sdoherty55
sdoherty55
"I''m just wondering, but couldn''t you have just used D3DXMatrixRotationAxis?"

No, because for two reaons:

1) You would run into problems when the matrices are multipled together. Instead of rotating by an Arbitrary Axis, you would be rotating for example the y relative to the x and the z relative to the y. This will also probably lead to Gimbal lock.

2) If it were that easy I am thinking someone would have told me that in the first five seconds of the post?

Give D3DXMatrixRotationAxis a try for yourself. Let me know what you find.

Thanks
maxell120
maxell120

    
// Camera is Rotated 90 Degrees making x the z.

float x = -vMove.z;
float y = vMove.y;
// Camera is Rotated 90 Degress making z the x.

float z = -vMove.x;


i'm a bit confused about this segment of code. how does this work and how does it affect my rotation?

-jm

[edited by - maxell120 on August 13, 2002 3:10:00 AM]
if you see me running, try and catch me!!
sdoherty55
sdoherty55
For my specific implementation, I was using reverse x and z coordinates. You don''t have to flip these axis, but you may have to reverse the sign depending on your implemtation.

PS: I never found this implementation to be perfectly smooth, but it is a step in the right direction. There should be some flipcode posts on how to improve the smoothness of the code...

Topic Locked

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

Sign in to reply to this topic.