Jump to content
  • Advertisement
Sign in to follow this  
ne0_kamen

Incorrect rotation with custom matrix [SOLVED]

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello there, Up until now I have been using OGL with my custom matrix just fine,but recently I have been running into some problems. I have a D3D and an OGL render system both working with my matrix class and converting them into appropriate format before multiplying. In my engine,every mesh is centered around the origin so I can rotate properly.But recently I have written an application which needs it's objects to rotate around 0,0,0 or other points and not around their center's positions.So I said simple,huh?Just multiply the rotation matrix first and after that the translation and you got it (or translate to desired rotation origin,rotate and then translate back).But then I got a problem - while in my d3d renderer everything worked like a charm,in OGL the objects where rotating not only around the point I desire,but also around their origin . So I will stop my rumbling and post some code :)Here is the relevant code of my matrix that could cause problems.I use a row major matrix consisted of 4 vectors.
T3D::Matrix T3D::Matrix::operator *(Matrix& m)
{
	Matrix result;

	result[0][0] = vec[0][0]*m[0][0]+vec[1][0]*m[0][1]+vec[2][0]*m[0][2]+vec[3][0]*m[0][3];
	result[0][1] = vec[0][1]*m[0][0]+vec[1][1]*m[0][1]+vec[2][1]*m[0][2]+vec[3][1]*m[0][3];
	result[0][2] = vec[0][2]*m[0][0]+vec[1][2]*m[0][1]+vec[2][2]*m[0][2]+vec[3][2]*m[0][3]; 
	result[0][3] = vec[0][3]*m[0][0]+vec[1][3]*m[0][1]+vec[2][3]*m[0][2]+vec[3][3]*m[0][3];
	result[1][0] = vec[0][0]*m[1][0]+vec[1][0]*m[1][1]+vec[2][0]*m[1][2]+vec[3][0]*m[1][3];
	result[1][1] = vec[0][1]*m[1][0]+vec[1][1]*m[1][1]+vec[2][1]*m[1][2]+vec[3][1]*m[1][3];
	result[1][2] = vec[0][2]*m[1][0]+vec[1][2]*m[1][1]+vec[2][2]*m[1][2]+vec[3][2]*m[1][3]; 
	result[1][3] = vec[0][3]*m[1][0]+vec[1][3]*m[1][1]+vec[2][3]*m[1][2]+vec[3][3]*m[1][3];
	result[2][0] = vec[0][0]*m[2][0]+vec[1][0]*m[2][1]+vec[2][0]*m[2][2]+vec[3][0]*m[2][3];
	result[2][1] = vec[0][1]*m[2][0]+vec[1][1]*m[2][1]+vec[2][1]*m[2][2]+vec[3][1]*m[2][3];
	result[2][2] = vec[0][2]*m[2][0]+vec[1][2]*m[2][1]+vec[2][2]*m[2][2]+vec[3][2]*m[2][3]; 
	result[2][3] = vec[0][3]*m[2][0]+vec[1][3]*m[2][1]+vec[2][3]*m[2][2]+vec[3][3]*m[2][3];
	result[3][0] = vec[0][0]*m[3][0]+vec[1][0]*m[3][1]+vec[2][0]*m[3][2]+vec[3][0]*m[3][3];
	result[3][1] = vec[0][1]*m[3][0]+vec[1][1]*m[3][1]+vec[2][1]*m[3][2]+vec[3][1]*m[3][3];
	result[3][2] = vec[0][2]*m[3][0]+vec[1][2]*m[3][1]+vec[2][2]*m[3][2]+vec[3][2]*m[3][3]; 
	result[3][3] = vec[0][3]*m[3][0]+vec[1][3]*m[3][1]+vec[2][3]*m[3][2]+vec[3][3]*m[3][3];

	return result;
}
void T3D::Matrix::translate(T3D::Vector3f& v)
{
	vec[3][0] = v[0];
	vec[3][1] = v[1];
	vec[3][2] = v[2];
	vec[3][3] = 1.0f;
}
void T3D::Matrix::scale(T3D::Vector3f& v)
{
	vec[0][0] = v[0];
	vec[1][1] = v[1];
	vec[2][2] = v[2];
	vec[3][3] = 1.0f;
}
T3D::Matrix& T3D::Matrix::rotateX(float degrees)
{
	float sinAngle = sin( toRadian(degrees) );
	float cosAngle = cos( toRadian(degrees) );

	vec[1][1] = cosAngle;
	vec[1][2] = sinAngle;
	vec[2][1] = -sinAngle;
	vec[2][2] = cosAngle;
	return *this;
}
T3D::Matrix& T3D::Matrix::rotateY(float degrees)
{
	float sinAngle = sin( toRadian(degrees) );
	float cosAngle = cos( toRadian(degrees) );

	vec[0][0] = cosAngle;
	vec[0][2] = -sinAngle;
	vec[2][0] = sinAngle;
	vec[2][2] = cosAngle;

	return *this;
}
T3D::Matrix& T3D::Matrix::rotateZ(float degrees)
{
	float sinAngle = sin( toRadian(degrees) );
	float cosAngle = cos( toRadian(degrees) );

	vec[0][0] = cosAngle;
	vec[0][1] = sinAngle;
	vec[1][0] = -sinAngle;
	vec[1][1] = cosAngle;

	return *this;
} 



Now here is the code I use to transform the above into d3d/ogl matrix;
	
// OGL	
void setTransform(Matrix& m)
{
   float value[16];
   int v = 0;
   for(int i = 0;i < 4;i++)
   {
	for(int j = 0;j < 4;j++)
	{
	   value[v++] = m[j];
	}
   }
   value[14] = -value[14];

   glLoadIdentity();
   gluLookAt(0,0,100,
   0,0,0,
   0,1.0f,0);
   glMultMatrixf(value);
} 
//D3D
void setTransform(Matrix& m)
{
D3DXMATRIX transform(m[0][0],m[0][1],m[0][2],m[0][3],
							     m[1][0],m[1][1],m[1][2],m[1][3],
								 m[2][0],m[2][1],m[2][2],m[2][3],
								 m[3][0],m[3][1],m[3][2],m[3][3]);
			m_pDevice->SetTransform(D3DTS_WORLD,&transform);
}


Now I will put two screenshoots,better describing the problem: Here is how it looks in d3d Free Image Hosting at www.ImageShack.us And here is how it looks in ogl Free Image Hosting at www.ImageShack.us Also it is worth to say that if I use glRotatef and then glTranslatef I can get the same results as in d3d mode.To help further with the debugging I will also post some the MODELVIEW matrix taken from ogl and d3d for the same transformations of the same object. Here is the result from d3d and ogl when I rotate by 10.0 on the x axis and then traslate (note that this is view * world matrix): [1 0 0 0] [0 0.984808 0.173648 0] [0 -0.173648 0.984808 0] [8 -9.26765 -106.489 1] Here is the result from ogl when I use glRotatef and glTraslatef(proper rotation): [1 0 0 0] [0 0.984808 0.173648 0] [0 -0.173648 0.984808 0] [8 -6.48928 -109.268 1] You may notice the difference in the positions,but if I rotate -10.0f on X then I get the same positions as in glRotatef,but with m[22] = -0.173648 instead of 0.173648 and m[3][1] = 0.173648 instead of - 0.173648. I hope that I have given a good description and not totally confused you as I am :) I appreciate your time. [Edited by - ne0_kamen on November 1, 2007 11:37:51 AM]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by ne0_kamen
Here is the result from ogl when I use glRotatef and glTraslatef(proper rotation):

Whats the result from the bad rotation matrix? edit: My bad I miss read your post, its the first one. I thought you were using glGetMatrix

I don't know Direct3D at all really but are you sure that the Y axis is inverted? You have value[14] = -value[14]; inverting the Y translation. Although this could just be my own lack of knowledge of Direct3D

Share this post


Link to post
Share on other sites
value[14] is not the Y,but the Z axis :) And yes I'm inverting the Z axis,because d3d and my engine is using left handed system where the greater the depth,the further you go into the screen,while in OGL it's the opposite.Also I don't see how this would change the rotation.I'm using the same positions(including -value[14]) with glTranslatef where as I said it rotates properly.

Thanks for your time.

Still looking for help.

Share this post


Link to post
Share on other sites
maybe you need to post your code how you do the transformation.

it is backward in openGL, which i mean

if you used glRotatef and then used glTranslatef, it actually will do translate first and then rotate.

i'm quite new to openGL, so if i didn't answer your question, please forgive me. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by lsio07
maybe you need to post your code how you do the transformation.

it is backward in openGL, which i mean

if you used glRotatef and then used glTranslatef, it actually will do translate first and then rotate.

i'm quite new to openGL, so if i didn't answer your question, please forgive me. :)


I now that,but that's the whole point of using a matrix,doesn't it ?I desire exactly that - to translate the object to a point,rotate around it and then translate back.And as I said before it works just perfectly in d3d.It is also working alright if I use glRotate and glTranslate.I just don't get how feeding d3d and ogl with the same matrix,while taking in account that ogl ir colum-major and d3d row-major can produce different results.My mind is totally going to explode :)I just post the matrix code hoping someone can track an error in the multiplication or something that my produce that different effect you can view from the images...Maybe it's a problem with the left-handyness of d3d,I don't know .Maybe it's more math oriented question,so I had to ask in the math forum ?

Thanks for the feedback!
Still looking for help.

Share this post


Link to post
Share on other sites
The matrix use in D3D is row major, where as OpenGL is column major. Therefore, you cannot just copy a matrix directly from D3D to OpenGL, you have to transpose the matrix.

If you change your coordinates system, not only translation but also rotation will be affect. Therefore, you need to inverting the whole z-column.

Also, there is another less obvious issue. That is, filping z-axis will cause the winding of 3D model inverted. As a result, the culling will be a messed up. To solve this issue, either stop using culling or reverse the winding of 3D model explicitly can do the job.

// OGL
void setTransform(Matrix& m)
{
float value[16];
int v = 0;
for(int i = 0;i < 4;i++)
{
for(int j = 0;j < 4;j++)
{
value[v++] = m[j]; //transpose the matrix
}
}

//inverting the whole z-column
value[8] = -value[8];
value[9] = -value[9];
value[10] = -value[10];
value[11] = -value[11];

Share this post


Link to post
Share on other sites

Just wanted to say that I have solved it.Thanks ma_hty for the info,but the matrix didn't need to be transposed - it is in already good format for ogl.As I use a row - major matrix(as is used by d3d),consisted of 4 vectors,each representing a row,my translation is in m[3][0],m[3][1] and m[3][2].So actually the loop was alright as the above positions match correctly value[12],value[13] and value[14] which are used by ogl as x,y and z coords.You gave me some insides,through,so I'm thankful.


My problem lied in that I'm inverting the z axis.As you have said,not only the z value needed to be inverted,but also the rotations.However,changing only the z column,produced some strange results in rotating about the other axis.So I just removed the value[14] = -value[14] and the rotation became the same as in d3d except that the object was backfacing the camera and the rotations were inversed.So to get the whole thing to work exactly the same in d3d and ogl I ultimately changed my coordinate system to right handed and used - to go into the screen and + to go out of the screen.Now it works beautifully.



Thanks everyone for the help.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!