void SolarSysDemo::genSphericalTexCoords() { // D3DXCreate* functions generate vertices with position // and normal data. But for texturing, we also need // tex-coords. So clone the mesh to change the vertex // format to a format with tex-coords. D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPNT::Decl->GetDeclaration(elements, &numElements); ID3DXMesh* temp = 0; HR(mSphere->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &temp)); ReleaseCOM(mSphere); // Now generate texture coordinates for each vertex. VertexPNT* vertices = 0; HR(temp->LockVertexBuffer(0, (void**)&vertices)); for(UINT i = 0; i < temp->GetNumVertices(); ++i) { // Convert to spherical coordinates. D3DXVECTOR3 p = vertices[i].pos; float theta = atan2f(p.z, p.x); float phi = acosf(p.y / sqrtf(p.x*p.x+p.y*p.y+p.z*p.z)); // Phi and theta give the texture coordinates, but are not in // the range [0, 1], so scale them into that range. float u = theta / (2.0f*D3DX_PI); float v = phi / D3DX_PI; // Save texture coordinates. vertices[i].tex0.x = u; vertices[i].tex0.y = v; } HR(temp->UnlockVertexBuffer()); // Clone back to a hardware mesh. HR(temp->CloneMesh(D3DXMESH_MANAGED | D3DXMESH_WRITEONLY, elements, gd3dDevice, &mSphere)); ReleaseCOM(temp); }
void Cone3D::buildTexCoords(IDirect3DDevice9* gd3dDevice) { D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPos::Decl->GetDeclaration(elements, &numElements); ID3DXMesh* temp = 0; HR(mpMesh->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &temp)); ReleaseCOM(mpMesh); // Now generate texture coordinates for each vertex. VertexPos* vertices = 0; HR(temp->LockVertexBuffer(0, (void**)&vertices)); D3DXVECTOR3 maxPoint(-FLT_MAX, -FLT_MAX, -FLT_MAX); D3DXVECTOR3 minPoint(FLT_MAX, FLT_MAX, FLT_MAX); for (UINT i = 0; i < temp->GetNumVertices(); ++i) { D3DXVec3Maximize(&maxPoint, &maxPoint, &vertices[i].mPos); D3DXVec3Minimize(&minPoint, &minPoint, &vertices[i].mPos); } float a = minPoint.z; float b = maxPoint.z; float h = b - a; for (int i = 0; i < (int)temp->GetNumVertices(); i++) { float x = vertices[i].mPos.x; float y = vertices[i].mPos.z; float z = vertices[i].mPos.y; float theta = atan2f(z, x); float y2 = y - b; float u = theta / (2.0f * D3DX_PI); float v = y2 / -h; vertices[i].mTexCoord.x = u; vertices[i].mTexCoord.y = v; } HR(temp->UnlockVertexBuffer()); HR(temp->CloneMesh(D3DXMESH_MANAGED | D3DXMESH_WRITEONLY, elements, gd3dDevice, &mpMesh)); ReleaseCOM(temp); }
void MeshX::BuildSkinnedMesh() { ID3DXMesh* oldMesh = allocMeshHierarchy.GetMeshList().front()->MeshData.pMesh; //compute normal D3DVERTEXELEMENT9 elements[MAX_FVF_DECL_SIZE]; oldMesh->GetDeclaration(elements); ID3DXMesh* tempMesh = 0; ID3DXMesh* tempOpMesh = 0; oldMesh->CloneMesh(D3DXMESH_SYSTEMMEM, elements, pDevice, &tempMesh); if( !HasNormals(tempMesh) ) D3DXComputeNormals(tempMesh, 0); //optimize the mesh DWORD* adj = new DWORD[tempMesh->GetNumFaces()*3]; ID3DXBuffer* remap = 0; tempMesh->GenerateAdjacency(0.00001f, adj); tempMesh->Optimize(D3DXMESH_SYSTEMMEM | D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_ATTRSORT, adj, 0, 0, &remap, &tempOpMesh); SafeRelease(tempMesh); // In the .X file (specifically the array DWORD vertexIndices[nWeights] // data member of the SkinWeights template) each bone has an array of // indices which identify the vertices of the mesh that the bone influences. // Because we have just rearranged the vertices (from optimizing), the vertex // indices of a bone are obviously incorrect (i.e., they index to vertices the bone // does not influence since we moved vertices around). In order to update a bone's // vertex indices to the vertices the bone _does_ influence, we simply need to specify // where we remapped the vertices to, so that the vertex indices can be updated to // match. This is done with the ID3DXSkinInfo::Remap method. skinInfo->Remap(tempOpMesh->GetNumVertices(), (DWORD*)remap->GetBufferPointer()); SafeRelease(remap); // Done with remap info. DWORD numBoneComboEntries = 0; ID3DXBuffer* boneComboTable = 0; DWORD maxVertInfluences; skinInfo->ConvertToIndexedBlendedMesh(tempOpMesh, 0, 128, 0, 0, 0, 0, &maxVertInfluences, &numBoneComboEntries, &boneComboTable, &this->mesh); SafeRelease(tempOpMesh); SafeRelease(boneComboTable); delete[] adj; }
void LoadXFile(const std::string & filename, ID3DXMesh** meshOut, std::vector<Mtrl> & mtrls, std::vector<IDirect3DTexture9*> & texs) { ID3DXMesh* meshSys = 0; ID3DXBuffer * adjBuffer = 0; ID3DXBuffer * mtrlBuffer = 0; DWORD numMtrls = 0; //step 1. Load the x file into system memory HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, gd3dDevice, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys)); //step 2. look into MAX_FVF_DECL_SIZE D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; HR(meshSys->GetDeclaration(elems)); bool hasNormals = false; D3DVERTEXELEMENT9 term = D3DDECL_END(); for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i) { //did we reach end? if(elems[i].Stream == 0xff) break; if(elems[i].Type == D3DDECLTYPE_FLOAT3 && elems[i].Usage == D3DDECLUSAGE_NORMAL && elems[i].UsageIndex == 0) { hasNormals = true; break; } } //step 3. D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPNT::Decl->GetDeclaration(elements, &numElements); ID3DXMesh * temp = 0; //HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &temp)); HR(meshSys->CloneMesh(D3DXMESH_32BIT, elements, gd3dDevice, &temp)); ReleaseCOM(meshSys); meshSys = temp; //step 4 if( hasNormals == false ) HR(D3DXComputeNormals(meshSys, 0)); //step 5 HR(meshSys->Optimize(D3DXMESH_MANAGED | D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut)); ReleaseCOM(meshSys); //Done w/ system mesh ReleaseCOM(adjBuffer); //done with buffer //step 6: get the materials and load the textures if(mtrlBuffer != 0 && numMtrls != 0) { D3DXMATERIAL *d3dxMtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); for(DWORD i = 0; i < numMtrls; ++i) { //save the ith material. MatD3D ambient //doesnt have a default value, so I'm setting //it to be the same as the diffuse Mtrl m; m.ambient = d3dxMtrls[i].MatD3D.Diffuse; m.diffuse = d3dxMtrls[i].MatD3D.Diffuse; m.spec = d3dxMtrls[i].MatD3D.Specular; m.specPower = d3dxMtrls[i].MatD3D.Power; mtrls.push_back(m); //check if the ith material has an associative texture if(d3dxMtrls[i].pTextureFilename != 0) { //yes, load the texture for the ith subset IDirect3DTexture9* tex = 0; char *texFN = d3dxMtrls[i].pTextureFilename; HR(D3DXCreateTextureFromFile(gd3dDevice, texFN, &tex)); //save the loaded texure texs.push_back(tex); } else { //no texture texs.push_back( 0 ); } } } ReleaseCOM(mtrlBuffer); // done with the buffer }
void LoadXFile( const std::string& filename, ID3DXMesh** meshOut, std::vector<Mtrl>& mtrls, std::vector<IDirect3DTexture9*>& texs) { // Step 1: Load the .x file from file into a system memory mesh. ID3DXMesh* meshSys = 0; ID3DXBuffer* adjBuffer = 0; ID3DXBuffer* mtrlBuffer = 0; DWORD numMtrls = 0; HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, gd3dDevice, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys)); // Step 2: Find out if the mesh already has normal info? D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; HR(meshSys->GetDeclaration(elems)); bool hasNormals = false; D3DVERTEXELEMENT9 term = D3DDECL_END(); for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i) { // Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}? if(elems[i].Stream == 0xff ) break; if( elems[i].Type == D3DDECLTYPE_FLOAT3 && elems[i].Usage == D3DDECLUSAGE_NORMAL && elems[i].UsageIndex == 0 ) { hasNormals = true; break; } } // Step 3: Change vertex format to VertexPNT. D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPNT::Decl->GetDeclaration(elements, &numElements); ID3DXMesh* temp = 0; HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &temp)); ReleaseCOM(meshSys); meshSys = temp; // Step 4: If the mesh did not have normals, generate them. if( hasNormals == false) HR(D3DXComputeNormals(meshSys, 0)); // Step 5: Optimize the mesh. HR(meshSys->Optimize(D3DXMESH_MANAGED | D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut)); ReleaseCOM(meshSys); // Done w/ system mesh. ReleaseCOM(adjBuffer); // Done with buffer. // Step 6: Extract the materials and load the textures. if( mtrlBuffer != 0 && numMtrls != 0 ) { D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); for(DWORD i = 0; i < numMtrls; ++i) { // Save the ith material. Note that the MatD3D property does not have an ambient // value set when its loaded, so just set it to the diffuse value. Mtrl m; m.ambient = d3dxmtrls[i].MatD3D.Diffuse; m.diffuse = d3dxmtrls[i].MatD3D.Diffuse; m.spec = d3dxmtrls[i].MatD3D.Specular; m.specPower = d3dxmtrls[i].MatD3D.Power; mtrls.push_back( m ); // Check if the ith material has an associative texture if( d3dxmtrls[i].pTextureFilename != 0 ) { // Yes, load the texture for the ith subset IDirect3DTexture9* tex = 0; char* texFN = d3dxmtrls[i].pTextureFilename; HR(D3DXCreateTextureFromFile(gd3dDevice, texFN, &tex)); // Save the loaded texture texs.push_back( tex ); } else { // No texture for the ith subset texs.push_back( 0 ); } } } ReleaseCOM(mtrlBuffer); // done w/ buffer }
WaterDemo::WaterDemo(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP) : D3DApp(hInstance, winCaption, devType, requestedVP) { if(!checkDeviceCaps()) { MessageBox(0, "checkDeviceCaps() Failed", 0, 0); PostQuitMessage(0); } InitAllVertexDeclarations(); mLight.dirW = D3DXVECTOR3(0.0f, -2.0f, -1.0f); D3DXVec3Normalize(&mLight.dirW, &mLight.dirW); mLight.ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f); mLight.diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); mLight.spec = D3DXCOLOR(0.7f, 0.7f, 0.7f, 1.0f); mGfxStats = new GfxStats(); mSky = new Sky("grassenvmap1024.dds", 10000.0f); D3DXMATRIX waterWorld; D3DXMatrixTranslation(&waterWorld, 0.0f, 2.0f, 0.0f); Mtrl waterMtrl; waterMtrl.ambient = D3DXCOLOR(0.26f, 0.23f, 0.3f, 0.90f); waterMtrl.diffuse = D3DXCOLOR(0.26f, 0.23f, 0.3f, 0.90f); waterMtrl.spec = 1.0f*WHITE; waterMtrl.specPower = 64.0f; Water::InitInfo waterInitInfo; waterInitInfo.dirLight = mLight; waterInitInfo.mtrl = waterMtrl; waterInitInfo.vertRows = 128; waterInitInfo.vertCols = 128; waterInitInfo.dx = 1.0f; waterInitInfo.dz = 1.0f; waterInitInfo.waveMapFilename0 = "wave0.dds"; waterInitInfo.waveMapFilename1 = "wave1.dds"; waterInitInfo.waveMapVelocity0 = D3DXVECTOR2(0.05f, 0.08f); waterInitInfo.waveMapVelocity1 = D3DXVECTOR2(-0.02f, 0.1f); waterInitInfo.texScale = 16.0f; waterInitInfo.toWorld = waterWorld; mWater = new Water(waterInitInfo); mWater->setEnvMap(mSky->getEnvMap()); ID3DXMesh* tempMesh = 0; LoadXFile("BasicColumnScene.x", &tempMesh, mSceneMtrls, mSceneTextures); // Get the vertex declaration for the NMapVertex. D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; UINT numElems = 0; HR(NMapVertex::Decl->GetDeclaration(elems, &numElems)); // Clone the mesh to the NMapVertex format. ID3DXMesh* clonedTempMesh = 0; HR(tempMesh->CloneMesh(D3DXMESH_MANAGED, elems, gd3dDevice, &clonedTempMesh)); // Now use D3DXComputeTangentFrameEx to build the TNB-basis for each vertex // in the mesh. HR(D3DXComputeTangentFrameEx( clonedTempMesh, // Input mesh D3DDECLUSAGE_TEXCOORD, 0, // Vertex element of input tex-coords. D3DDECLUSAGE_BINORMAL, 0, // Vertex element to output binormal. D3DDECLUSAGE_TANGENT, 0, // Vertex element to output tangent. D3DDECLUSAGE_NORMAL, 0, // Vertex element to output normal. 0, // Options 0, // Adjacency 0.01f, 0.25f, 0.01f, // Thresholds for handling errors &mSceneMesh, // Output mesh 0)); // Vertex Remapping // Done with temps. ReleaseCOM(tempMesh); ReleaseCOM(clonedTempMesh); D3DXMatrixIdentity(&mSceneWorld); D3DXMatrixIdentity(&mSceneWorldInv); HR(D3DXCreateTextureFromFile(gd3dDevice, "floor_nmap.bmp", &mSceneNormalMaps[0])); HR(D3DXCreateTextureFromFile(gd3dDevice, "bricks_nmap.bmp", &mSceneNormalMaps[1])); HR(D3DXCreateTextureFromFile(gd3dDevice, "whitetex.dds", &mWhiteTex)); // Initialize camera. gCamera->pos().y = 7.0f; gCamera->pos().z = -30.0f; gCamera->setSpeed(10.0f); mGfxStats->addVertices(mSceneMesh->GetNumVertices()); mGfxStats->addTriangles(mSceneMesh->GetNumFaces()); mGfxStats->addVertices(mWater->getNumVertices()); mGfxStats->addTriangles(mWater->getNumTriangles()); mGfxStats->addVertices(mSky->getNumVertices()); mGfxStats->addTriangles(mSky->getNumTriangles()); buildFX(); onResetDevice(); }
void XManager::loadXFile(IDirect3DDevice9* dev, const std::string& filename, ID3DXMesh** meshOut, std::vector<Material>* mtrls, std::vector<IDirect3DTexture9*>* texs) { // Step 1: Load the .x file from file into a system memory mesh. ID3DXMesh* meshSys = 0; ID3DXBuffer* adjBuffer = 0; ID3DXBuffer* mtrlBuffer = 0; DWORD numMtrls = 0; HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, dev, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys)); // Step 2: Find out if the mesh already has normal info? D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; HR(meshSys->GetDeclaration(elems)); bool hasNormals = false; D3DVERTEXELEMENT9 term = D3DDECL_END(); for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i) { // Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}? if(elems[i].Stream == 0xff ) break; if( elems[i].Type == D3DDECLTYPE_FLOAT3 && elems[i].Usage == D3DDECLUSAGE_NORMAL && elems[i].UsageIndex == 0 ) { hasNormals = true; break; } } // Step 3: Change vertex format to CustomVertex3NormalUV D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; CustomVertex3NormalUV::decl->GetDeclaration(elements, &numElements); ID3DXMesh* temp = 0; HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, elements, dev, &temp)); SAFERELEASECOM(meshSys); meshSys = temp; // Step 4: If the mesh did not have normals, generate them. if( hasNormals == false) HR(D3DXComputeNormals(meshSys, 0)); // Step 5: Optimize the mesh. HR(meshSys->Optimize(D3DXMESH_MANAGED | D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut)); SAFERELEASECOM(meshSys); // Done w/ system mesh. SAFERELEASECOM(adjBuffer); // Done with buffer. // Step 6: Extract the materials and load the textures. if( mtrlBuffer != 0 && numMtrls != 0 ) { D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); for(DWORD i = 0; i < numMtrls; ++i) { // Save the ith material. Note that the MatD3D property does not have an ambient // value set when its loaded, so just set it to the diffuse value. Material m; m.ambient = d3dxmtrls[i].MatD3D.Diffuse; m.diffuse = d3dxmtrls[i].MatD3D.Diffuse; m.spec = d3dxmtrls[i].MatD3D.Specular; m.specPower = d3dxmtrls[i].MatD3D.Power; mtrls->push_back( m ); // Check if the ith material has an associative texture if( d3dxmtrls[i].pTextureFilename != 0 ) { IDirect3DTexture9* tex = 0; std::string s(d3dxmtrls[i].pTextureFilename); const char folder[] = "./texture/"; unsigned int pos = s.find_last_of('\/'); std::string newFileName(folder); // std::string::npos gets returned if no / was found if(pos != std::string::npos) { //std::string sub = s.substr(pos,s.size()); if(strcmp(s.substr(pos+1,s.size()).c_str(),"Watcher.tga") == 0) { newFileName.append("Watcher_Black.tga"); } else { newFileName.append(s.substr(pos+1,s.size())); } } else { newFileName.append(s); } // Save the loaded texture HR(D3DXCreateTextureFromFile(dev, newFileName.c_str(), &tex)); texs->push_back( tex ); } else {
//-------------------------------------------------------------------------------------- HRESULT CLoaderXFile::Load( WCHAR* szFileName, FRAME_TRANSFORM_TYPE requestedBHT ) { HRESULT hr = E_FAIL; ID3DXBuffer *pMat = NULL; ID3DXMesh *pRawMesh = NULL; ID3DXMesh *pMesh = NULL; DWORD cMat; IDirect3DDevice9* pDev9 = NULL; DWORD* pAdjBuffer = NULL; // Create a d3d9 object IDirect3D9* pD3D9 = Direct3DCreate9( D3D_SDK_VERSION ); if( pD3D9 == NULL ) return E_FAIL; D3DPRESENT_PARAMETERS pp; pp.BackBufferWidth = 320; pp.BackBufferHeight = 240; pp.BackBufferFormat = D3DFMT_X8R8G8B8; pp.BackBufferCount = 1; pp.MultiSampleType = D3DMULTISAMPLE_NONE; pp.MultiSampleQuality = 0; pp.SwapEffect = D3DSWAPEFFECT_DISCARD; pp.hDeviceWindow = GetShellWindow(); pp.Windowed = true; pp.Flags = 0; pp.FullScreen_RefreshRateInHz = 0; pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; pp.EnableAutoDepthStencil = false; hr = pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &pDev9 ); if(FAILED(hr)) goto Error; if( szFileName ) { hr = D3DXLoadMeshFromX( szFileName, 0, pDev9, NULL, &pMat, NULL, &cMat, &pRawMesh ); if(FAILED(hr)) goto Error; } D3DVERTEXELEMENT9 declTanBi[] = { { 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 }, { 0, 32, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, { 0, 44, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, D3DDECL_END() }; D3DVERTEXELEMENT9* pdecl = declTanBi; // Make a clone with the desired vertex format. if( SUCCEEDED( pRawMesh->CloneMesh( D3DXMESH_32BIT | D3DXMESH_DYNAMIC, pdecl, pDev9, &m_pMesh ) ) ) { // Optimize pAdjBuffer = new DWORD[ 3*m_pMesh->GetNumFaces() ]; if( !pAdjBuffer ) { hr = E_OUTOFMEMORY; goto Error; } m_pMesh->GenerateAdjacency( 0.001f, pAdjBuffer ); m_pMesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT, pAdjBuffer, NULL, NULL, NULL ); // Attributes m_pMesh->GetAttributeTable( NULL, &m_dwNumAttr ); if( m_dwNumAttr > 0 ) { m_pAttr = new D3DXATTRIBUTERANGE[m_dwNumAttr]; m_pMesh->GetAttributeTable( m_pAttr, &m_dwNumAttr ); } // Materials m_dwNumMaterials = cMat; if( m_dwNumMaterials > 0 ) { D3DXMATERIAL* pMaterialBuffer = (D3DXMATERIAL*)pMat->GetBufferPointer(); m_pMats = new D3DXMATERIAL[ m_dwNumMaterials ]; if( !m_pMats ) { hr = E_OUTOFMEMORY; goto Error; } for( DWORD m=0; m<m_dwNumMaterials; m++ ) { CopyMemory( &m_pMats[m], &pMaterialBuffer[m], sizeof(D3DXMATERIAL) ); } } // Create the intermediate mesh hr = CreateIntermediateMesh( declTanBi, 6 ); if(FAILED(hr)) goto Error; } hr = S_OK; Error: SAFE_RELEASE( pMat ); SAFE_RELEASE( pRawMesh ); SAFE_RELEASE( pMesh ); SAFE_RELEASE( pDev9 ); SAFE_RELEASE( pD3D9 ); SAFE_DELETE_ARRAY( pAdjBuffer ); return hr; }
void SphereCylDemo::genCylTexCoords(AXIS axis) { // D3DXCreate* functions generate vertices with position // and normal data. But for texturing, we also need // tex-coords. So clone the mesh to change the vertex // format to a format with tex-coords. D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPNT::Decl->GetDeclaration(elements, &numElements); ID3DXMesh* temp = 0; HR(mCylinder->CloneMesh(D3DXMESH_SYSTEMMEM, elements, gd3dDevice, &temp)); ReleaseCOM(mCylinder); // Now generate texture coordinates for each vertex. VertexPNT* vertices = 0; HR(temp->LockVertexBuffer(0, (void**)&vertices)); // We need to get the height of the cylinder we are projecting the // vertices onto. That height depends on which axis the client has // specified that the cylinder lies on. The height is determined by // finding the height of the bounding cylinder on the specified axis. D3DXVECTOR3 maxPoint(-FLT_MAX, -FLT_MAX, -FLT_MAX); D3DXVECTOR3 minPoint(FLT_MAX, FLT_MAX, FLT_MAX); for(UINT i = 0; i < temp->GetNumVertices(); ++i) { D3DXVec3Maximize(&maxPoint, &maxPoint, &vertices[i].pos); D3DXVec3Minimize(&minPoint, &minPoint, &vertices[i].pos); } float a = 0.0f; float b = 0.0f; float h = 0.0f; switch( axis ) { case X_AXIS: a = minPoint.x; b = maxPoint.x; h = b-a; break; case Y_AXIS: a = minPoint.y; b = maxPoint.y; h = b-a; break; case Z_AXIS: a = minPoint.z; b = maxPoint.z; h = b-a; break; } // Iterate over each vertex and compute its texture coordinate. for(UINT i = 0; i < temp->GetNumVertices(); ++i) { // Get the coordinates along the axes orthogonal to the // axis the cylinder is aligned with. float x = 0.0f; float y = 0.0f; float z = 0.0f; switch( axis ) { case X_AXIS: x = vertices[i].pos.y; z = vertices[i].pos.z; y = vertices[i].pos.x; break; case Y_AXIS: x = vertices[i].pos.x; z = vertices[i].pos.z; y = vertices[i].pos.y; break; case Z_AXIS: x = vertices[i].pos.x; z = vertices[i].pos.y; y = vertices[i].pos.z; break; } // Convert to cylindrical coordinates. float theta = atan2f(z, x); float y2 = y - b; // Transform [a, b]-->[-h, 0] // Transform theta from [0, 2*pi] to [0, 1] range and // transform y2 from [-h, 0] to [0, 1]. float u = theta / (2.0f*D3DX_PI); float v = y2 / -h; // Save texture coordinates. vertices[i].tex0.x = u; vertices[i].tex0.y = v; } HR(temp->UnlockVertexBuffer()); // Clone back to a hardware mesh. HR(temp->CloneMesh(D3DXMESH_MANAGED | D3DXMESH_WRITEONLY, elements, gd3dDevice, &mCylinder)); ReleaseCOM(temp); }