Jump to content
  • Advertisement
Sign in to follow this  
Toolmaker

Using D3DXMatrixTransformation2D in DX9

This topic is 5143 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

I'm having a little bit of trouble rotating my 2D sprite. I'm using textured quads and I'm trying to write my blit function. It works fine, until I'm going to add rotation, which looks like this:
// ... Fill the vertices

    // Check if we need to rotate the texture
    if (fRotate != 0)
    {
        D3DXVECTOR2 vCenter(m_ImgInfo.Width / 2.0f, m_ImgInfo.Height / 2.0f);
        D3DXVECTOR2 vScale(1.0f, 1.0f);
        D3DXVECTOR2 vRotCenter(m_ImgInfo.Width / 2.0f, m_ImgInfo.Height / 2.0f);
        D3DXMatrixTransformation2D(&matRotation, &vCenter, NULL, &vScale, &vRotCenter, fRotate, NULL);
        pRender->m_pDevice->SetTransform(D3DTS_WORLD, &matRotation);
    }

    // Unlock the vertexbuffer
    pRender->m_VertexBuffer->Unlock();

    // Draw the texture
    pRender->m_pDevice->SetTexture(0, this->m_lpTexture);
    return (pRender->m_pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2));

What's wrong with this code? Toolmaker

Share this post


Link to post
Share on other sites
Advertisement
Nothing's wrong with your code. When you say your 2D sprite, I assume you created your own sprite from a transformed quad. In other words, you're using XYZ_RHW right? Think about the name given to the vertices. It's "transformed vertices". Now that you think about it, it probably makes more sense. You can't use the World, View, or Projection transforms when drawing pre-transformed vertices (that's your job to transform them). You have to rotate the object yourself. If you just take each vertex and multiply it by your transformation matrix, then save the vertices, you should be set. It's a vector multiplied by a matrix. It should be easy to calculate with simple matrix multiplication or you could use a helper function.

Good luck,
Chris

Share this post


Link to post
Share on other sites
So instead of using SetTransform I need to multiply all the x and y values in the vertices?

In case you want to know how I fill my vertices:

TLVERTEX *vertices;
D3DXMATRIX matRotation;

pRender->m_VertexBuffer->Lock(0, 0, (void**)&vertices, NULL);

vertices[0].colour = VertexColor;
vertices[0].x = (float) pDest->left - 0.5f;
vertices[0].y = (float) pDest->top - 0.5f;
vertices[0].z = 0.0f;
vertices[0].rhw = 1.0f;
vertices[0].v = 0.0f;
vertices[0].u = 0.0f;

vertices[1].colour = VertexColor;
vertices[1].x = (float) pDest->right - 0.5f;
vertices[1].y = (float) pDest->top - 0.5f;
vertices[1].z = 0.0f;
vertices[1].rhw = 1.0f;
vertices[1].u = 1.0f;
vertices[1].v = 0.0f;

vertices[2].colour = VertexColor;
vertices[2].x = (float) pDest->right - 0.5f;
vertices[2].y = (float) pDest->bottom - 0.5f;
vertices[2].z = 0.0f;
vertices[2].rhw = 1.0f;
vertices[2].u = 1.0f;
vertices[2].v = 1.0f;

vertices[3].colour = VertexColor;
vertices[3].x = (float) pDest->left - 0.5f;
vertices[3].y = (float) pDest->bottom - 0.5f;
vertices[3].z = 0.0f;
vertices[3].rhw = 1.0f;
vertices[3].u = 0.0f;
vertices[3].v = 1.0f;


Share this post


Link to post
Share on other sites
Did you change the values of the vertices after the rotation was implemented as Chris said? Because its not going to work with the same values of pretransformed vertices.

Share this post


Link to post
Share on other sites
It would go something like this:


void TransformMe(D3DXMATRIX fpMatrix)
{
pMesh->LockVertexBuffer(0, (void**)&pData);
for (int x=0; x < NumVertices; x++)
{
pStruct = (DataStruct*)pData;
NewPosition.x = (*fpMatrix)._11*pStruct->Position.x +
(*fpMatrix)._21*pStruct->Position.y +
(*fpMatrix)._31*pStruct->Position.z +
(*fpMatrix)._41;
NewPosition.y = (*fpMatrix)._12*pStruct->Position.x +
(*fpMatrix)._22*pStruct->Position.y +
(*fpMatrix)._32*pStruct->Position.z +
(*fpMatrix)._42;
NewPosition.z = 0;
NewPosition.w = 1;
pStruct->Position = NewPosition;
pData += NumBytes;
}
pMesh->UnlockVertexBuffer();
}




pMesh is an ID3DXMesh interface, but you can just lock a vertex buffer. You can remove the NewPosition.z value or just set it to 0 (I removed it for you). NewPosition is a 4D float vector and represents your XYZ_RHW values. Position is also a 4D float vector in your FVF structure and represents the same thing. I modified the code a little, since this comes from what I do to 3D stuff, but you can further reduce it if you want. The way it is above, just be sure you use the D3DXMatrixTransformation2D function to get a proper transform passed in, which you are doing.

Chris

Share this post


Link to post
Share on other sites
I have no clue about the other code, I'm a pure n00b at this. Perhaps I should get a book that covers 2D game engine in D3D9 extensively. Are there any hints for that?

As for now, I've tried this code, which a friend gave me and worked for him, but not for me for a reason:

D3DXMATRIX matPosition, matRotation, matScaling, matTransform;

D3DXMatrixScaling(&matScaling, 1.0f, 1.0f, 1.0f );

D3DXMatrixTranslation( &matPosition, (float)(pDest->left + pDest->right) / 2.0f, (float)(pDest->top + pDest->bottom) / 2.0f, 0.0f );

//Set the Rotation Matrix
D3DXMatrixRotationZ( &matRotation, fRotation );

D3DXMatrixMultiply( &matTransform, &matScaling, &matPosition );
D3DXMatrixMultiply( &matTransform, &matRotation, &matTransform );

//D3DXMatrixMultiply( &matTransform, &matScaling, &matRotation );

pRender->m_pDevice->SetTransform( D3DTS_WORLD, &matTransform );

//pRender->m_pDevice->SetVertexShader(NULL);
//pRender->m_pDevice->SetStreamSource(0, pRender->m_VertexBuffer, 0, sizeof(TLVERTEX));

// Draw the texture
pRender->m_pDevice->SetTexture(0, this->m_lpTexture);
return (pRender->m_pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2));



Ideas?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The thing to understand is that there are 2 types of vertices: Transformed and Untransformed. Well that's not entirely true, but any vertice will be in one of these two groups when it travels through the video card pipeline.

Untransformed vertices are a given when using the D3DFVF_XYZ type. The position vector (3 floats) in your FVF structure define the units in world space. The units are just floating point numbers, where their size is relative to the projection matrix. These units can be transformed by two other matrices (well they are transformed by the projection matrix obviously as I've stated): the View matrix and the World transform matrix. The view matrix and world transform matrix aren't special. You could set one to Identity (that is 1's in the diagonal of the matrix, 0 everywhere else), and use the other as if it was just both of them combined. For example:

View = Identity;
World = MyWorld*MyView; // I can't remember if this is the right order of multiplication, it doesn't matter, that's not my point.

For simplicity, the video card pipeline just takes Untransformed vertices and multiplies them through the 3 matrices, World, View, and Projection. Once multiplied through these matrices, the new vertex is considered to be in Screen Space. It is a vertex that was defined by some 3D point in world space and is now defined as an X,Y pixel in Screen Space.

Transformed vertices are a given when using the D3DFVF_XYZ_RHW type. The position vector (2 floats) in your FVF structure define the pixels from top/left corner of the screen. For simplicity's sake, the z value and w value (another 2 floats) after that are just set to 0 and 1 respectively. Don't get bogged down in what they do yet. These vertices, in their Transformed state, are considered to already be in Screen Space, therefore no projection, view, or world matrices in the video card pipeline are multiplied into the position vector.

The D3DXSprite interface uses transformed vertices, but it has a function SetTransform() that will just move the vertices around (scale, translate, and rotate them) manually, without using the graphics card pipeline.

Now for the reason for all of that. The code your friend gave you can not move a series of vertices created with D3DFVF_XYZ_RHW. The code will move a series of vertices created with D3DFVF_XYZ. Does this all make a little more sense, or did you know all of this already and I'm just assuming too much?

I can't recommend a book on 2D that I've read, because I haven't read any. There are some out there, probably in the Andre LaMothe Game Development series.

Good luck,
Chris

Share this post


Link to post
Share on other sites
Wow, that makes. Sense! Thanks for the long answer.

In other words, I just need to turn my vertex into XYZ form. I'll try that later today. And perhaps I'm going to switch back to the ID3DXSprite interface and try it a bit more.

Thanks!


++Supernat02->Rating;

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!