Sign in to follow this  
Hover

[D3DX] .x vertex buffer returning #QNAN00 values

Recommended Posts

I'm having a rather complicated problem involving grabbing vertices from a mesh's vertex buffer. First I load a mesh from .x file like so:
LPD3DXBUFFER bufMaterial;
D3DXLoadMeshFromX(L"bigcliff.x",
		D3DXMESH_SYSTEMMEM,
		d3dDevice,
		NULL,
		&bufMaterial,
		NULL,
		&numMaterials,
		&meshes[0]);

D3DXMATERIAL* tempMaterials = (D3DXMATERIAL*)bufMaterial->GetBufferPointer();
material = new D3DMATERIAL9[numMaterials];
texture = new LPDIRECT3DTEXTURE9[numMaterials];
	
for (DWORD i = 0; i< numMaterials; i++)
{
	material[i] = tempMaterials[i].MatD3D;
	material[i].Ambient = material[i].Diffuse;
	if(FAILED(D3DXCreateTextureFromFileA(d3dDevice,	
					tempMaterials[i].pTextureFilename,
					&texture[i])))
					texture[i] = NULL;
}

Then it's passed into a class in a different .cpp file. In there I do a ray/mesh intersection with D3DXIntersect and store the face index into fIndex. Then I get the indices of the vertices of the polygon intersected as follows:
WORD iv1, iv2, iv3;
WORD* indexBuffer;

MeshList->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&indexBuffer);
iv1 = indexBuffer[fIndex*3 + 0];
iv2 = indexBuffer[fIndex*3 + 1];
iv3 = indexBuffer[fIndex*3 + 2];

From there I grab the vertices from those indices from the vertex buffer as follows:
CUSTOMVERTEX v1, v2, v3;
CUSTOMVERTEX* pVertex;

MeshList->LockVertexBuffer(D3DLOCK_READONLY, (PVOID*)&pVertex);
v1 = pVertex[iv1];
v2 = pVertex[iv2];
v3 = pVertex[iv3];

With the following custom vertex definitions loaded from another .h file:
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL)
struct CUSTOMVERTEX {FLOAT X, Y, Z; D3DVECTOR NORMAL;};

However, at this point when I do an intersection with the mesh, I'm getting values like v2={X=-1.#QNAN00 Y=-7.8011589 Z=4.1131282 NORMAL=etc...}. This is especially confusing because when I do a search for the valid values I get, they're in the MeshTextureCoords section of the .x file, which would explain only getting 2 coordinate values. Also, as far as I can tell, the NORMAL values aren't anywhere in the .x file, so I'm not even sure how it's determining those. Why am I getting QNAN values from the mesh's vertex buffer? Where is it finding these crazy normals from? Note: I omitted some code trying to only post the relevant stuff, so be assured that I do unlock my buffers shortly after using them and before I mess around with any other buffers.

Share this post


Link to post
Share on other sites
The problem is that when you call D3DXLoadMeshFromX() you can't just assume that the vertex format is position + normal (as you do when you lock the returned vertex buffer and cast the pointer to your custom vertex format). In fact the D3DXLoadMeshFromX() function is smart enough to create a vertex format that exactly describes what you've got in the X file, so if you have MeshTextureCoords(u,v) data in the X file that you loaded, then the vertex format of the mesh will include UV. Look through the API on how to use pMesh->GetFVF() to learn what kind of vertex format the D3DXLoadMeshFromX() created for you. Whatever it is you must either convert it to the custom vertex format or match your custom vertex format to it.

Share this post


Link to post
Share on other sites
Quote:
Original post by Steve_Segreto
Look through the API on how to use pMesh->GetFVF() to learn what kind of vertex format the D3DXLoadMeshFromX() created for you. Whatever it is you must either convert it to the custom vertex format or match your custom vertex format to it.


That makes a lot of sense. I would appreciate some elaboration on conforming my FVF to that of the mesh though. I can get the FVF with GetFVF() so I know what structure the custom vertices should follow, but how would I create a struct to store that information in when I get it dynamically? I guess I could just declare it as a BYTE* and use GetNumBytesPerVertex() to set it the right size, but then it would just be a big chunk of data with no way of knowing where the XYZ information I need is.

Share this post


Link to post
Share on other sites
Perhaps mesh->GetDeclaration(...) would serve you better.

The array that's filled has information about each element of the vertex, including offsets to the position, normal, texcoords, etc.

So, no, you can't hardcode access to each vertex (unless it's the position, which is offset 0), but you can setup offsets to grab the info you want.

BYTE *vertex;
WORD texoffset; // find this in the declaration array
D3DXVECTOR2 tu = *(D3DXVECTOR2*)(vertex+vertNum*numBytesPerVertex+texoffset);

Share this post


Link to post
Share on other sites
I ended up going the other way and making the mesh conform to my standards. I might end up doing vice versa as I had planned in the future, but this works for now. I was getting deep into messing around in BYTEs and pointers and while it probably would have all worked in the end, I didn't need it for what I was doing and the alternative was much cleaner.

For anyone curious who stumbles on this thread, I did it by using D3DXLoadMeshFromX to load into tempMesh and then adding this after it loaded:


//Change vertex format
D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
D3DXDeclaratorFromFVF(CUSTOMFVF, decl);
tempMesh->CloneMesh(D3DXMESH_SYSTEMMEM, decl, d3dDevice, &meshes[0]);



All the collisions with the mesh finally work properly because I'm actually grabbing the right data. Thank you Steve and Buckeye for setting me in the right direction, I appreciate it!

Share this post


Link to post
Share on other sites
Sorry for digging up an old thread, but I now have a similar problem that has been bugging me all week, I have tried the bit in the last post and it works fine for getting out the information I need but the textures dont load which I assume is because the clone process removes the coordinates.
Is there a way around this or should I try and work out the declaration bit. It is rather confusing for me at the moment.

Thanks in advance
Chris

Share this post


Link to post
Share on other sites
Quote:
Sorry for digging up an old thread, but I now have a similar problem..

"Digging up" old threads may not be a good idea unless you have comments on the original topic. It's not clear from the description of your problem that you're getting invalid numbers somewhere (the original topic). Are you?

If not, or you're not sure, all the more reason to start a new thread. If you do, you should describe a little more thoroughly your particular problem. For instance, it isn't really clear what you mean by "textures don't load" or trying "bits." Posting code snippets where you get errors usually helps those who want to help you.[SMILE]

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