Sign in to follow this  
majek

Model/texture flipped backwards?

Recommended Posts

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! [img]http://www.majeks.com/misc/axis1.jpg[/img] [img]http://www.majeks.com/misc/axis2.jpg[/img]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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 matrix
D3DXMATRIXA16 matProj;
FLOAT aspectRatio = 800.0f / 600.0f;
D3DXMatrixPerspectiveRH(&matProj, D3DX_PI / 4, aspectRatio, 1.0f, 1000.0f);
D3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);


Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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 :(

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
wow that worked perfectly! thanks so much for your help :) now I can finally work on the rest of the program lol

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this