Jump to content
  • Advertisement
Sign in to follow this  
Kram

D3DXMatrixRotationY Query

This topic is 3801 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 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 this post


Link to post
Share on other sites
Advertisement
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 exists
D3DXMatrixRotationY(&matRotation, index);

matResult = matRotation * matTranslation;

//apply matResult

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Kram
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?

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Kram
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...
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 simotix
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.
Looks fine to me. What makes you think it's only moving half the distance?

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!