Archived

This topic is now archived and is closed to further replies.

SGreth

D3DXLoadMeshFromX and Vertex/Index buffers

Recommended Posts

Hello everyone. I''m using D3DXLoadMeshFromX to load up a static mesh file (no hierarchy...i.e. animation). I need to dump the mesh information to the collision system I''m using (Opcode). After loading the mesh I lock the vertex/index buffers and start trolling through them. So far so good. The model contains 4 or 5 meshes inside of it (it''m actually using the biplane example ''airplane 2.x'' from the DX 9.0 SDK). After I get by the first mesh (the body of the airplane) the rest of the mesh''s data isn''t correct. I tested out my ''walk'' through the vertex/index buffer by rendering the buffers using DrawPrimitiveUP just for testing. Since the documentation doesn''t say anything about it, I''m wondering if anybody else has tried using the model data from a mesh loaded with D3DXLoadMeshFromX. Any help would be *greatly* appreciated as I''m super-stuck on this one. Thanks, ~Rob

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
i use D3DXLoadMeshFromX to load entire .x models into one ID3DXMesh without problems, whether there is only one mesh in the .x or multiple meshs. some of the models i use have cloase to a 100 meshs in them. as it says in the help, "All the meshes in the file will be collapsed into one output mesh. If the file contains a frame hierarchy, all the transformations will be applied to the mesh." i''ve found this to be the case and have never run into a problem with it not applying the necessary transformations (yet ).

it sounds as if you''re loading the meshs individually, as you mention buffer<b>S</b> not buffer. care to show us your model loading code?

Share this post


Link to post
Share on other sites
Oh, I''m loading them all into one buffer, sorry for any confusion...here is what I have for loading code. Also, I''m tossing in my code that feeds data to the collision detection system. Opcode actually has the application register a callback which it calls for each face in the mesh.


//Load the DirectX File.
if(FAILED(D3DXLoadMeshFromX(szFileName, D3DXMESH_MANAGED | D3DXMESH_32BIT,
GetHyperspace()->GetHardware()->GetRenderingDevice(),
&pAdjacencyBuffer, &pD3DXMtrlBuffer, NULL, &dwNumMaterials, &pMesh)))
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: D3DXLoadMeshFromX() failed for %s", szFileName);
value = H_ERR_INVALID_ATTRIBUTE_NAME;
}
else
{
dw32BitFlag = (pMesh->GetOptions() & D3DXMESH_32BIT);
// perform simple cleansing operations on mesh
if( FAILED( D3DXCleanMesh( pMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), &pTempMesh,
(DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL ) ) )
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: D3DXCleanMesh() failed for %s", szFileName);
value = H_ERR_INVALID_ATTRIBUTE_NAME;
}
else
{
pMesh->Release();
pMesh = pTempMesh;

// Perform a weld to try and remove excess vertices like the model bigship1.x in the DX9.0 SDK (current model is fixed)
// Weld the mesh using all epsilons of 0.0f. A small epsilon like 1e-6 works well too
memset(&Epsilons, 0, sizeof(D3DXWELDEPSILONS));
if( FAILED( D3DXWeldVertices( pMesh, 0, &Epsilons,
(DWORD*)pAdjacencyBuffer->GetBufferPointer(),
(DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL ) ) )
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: D3DXWeldVertices() failed for %s", szFileName);
value = H_ERR_INVALID_ATTRIBUTE_NAME;
}
else
{
// verify validity of mesh for simplification
if( FAILED( D3DXValidMesh( pMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL ) ) )
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: D3DXValidMesh() failed for %s", szFileName);
value = H_ERR_INVALID_ATTRIBUTE_NAME;
}
else
{
//Get a pointer to the materials for this mesh.
d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();

//Allocate an array of material pointers.
m_ppMaterials = new CHyperMaterial*[dwNumMaterials];
m_dwMaterialCount = dwNumMaterials;

//Create the HyperMaterials and fill them in with the appropriate data.
for( int i=0; i {
//Create a HyperMaterial.
GetHyperspace()->CreateMaterial(&m_ppMaterials);

//Set the material texture.
if(d3dxMaterials[i].pTextureFilename)
m_ppMaterials[i]->SetTexture(d3dxMaterials[i].pTextureFilename);

//Set the material colors.
m_ppMaterials[i]->SetAmbient(CHyperColor4(d3dxMaterials[i].MatD3D.Ambient.r,
d3dxMaterials[i].MatD3D.Ambient.g,
d3dxMaterials[i].MatD3D.Ambient.b,
d3dxMaterials[i].MatD3D.Ambient.a));
m_ppMaterials[i]->SetDiffuse(CHyperColor4(d3dxMaterials[i].MatD3D.Diffuse.r,
d3dxMaterials[i].MatD3D.Diffuse.g,
d3dxMaterials[i].MatD3D.Diffuse.b,
d3dxMaterials[i].MatD3D.Diffuse.a));
m_ppMaterials[i]->SetEmissive(CHyperColor4(d3dxMaterials[i].MatD3D.Emissive.r,
d3dxMaterials[i].MatD3D.Emissive.g,
d3dxMaterials[i].MatD3D.Emissive.b,
d3dxMaterials[i].MatD3D.Emissive.a));
m_ppMaterials[i]->SetSpecular(CHyperColor4(d3dxMaterials[i].MatD3D.Specular.r,
d3dxMaterials[i].MatD3D.Specular.g,
d3dxMaterials[i].MatD3D.Specular.b,
d3dxMaterials[i].MatD3D.Specular.a));
m_ppMaterials[i]->SetSpecularPower(d3dxMaterials[i].MatD3D.Power);
}
//Release the interfaces we don''t need anymore.
pD3DXMtrlBuffer->Release();
pD3DXMtrlBuffer = NULL;

// Lock the vertex buffer, to generate a simple bounding sphere
if(FAILED(pMesh->GetVertexBuffer( &pVertexBuffer )))
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: GetVertexBuffer() failed for %s", szFileName);
value = H_ERR_D3DINVALID_DATA;
}
else
{
if(FAILED(pVertexBuffer->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK )))
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: Lock() failed for %s", szFileName);
value = H_ERR_D3D_VBUFFER_LOCK;
}
else
{
//Compute the bounding sphere for the model.
if(FAILED(D3DXComputeBoundingSphere( (D3DXVECTOR3*)pVertices, pMesh->GetNumVertices(),
D3DXGetFVFVertexSize(pMesh->GetFVF()),
&vObjectCenter, &fObjectRadius )))
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: D3DXComputeBoundingSphere() failed for %s", szFileName);
}
else
{
//Let go of the vertex buffer.
pVertexBuffer->Unlock();
pVertexBuffer->Release();
m_StaticMesh = pMesh;

if ( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
{
if(FAILED(pMesh->CloneMeshFVF( dw32BitFlag|D3DXMESH_MANAGED, pMesh->GetFVF() | D3DFVF_NORMAL,
GetHyperspace()->GetHardware()->GetRenderingDevice(),
&pTempMesh )))
{
GetHyperspace()->GetLogger()->Log(H_LOG_LEVEL_ERROR, LOG_MODEL, MODEL_IMPORT_X_FILE,
"XFILE: CloneMeshFVF() failed for %s", szFileName);
}
else
{
D3DXComputeNormals( pTempMesh, NULL );

pMesh->Release();
m_StaticMesh = pTempMesh;
}
}

//Save off the FVF and the vertex size.
m_dwFVF = m_StaticMesh->GetFVF();
m_iVertexSize = D3DXGetFVFVertexSize(m_dwFVF);

//Create the static progressive mesh here.
m_pStaticProgressiveMesh = CreateProgressiveMesh(m_StaticMesh, (DWORD *)pAdjacencyBuffer->GetBufferPointer(),
&m_dwStaticProgressiveMeshCount);

//Fill in a creation structure for creating a collision model.
Opcode::OPCODECREATE OpCodeCreate;
OpCodeCreate.mCanRemap = false;
OpCodeCreate.mQuantized = true;
OpCodeCreate.mKeepOriginal = true; //We keep the original to compute the entire mesh''s AABB.
OpCodeCreate.mNoLeaf = true;

//Setup the mesh information.
OpCodeCreate.mIMesh = new Opcode::MeshInterface();
OpCodeCreate.mIMesh->SetNbTriangles(m_StaticMesh->GetNumFaces());
OpCodeCreate.mIMesh->SetNbVertices(m_StaticMesh->GetNumVertices());
OpCodeCreate.mIMesh->SetCallback(OPCODE_Request, this);

m_StaticMesh->LockVertexBuffer(D3DLOCK_READONLY, (void **)&m_pVertexBuffer);
m_StaticMesh->LockIndexBuffer(D3DLOCK_READONLY, (void **)&m_pIndexBuffer);

//Build the OPCODE model.
m_CollisionModel.Build(OpCodeCreate);

//Unlock the DirectX buffers.
m_StaticMesh->UnlockVertexBuffer();
m_StaticMesh->UnlockIndexBuffer();
}
}
}
}
}
}


void CModel::OPCODE_Request(unsigned int triangle_index,
Opcode::VertexPointers& triangle, void* pUserData)
{//@CODE_25628
CModel *pThis = (CModel *)pUserData;
USHORT nStride = pThis->m_iVertexSize;
DWORD nIndex;

//Fill in the vertex pointer.
nIndex = (DWORD)pThis->m_pIndexBuffer[triangle_index * 12];
triangle.Vertex[0] = (const IceMaths:oint *)((float *)(pThis->m_pVertexBuffer + (nIndex * nStride)));

nIndex = (DWORD)pThis->m_pIndexBuffer[(triangle_index * 12) + sizeof(DWORD)];
triangle.Vertex[1] = (const IceMaths:oint *)((float *)(pThis->m_pVertexBuffer + (nIndex * nStride)));

nIndex = (DWORD)pThis->m_pIndexBuffer[(triangle_index * 12) + (sizeof(DWORD)*2)];
triangle.Vertex[2] = (const IceMaths:oint *)((float *)(pThis->m_pVertexBuffer + (nIndex * nStride)));
}//@CODE_25628

Share this post


Link to post
Share on other sites
Got it....
Inside of the method where I ''register'' my geometry with the collision detection library, I had some pointer issues with the index buffer. The index buffer is a BYTE *, so accessing it as a DWORD proved to be a bit of a problem. After cooking up a DWORD * and accessing that array, instead of the BYTE *, the problems seems to be fixed.

Thanks for anyone who wasted some time scouring my code...
~Rob

...
nIndex = (DWORD)pThis->m_pIndexBuffer[triangle_index * 12];

triangle.Vertex[0] = (const IceMaths:oint *)((float *)(pThis->m_pVertexBuffer + (nIndex * nStride)));

nIndex = (DWORD)pThis->m_pIndexBuffer[(triangle_index * 12) + sizeof(DWORD)];

triangle.Vertex[1] = (const IceMaths:oint *)((float *)(pThis->m_pVertexBuffer + (nIndex * nStride)));

nIndex = (DWORD)pThis->m_pIndexBuffer[(triangle_index * 12) + (sizeof(DWORD)*2)];

triangle.Vertex[2] = (const IceMaths:oint *)((float *)(pThis->m_pVertexBuffer + (nIndex * nStride)));
...

Share this post


Link to post
Share on other sites