#include "dxstdafx.h" #include "Mesh.h" extern IDirect3DDevice9* g_pd3dDevice; // source: DirectX SDK Samples / OptimizedMesh Mesh::Mesh(float preferredDiameter) { originalDiameter = 1; this->preferredDiameter = preferredDiameter; originalSize = D3DXVECTOR3(1,1,1); position = D3DXVECTOR3(0,0,0); containerSize = D3DXVECTOR3(1,1,1); numMaterials = 0; pMesh = NULL; //if (g_pd3dDevice == NULL) exit(-1); } Mesh::Mesh(LPCWSTR fileName, float preferredDiameter, D3DXVECTOR3 offset) { originalDiameter = 1; this->preferredDiameter = preferredDiameter; originalSize = D3DXVECTOR3(1,1,1); position = D3DXVECTOR3(0,0,0); containerSize = D3DXVECTOR3(1,1,1); numMaterials = 0; pMesh = NULL; Load(fileName); Move(offset); } void Mesh::Move(D3DXVECTOR3 movement) { position += movement; // keep some distance from the walls D3DXVECTOR3 maxOffset = containerSize*0.99f - GetMeshSize(); D3DXVECTOR3 minOffset = -maxOffset; /* if (position.x > maxOffset.x) position.x = maxOffset.x; if (position.y > maxOffset.y) position.y = maxOffset.y; if (position.z > maxOffset.z) position.z = maxOffset.z; if (position.x < minOffset.x) position.x = minOffset.x; if (position.y < minOffset.y) position.y = minOffset.y; if (position.z < minOffset.z) position.z = minOffset.z;*/ } Mesh::~Mesh() { SAFE_RELEASE( pMesh ); } HRESULT Mesh::CalculateMeshSize( ) { // default size originalSize = D3DXVECTOR3(1,1,1); originalDiameter = 1; IDirect3DVertexBuffer9* pMeshVB = NULL; D3DXVECTOR3 minPos, maxPos; BYTE* pVertices; // Lock the vertex buffer to generate a simple bounding box hr = pMesh->GetVertexBuffer( &pMeshVB ); if( SUCCEEDED( hr ) ) { hr = pMeshVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_NOSYSLOCK ); if( SUCCEEDED(hr) ) { V( D3DXComputeBoundingBox( ( D3DXVECTOR3*)pVertices, pMesh->GetNumVertices(), D3DXGetFVFVertexSize( pMesh->GetFVF() ), &minPos, &maxPos ) ); D3DXVECTOR3 vCenter = ( minPos + maxPos ) / 2.0f; // eliminating offset from the mesh DWORD numVerts = pMesh->GetNumVertices(); // get the face count DWORD vertSize = D3DXGetFVFVertexSize(pMesh->GetFVF()); // calculate vertex size for (DWORD i = 0; i < numVerts; i++) // loop through the vertices { D3DXVECTOR3 *vPtr=(D3DXVECTOR3*)pVertices; *vPtr -= vCenter; // eliminating offset pVertices += vertSize; // set pointer to next vertex } pMeshVB->Unlock(); pMeshVB->Release(); // size of the object originalSize = ( maxPos - minPos ) / 2.0f; // object "diameter" is calculated from the size of the bounding box only originalDiameter = sqrt( originalSize.x * originalSize.x + originalSize.y * originalSize.y + originalSize.z * originalSize.z) / 1.732f; } } return hr; } void Mesh::Load( LPCWSTR fileName ) { SAFE_RELEASE( pMesh ); pMesh = NULL; // HRESULT hr; if (FAILED( D3DXLoadMeshFromX(fileName, D3DXMESH_MANAGED, g_pd3dDevice, NULL, NULL, NULL, &numMaterials, &pMesh) )) { MessageBox(NULL, L"Media not found!", fileName, MB_ICONEXCLAMATION); exit(-1); } /* if ( FAILED( CalculateMeshSize() )) { MessageBox(NULL, L"Could not calculate bounding box!\nUsing original mesh size...", fileName, MB_ICONEXCLAMATION); } DWORD *rgdwAdjacency = NULL; // Make sure there are normals which are required for lighting if( !(pMesh->GetFVF() & D3DFVF_NORMAL) ) { ID3DXMesh* pTempMesh; V( pMesh->CloneMeshFVF( pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL, g_pd3dDevice, &pTempMesh ) ); V( D3DXComputeNormals( pTempMesh, NULL ) ); SAFE_RELEASE( pMesh ); pMesh = pTempMesh; } // Optimize the mesh for this graphics card's vertex cache rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]; if( rgdwAdjacency == NULL ) return ; V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) ); V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) ); delete[] rgdwAdjacency; */ } void Mesh::computeTangent() { //V(D3DXComputeTangentFrame(pMesh,D3DXTANGENT_DONT_NORMALIZE_PARTIALS)); D3DXComputeTangentFrameEx(pMesh, D3DDECLUSAGE_TEXCOORD, 0, D3DDECLUSAGE_TANGENT, 0, D3DDECLUSAGE_BINORMAL, 0, D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_DONT_NORMALIZE_PARTIALS | D3DXTANGENT_GENERATE_IN_PLACE, NULL, 0.01f, 0.25f, 0.01f, NULL, NULL); } HRESULT Mesh::Draw() { HRESULT hr; // Set and draw each of the materials in the mesh for( DWORD iMaterial = 0; iMaterial < numMaterials; iMaterial++ ) { V( pMesh->DrawSubset( iMaterial ) ); } return S_OK; }