// ... 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));
Using D3DXMatrixTransformation2D in DX9
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:
What's wrong with this code?
Toolmaker
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
Good luck,
Chris
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:
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;
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.
It would go something like this:
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
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
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:
Ideas?
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?
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
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
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement