Graphics::Graphics() { mBufferFactory = new BufferFactory(); initBuffers(); initEffect(); initFonts(); mWhiteTexture = loadTexture("data/imgs/white.bmp"); // TESTING.. D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; UINT numElems = 0; VertexPNT::Decl->GetDeclaration(elems, &numElems); D3DXCreateMesh(2, 4, D3DXMESH_MANAGED, elems, gd3dDevice, &mRayMesh); onResetDevice(); }
void ObjParser::Load(LPCSTR Filename, LPDIRECT3DDEVICE9 pDevice) { FILE* fileHandle = fopen(Filename, "r+"); if( fileHandle == NULL ) return; char line[256]; D3DXVECTOR3 vec; while( !feof(fileHandle) )//Foreach Line { fgets(line, 256, fileHandle); #pragma region Line Read switch(line[0]) { case 'm': { LPCSTR name = new CHAR[256]; sscanf_s(line, "mtllib %s", name, 255); ParseMaterial(name); } break; case 'v'://Vertex Item { switch(line[1]) { case ' '://Vertex { sscanf_s(line, "v %f %f %f", &vec.x, &vec.y, &vec.z ); Vertexs.push_back(vec); mVertexsHT.push_back(NULL);//expand HashTable } break; case 't'://Texture Coordinates { D3DXVECTOR3 tex; sscanf_s(line, "vt %f %f %f", &vec.x, &vec.y, &vec.z); Textures.push_back(vec); } break; case 'n'://Normal { D3DXVECTOR3 nor; sscanf_s(line, "vn %f %f %f", &vec.x, &vec.y, &vec.z ); Normals.push_back(vec); } break; default:// Not supposed to happen assert( false ); } } break; case 'f'://Face Item { DWORD quadP[4];//Position Index quad DWORD quadT[4];//Texture Index quad DWORD quadN[4];//Normal Index quad memset(quadP, -1, sizeof(DWORD)*4); memset(quadT, -1, sizeof(DWORD)*4); memset(quadN, -1, sizeof(DWORD)*4); int size = strlen(line); int barCount = std::count(line, line+size, '/'); int readed = 0; //By default .obj file puts faces with CW winding switch( barCount ) { case 0:// tri/quad pos { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d %d %d %d", &quadP[3], &quadP[2], &quadP[1], &quadP[0] ); else readed = sscanf_s(line, "f %d %d %d %d", &quadP[0], &quadP[1], &quadP[2], &quadP[3] ); assert( readed == 3 || readed == 4 ); } break; case 3:// tri pos/tex { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d %d/%d %d/%d", &quadP[2], &quadT[2], &quadP[1], &quadT[1], &quadP[0], &quadT[0] ); else readed = sscanf_s(line, "f %d/%d %d/%d %d/%d", &quadP[0], quadT[0], &quadP[1], quadT[1], &quadP[2], quadT[2] ); assert( readed == 6 ); readed /= 2; } break; case 4:// quad pos/tex { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d %d/%d %d/%d %d/%d", &quadP[3], &quadT[3], &quadP[2], &quadT[2], &quadP[1], &quadT[1], &quadP[0], &quadT[0] ); else readed = sscanf_s(line, "f %d/%d %d/%d %d/%d %d/%d", &quadP[0], &quadT[0], &quadP[1], &quadT[1], &quadP[2], &quadT[2], &quadP[3], &quadT[3] ); assert( readed == 8 ); readed /= 2; } break; case 6:// tri pos/tex/nor { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[2], &quadT[2], &quadN[2], &quadP[1], &quadT[1], &quadN[1], &quadP[0], &quadT[0], &quadN[0] ); else readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[0], &quadT[0], &quadN[0], &quadP[1], &quadT[1], &quadN[1], &quadP[2], &quadT[2], &quadN[2] ); assert( readed == 9 ); readed /= 3; } break; case 8:// quad pos/tex/nor { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[3], &quadT[3], &quadN[3], &quadP[2], &quadT[2], &quadN[2], &quadP[1], &quadT[1], &quadN[1], &quadP[0], &quadT[0], &quadN[0] ); else readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[0], &quadT[0], &quadN[0], &quadP[1], &quadT[1], &quadN[1], &quadP[2], &quadT[2], &quadN[2], &quadP[3], &quadT[3], &quadN[3] ); assert( readed == 12 ); readed /= 3; } break; default:// Not supposed to happen assert( false ); } //The indexs are in 1 Base, we transform to 0 Base for( int i=0; i < 4 ; ++i ) { quadP[i]--; quadT[i]--; quadN[i]--; } for(int j=0; j < 3 ; ++j) { VertexTextureNormal NewVertex; NewVertex.SetPosition( Vertexs[quadP[j]] ); if( quadT[j] != (DWORD(-1)-1) ) NewVertex.SetTexture ( Textures[quadT[j]].x, Textures[quadT[j]].y ); if( quadN[j] != (DWORD(-1)-1) ) NewVertex.SetNormal ( Normals[quadN[j]] ); DWORD index = AddVertex(quadP[j], NewVertex); mIndexs.push_back(index); } if( readed == 4 )// quad readed { quadP[1] = quadP[2]; quadT[1] = quadT[2]; quadN[1] = quadN[2]; quadP[2] = quadP[3]; quadT[2] = quadT[3]; quadN[1] = quadN[2]; for(int j=0; j < 3 ; ++j) { VertexTextureNormal NewVertex; NewVertex.SetPosition( Vertexs[quadP[j]] ); if( quadT[j] != (DWORD(-1)-1) ) NewVertex.SetTexture ( Textures[quadT[j]].x, Textures[quadT[j]].y ); if( quadN[j] != (DWORD(-1)-1) ) NewVertex.SetNormal ( Normals[quadN[j]] ); DWORD index = AddVertex(quadP[j], NewVertex); mIndexs.push_back(index); } } } break; } #pragma endregion } fclose(fileHandle); DWORD FVF = NULL; D3DVERTEXELEMENT9* pMeshVDeclaration = NULL; int code = 0; IdentifieLoadedFormat(FVF, pMeshVDeclaration, code); if( code == 0 ) return; //Setup Mesh with VertexDeclaration corresponding to the loaded data LPD3DXMESH pMesh = NULL; HRESULT hr = NULL; int FacesCount = mIndexs.size()/3; switch( m_VertexMetaFormat ) { case VertexMetaFormat::VertexDeclaration: { if( FacesCount > 65535 )// if huge mesh, 32 bits face index hr = D3DXCreateMesh(FacesCount, mVertexs.size(), D3DXMESH_32BIT | D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , pMeshVDeclaration, pDevice, &pMesh); else hr = D3DXCreateMesh(FacesCount, mVertexs.size(), D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , pMeshVDeclaration, pDevice, &pMesh); } break; case VertexMetaFormat::FVF: { if( FacesCount > 65535 )// if huge mesh, 32 bits face index hr = D3DXCreateMeshFVF(FacesCount, Vertexs.size(), D3DXMESH_32BIT | D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , FVF, pDevice, &pMesh); else hr = D3DXCreateMeshFVF(FacesCount, Vertexs.size(), D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , FVF, pDevice, &pMesh); } break; default: assert( false ); } assert( !FAILED(hr) ); //Puts vertex data inside loadedData in the smallest format needed //(not nesesarily VertexTextureNormal) void* loadedData = NULL; void* loadedIndex = NULL; size_t size = 0; //Pass to our vertex format PutLoadedDataInVertexDeclarationFormat(loadedData,loadedIndex,size,code, FacesCount); //Free Auxiliary Arrays Vertexs.clear(); Textures.clear(); Normals.clear(); mVertexsHT.clear(); void* data = NULL; //Loads the Vertex Buffer if( FAILED(pMesh->LockVertexBuffer(NULL, &data)) ) return; memcpy(data, loadedData, size*mVertexs.size()); pMesh->UnlockVertexBuffer(); //Loads the Index Buffer if( FAILED(pMesh->LockIndexBuffer(NULL, &data)) ) return; if( FacesCount > 65535 ) memcpy(data, loadedIndex, sizeof(DWORD)*mIndexs.size()); else memcpy(data, loadedIndex, sizeof(WORD)*mIndexs.size()); pMesh->UnlockIndexBuffer(); //Free main Arrays mVertexs.clear(); mIndexs.clear(); //Mesh data ready m_RootMeshContainer = new D3DXMESHCONTAINER; m_RootMeshContainer->MeshData.pMesh = pMesh; return; }
HRESULT XFileCreator::CreateMesh(std::vector<Vertex> vertices, std::vector<Face> faces) { HRESULT hr; DWORD numFaces = faces.size(); DWORD numVertices = vertices.size(); PD(L"number of vertices: ", numVertices); PD(L"number of faces: ", numFaces); D3DVERTEXELEMENT9 localVertDecl[MAX_FVF_DECL_SIZE] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END() }; hr = D3DXCreateMesh(numFaces, numVertices, D3DXMESH_MANAGED | D3DXMESH_32BIT, localVertDecl, mDevice, &mMesh); PD(hr, L"create mesh"); if(FAILED(hr)) return hr; LOCAL_VERTEX *pVertices = NULL; hr = mMesh->LockVertexBuffer(0, (void**)&pVertices); PD(hr, L"lock vertex buffer"); if(FAILED(hr)) return hr; for ( DWORD i = 0; i < numVertices; ++i ) { pVertices[i].pos = D3DXVECTOR3(vertices[i].pos.x, vertices[i].pos.y, vertices[i].pos.z); } hr = mMesh->UnlockVertexBuffer(); PD(hr, L"unlock vertex buffer"); if(FAILED(hr)) return hr; DWORD* pIndices = NULL; hr = mMesh->LockIndexBuffer(0, (void**)&pIndices); PD(hr, L"lock index buffer"); if(FAILED(hr)) return hr; for ( DWORD i = 0; i < numFaces; i++ ) { pIndices[3 * i] = faces[i].vertices[0]; pIndices[3 * i + 1] = faces[i].vertices[1]; pIndices[3 * i + 2] = faces[i].vertices[2]; } hr = mMesh->UnlockIndexBuffer(); PD(hr, L"unlock index buffer"); if(FAILED(hr)) return hr; DWORD* pAdjacency = new DWORD[numFaces * 3]; hr = mMesh->GenerateAdjacency(1e-6f, pAdjacency); PD(hr, L"generate adjacency"); if(FAILED(hr)) return hr; hr = D3DXComputeNormals(mMesh, pAdjacency); PD(hr, L"compute normals"); if(FAILED(hr)) return hr; delete [] pAdjacency; return D3D_OK; }
PondWater::PondWater(InitInfo& initInfo) { mInitInfo = initInfo; mWidth = (initInfo.vertCols-1)*initInfo.dx; mDepth = (initInfo.vertRows-1)*initInfo.dz; mWaveMapOffset0 = D3DXVECTOR2(0.0f, 0.0f); mWaveMapOffset1 = D3DXVECTOR2(0.0f, 0.0f); DWORD numTris = (initInfo.vertRows-1)*(initInfo.vertCols-1)*2; DWORD numVerts = initInfo.vertRows*initInfo.vertCols; //=============================================================== // Allocate the mesh. D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; UINT numElems = 0; HR(VertexPT::Decl->GetDeclaration(elems, &numElems)); HR(D3DXCreateMesh(numTris, numVerts, D3DXMESH_MANAGED, elems, gd3dDevice, &mMesh)); //=============================================================== // Write the grid vertices and triangles to the mesh. VertexPT* v = 0; HR(mMesh->LockVertexBuffer(0, (void**)&v)); std::vector<D3DXVECTOR3> verts; std::vector<DWORD> indices; GenTriGrid(mInitInfo.vertRows, mInitInfo.vertCols, mInitInfo.dx, mInitInfo.dz, D3DXVECTOR3(0.0f, 0.0f, 0.0f), verts, indices); for(int i = 0; i < mInitInfo.vertRows; ++i) { for(int j = 0; j < mInitInfo.vertCols; ++j) { DWORD index = i * mInitInfo.vertCols + j; v[index].pos = verts[index]; v[index].tex0 = D3DXVECTOR2((float)j/mInitInfo.vertCols, (float)i/mInitInfo.vertRows) * initInfo.texScale; } } HR(mMesh->UnlockVertexBuffer()); //=============================================================== // Write triangle data so we can compute normals. WORD* indexBuffPtr = 0; HR(mMesh->LockIndexBuffer(0, (void**)&indexBuffPtr)); DWORD* attBuff = 0; HR(mMesh->LockAttributeBuffer(0, &attBuff)); for(UINT i = 0; i < mMesh->GetNumFaces(); ++i) { indexBuffPtr[i*3+0] = (WORD)indices[i*3+0]; indexBuffPtr[i*3+1] = (WORD)indices[i*3+1]; indexBuffPtr[i*3+2] = (WORD)indices[i*3+2]; attBuff[i] = 0; // All in subset 0. } HR(mMesh->UnlockIndexBuffer()); HR(mMesh->UnlockAttributeBuffer()); //=============================================================== // Optimize for the vertex cache and build attribute table. DWORD* adj = new DWORD[mMesh->GetNumFaces()*3]; HR(mMesh->GenerateAdjacency(EPSILON, adj)); HR(mMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT, adj, 0, 0, 0)); delete[] adj; //=============================================================== // Create textures/effect. HR(D3DXCreateTextureFromFile(gd3dDevice, initInfo.waveMapFilename0.c_str(), &mWaveMap0)); HR(D3DXCreateTextureFromFile(gd3dDevice, initInfo.waveMapFilename1.c_str(), &mWaveMap1)); D3DVIEWPORT9 vp = {0, 0, 512, 512, 0.0f, 1.0f}; mRefractMap = new DrawableTex2D(512, 512, 0, D3DFMT_X8R8G8B8, true, D3DFMT_D24X8, vp, true); mReflectMap = new DrawableTex2D(512, 512, 0, D3DFMT_X8R8G8B8, true, D3DFMT_D24X8, vp, true); buildFX(); }
Geometry::Geometry(LPDIRECT3DDEVICE9 d3ddev, const std::string& filename, LPD3DXEFFECT shader) : m_shape(NONE), m_mesh(nullptr), m_shader(shader), m_texture(nullptr) { // Create a assimp mesh std::string errorBuffer; Assimpmesh mesh; if(!mesh.Initialise(filename, errorBuffer)) { ShowMessageBox(errorBuffer); } std::vector<unsigned long> indexData; std::vector<MeshVertex> vertexData; const std::vector<Assimpmesh::SubMesh>& subMeshes = mesh.GetMeshes(); for(unsigned int i = 0; i < subMeshes.size(); ++i) { // Fill in vertex data for(unsigned int j = 0; j < subMeshes[i].vertices.size(); ++j) { MeshVertex v; v.normal.x = subMeshes[i].vertices[j].nx; v.normal.y = subMeshes[i].vertices[j].ny; v.normal.z = subMeshes[i].vertices[j].nz; v.position.x = subMeshes[i].vertices[j].x; v.position.y = subMeshes[i].vertices[j].y; v.position.z = subMeshes[i].vertices[j].z; v.uvs.x = subMeshes[i].vertices[j].u; v.uvs.y = subMeshes[i].vertices[j].v; vertexData.push_back(v); } for(unsigned int j = 0; j < subMeshes[i].indices.size(); ++j) { indexData.push_back(subMeshes[i].indices[j]); } } // Mesh Vertex Declaration D3DVERTEXELEMENT9 VertexDecl[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; // Create the DirectX Mesh if(FAILED(D3DXCreateMesh(indexData.size()/3, vertexData.size(), D3DXMESH_MANAGED | D3DXMESH_32BIT, VertexDecl, d3ddev, &m_mesh))) { ShowMessageBox("Mesh " + filename + " creation failed"); } // Fill in the vertex buffer MeshVertex* vertexBuffer; if(FAILED(m_mesh->LockVertexBuffer(0, (void**)&vertexBuffer))) { ShowMessageBox(filename + " Vertex buffer lock failed"); } #pragma warning(disable: 4996) std::copy(vertexData.begin(), vertexData.end(), vertexBuffer); m_mesh->UnlockVertexBuffer(); // Fill in the index buffer DWORD* indexBuffer; if(FAILED(m_mesh->LockIndexBuffer(0, (void**)&indexBuffer))) { ShowMessageBox(filename + " Index buffer lock failed"); } #pragma warning(disable: 4996) std::copy(indexData.begin(), indexData.end(), indexBuffer); m_mesh->UnlockIndexBuffer(); CreateMeshData<MeshVertex, DWORD>(false); }
/** * Creates a D3DXMESH from a FStaticMeshRenderData * @param Triangles The triangles to create the mesh from. * @param bRemoveDegenerateTriangles True if degenerate triangles should be removed * @param OutD3DMesh Mesh to create * @return Boolean representing success or failure */ bool ConvertRawMeshToD3DXMesh( IDirect3DDevice9* Device, FRawMesh& RawMesh, const bool bRemoveDegenerateTriangles, TRefCountPtr<ID3DXMesh>& OutD3DMesh ) { TArray<D3DVERTEXELEMENT9> VertexElements; GetD3D9MeshVertexDeclarations(VertexElements); TArray<FUtilVertex> Vertices; TArray<uint16> Indices; TArray<uint32> Attributes; int32 NumWedges = RawMesh.WedgeIndices.Num(); int32 NumTriangles = NumWedges / 3; int32 NumUVs = 0; for (; NumUVs < 8; ++NumUVs) { if (RawMesh.WedgeTexCoords[NumUVs].Num() != RawMesh.WedgeIndices.Num()) { break; } } bool bHaveColors = RawMesh.WedgeColors.Num() == NumWedges; bool bHaveNormals = RawMesh.WedgeTangentZ.Num() == NumWedges; bool bHaveTangents = bHaveNormals && RawMesh.WedgeTangentX.Num() == NumWedges && RawMesh.WedgeTangentY.Num() == NumWedges; for(int32 TriangleIndex = 0;TriangleIndex < NumTriangles;TriangleIndex++) { bool bTriangleIsDegenerate = false; if( bRemoveDegenerateTriangles ) { // Detect if the triangle is degenerate. for(int32 EdgeIndex = 0;EdgeIndex < 3;EdgeIndex++) { const int32 Wedge0 = TriangleIndex * 3 + EdgeIndex; const int32 Wedge1 = TriangleIndex * 3 + ((EdgeIndex + 1) % 3); if((RawMesh.GetWedgePosition(Wedge0) - RawMesh.GetWedgePosition(Wedge1)).IsNearlyZero(THRESH_POINTS_ARE_SAME * 4.0f)) { bTriangleIsDegenerate = true; break; } } } if(!bTriangleIsDegenerate) { Attributes.Add(RawMesh.FaceMaterialIndices[TriangleIndex]); for(int32 J=0;J<3;J++) { FUtilVertex* Vertex = new(Vertices) FUtilVertex; FMemory::Memzero(Vertex,sizeof(FUtilVertex)); int32 WedgeIndex = TriangleIndex * 3 + J; Vertex->Position = RawMesh.GetWedgePosition(WedgeIndex); if (bHaveColors) { Vertex->Color = RawMesh.WedgeColors[WedgeIndex]; } else { Vertex->Color = FColor::White; } //store the smoothing mask per vertex since there is only one per-face attribute that is already being used (materialIndex) Vertex->SmoothingMask = RawMesh.FaceSmoothingMasks[TriangleIndex]; if (bHaveTangents) { Vertex->TangentX = RawMesh.WedgeTangentX[WedgeIndex]; Vertex->TangentY = RawMesh.WedgeTangentY[WedgeIndex]; } if (bHaveNormals) { Vertex->TangentZ = RawMesh.WedgeTangentZ[WedgeIndex]; } for(int32 UVIndex = 0; UVIndex < NumUVs; UVIndex++) { Vertex->UVs[UVIndex] = RawMesh.WedgeTexCoords[UVIndex][WedgeIndex]; } Indices.Add(Vertices.Num() - 1); } } } // This code uses the raw triangles. Needs welding, etc. const int32 NumFaces = Indices.Num() / 3; const int32 NumVertices = NumFaces*3; check(Attributes.Num() == NumFaces); check(NumFaces * 3 == Indices.Num()); // Create mesh for source data if (FAILED(D3DXCreateMesh(NumFaces,NumVertices,D3DXMESH_SYSTEMMEM,(D3DVERTEXELEMENT9 *)VertexElements.GetData(),Device,OutD3DMesh.GetInitReference()) ) ) { UE_LOG(LogD3D9MeshUtils, Warning, TEXT("D3DXCreateMesh() Failed!")); return false; } // Fill D3DMesh mesh FUtilVertex* D3DVertices; uint16* D3DIndices; ::DWORD * D3DAttributes; OutD3DMesh->LockVertexBuffer(0,(LPVOID*)&D3DVertices); OutD3DMesh->LockIndexBuffer(0,(LPVOID*)&D3DIndices); OutD3DMesh->LockAttributeBuffer(0, &D3DAttributes); FMemory::Memcpy(D3DVertices,Vertices.GetTypedData(),Vertices.Num() * sizeof(FUtilVertex)); FMemory::Memcpy(D3DIndices,Indices.GetTypedData(),Indices.Num() * sizeof(uint16)); FMemory::Memcpy(D3DAttributes,Attributes.GetTypedData(),Attributes.Num() * sizeof(uint32)); OutD3DMesh->UnlockIndexBuffer(); OutD3DMesh->UnlockVertexBuffer(); OutD3DMesh->UnlockAttributeBuffer(); return true; }
/** Merges a set of D3DXMeshes. */ static void MergeD3DXMeshes( IDirect3DDevice9* Device, TRefCountPtr<ID3DXMesh>& OutMesh,TArray<int32>& OutBaseFaceIndex,const TArray<ID3DXMesh*>& Meshes) { TArray<D3DVERTEXELEMENT9> VertexElements; GetD3D9MeshVertexDeclarations(VertexElements); // Count the number of faces and vertices in the input meshes. int32 NumFaces = 0; int32 NumVertices = 0; for(int32 MeshIndex = 0;MeshIndex < Meshes.Num();MeshIndex++) { NumFaces += Meshes[MeshIndex]->GetNumFaces(); NumVertices += Meshes[MeshIndex]->GetNumVertices(); } // Create mesh for source data VERIFYD3D9RESULT(D3DXCreateMesh( NumFaces, NumVertices, D3DXMESH_SYSTEMMEM, (D3DVERTEXELEMENT9*)VertexElements.GetData(), Device, OutMesh.GetInitReference() ) ); // Fill D3DXMesh FUtilVertex* ResultVertices; uint16* ResultIndices; ::DWORD * ResultAttributes; OutMesh->LockVertexBuffer(0,(LPVOID*)&ResultVertices); OutMesh->LockIndexBuffer(0,(LPVOID*)&ResultIndices); OutMesh->LockAttributeBuffer(0, &ResultAttributes); int32 BaseVertexIndex = 0; int32 BaseFaceIndex = 0; for(int32 MeshIndex = 0;MeshIndex < Meshes.Num();MeshIndex++) { ID3DXMesh* Mesh = Meshes[MeshIndex]; FUtilVertex* Vertices; uint16* Indices; ::DWORD * Attributes; Mesh->LockVertexBuffer(0,(LPVOID*)&Vertices); Mesh->LockIndexBuffer(0,(LPVOID*)&Indices); Mesh->LockAttributeBuffer(0, &Attributes); for(uint32 FaceIndex = 0;FaceIndex < Mesh->GetNumFaces();FaceIndex++) { for(uint32 VertexIndex = 0;VertexIndex < 3;VertexIndex++) { *ResultIndices++ = BaseVertexIndex + *Indices++; } } OutBaseFaceIndex.Add(BaseFaceIndex); BaseFaceIndex += Mesh->GetNumFaces(); FMemory::Memcpy(ResultVertices,Vertices,Mesh->GetNumVertices() * sizeof(FUtilVertex)); ResultVertices += Mesh->GetNumVertices(); BaseVertexIndex += Mesh->GetNumVertices(); FMemory::Memcpy(ResultAttributes,Attributes,Mesh->GetNumFaces() * sizeof(uint32)); ResultAttributes += Mesh->GetNumFaces(); Mesh->UnlockIndexBuffer(); Mesh->UnlockVertexBuffer(); Mesh->UnlockAttributeBuffer(); } OutMesh->UnlockIndexBuffer(); OutMesh->UnlockVertexBuffer(); OutMesh->UnlockAttributeBuffer(); }
void Terrain::buildSubGridMesh(RECT& R, VertexPNT* gridVerts) { //=============================================================== // Create the subgrid mesh. ID3DXMesh* subMesh = 0; D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; UINT numElems = 0; HR(VertexPNT::Decl->GetDeclaration(elems, &numElems)); HR(D3DXCreateMesh(SubGrid::NUM_TRIS, SubGrid::NUM_VERTS, D3DXMESH_MANAGED, elems, gd3dDevice, &subMesh)); //=============================================================== // Build Vertex Buffer. Copy rectangle of vertices from the // grid into the subgrid structure. VertexPNT* v = 0; HR(subMesh->LockVertexBuffer(0, (void**)&v)); int k = 0; for(int i = R.top; i <= R.bottom; ++i) { for(int j = R.left; j <= R.right; ++j) { v[k++] = gridVerts[i*mVertCols+j]; } } //=============================================================== // Compute the bounding box before unlocking the vertex buffer. AABB bndBox; HR(D3DXComputeBoundingBox((D3DXVECTOR3*)v, subMesh->GetNumVertices(), sizeof(VertexPNT), &bndBox.minPt, &bndBox.maxPt)); HR(subMesh->UnlockVertexBuffer()); //=============================================================== // Build Index and Attribute Buffer. // Get indices for subgrid (we don't use the verts here--the verts // are given by the parameter gridVerts). std::vector<D3DXVECTOR3> tempVerts; std::vector<DWORD> tempIndices; GenTriGrid(SubGrid::NUM_ROWS, SubGrid::NUM_COLS, mDX, mDZ, D3DXVECTOR3(0.0f, 0.0f, 0.0f), tempVerts, tempIndices); WORD* indices = 0; DWORD* attBuff = 0; HR(subMesh->LockIndexBuffer(0, (void**)&indices)); HR(subMesh->LockAttributeBuffer(0, &attBuff)); for(int i = 0; i < SubGrid::NUM_TRIS; ++i) { indices[i*3+0] = (WORD)tempIndices[i*3+0]; indices[i*3+1] = (WORD)tempIndices[i*3+1]; indices[i*3+2] = (WORD)tempIndices[i*3+2]; attBuff[i] = 0; // All in subset 0. } HR(subMesh->UnlockIndexBuffer()); HR(subMesh->UnlockAttributeBuffer()); //=============================================================== // Optimize for the vertex cache and build attribute table. DWORD* adj = new DWORD[subMesh->GetNumFaces()*3]; HR(subMesh->GenerateAdjacency(EPSILON, adj)); HR(subMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT, adj, 0, 0, 0)); delete[] adj; //=============================================================== // Save the mesh and bounding box. mSubGridMeshes.push_back(subMesh); mSubGridBndBoxes.push_back(bndBox); }
void Terrain::buildGeometry() { //=============================================================== // Create one large mesh for the grid in system memory. DWORD numTris = (mVertRows-1)*(mVertCols-1)*2; DWORD numVerts = mVertRows*mVertCols; ID3DXMesh* mesh = 0; D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; UINT numElems = 0; HR(VertexPNT::Decl->GetDeclaration(elems, &numElems)); HR(D3DXCreateMesh(numTris, numVerts, D3DXMESH_SYSTEMMEM|D3DXMESH_32BIT, elems, gd3dDevice, &mesh)); //=============================================================== // Write the grid vertices and triangles to the mesh. VertexPNT* v = 0; HR(mesh->LockVertexBuffer(0, (void**)&v)); std::vector<D3DXVECTOR3> verts; std::vector<DWORD> indices; GenTriGrid(mVertRows, mVertCols, mDX, mDZ, D3DXVECTOR3(0.0f, 0.0f, 0.0f), verts, indices); float w = mWidth; float d = mDepth; for(UINT i = 0; i < mesh->GetNumVertices(); ++i) { // We store the grid vertices in a linear array, but we can // convert the linear array index to an (r, c) matrix index. int r = i / mVertCols; int c = i % mVertCols; v[i].pos = verts[i]; v[i].pos.y = mHeightmap(r, c); v[i].tex0.x = (v[i].pos.x + (0.5f*w)) / w; v[i].tex0.y = (v[i].pos.z - (0.5f*d)) / -d; } // Write triangle data so we can compute normals. DWORD* indexBuffPtr = 0; HR(mesh->LockIndexBuffer(0, (void**)&indexBuffPtr)); for(UINT i = 0; i < mesh->GetNumFaces(); ++i) { indexBuffPtr[i*3+0] = indices[i*3+0]; indexBuffPtr[i*3+1] = indices[i*3+1]; indexBuffPtr[i*3+2] = indices[i*3+2]; } HR(mesh->UnlockIndexBuffer()); // Compute Vertex Normals. HR(D3DXComputeNormals(mesh, 0)); //=============================================================== // Now break the grid up into subgrid meshes. // Find out the number of subgrids we'll have. For example, if // m = 513, n = 257, SUBGRID_VERT_ROWS = SUBGRID_VERT_COLS = 33, // then subGridRows = 512/32 = 16 and sibGridCols = 256/32 = 8. int subGridRows = (mVertRows-1) / (SubGrid::NUM_ROWS-1); int subGridCols = (mVertCols-1) / (SubGrid::NUM_COLS-1); for(int r = 0; r < subGridRows; ++r) { for(int c = 0; c < subGridCols; ++c) { // Rectangle that indicates (via matrix indices ij) the // portion of global grid vertices to use for this subgrid. RECT R = { c * (SubGrid::NUM_COLS-1), r * (SubGrid::NUM_ROWS-1), (c+1) * (SubGrid::NUM_COLS-1), (r+1) * (SubGrid::NUM_ROWS-1) }; buildSubGridMesh(R, v); } } HR(mesh->UnlockVertexBuffer()); ReleaseCOM(mesh); // Done with global mesh. }
void optimizePhysXMesh(int flag, IDirect3DDevice9* D3DDevice, float epsilon, std::vector<physx::PxVec3>& pxVertices, oiram::IndexBuffer& indexBuffer) { assert(D3DDevice); D3DVERTEXELEMENT9 szDecl[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0xFF, 0, D3DDECLTYPE_UNUSED, 0, 0, 0} }; // 创建D3D MESH LPD3DXMESH pMesh = 0; DWORD options = D3DXMESH_SYSTEMMEM | D3DXMESH_DYNAMIC; if (indexBuffer.use32BitIndices) options |= D3DXMESH_32BIT; DWORD numVertices = static_cast<DWORD>(pxVertices.size()), numFaces = numVertices / 3; HRESULT hr = D3DXCreateMesh(numFaces, numVertices, options, szDecl, D3DDevice, &pMesh); if (SUCCEEDED(hr)) { LPVOID pData = nullptr; // 填充Index Buffer if (SUCCEEDED(pMesh->LockIndexBuffer(D3DLOCK_DISCARD, &pData))) { if (indexBuffer.use32BitIndices) memcpy(pData, indexBuffer.uiIndexBuffer.data(), indexBuffer.uiIndexBuffer.size() * sizeof(physx::PxU32)); else memcpy(pData, indexBuffer.usIndexBuffer.data(), indexBuffer.usIndexBuffer.size() * sizeof(physx::PxU16)); pMesh->UnlockIndexBuffer(); } // 填充Vertex Buffer if (SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_DISCARD, &pData))) { memcpy(pData, pxVertices.data(), pxVertices.size() * sizeof(physx::PxVec3)); pMesh->UnlockVertexBuffer(); } // 进行Mesh优化 DWORD dwFaces = pMesh->GetNumFaces(); std::vector<DWORD> szAdjacencies(dwFaces * 3); DWORD* pAdjacency = &szAdjacencies[0]; pMesh->GenerateAdjacency(epsilon, pAdjacency); // 清理mesh hr = D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION, pMesh, pAdjacency, &pMesh, pAdjacency, NULL); if (SUCCEEDED(hr)) { // 去除mesh中重复的顶点 hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDALL, NULL, pAdjacency, pAdjacency, NULL, NULL); if (SUCCEEDED(hr)) { // 将优化后的数据写回mesh data DWORD numIndices = pMesh->GetNumFaces() * 3; indexBuffer.use32BitIndices = numIndices > 65535; if (indexBuffer.use32BitIndices) indexBuffer.uiIndexBuffer.resize(numIndices); else indexBuffer.usIndexBuffer.resize(numIndices); // 取出Index Buffer if (SUCCEEDED(pMesh->LockIndexBuffer(D3DLOCK_READONLY | D3DLOCK_DISCARD, &pData))) { if (indexBuffer.use32BitIndices) memcpy(indexBuffer.uiIndexBuffer.data(), pData, indexBuffer.uiIndexBuffer.size() * sizeof(physx::PxU32)); else memcpy(indexBuffer.usIndexBuffer.data(), pData, indexBuffer.usIndexBuffer.size() * sizeof(physx::PxU16)); pMesh->UnlockIndexBuffer(); } // 取出Vertex Buffer DWORD dwVertices = pMesh->GetNumVertices(); pxVertices.resize(dwVertices); if (SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_READONLY | D3DLOCK_DISCARD, &pData))) { memcpy(pxVertices.data(), pData, pxVertices.size() * sizeof(physx::PxVec3)); pMesh->UnlockVertexBuffer(); } } } pMesh->Release(); } }
void Model::CreateFromSDKMeshFile(ID3D11Device* device, LPCWSTR fileName) { _ASSERT(FileExists(fileName)); // Use the SDKMesh class to load in the data SDKMesh sdkMesh; sdkMesh.Create(fileName); wstring directory = GetDirectoryFromFileName(fileName); // Make materials UINT numMaterials = sdkMesh.GetNumMaterials(); for (UINT i = 0; i < numMaterials; ++i) { MeshMaterial material; SDKMESH_MATERIAL* mat = sdkMesh.GetMaterial(i); memcpy(&material.AmbientAlbedo, &mat->Ambient, sizeof(D3DXVECTOR4)); memcpy(&material.DiffuseAlbedo, &mat->Diffuse, sizeof(D3DXVECTOR4)); memcpy(&material.SpecularAlbedo, &mat->Specular, sizeof(D3DXVECTOR4)); memcpy(&material.Emissive, &mat->Emissive, sizeof(D3DXVECTOR4)); material.Alpha = mat->Diffuse.w; material.SpecularPower = mat->Power; material.DiffuseMapName = AnsiToWString(mat->DiffuseTexture); material.NormalMapName = AnsiToWString(mat->NormalTexture); LoadMaterialResources(material, directory, device); meshMaterials.push_back(material); } // Make a D3D9 device IDirect3DDevice9Ptr d3d9Device = CreateD3D9Device(); UINT numMeshes = sdkMesh.GetNumMeshes(); for (UINT meshIdx = 0; meshIdx < numMeshes; ++meshIdx) { // Figure out the index type UINT ops = D3DXMESH_MANAGED; UINT indexSize = 2; Mesh::IndexType indexType = Mesh::Index16Bit; if (sdkMesh.GetIndexType(meshIdx) == IT_32BIT) { ops |= D3DXMESH_32BIT; indexSize = 4; indexType = Mesh::Index32Bit; } // Make a D3DX mesh ID3DXMesh* d3dxMesh = NULL; UINT numPrims = static_cast<UINT>(sdkMesh.GetNumIndices(meshIdx) / 3); UINT numVerts = static_cast<UINT>(sdkMesh.GetNumVertices(meshIdx, 0)); UINT vbIndex = sdkMesh.GetMesh(meshIdx)->VertexBuffers[0]; UINT ibIndex = sdkMesh.GetMesh(meshIdx)->IndexBuffer; const D3DVERTEXELEMENT9* vbElements = sdkMesh.VBElements(vbIndex); DXCall(D3DXCreateMesh(numPrims, numVerts, ops, vbElements, d3d9Device, &d3dxMesh)); IUnknownReleaser<ID3DXMesh> meshReleaser(d3dxMesh); // Copy in vertex data BYTE* verts = NULL; BYTE* srcVerts = reinterpret_cast<BYTE*>(sdkMesh.GetRawVerticesAt(vbIndex)); UINT vbStride = sdkMesh.GetVertexStride(meshIdx, 0); UINT declStride = D3DXGetDeclVertexSize(vbElements, 0); DXCall(d3dxMesh->LockVertexBuffer(0, reinterpret_cast<void**>(&verts))); for (UINT vertIdx = 0; vertIdx < numVerts; ++vertIdx) { memcpy(verts, srcVerts, declStride); verts += declStride; srcVerts += vbStride; } DXCall(d3dxMesh->UnlockVertexBuffer()); // Copy in index data void* indices = NULL; void* srcIndices = sdkMesh.GetRawIndicesAt(ibIndex); DXCall(d3dxMesh->LockIndexBuffer(0, &indices)); memcpy(indices, srcIndices, numPrims * 3 * indexSize); DXCall(d3dxMesh->UnlockIndexBuffer()); // Set up the attribute table DWORD* attributeBuffer = NULL; DXCall(d3dxMesh->LockAttributeBuffer(0, &attributeBuffer)); UINT numSubsets = sdkMesh.GetNumSubsets(meshIdx); D3DXATTRIBUTERANGE* attributes = new D3DXATTRIBUTERANGE[numSubsets]; ArrayDeleter<D3DXATTRIBUTERANGE> attributeDeleter(attributes); for (UINT i = 0; i < numSubsets; ++i) { SDKMESH_SUBSET* subset = sdkMesh.GetSubset(meshIdx, i); attributes[i].AttribId = subset->MaterialID; attributes[i].FaceStart = static_cast<DWORD>(subset->IndexStart / 3); attributes[i].FaceCount = static_cast<DWORD>(subset->IndexCount / 3); attributes[i].VertexStart = static_cast<DWORD>(subset->VertexStart); // attributes[i].VertexCount = static_cast<DWORD>(subset->VertexCount); attributes[i].VertexCount = numVerts; for (UINT faceIdx = attributes[i].FaceStart; faceIdx < attributes[i].FaceStart + attributes[i].FaceCount; ++faceIdx) attributeBuffer[faceIdx] = subset->MaterialID; } DXCall(d3dxMesh->UnlockAttributeBuffer()); d3dxMesh->SetAttributeTable(attributes, numSubsets); // Generate initial adjacency vector<DWORD> initialAdjacency; initialAdjacency.resize(d3dxMesh->GetNumFaces() * 3); DXCall(d3dxMesh->GenerateAdjacency(0.0001f, &initialAdjacency[0])); // Make the mesh Mesh mesh; mesh.CreateFromD3DXMesh(directory, device, d3d9Device, d3dxMesh, false, false, &initialAdjacency[0], indexType); meshes.push_back(mesh); } }
void PropsDemo::buildGrass() { D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; UINT numElems = 0; HR(GrassVertex::Decl->GetDeclaration(elems, &numElems)); HR(D3DXCreateMesh(NUM_GRASS_BLOCKS*2, NUM_GRASS_BLOCKS*4, D3DXMESH_MANAGED, elems, gd3dDevice, &mGrassMesh)); GrassVertex* v = 0; WORD* k = 0; HR(mGrassMesh->LockVertexBuffer(0, (void**)&v)); HR(mGrassMesh->LockIndexBuffer(0, (void**)&k)); int indexOffset = 0; // Scale down the region in which we generate grass. int w = (int)(mTerrain->getWidth() * 0.15f); int d = (int)(mTerrain->getDepth() * 0.15f); // Randomly generate a grass block (three intersecting quads) around the // terrain in the height range [35, 50] (similar to the trees). for(int i = 0; i < NUM_GRASS_BLOCKS; ++i) { //============================================ // Construct vertices. // Generate random position in region. Note that we also shift // this region to place it in the world. float x = (float)((rand() % w) - (w*0.5f)) - 30.0f; float z = (float)((rand() % d) - (d*0.5f)) - 20.0f; float y = mTerrain->getHeight(x, z); // Only generate grass blocks in this height range. If the height // is outside this range, generate a new random position and // try again. if(y < 37.0f || y > 40.0f) { --i; // We are trying again, so decrement back the index. continue; } float sx = GetRandomFloat(0.75f, 1.25f); float sy = GetRandomFloat(0.75f, 1.25f); float sz = GetRandomFloat(0.75f, 1.25f); D3DXVECTOR3 pos(x, y, z); D3DXVECTOR3 scale(sx, sy, sz); buildGrassFin(v, k, indexOffset, pos, scale); v += 4; k += 6; } HR(mGrassMesh->UnlockVertexBuffer()); HR(mGrassMesh->UnlockIndexBuffer()); // Fill in the attribute buffer (everything in subset 0) DWORD* attributeBufferPtr = 0; HR(mGrassMesh->LockAttributeBuffer(0, &attributeBufferPtr)); for(UINT i = 0; i < mGrassMesh->GetNumFaces(); ++i) attributeBufferPtr[i] = 0; HR(mGrassMesh->UnlockAttributeBuffer()); DWORD* adj = new DWORD[mGrassMesh->GetNumFaces()*3]; HR(mGrassMesh->GenerateAdjacency(EPSILON, adj)); HR(mGrassMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_VERTEXCACHE, adj, 0, 0, 0)); delete [] adj; }