# D3DXMatrixRotationY Query

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

## Recommended Posts

Hello All, I have a question about the D3DXMatrixRotationY method. Currently I have a nice spinning cube in my app, and I was wanting to be able to shift the cube left, right, up and down with the keyboard. This I can do, but when the cube is spinning and I shift the cube along the X axis, the spinning starts to become more of a wide rotation around the world Y axis. My question, is how do I make the cube rotate around its own Y axis, and not the world Y axis? I am currently doing it like this:
static float index = 0.0f; index+=0.03f;    // an ever-increasing float value
D3DXMATRIX matRotateY;
D3DXMatrixRotationY(&matRotateY, index);
p_d3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY));


(Although i dont really understand that D3DXMATRIX stuff yet). Do I just need to change the D3DTS_WORLD parameter to something else? Thanks a lot! Mark

##### Share on other sites
Matrices are not like normal numbers.
For example:
You have the number 5 and 3. 5 * 3 = 15. But 3 * 5 = 15 too.

With matrices you have to multiplicate the matrices in a certain order. Lets say you first translate it. And then start to rotate it (this is what's happening in your case)

You first move it along the x-axis, and then you start to rotate around (0, 0, 0), this is because matrices work that way.

What you want to do is first rotate, and then translate. What happens is: You start to rotate around (0, 0, 0), so it rotates like you want it too. And then you apply the translation.

In code (did not check for errors):

float index = 0.0f;index += 0.03f;D3DXMATRIX matTranslation;D3DXMATRIX matRotation;D3DXMATRIX matResult;D3DXMatrixTranslateX(&matTranslation, 5.0f); //don't know if this function existsD3DXMatrixRotationY(&matRotation, index);matResult = matRotation * matTranslation;//apply matResult

##### Share on other sites
Ah, you know what Max, that is probably exactly what I am doing! I'll have a look tonight after work. Thanks for the advice.

##### Share on other sites
actually I dont know what the issue is, here is the code for my game entity's render method:

void GameEntity::Render(IDirect3DDevice9* p_d3dDevice){	// select which vertex format we are using    p_d3dDevice->SetFVF(CUSTOMFVF);    // set the view transform    D3DXMATRIX matView;    // the view transform matrix    D3DXMatrixLookAtLH(&matView,    &D3DXVECTOR3 (0.0f, 8.0f, 25.0f),					// the camera position    &D3DXVECTOR3 (0.0f, 0.0f, 0.0f),					// the look-at position    &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));					// the up direction    p_d3dDevice->SetTransform(D3DTS_VIEW, &matView);    // set the projection transform    D3DXMATRIX matProjection;    // the projection transform matrix    D3DXMatrixPerspectiveFovLH(&matProjection,                               D3DXToRadian(45),    // the horizontal field of view                               (FLOAT)640 / (FLOAT)480, // aspect ratio                               1.0f,    // the near view-plane                               500.0f);    // the far view-plane    p_d3dDevice->SetTransform(D3DTS_PROJECTION, &matProjection);    // set the world transform    static float index = 0.0f; index+=0.03f;    // an ever-increasing float value    D3DXMATRIX matRotateY;						// a matrix to store the rotation    D3DXMatrixRotationY(&matRotateY, index);    // the rotation matrix    p_d3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY));    // set the world transform    // select the vertex buffer to display    p_d3dDevice->SetStreamSource(0, this->GetVertexBuffer(), 0, sizeof(CUSTOMVERTEX));    // set the texture    p_d3dDevice->SetTexture(0, m_triangleTexture);    // draw the textured square    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2); }

What I should mention too is that when I press the keyboard keys to move the object left and right, this is the code that does it:

void GameEntity::MoveRight(){	std::vector<CUSTOMVERTEX>::iterator vectorIterator;	for(vectorIterator = m_vertices.begin(); vectorIterator != m_vertices.end(); ++vectorIterator)		vectorIterator->X -= MOVEMENT_SIZE;	SetupVertexBuffer();}void GameEntity::MoveLeft(){	std::vector<CUSTOMVERTEX>::iterator vectorIterator;	for(vectorIterator = m_vertices.begin(); vectorIterator != m_vertices.end(); ++vectorIterator)		vectorIterator->X += MOVEMENT_SIZE;	SetupVertexBuffer();}

so when this happens, the cube still rotates around the Y axis, but is offset on the X axis byt how many times you've hit the keys...

I hope someone can help with this.

Thanks
Mark

##### Share on other sites
You're modifying the locations of your vertices to translate your mesh. That's why it doesn't work. Because you're modifying the vertices themselves, they have an offset position in local space. When you transform it into world space, the rotation occurs about the origin of the cube (which is no longer the centre of the cube since you moved it). In other words, you're performing translation before rotation, when it should be the other way around. Modifying every vertex like that is horrificly slow, anyway.

The solution is to use a proper world matrix to move and rotate your cube. D3DX provides the D3DXMatrixTranslation() function to produce a translation matrix. You then multiply it by your rotation matrix to produce the desired output. Remember, rotation comes before translation. So remember to do matRotate * matTranslate, not matTranslate * matRotate!

D3DX also provides functions such as D3DXMatrixAffineTransformation(), which performs all this for you. But it may be a little heavy-weight for this application (and you'll need to use quaternions).

##### Share on other sites
Ok so let me see if I have this correct.

When I load the app, I have a simple spinning cube, which is rotating on the Y axis.

When I then hit the Right keyboard key, I increase the X axis location of the cubes vertices (which I see is slow).

Then in the transformation, I am shifting the cube along the X axis, THEN I am rotating the cube, which is rotating around an axis that has moved?

I sort of understand what to do to fix it, but in the design should I store sort of member variables like m_xOffset and m_yOffset, then in the Render() method, use this as the parameters of the D3DXMatrixTranslation method?

Thanks for the help, this translation stuff is getting me a little confused!

##### Share on other sites
Quote:
 Original post by KramThen in the transformation, I am shifting the cube along the X axis, THEN I am rotating the cube, which is rotating around an axis that has moved?

Essentially. Since you modified the location of the cube's vertices (when you press the right/left key), the cube is no longer centred around the origin. Since the rotation happens about the origin, your cube will appear to "orbit" a certain location.

Quote:
 I sort of understand what to do to fix it, but in the design should I store sort of member variables like m_xOffset and m_yOffset, then in the Render() method, use this as the parameters of the D3DXMatrixTranslation method?

Yep.

##### Share on other sites
Sweet, and it works well. Thanks for the help!

I suppose I should also ask then, if I was going to shift the cube from one location to another when the user clicks the mouse button, how would I go about changing the x and y offset variables?

In other words, I know I cant just change the x and y offsets to be whatever the user clicks, I need to get the difference between where the user clicked (say 150,200) and the current "location" of the cube...

How would one do this?

Thanks again for the help!

##### Share on other sites
I am having a similar problem and after reading this thread I still can not fix the problem. It looks as if the X is only moving half of its distance for me. However, how I do my transform may just be wrong.

void CPlane::Rotate(float fX, float fY, float fZ){	D3DXMatrixIdentity(&m_mTransform);	if(fX)	D3DXMatrixRotationX(&m_mTransform, fX);	if(fY)	D3DXMatrixRotationY(&m_mTransform, fY);	if(fZ)	D3DXMatrixRotationZ(&m_mTransform, fZ);	m_mTransform._41 = m_vLocation.GetX();	m_mTransform._42 = m_vLocation.GetY();	m_mTransform._43 = m_vLocation.GetZ();}

##### Share on other sites
Quote:
 Original post by KramI suppose I should also ask then, if I was going to shift the cube from one location to another when the user clicks the mouse button, how would I go about changing the x and y offset variables?In other words, I know I cant just change the x and y offsets to be whatever the user clicks, I need to get the difference between where the user clicked (say 150,200) and the current "location" of the cube...
Why? You want to set the new position of the cube to the position that was clicked, so you'll want to set the X and Y values to that position.

If you mean you want the cube to move over several frames, then yes - you'll need the old position, the new position, and the interpolation between then (0..1), and then just set the position to oldPos * (1-time) + newPos * time or similar.

Quote:
 Original post by simotixI am having a similar problem and after reading this thread I still can not fix the problem. It looks as if the X is only moving half of its distance for me. However, how I do my transform may just be wrong.
Looks fine to me. What makes you think it's only moving half the distance?

##### Share on other sites
Quote:
 Original post by Evil SteveWhy? You want to set the new position of the cube to the position that was clicked, so you'll want to set the X and Y values to that position.If you mean you want the cube to move over several frames, then yes - you'll need the old position, the new position, and the interpolation between then (0..1), and then just set the position to oldPos * (1-time) + newPos * time or similar.

Hmm, ok then, maybe I'm thinking about this incorrectly, but when I create the cube, the X, Y and Z vectors are around the -3...3 range, and the cube is centered on the screen. When I click the mouse directly next to the cube, I get X and Y's of say 200, 225 which is the X and Y offsets from the top left corner of my window. What am I doing wrong?

##### Share on other sites
The coordinates of the mouse click you're getting (which probably come from the Windows API one way or another) are in a different coordinate space than what you're using for your graphics. The mouse click is in screen space, you have to convert it to world space. This can be done with D3DXVec3Unproject, if you'd like.

##### Share on other sites
Quote:
 Original post by MJPThe coordinates of the mouse click you're getting (which probably come from the Windows API one way or another) are in a different coordinate space than what you're using for your graphics. The mouse click is in screen space, you have to convert it to world space. This can be done with D3DXVec3Unproject, if you'd like.

Ah I see, thats what I needed to know! I'll have a go at that method tonight when I get home from work.

Also, I just wanted to clarify, that changing the X and Y coords when the user clicks the mouse. Is the X and Y "changing" done in the D3DXMatrixRotationX and D3DXMatrixRotationY methods? I thought these were to offset the object from the origin? If I am correct, then you cant just plug in the mouse's X and Y's can you?

##### Share on other sites
Ok so I am getting there!

Below is my Render method and a helper method to get the converted mouse coords

void GameEntity::Render(IDirect3DDevice9* p_d3dDevice){	// select which vertex format we are using    p_d3dDevice->SetFVF(CUSTOMFVF);    // set the view transform    D3DXMATRIX matView;    // the view transform matrix    D3DXMatrixLookAtLH(&matView,    &D3DXVECTOR3 (0.0f, 8.0f, 25.0f),					// the camera position    &D3DXVECTOR3 (0.0f, 0.0f, 0.0f),					// the look-at position    &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));					// the up direction    p_d3dDevice->SetTransform(D3DTS_VIEW, &matView);    // set the world transform    static float index = 0.0f; index += 0.03f;				// an ever-increasing float value    D3DXMATRIX matRotateY;									// a matrix to store the rotation    D3DXMatrixRotationY(&matRotateY, index);				// the rotation matrix	    // set the projection transform    D3DXMATRIX matProjection;    // the projection transform matrix    D3DXMatrixPerspectiveFovLH(&matProjection,                               D3DXToRadian(45),    // the horizontal field of view                               (FLOAT)640 / (FLOAT)480, // aspect ratio                               1.0f,    // the near view-plane                               500.0f);    // the far view-plane    p_d3dDevice->SetTransform(D3DTS_PROJECTION, &matProjection);		D3DXVECTOR3* transformedPoints = 0;	transformedPoints = this->SetupLocalMousePoints(p_d3dDevice);	if (transformedPoints)	{		m_xOffset = transformedPoints->x;		m_yOffset = transformedPoints->y;	}	//translate the X and Y of needed	D3DXMATRIX matTranslate;	D3DXMatrixTranslation(&matTranslate, m_xOffset, m_yOffset, m_zOffset);	//ALWAYS, Rotate before Translate    p_d3dDevice->SetTransform(D3DTS_WORLD, &(matRotateY * matTranslate));  // set the world transform    // select the vertex buffer to display    p_d3dDevice->SetStreamSource(0, this->GetVertexBuffer(), 0, sizeof(CUSTOMVERTEX));    // set the texture    p_d3dDevice->SetTexture(0, m_triangleTexture);    // draw the textured square    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);    p_d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2); }D3DXVECTOR3* GameEntity::SetupLocalMousePoints(IDirect3DDevice9* p_d3dDevice){	if (m_mousePoint)	{		D3DXVECTOR3 result;		D3DXVECTOR3 screenPoint;		D3DVIEWPORT9 viewport;		D3DXMATRIX matProjection;		D3DXMATRIX matView;		D3DXMATRIX matTranslate;		screenPoint.x = m_mousePoint->x;		screenPoint.y = m_mousePoint->y;		screenPoint.z = 0.0f;		p_d3dDevice->GetViewport(&viewport);		p_d3dDevice->GetTransform( D3DTS_PROJECTION, &matProjection );		p_d3dDevice->GetTransform( D3DTS_VIEW, &matView );		p_d3dDevice->GetTransform( D3DTS_WORLD, &matTranslate );		//transform the mouse clicked location		D3DXVec3Unproject( &result, &screenPoint, &viewport, &matProjection, &matView, &matTranslate );		m_mousePoint = 0;		return &result;	}	return NULL;}

This somewhat works, I think. I say, I think, because I am getting values converted into my world space, but I dont think they are correct.

If I understand how D3DXVec3Unproject works, I need to basically setup the VIEW, PROJECTION and WORLD Transforms first, then convert the users mouse click into the current world space.

I think I am doing this, but if I click in the very top left corner, my X and Y values are like X: -23, Y: 8. I was kind of expecting more like a Y value of +25 or something??

Anyways, with that aside, once I have my X and Y values, is the code (as listed above):

D3DXVECTOR3* transformedPoints = 0;transformedPoints = this->SetupLocalMousePoints(p_d3dDevice);if (transformedPoints){    m_xOffset = transformedPoints->x;    m_yOffset = transformedPoints->y;}//translate the X and Y of neededD3DXMATRIX matTranslate;D3DXMatrixTranslation(&matTranslate, m_xOffset, m_yOffset, m_zOffset);

Correct? If I want to simply move the cube to the clicked location?

Thanks!
Mark

##### Share on other sites
sorry to bump, but I totally stuck here, any assistance with getting the correct X and Y from D3DXVec3Unproject would be greatly appreciated!

Thanks
Mark