Model/texture flipped backwards?

Started by
9 comments, last by majek 14 years, 8 months ago
Hi, my question is sort of hard to explain but I'll try. I'm making a simple model viewer with direct3d 9, it loads mesh data from a .SMD file and stores the vertices in a vertex buffer. Here's how the data looks:
//<int|Parent bone> <float|PosX PosY PosZ> <normal|NormX NormY NormZ> <normal|U V>

axis.tga
0 -2.000000 -2.000000 40.000000 -1.000000 0.000000 0.000000 0.383350 0.578400 
0 -2.000000 2.000000 -40.000000 -1.000000 0.000000 0.000000 0.300850 0.314400 
0 -2.000000 -2.000000 -40.000000 -1.000000 0.000000 0.000000 0.383350 0.314400 
axis.tga
0 -2.000000 -2.000000 40.000000 -1.000000 0.000000 0.000000 0.713350 0.578400 
0 -2.000000 2.000000 40.000000 -1.000000 0.000000 0.000000 0.630850 0.578400 
0 -2.000000 2.000000 -40.000000 -1.000000 0.000000 0.000000 0.630850 0.314400 
axis.tga
0 -2.000000 2.000000 -40.000000 0.000000 0.000000 -1.000000 0.630850 0.314400 
0 2.000000 -2.000000 -40.000000 0.000000 0.000000 -1.000000 0.465850 0.314400 
0 -2.000000 -2.000000 -40.000000 0.000000 0.000000 -1.000000 0.383350 0.314400 
...
The only values I need are PosX-Y-Z, NormX-Y-Z, and U-V. This is how I load them into the vertex buffer:
#define D3DFVF_MESHVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
	
struct MESHVERTEX
{
	D3DXVECTOR3 Position, Normal;
	D3DXVECTOR2 UV;
};
	
vector<MESHVERTEX> vertices;
vector<WORD> indices;
WORD index = 0;
	
// Loop
vector<string> s = Split(line, " ");
	
MESHVERTEX vertex;
vertex.Position = D3DXVECTOR3(StringToFloat(s[1]), StringToFloat(s[2]), StringToFloat(s[3]));
vertex.Normal = D3DXVECTOR3(StringToFloat(s[4]), StringToFloat(s[5]), StringToFloat(s[6]));
vertex.UV = D3DXVECTOR2(StringToFloat(s[7]), StringToFloat(s[8]));
	
vertices.push_back(vertex);
indices.push_back(index);
index++;
// Loop
	
LPD3DXMESH mesh = NULL;
	
// Create the mesh
D3DXCreateMeshFVF((DWORD)vertices.size() / 3, (DWORD)vertices.size(), D3DXMESH_MANAGED, D3DFVF_MESHVERTEX, D3DDevice, &mesh)
	
// Fill the vertex buffer
VOID* pVertices;
mesh->LockVertexBuffer(D3DLOCK_DISCARD, (void**)&pVertices)
memcpy(pVertices, &(vertices[0]), vertices.size() * sizeof(MESHVERTEX));
mesh->UnlockVertexBuffer();
	
// Fill the index buffer
VOID* pIndices;
mesh->LockIndexBuffer(D3DLOCK_DISCARD, (void**)&pIndices)
memcpy(pIndices, &(indices[0]), indices.size() * sizeof(WORD));
mesh->UnlockIndexBuffer();
	
prop.Mesh = mesh;
It seems to work, but when I draw the mesh, the model and texture is flipped around wierd. This is how I draw them:
VOID DrawProp(PROP prop)
{
	D3DXMATRIXA16 matScale;
	D3DXMATRIXA16 matRotX, matRotY, matRotZ;
	D3DXMATRIXA16 matTrans;
	
	// Create the scale matrix
	D3DXMatrixScaling(&matScale, prop.Scale.x, prop.Scale.y, prop.Scale.z);
	
	// Create the rotation matrices
	D3DXMatrixRotationX(&matRotX, DEGTORAD(prop.Rotation.x)); // Pitch
	D3DXMatrixRotationY(&matRotY, DEGTORAD(prop.Rotation.y)); // Yaw
	D3DXMatrixRotationZ(&matRotZ, DEGTORAD(prop.Rotation.z)); // Roll
			
	// Create the translation/position matrix
	D3DXMatrixTranslation(&matTrans, prop.Position.x, prop.Position.y, prop.Position.z);
	
	// Create the world matrix (S * R * T)
	D3DXMATRIXA16 matRot = (matRotX * matRotY * matRotZ);
	D3DXMATRIX matWorld = matScale * matRot * matTrans;
	
	// Set the world transform to the resulting world matrix
	D3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
	
	D3DDevice->SetTexture(0, prop.Textures[0]);
	prop.Mesh->DrawSubset(0);
}

I included a couple pics so you can see what I mean, the first one is how the mesh looks when I draw it, the second one is how it's supposed to look (in my modeling program). I've tried everything and I can't figure it out. Any help would be greatly appreciated, thanks! axis1.jpg axis2.jpg
Advertisement
SMD files (used for Half-Life, etc.) are created in a right-handed world. DirectX is a left-handed world. In SMD world, the z-axis is anti-parallel to the DX z-axis.

I've played around with conversions but with only minor success. I just create my models, compensating for the handedness and living with it.

I wrote a utility (SMD2X.exe) you can try out at www.veazie.org (converts SMDs to x-file format) but (as I remember) the mesh is still mirror-image. Just moves SMD info to an x-file.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

thanks for the quick reply! I've never had this problem using opengl so I was thinking the same thing. I found an article on MSDN that explains how to convert the mesh to a left-handed coordinate system, but it's a bit confusing.

Quote:
Direct3D uses a left-handed coordinate system. If you are porting an application that is based on a right-handed coordinate system, you must make two changes to the data passed to Direct3D.

Flip the order of triangle vertices so that the system traverses them clockwise from the front. In other words, if the vertices are v0, v1, v2, pass them to Direct3D as v0, v2, v1.

Use the view matrix to scale world space by -1 in the z-direction. To do this, flip the sign of the _31, _32, _33, and _34 member of the D3DMATRIX structure that you use for your view matrix.

To obtain what amounts to a right-handed world, use the D3DXMatrixPerspectiveRH and D3DXMatrixOrthoRH functions to define the projection transform. However, be careful to use the corresponding D3DXMatrixLookAtRH function, reverse the backface-culling order, and lay out the cube maps accordingly


I know how to feed the vertices to the buffer correctly, but I don't understand the second step. Can someone help me out with this? Thanks!
If you want to use the same coordinate system as OpenGL, and not have to bother changing the models, then simply use D3DXMatrixPerspectiveRH for your projection matrix, and there's nothing else to it.
Quote:To do this, flip the sign of the _31, _32, _33, and _34 member of the D3DMATRIX structure that you use for your view matrix.


Sounds like, after you create your view matrix:
viewMat._31 = -viewMat._31;viewMat._32 = -viewMat._32;viewMat._33 = -viewMat._33;viewMat._34 = -viewMat._34;

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

I tried using D3DXMatrixPerspectiveRH and D3DXMatrixPerspectiveFovRH, it changes the perspective to look down the negative z axis, but its still drawing the model/texture incorrectly. It seems to be flipped inside out or something, and the texture coordinates are mapped wrong. Am I doing something wrong?

// Set up projection matrixD3DXMATRIXA16 matProj;FLOAT aspectRatio = 800.0f / 600.0f;D3DXMatrixPerspectiveRH(&matProj, D3DX_PI / 4, aspectRatio, 1.0f, 1000.0f);D3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);
From you own post:
Quote:However, be careful to use the corresponding D3DXMatrixLookAtRH function, reverse the backface-culling order..

Are you doing all that, also?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Hmm, it seems to be drawing the model correctly now, but the texture coords are still messed up. I made the changes to the view matrix, and I had to set D3DRS_CULLMODE to D3DCULL_CW. Here's my code:

D3DXVECTOR3 CameraPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f);D3DXVECTOR3 CameraRotation = D3DXVECTOR3(0.0f, 0.0f, 0.0f); VOID SetupCamera(){	// Set up view matrix	D3DXVECTOR3 up, look, right; // Camera axis	up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);	look = D3DXVECTOR3(0.0f, 0.0f, 1.0f);	right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);	// Pitch rotation	D3DXMATRIX pitchMatrix;	D3DXMatrixRotationAxis(&pitchMatrix, &right, CameraRotation.x); 	D3DXVec3TransformCoord(&look, &look, &pitchMatrix); 	D3DXVec3TransformCoord(&up, &up, &pitchMatrix);	// Yaw rotation	D3DXMATRIX yawMatrix;	D3DXMatrixRotationAxis(&yawMatrix, &up, CameraRotation.y);	D3DXVec3TransformCoord(&look, &look, &yawMatrix); 	D3DXVec3TransformCoord(&right, &right, &yawMatrix);	// Roll rotation	D3DXMATRIX rollMatrix;	D3DXMatrixRotationAxis(&rollMatrix, &look, CameraRotation.z);	D3DXVec3TransformCoord(&right, &right, &rollMatrix); 	D3DXVec3TransformCoord(&up, &up, &rollMatrix);	D3DXMATRIX matView;	D3DXMatrixIdentity(&matView);	matView._31 = -matView._31;	matView._32 = -matView._32;	matView._33 = -matView._33;	matView._34 = -matView._34;	matView._11 = right.x; matView._12 = up.x; matView._13 = look.x;	matView._21 = right.y; matView._22 = up.y; matView._23 = look.y;	matView._31 = right.z; matView._32 = up.z; matView._33 = look.z; // ?	matView._41 = - D3DXVec3Dot(&CameraPosition, &right); 	matView._42 = - D3DXVec3Dot(&CameraPosition, &up);	matView._43 = - D3DXVec3Dot(&CameraPosition, &look);	D3DDevice->SetTransform(D3DTS_VIEW, &matView);	// Set up projection matrix	D3DXMATRIXA16 matProj;	FLOAT aspectRatio = 800.0f / 600.0f;	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, aspectRatio, 1.0f, 1000.0f);	D3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);}


Here's how the render looks now: http://www.majeks.com/misc/axis3.jpg

The arrows are supposed to be red/green/blue and the letters are supposed to be white :( I'm not using the D3DXMatrixLookAtRH function, should I be?
This is very odd, I tried loading a few different .smd files and its drawing the models correctly, but the texture is flipped upside down! I figured that out when I loaded this globe model, here's a pic (left: d3d, right: modeling program): http://www.majeks.com/misc/globe.jpg

I modified the loop so it reads the vertex data in 1-3-2 order like the article said, but I have no idea how I'm going to flip the uv data right-side up so it textures correctly lol. Here's my code:

MESHVERTEX vertex;vertex.Position = D3DXVECTOR3(StringToFloat(s[1]), StringToFloat(s[3]), StringToFloat(s[2]));vertex.Normal = D3DXVECTOR3(StringToFloat(s[4]), StringToFloat(s[6]), StringToFloat(s[5]));vertex.UV = D3DXVECTOR2(StringToFloat(s[7]), StringToFloat(s[8]));				vertices.push_back(vertex);indices.push_back(index);index++;


please help :(
To display texture coords correctly when converting an SMD to an x-file for display in a left-handed system, I read in the texcoords tu and tv from the SMD and output them as tu, 1.0f-tv.

You might try something like that.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement