//----------------------------------------------------------------------------- // Convert the mesh to the format specified by the given vertex declarations. //----------------------------------------------------------------------------- HRESULT CDXUTMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9 *pDecl, bool bAutoComputeNormals, bool bAutoComputeTangents, bool bSplitVertexForOptimalTangents ) { LPD3DXMESH pTempMesh = NULL; if( m_pMesh ) { if( FAILED( m_pMesh->CloneMesh( m_pMesh->GetOptions(), pDecl, pd3dDevice, &pTempMesh ) ) ) { SAFE_RELEASE( pTempMesh ); return E_FAIL; } } // Check if the old declaration contains a normal. bool bHadNormal = false; bool bHadTangent = false; D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE]; if( m_pMesh && SUCCEEDED( m_pMesh->GetDeclaration( aOldDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index ) { if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHadNormal = true; } if( aOldDecl[index].Usage == D3DDECLUSAGE_TANGENT ) { bHadTangent = true; } } } // Check if the new declaration contains a normal. bool bHaveNormalNow = false; bool bHaveTangentNow = false; D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE]; if( pTempMesh && SUCCEEDED( pTempMesh->GetDeclaration( aNewDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index ) { if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHaveNormalNow = true; } if( aNewDecl[index].Usage == D3DDECLUSAGE_TANGENT ) { bHaveTangentNow = true; } } } SAFE_RELEASE( m_pMesh ); if( pTempMesh ) { m_pMesh = pTempMesh; if( !bHadNormal && bHaveNormalNow && bAutoComputeNormals ) { // Compute normals in case the meshes have them D3DXComputeNormals( m_pMesh, NULL ); } if( bHaveNormalNow && !bHadTangent && bHaveTangentNow && bAutoComputeTangents ) { ID3DXMesh* pNewMesh; HRESULT hr; DWORD *rgdwAdjacency = NULL; rgdwAdjacency = new DWORD[m_pMesh->GetNumFaces() * 3]; if( rgdwAdjacency == NULL ) return E_OUTOFMEMORY; V( m_pMesh->GenerateAdjacency(1e-6f,rgdwAdjacency) ); float fPartialEdgeThreshold; float fSingularPointThreshold; float fNormalEdgeThreshold; if( bSplitVertexForOptimalTangents ) { fPartialEdgeThreshold = 0.01f; fSingularPointThreshold = 0.25f; fNormalEdgeThreshold = 0.01f; } else { fPartialEdgeThreshold = -1.01f; fSingularPointThreshold = 0.01f; fNormalEdgeThreshold = -1.01f; } // Compute tangents, which are required for normal mapping hr = D3DXComputeTangentFrameEx( m_pMesh, D3DDECLUSAGE_TEXCOORD, 0, D3DDECLUSAGE_TANGENT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, 0, rgdwAdjacency, fPartialEdgeThreshold, fSingularPointThreshold, fNormalEdgeThreshold, &pNewMesh, NULL ); SAFE_DELETE_ARRAY( rgdwAdjacency ); if( FAILED(hr) ) return hr; SAFE_RELEASE( m_pMesh ); m_pMesh = pNewMesh; } } return S_OK; }
void CShowPoints9::SetMesh(LPD3DXMESH pNewMesh, LPD3DXSKININFO pNewSkin) { HRESULT hr = S_OK; NumPoints = 0; UnskinnedVB.resize(0); SAFE_RELEASE(SkinnedVB); SAFE_RELEASE(Skin); if(pNewMesh == NULL) return; IDirect3DDevice9* device = DXUTGetD3D9Device(); {//EFFECT V( device->CreateVertexDeclaration( Elements, &Declaration ) ); ID3DXBuffer* pErrors = NULL; V( SASCreateEffectFromResource( device, NULL, MAKEINTRESOURCE(IDR_SHOWLINES9FX), MAKEINTRESOURCE(RT_RCDATA), NULL, NULL, 0, NULL, &Effect, &pErrors)); if(pErrors) DXVGetApp().OutputA( (const char*)pErrors->GetBufferPointer() ); SAFE_RELEASE(pErrors); }//EFFECT D3DVERTEXELEMENT9 declIn[ MAX_FVF_DECL_SIZE ]; V( pNewMesh->GetDeclaration(declIn) ); int iPos= -1; int iNorm= -1; for( int i = 0 ; declIn[i].Stream != 255 && i < MAX_FVF_DECL_SIZE; i++) { if(declIn[i].Usage == D3DDECLUSAGE_POSITION && declIn[i].UsageIndex == 0) iPos = i; if(declIn[i].Usage == D3DDECLUSAGE_NORMAL && declIn[i].UsageIndex == 0) iNorm = i; } if(iPos == -1 || iNorm == -1) return; if( (( declIn[iPos].Type & (D3DDECLTYPE_FLOAT3|D3DDECLTYPE_FLOAT4)) == 0 ) || (( declIn[iNorm].Type & (D3DDECLTYPE_FLOAT3|D3DDECLTYPE_FLOAT4)) == 0 ) ) return; NumPoints = pNewMesh->GetNumVertices(); int MeshStride = pNewMesh->GetNumBytesPerVertex(); if(pNewSkin) { V( pNewSkin->Clone( &Skin ) ); V( Skin->SetDeclaration(Elements) ); } //GET VERTEX DATA BYTE* pSrcVB= NULL; V( pNewMesh->LockVertexBuffer( D3DLOCK_READONLY, (LPVOID*)&pSrcVB ) ); UnskinnedVB.resize(pNewMesh->GetNumVertices()); for( DWORD iVert = 0; iVert < pNewMesh->GetNumVertices(); iVert++) { Vertex& v0 = UnskinnedVB[iVert]; v0.Position = *(D3DXVECTOR3*) (pSrcVB+(MeshStride*iVert)+declIn[iPos].Offset); } V( pNewMesh->UnlockVertexBuffer() ); V( device->CreateVertexBuffer( NumPoints*Stride , D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &SkinnedVB, NULL) ); //Fill in with initial values so unskinned meshes do not have to do this every render. pSrcVB=(BYTE*)(void*)&UnskinnedVB.front(); BYTE* pDstVB=NULL; V( SkinnedVB->Lock(0, 0, (void**)&pDstVB, 0 ) ); { memcpy( pDstVB, pSrcVB, Stride*pNewMesh->GetNumVertices() ); } V( SkinnedVB->Unlock() ); }
//----------------------------------------------------------------------------- // Name: CDXUTMesh::SetVertexDecl // Desc: Convert the mesh to the format specified by the given vertex // declarations. //----------------------------------------------------------------------------- HRESULT CDXUTMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9 *pDecl ) { LPD3DXMESH pTempSysMemMesh = NULL; LPD3DXMESH pTempLocalMesh = NULL; if( m_pSysMemMesh ) { if( FAILED( m_pSysMemMesh->CloneMesh( m_pSysMemMesh->GetOptions(), pDecl, pd3dDevice, &pTempSysMemMesh ) ) ) return E_FAIL; } if( m_pLocalMesh ) { if( FAILED( m_pLocalMesh->CloneMesh( m_pLocalMesh->GetOptions(), pDecl, pd3dDevice, &pTempLocalMesh ) ) ) { SAFE_RELEASE( pTempSysMemMesh ); return E_FAIL; } } // Check if the old declaration contains a normal. bool bHadNormal = false; D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE]; if( m_pSysMemMesh && SUCCEEDED( m_pSysMemMesh->GetDeclaration( aOldDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index ) if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHadNormal = true; break; } } // Check if the new declaration contains a normal. bool bHaveNormalNow = false; D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE]; if( pTempSysMemMesh && SUCCEEDED( pTempSysMemMesh->GetDeclaration( aNewDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index ) if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHaveNormalNow = true; break; } } SAFE_RELEASE( m_pSysMemMesh ); SAFE_RELEASE( m_pLocalMesh ); if( pTempSysMemMesh ) { m_pSysMemMesh = pTempSysMemMesh; if( !bHadNormal && bHaveNormalNow ) { // Compute normals in case the meshes have them D3DXComputeNormals( m_pSysMemMesh, NULL ); } } if( pTempLocalMesh ) { m_pLocalMesh = pTempLocalMesh; if( !bHadNormal && bHaveNormalNow ) { // Compute normals in case the meshes have them D3DXComputeNormals( m_pLocalMesh, NULL ); } } return S_OK; }
DWORD MeshParameterization::OnGenerateAtlas( DWORD size, void * params ) { VERIFY_MESSAGE_SIZE( size, sizeof( GENERATEATLASMESSAGE ) ); GENERATEATLASMESSAGE * msg = (GENERATEATLASMESSAGE*)params; if( !msg ) { return MSG_ERROR; } bool bUseIncomingTexCoords = msg->useIncomingTexCoords; GenerateBounds(); HRESULT hr; //This should be changed to use a new mesh parameterization technique DWORD numFaces = (DWORD)m_Faces->size(); DWORD numVertices = (DWORD)m_CollapsedMesh->size(); DWORD curError = 0; if( !bUseIncomingTexCoords && numFaces > 0 && numVertices > 0 ) { DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 ; DWORD flags = D3DXMESH_SYSTEMMEM ;// | D3DXMESH_MANAGED ;// | D3DXMESH_SOFTWAREPROCESSING | D3DXMESH_SYSTEMMEM |; LPD3DXMESH mesh = NULL; hr = D3DXCreateMeshFVF( numFaces, numVertices, flags, fvf, m_pDevice, &mesh ); if( FAILED( hr ) ) { curError = GetLastError(); EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in create mesh fvf\n")); return MSG_ERROR; } //now fill with data BYTE * vertexData; BYTE * indexData; hr = mesh->LockVertexBuffer( 0, (LPVOID*)&vertexData ); hr = mesh->LockIndexBuffer( 0, (LPVOID*)&indexData ); D3DVERTEXELEMENT9 Decl[ MAX_FVF_DECL_SIZE ]; mesh->GetDeclaration( Decl ); paramVertex * pVertOriginal = (paramVertex*)vertexData; for( int i = 0; i < (int)numVertices; i++ ) { paramVertex * pVert = (paramVertex*)vertexData; pVert->x = (*m_CollapsedMesh)[i].originalPosition.x; pVert->y = (*m_CollapsedMesh)[i].originalPosition.y; pVert->z = (*m_CollapsedMesh)[i].originalPosition.z; pVert->nx = -(*m_CollapsedMesh)[i].normal.x; pVert->ny = -(*m_CollapsedMesh)[i].normal.y; pVert->nz = -(*m_CollapsedMesh)[i].normal.z; pVert->u = (*m_CollapsedMesh)[i].generatedU; pVert->v = (*m_CollapsedMesh)[i].generatedV; NormalizeUV( pVert->u ); NormalizeUV( pVert->v ); vertexData += sizeof( paramVertex ); } for( int i = 0; i < (int)numFaces; i++ ) { unsigned short * index = (unsigned short*)indexData; index[0] = ( unsigned short )(*m_Faces)[ i ].index[ 0 ]; index[1] = ( unsigned short )(*m_Faces)[ i ].index[ 1 ]; index[2] = ( unsigned short )(*m_Faces)[ i ].index[ 2 ]; indexData += sizeof( unsigned short )*3;//32 bit indices triangles } LPD3DXBUFFER imt; hr = D3DXComputeIMTFromPerVertexSignal( mesh, (const float*)pVertOriginal + 3*sizeof(float), 3, sizeof(paramVertex), 0L, 0, 0, &imt ); mesh->UnlockIndexBuffer(); mesh->UnlockVertexBuffer(); //tensors float * tensors = new float[ 3*numFaces ]; for( int i = 0; i < 3*(int)numFaces; i += 3 ) { tensors[ i ] = 4.f; tensors[ i + 1 ] = 0.f; tensors[ i + 2 ] = 4.f; } //some checks numVertices = mesh->GetNumVertices(); numFaces = mesh->GetNumFaces(); //create adjacency DWORD * adjacency = new DWORD[ 3*numFaces ]; memset( adjacency, 0, sizeof(DWORD)*3*numFaces ); hr = mesh->GenerateAdjacency( 0.001f, adjacency ); //hr = mesh->ConvertPointRepsToAdjacency( NULL, adjacency ); if( FAILED( hr ) ) { curError = GetLastError(); EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in generate adjacency\n")); return MSG_ERROR; } /* save to mesh to check model uvs D3DXMATERIAL mat; mat.MatD3D.Ambient.r = mat.MatD3D.Ambient.a =mat.MatD3D.Ambient.b =mat.MatD3D.Ambient.g = 0; mat.MatD3D.Diffuse.r = mat.MatD3D.Diffuse.a =mat.MatD3D.Diffuse.b =mat.MatD3D.Diffuse.g = 1; mat.pTextureFilename = "tex.dds"; D3DXSaveMeshToX( "mesh.x", mesh, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT ); */ float * imtTensor = tensors;//(float*)imt->GetBufferPointer(); float stretchout; unsigned int charts; LPD3DXMESH meshOut = NULL; LPD3DXBUFFER remappedData = NULL; LPD3DXBUFFER faceData = NULL; D3DXATTRIBUTERANGE Attrib; memset(&Attrib, 0, sizeof(D3DXATTRIBUTERANGE)); Attrib.FaceCount = numFaces; Attrib.VertexCount = numVertices; mesh->SetAttributeTable(&Attrib, 1); int gutter = m_TexSize / 32; gutter = min( gutter, 6 ); hr = D3DXUVAtlasCreate( mesh, 0, .5, m_TexSize, m_TexSize, 6, //gutter 0, adjacency, 0, imtTensor, (LPD3DXUVATLASCB)UVGenCallback, .0001f, 0, //D3DXUVATLAS_GEODESIC_QUALITY , D3DXUVATLAS_GEODESIC_FAST, &meshOut, &faceData, &remappedData, &stretchout, &charts ); if( FAILED( hr ) ) { curError = GetLastError(); EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in uv atlas create\n")); return MSG_ERROR; } /* save to mesh to check model uvs hr = meshOut->ConvertPointRepsToAdjacency( NULL, adjacency ); D3DXSaveMeshToX( "mesh2.x", meshOut, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT ); */ delete [] adjacency; delete [] tensors; //Generate our lightmap cache data for passing on and saving GenerateCache( meshOut, remappedData ); GenerateTriangleTexelData(); meshOut->Release(); faceData->Release(); remappedData->Release(); mesh->Release(); } else if( bUseIncomingTexCoords ) { GenerateCache(); GenerateTriangleTexelData(); } return MSG_HANDLED_STOP; }