HRESULT LoadMesh(IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh) { ID3DXMesh* pMesh = NULL; WCHAR str[MAX_PATH]; HRESULT hr; V_RETURN(DXUTFindDXSDKMediaFileCch(str, MAX_PATH, strFileName)); V_RETURN(D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh)); DWORD* rgdwAdjacency = NULL; if(!(pMesh->GetFVF() & D3DFVF_NORMAL)) { ID3DXMesh* pTempMesh; V(pMesh->CloneMeshFVF(pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL, pd3dDevice, &pTempMesh)); V(D3DXComputeNormals(pTempMesh, NULL)); SAFE_RELEASE(pMesh); pMesh = pTempMesh; } rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]; if(rgdwAdjacency == NULL) return E_OUTOFMEMORY; V(pMesh->GenerateAdjacency(1e-6f, rgdwAdjacency)); V(pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL)); delete []rgdwAdjacency; *ppMesh = pMesh; return S_OK; }
HRESULT CMesh3D::InitialMesh(LPCSTR Name, FILE *FileLog ) { m_pMesh = 0; m_pMeshMaterial = 0; m_pMeshTextura = 0; m_SizeFVF = 0; m_Alpha = 1.0f; ID3DXBuffer *pMaterialBuffer = 0; if ( FAILED( D3DXLoadMeshFromX( Name, D3DXMESH_SYSTEMMEM, g_pD3DDevice, 0, &pMaterialBuffer, 0, &m_TexturCount, &m_pMesh ) ) ) { if ( m_pMesh == 0 ) { if ( FileLog ) fprintf( FileLog, "error load x file '%s'\n", Name ); return E_FAIL; } } if ( m_pMesh->GetFVF() & D3DFVF_XYZ ) m_SizeFVF += sizeof(float)*3; if ( m_pMesh->GetFVF() & D3DFVF_NORMAL ) m_SizeFVF += sizeof(float)*3; if ( m_pMesh->GetFVF() & D3DFVF_TEX1 ) m_SizeFVF += sizeof(float)*2; m_pMesh->GetVertexBuffer( &m_VertexBuffer ); m_pMesh->GetIndexBuffer( &m_IndexBuffer ); // Извлекаем свойства материала и названия{имена} структуры D3DXMATERIAL *D3DXMeshMaterial = (D3DXMATERIAL *)pMaterialBuffer->GetBufferPointer(); m_pMeshMaterial = new D3DMATERIAL9[m_TexturCount]; m_pMeshTextura = new IDirect3DTexture9*[m_TexturCount]; for ( DWORD i = 0; i < m_TexturCount; i++ ) { // Копируем материал m_pMeshMaterial[i] = D3DXMeshMaterial[i].MatD3D; // Установить окружающего свет m_pMeshMaterial[i].Ambient = m_pMeshMaterial[i].Diffuse; // Загружаем текстуру string FileName = string( "model//" ) + string( D3DXMeshMaterial[i].pTextureFilename ); if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, FileName.c_str(), &m_pMeshTextura[i] ))) { fprintf( FileLog, "error load texture '%s'\n", D3DXMeshMaterial[i].pTextureFilename ); m_pMeshTextura[i] = 0; } } // Уничтожаем буфер материала pMaterialBuffer->Release(); return S_OK; }
//-------------------------------------------------------------------------------------- // This function loads the mesh and ensures the mesh has normals; it also optimizes the // mesh for the graphics card's vertex cache, which improves performance by organizing // the internal triangle list for less cache misses. //-------------------------------------------------------------------------------------- HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh ) { ID3DXMesh* pMesh = NULL; WCHAR str[MAX_PATH]; HRESULT hr; // Load the mesh with D3DX and get back a ID3DXMesh*. For this // sample we'll ignore the X file's embedded materials since we know // exactly the model we're loading. See the mesh samples such as // "OptimizedMesh" for a more generic mesh loading example. V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) ); V_RETURN( D3DXLoadMeshFromX( str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh ) ); 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, pd3dDevice, &pTempMesh ) ); V( D3DXComputeNormals( pTempMesh, NULL ) ); SAFE_RELEASE( pMesh ); pMesh = pTempMesh; } // Optimize the mesh for this graphics card's vertex cache // so when rendering the mesh's triangle list the vertices will // cache hit more often so it won't have to re-execute the vertex shader // on those vertices so it will improve perf. rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]; if( rgdwAdjacency == NULL ) return E_OUTOFMEMORY; V( pMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) ); V( pMesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL ) ); delete []rgdwAdjacency; *ppMesh = pMesh; return S_OK; }
//-------------------------------------------------------------------------------------- //메쉬 불러오는 함수 //-------------------------------------------------------------------------------------- HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh ) { ID3DXMesh* pMesh = NULL; WCHAR str[MAX_PATH]; HRESULT hr; V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) ); V_RETURN( D3DXLoadMeshFromX( str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh ) ); DWORD* rgdwAdjacency = NULL; // mesh에 노말벡터 생성하는 코드 if( !( pMesh->GetFVF() & D3DFVF_NORMAL ) ) { ID3DXMesh* pTempMesh; V( pMesh->CloneMeshFVF( pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL, pd3dDevice, &pTempMesh ) ); V( D3DXComputeNormals( pTempMesh, NULL ) ); SAFE_RELEASE( pMesh ); pMesh = pTempMesh; } //성능 향상을 도모하고자 인접 정보를 기록 //각 mesh(삼각형) 정보 테이블을 가지는 형태 //해당 정보는 pMesh가 가지고 있음 //각 mesh 정보는 인접할 수 있는 점의 최대 개수가 3개 이내임을 활용해 효율적으로 vertex 운영 rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]; if( rgdwAdjacency == NULL ) return E_OUTOFMEMORY; V( pMesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) ); //버텍스 캐쉬를 활용하는 것 V( pMesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL ) ); delete []rgdwAdjacency; //callback out 변수에 최종 값 저장 *ppMesh = pMesh; return S_OK; }
HRESULT FaceHierarchyLoader::CreateMeshContainer(LPCSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer) { ID3DXMesh* pSrcMesh = pMeshData->pMesh; D3DXMESHCONTAINER* pContainer = new D3DXMESHCONTAINER(); memset(pContainer, 0, sizeof(D3DXMESHCONTAINER)); pSrcMesh->CloneMeshFVF(pSrcMesh->GetOptions(), pSrcMesh->GetFVF(), g_pDevice, &pContainer->MeshData.pMesh); *ppNewMeshContainer = pContainer; return S_OK; }
void LODManager::Render(IDirect3DDevice9 *D3DDevice) { const char *meshpath = (lod == GRID_FARNEAR ? "landscape\\lod\\farnear\\" : (lod == GRID_FARFAR ? "landscape\\lod\\farfar\\" : "landscape\\lod\\farinf\\")); const char *textpath = (lod == GRID_FARNEAR ? "landscapelod\\generated\\farnear\\" : (lod == GRID_FARFAR ? "landscapelod\\generated\\farfar\\" : "landscapelod\\generated\\farinf\\")); int nativeminx = (GRID_SIZE * 32) + (Constants.Coordinates.x - GridDistantCount.Get()); int nativeminy = (GRID_SIZE * 32) + (Constants.Coordinates.y - GridDistantCount.Get()); int nativemaxx = (GRID_SIZE * 32) + (Constants.Coordinates.x + GridDistantCount.Get()); int nativemaxy = (GRID_SIZE * 32) + (Constants.Coordinates.y + GridDistantCount.Get()); /* y-axis has flipped rounding */ nativeminx = (nativeminx / 32) - GRID_SIZE; nativeminy = (nativeminy / 32) - GRID_SIZE + 0; nativemaxx = (nativemaxx / 32) - GRID_SIZE; nativemaxy = (nativemaxy / 32) - GRID_SIZE + 0; int gridx = Constants.Coordinates.x / 32; int gridy = Constants.Coordinates.y / 32; for (int x = (gridx - extend); x <= (gridx + extend); x++) for (int y = (gridy - extend); y <= (gridy + extend); y++) { /* TODO: try radius, seems it's not a box */ /* leave out Oblivion's native tiles */ if ((x >= nativeminx) && (x <= nativemaxx) && (y >= nativeminy) && (y <= nativemaxy)) continue; /* leave out other LOD's inner tiles */ if ((abs(gridx - x) <= inner) && (abs(gridy - y) <= inner)) continue; /* where are we? */ const float TileOffset[4] = {x * TILE_DIM, y * TILE_DIM, 0, 0}; /* filter outside-array coordinates */ if (((GRID_OFFSET + y) >= 0) && ((GRID_OFFSET + y) < GRID_SIZE) && ((GRID_OFFSET + x) >= 0) && ((GRID_OFFSET + x) < GRID_SIZE)) { /* never seen, never attempted */ if (MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) { /* TODO: 32 means 32x32 cells, in theory that can be different as well */ char buf[256]; sprintf(buf, "%02d.%02d.%02d.32", WorldSpace, x * 32, y * 32); char pth[256]; strcpy(pth, meshpath); strcat(pth, buf); strcat(pth, ".x"); /* no textures without mesh, but we can render texture-free */ if ((MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = MeshManager::GetSingleton()->LoadPrivateMesh(pth, MR_REGULAR)) != -1) { if (ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) { strcpy(pth, textpath); strcat(pth, buf); strcat(pth, ".dds"); ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->LoadPrivateTexture(pth, TR_PLANAR); } if (NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] < -1) { strcpy(pth, textpath); strcat(pth, buf); strcat(pth, "_fn.dds"); NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->LoadPrivateTexture(pth, TR_PLANAR); } /* put the addresses */ ManagedMeshRecord *mesh = Meshes [lod][GRID_OFFSET + y][GRID_OFFSET + x] = MeshManager::GetSingleton()->GetMesh (MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]); ManagedTextureRecord *colr = Colors [lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->GetTexture(ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]); ManagedTextureRecord *norm = Normals[lod][GRID_OFFSET + y][GRID_OFFSET + x] = TextureManager::GetSingleton()->GetTexture(NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x]); /* failure to load all resources */ if (!mesh || !colr || !norm) { if (mesh) mesh->Release(); if (colr) colr->Release(); if (norm) norm->Release(); MeshIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1; ColrIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1; NormIDs[lod][GRID_OFFSET + y][GRID_OFFSET + x] = -1; continue; } #if defined(OBGE_GAMMACORRECTION) /* remember DeGamma for this kind of texture */ static const bool PotDeGamma = true; colr->GetTexture()->SetPrivateData(GammaGUID, &PotDeGamma, sizeof(PotDeGamma), 0); #endif } } /* get the addresses */ ManagedMeshRecord *mesh = Meshes [lod][GRID_OFFSET + y][GRID_OFFSET + x]; ManagedTextureRecord *colr = Colors [lod][GRID_OFFSET + y][GRID_OFFSET + x]; ManagedTextureRecord *norm = Normals[lod][GRID_OFFSET + y][GRID_OFFSET + x]; ID3DXMesh *m; if (mesh && (m = (ID3DXMesh *)mesh->GetMesh())) { #if 0 DWORD FVF = m->GetFVF(); DWORD size = m->GetNumBytesPerVertex(); DWORD numf = m->GetNumFaces(); DWORD numv = m->GetNumVertices(); IDirect3DIndexBuffer9 *pIB; m->GetIndexBuffer(&pIB); IDirect3DVertexBuffer9 *pVB; m->GetVertexBuffer(&pVB); D3DDevice->SetStreamSource(0, pVB, 0, size); D3DDevice->SetFVF(FVF); D3DDevice->SetTexture(0, colr->GetTexture()); D3DDevice->SetTexture(1, norm->GetTexture()); D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numv, 0, numf); #endif D3DDevice->SetTexture(0, colr ? colr->GetTexture() : NULL); D3DDevice->SetTexture(1, norm ? norm->GetTexture() : NULL); D3DDevice->SetVertexShader(vShader[lod]); D3DDevice->SetPixelShader (pShader[lod]); D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1); m->DrawSubset(0); } } /* water-planes */ D3DDevice->SetVertexShader(vShaderW); D3DDevice->SetPixelShader (pShaderW); D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1); D3DDevice->SetStreamSource(0, WaterVertex, 0, sizeof(WaterTile)); D3DDevice->SetFVF(WATERTILEFORMAT); D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } const float TileOffset[4] = {0, 0, 0, 1}; /* infini-plane */ D3DDevice->SetVertexShader(vShaderW); D3DDevice->SetPixelShader (pShaderW); D3DDevice->SetVertexShaderConstantF(32, TileOffset, 1); D3DDevice->SetStreamSource(0, InfiniteVertex, 0, sizeof(WaterTile)); D3DDevice->SetFVF(WATERTILEFORMAT); D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); }
VCNNode* D3DConverter::ConvertMesh(const std::wstring& name, LPD3DXMESHCONTAINER baseMeshContainer, D3DXFRAME* frameRoot, ID3DXAnimationController* animController, LPDIRECT3DDEVICE9 device) { MultiAnimMC* meshContainer = static_cast<MultiAnimMC*>(baseMeshContainer); ID3DXMesh* systemMesh = meshContainer->MeshData.pMesh; // Load vertex caches // DWORD meshFVF = systemMesh->GetFVF(); size_t vertexCount = systemMesh->GetNumVertices(); const DWORD stride = D3DXGetFVFVertexSize( meshFVF ); const DWORD normalStride = D3DXGetFVFVertexSize( D3DFVF_NORMAL ); const DWORD diffuseStride = D3DXGetFVFVertexSize( D3DFVF_DIFFUSE ); const DWORD textureStride = D3DXGetFVFVertexSize( D3DFVF_TEX1 ); std::vector<VCNFloat> vtPositionBuffer( vertexCount * kCacheStrides[VT_POSITION] ); std::vector<VCNFloat> vtBlendWeights( vertexCount * kCacheStrides[VT_BLENDWEIGHTS] ); //TODO Verify the size of this shit std::vector<DWORD> vtBlendIndices( vertexCount * kCacheStrides[VT_BLENDINDICES] ); //TODO Verify the size of this shit std::vector<VCNFloat> vtNormalBuffer( vertexCount * kCacheStrides[VT_LIGHTING] ); std::vector<VCNFloat> vtTextureBuffer( vertexCount * kCacheStrides[VT_DIFFUSE_TEX_COORDS] ); VCNFloat* vtPositionBuf = &vtPositionBuffer[0]; VCNFloat* vtBlendWeightBuf = &vtBlendWeights[0]; DWORD* vtBlendIndicesBuf = &vtBlendIndices[0]; VCNFloat* vtNormalBuf = &vtNormalBuffer[0]; VCNFloat* vtTextureBuf = &vtTextureBuffer[0]; BYTE* vbptr = NULL; BYTE* vblineptr = NULL; systemMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&vblineptr); DWORD positionBlendAndIndicesStride = GetPositionStride(meshFVF); for(VCNUInt i = 0; i < vertexCount; ++i) { vbptr = vblineptr; if ( ContainsPositionInformation(meshFVF) ) { // Read position float* posData = (float*)vbptr; *vtPositionBuf = posData[0]; vtPositionBuf++; *vtPositionBuf = posData[1]; vtPositionBuf++; *vtPositionBuf = posData[2]; vtPositionBuf++; if (ContainsBlending(meshFVF)) { // Get blend weights size_t blendCount = (positionBlendAndIndicesStride / 4) - 3 - 1; // -3 to remove xyz, -1 to remove indices which come after for(size_t i = 0; i < blendCount; ++i) { *vtBlendWeightBuf = posData[3 + i]; vtBlendWeightBuf++; } vtBlendWeightBuf += 4 - blendCount; //each item is an array of 4 floats // Get blend indices // TODO SKIN Check the format we have to send this data as. if ( ContainsFlag(meshFVF, D3DFVF_LASTBETA_UBYTE4) ) { *vtBlendIndicesBuf = ((DWORD*)vbptr)[3 + blendCount]; vtBlendIndicesBuf++; } } vbptr += positionBlendAndIndicesStride; } else { VCN_ASSERT_FAIL( VCNTXT("Mesh FVF not supported (no vertex position) [FVF = %d, stride = %d]"), meshFVF, stride ); } // Read normal if ( ContainsFlag(meshFVF, D3DFVF_NORMAL) ) { D3DXVECTOR3* normal = (D3DXVECTOR3*)(vbptr); *vtNormalBuf = normal->x; vtNormalBuf++; *vtNormalBuf = normal->y; vtNormalBuf++; *vtNormalBuf = normal->z; vtNormalBuf++; // Set default diffuse color std::fill(vtNormalBuf, vtNormalBuf+3, 1.0f); vtNormalBuf += 3; vbptr += normalStride; } else { VCN_ASSERT_FAIL( VCNTXT("Mesh FVF not supported (no normals) [FVF = %d, stride = %d]"), meshFVF, stride ); } if ( ContainsFlag(meshFVF, D3DFVF_DIFFUSE) ) vbptr += diffuseStride; // Read texcoords // the check with D3DFVF_TEX0 is pretty useless as it's always true... the flag value is 0... if ( ContainsFlag(meshFVF, D3DFVF_TEX0) || ContainsFlag(meshFVF, D3DFVF_TEX1) ) { float* texCoords = (float*)(vbptr); *vtTextureBuf = texCoords[0]; vtTextureBuf++; *vtTextureBuf = texCoords[1]; vtTextureBuf++; vbptr += textureStride; } else { VCN_ASSERT_FAIL( VCNTXT("Mesh FVF not supported (no texture coordinates) [FVF = %d, stride = %d]"), meshFVF, stride ); } vblineptr += stride; } systemMesh->UnlockVertexBuffer(); VCND3D9* renderer = VCNRenderCore::GetInstance()->Cast<VCND3D9>(); // Generate cache resources that will be bind to Vicuna's meshes VCNResID positionCache = renderer->CreateCache(VT_POSITION, &vtPositionBuffer[0], vertexCount * kCacheStrides[VT_POSITION]); VCNResID lightingCache = renderer->CreateCache(VT_LIGHTING, &vtNormalBuffer[0], vertexCount * kCacheStrides[VT_LIGHTING]); VCNResID textureCache = renderer->CreateCache(VT_DIFFUSE_TEX_COORDS, &vtTextureBuffer[0], vertexCount * kCacheStrides[VT_DIFFUSE_TEX_COORDS]); VCNResID blendWeightCache = renderer->CreateCache(VT_BLENDWEIGHTS, &vtBlendWeights[0], vertexCount * kCacheStrides[VT_BLENDWEIGHTS]); VCNResID blendIndiceCache = renderer->CreateCache(VT_BLENDINDICES, &vtBlendIndices[0], vertexCount * kCacheStrides[VT_BLENDINDICES]); // Get model faces // VCNUShort* ibptr = 0; std::vector<VCNUShort> indices( systemMesh->GetNumFaces() * 3 ); systemMesh->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&ibptr); for(VCNUInt i = 0; i < systemMesh->GetNumFaces(); i++) { indices[(i * 3) + 0] = *(ibptr++); indices[(i * 3) + 1] = *(ibptr++); indices[(i * 3) + 2] = *(ibptr++); } systemMesh->UnlockIndexBuffer(); // Load materials // std::vector<VCNResID> materialIDS; D3DXMATERIAL* d3dxMaterials = meshContainer->pMaterials; for (DWORD i = 0; i < meshContainer->NumMaterials; ++i) { VCNResID materialID = kInvalidResID; // Create the texture if it exists - it may not if ( d3dxMaterials[i].pTextureFilename ) { VCNResID textureID = kInvalidResID; VCNString texturePath = VCNTXT("Textures/"); texturePath += VCN_A2W(d3dxMaterials[i].pTextureFilename); // Check if the texture is already loaded VCND3D9Texture* resTexture = VCNResourceCore::GetInstance()->GetResource<VCND3D9Texture>(texturePath); if ( !resTexture ) { textureID = VCNMaterialCore::GetInstance()->CreateTexture(texturePath); VCN_ASSERT_MSG( textureID != kInvalidResID, VCNTXT("Can't load texture %s"), texturePath.c_str() ); } else { textureID = resTexture->GetResourceID(); } VCNMaterial* material = new VCNMaterial(); const VCNString materialName = StringBuilder() << name << VCNTXT("_material_") << i; material->SetName( materialName ); VCNColor ambient = VCNColor((const VCNFloat*)&d3dxMaterials[i].MatD3D.Ambient); ambient.a = 1.0f; ambient += VCNColor(0.5f, 0.5f, 0.5f, 0); material->SetAmbientColor( ambient ); material->SetDiffuseColor( VCNColor((const VCNFloat*)&d3dxMaterials[i].MatD3D.Diffuse) ); material->SetSpecularColor( VCNColor((const VCNFloat*)&d3dxMaterials[i].MatD3D.Specular) ); material->SetSpecularPower( d3dxMaterials[i].MatD3D.Power ); VCNEffectParamSet& params = material->GetEffectParamSet(); params.SetEffectID( eidSkinned ); params.AddResource( VCNTXT("DiffuseTexture"), textureID ); // Add material as a resource. materialID = VCNResourceCore::GetInstance()->AddResource( material->GetName(), material ); } materialIDS.push_back( materialID ); } // Get the model attribute table with which we will instantiate has many mesh. // DWORD attribTableSize; std::vector<D3DXATTRIBUTERANGE> attribTable; HRESULT hr = systemMesh->GetAttributeTable( 0, &attribTableSize ); if ( FAILED(hr) ) return 0; attribTable.resize( attribTableSize ); hr = systemMesh->GetAttributeTable( &attribTable[0], &attribTableSize ); if ( FAILED(hr) ) return 0; // Set the root node VCNNode* rootNode = attribTableSize > 1 ? VCNNodeCore::GetInstance()->CreateNode<VCNNode>() : VCNNodeCore::GetInstance()->CreateNode<VCNRenderNode>(); rootNode->SetTag( StringBuilder() << name << VCNTXT("_Root") ); // For each attribute, we get the material texture for (DWORD i = 0; i < attribTableSize; ++i) { VCNRenderNode* partNode = attribTableSize == 1 ? safe_pointer_cast<VCNRenderNode*>( rootNode ) : VCNNodeCore::GetInstance()->CreateNode<VCNRenderNode>(); const VCNString partNodeName = StringBuilder() << name << VCNTXT("_Part_") << i; partNode->SetTag( partNodeName ); VCNMesh* partMesh = new VCNMesh(); partMesh->SetCacheID(VT_POSITION, positionCache); //SKIN do this for blend weights and blend indices partMesh->SetCacheID(VT_LIGHTING, lightingCache); partMesh->SetCacheID(VT_DIFFUSE_TEX_COORDS, textureCache); partMesh->SetCacheID(VT_BLENDWEIGHTS, blendWeightCache); partMesh->SetCacheID(VT_BLENDINDICES, blendIndiceCache); partMesh->SetPrimitiveType(PT_TRIANGLELIST); partMesh->SetBoneInfluenceCount( meshContainer->m_dwMaxNumFaceInfls ); size_t numBones = meshContainer->pSkinInfo == nullptr ? 0 : meshContainer->pSkinInfo->GetNumBones(); if (numBones > 0) { auto offsets = std::vector<Matrix4>(numBones); std::transform( std::begin(meshContainer->m_amxBoneOffsets), std::end(meshContainer->m_amxBoneOffsets), std::begin(offsets), [](const D3DXMATRIX& mat) { return Matrix4( (VCNFloat*)mat.m ); }); partMesh->SetBoneOffsets( std::move(offsets) ); LPD3DXBONECOMBINATION boneCombination = reinterpret_cast<LPD3DXBONECOMBINATION>( meshContainer->m_pBufBoneCombos->GetBufferPointer() ); size_t numPaletteEntries = meshContainer->m_dwNumPaletteEntries; std::vector<size_t> matriceIndexes; for(size_t paletteIndex = 0; paletteIndex < numPaletteEntries; ++paletteIndex) { size_t matIndex = boneCombination[i].BoneId[paletteIndex]; if ( matIndex == std::numeric_limits<size_t>::max()) continue; matriceIndexes.push_back(matIndex); } partMesh->SetMatrixPaletteIndexes(matriceIndexes); } const DWORD partFaceCount = attribTable[i].FaceCount; const void* partFaceBufferStart = &indices[attribTable[i].FaceStart * 3]; const VCNResID indexCacheID = renderer->CreateCache(VT_INDEX, partFaceBufferStart, partFaceCount * 3 * kCacheStrides[VT_INDEX]); partMesh->SetFaceCount( attribTable[i].FaceCount ); partMesh->SetFaceCache( indexCacheID ); // Compute bounding sphere float radius; D3DXVECTOR3 center; D3DXComputeBoundingSphere( (D3DXVECTOR3*)(&vtPositionBuffer[0] + attribTable[i].VertexStart * 3), attribTable[i].VertexCount, stride, ¢er, &radius ); VCNSphere modelBoundSphere( radius, V2V<Vector3>(center) ); partMesh->SetBoundingSphere( modelBoundSphere ); // Add mesh resource const VCNString partMeshName = StringBuilder() << name << VCNTXT("_part_") << i; const VCNResID partMeshID = VCNResourceCore::GetInstance()->AddResource( partMeshName, partMesh ); // Set model part node attributes partNode->SetMeshID( partMeshID ); if (animController && numBones > 0) { partNode->AddComponent( new VCND3DAnimator(partMeshID, animController, frameRoot, meshContainer->m_apmxBonePointers) ); } size_t index = attribTable[i].AttribId; index = index >= materialIDS.size() ? materialIDS.size() - 1 : index; partNode->SetMaterialID( materialIDS[index] ); // Add children to root if ( attribTableSize > 1 ) { rootNode->AttachChild( partNode->GetNodeID() ); } } return rootNode; }
BOOL RenderPick::Init(UINT width, UINT height, HWND hwnd, BOOL windowed, D3DDEVTYPE devType) { HRESULT hr = Render::Init(width, height, hwnd, windowed, devType); SGL_FAILED_DO(hr, MYTRACE_DX("Render::Init", hr); return FALSE); // Create the teapot. ID3DXMesh* teapot; D3DXCreateTeapot(m_D3DDev, &teapot, NULL); m_Teapot.Attach(teapot); // Compute the bounding sphere. BYTE* v = 0; teapot->LockVertexBuffer(0, (void**) &v); D3DXComputeBoundingSphere((D3DXVECTOR3*) v, teapot->GetNumVertices(), D3DXGetFVFVertexSize(teapot->GetFVF()), &m_BSphere.center, &m_BSphere.radius); teapot->UnlockVertexBuffer(); // Build a sphere mesh that describes the teapot's bounding sphere. ID3DXMesh* sphere; D3DXCreateSphere(m_D3DDev, m_BSphere.radius, 20, 20, &sphere, NULL); m_Sphere.Attach(sphere); // Set light. D3DXVECTOR3 dir(0.707f, -0.0f, 0.707f); D3DXCOLOR clr(1.0f, 1.0f, 1.0f, 1.0f); D3DLIGHT9 light; SGL::InitDirLight(&light, dir, clr); m_D3DDev->SetLight(0, &light); m_D3DDev->LightEnable(0, TRUE); m_D3DDev->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE); m_D3DDev->SetRenderState(D3DRS_SPECULARENABLE, FALSE); // Set view matrix. D3DXVECTOR3 pos(0.0f, 0.0f, -10.0f); D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &pos, &target, &up); m_D3DDev->SetTransform(D3DTS_VIEW, &V); // Set projection matrix. D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.25f, (float) width / (float) height, 1.0f, 1000.0f); m_D3DDev->SetTransform(D3DTS_PROJECTION, &proj); // Setup a basic scene. m_BasicScene.reset(new BasicScene(m_D3DDev)); if (!m_BasicScene->Init()) return FALSE; if (!InitFont()) return FALSE; return TRUE; }
bool CMeshBundle::loadMesh( const CResourceId& id, const CResourceId& fullName, CMesh& mesh ) const { // try to load with D3DX // obsolete case: .X files if( CStringHelper::endsWith( fullName.getUniqueName(), ".x" ) || CStringHelper::endsWith( fullName.getUniqueName(), ".X" ) ) { ID3DXBuffer* adjancency = NULL; ID3DXBuffer* material = NULL; ID3DXBuffer* effects = NULL; DWORD matCount; ID3DXMesh* dxmesh = NULL; HRESULT hres = D3DXLoadMeshFromX( fullName.getUniqueName().c_str(), D3DXMESH_SYSTEMMEM, &CD3DDevice::getInstance().getDevice(), &adjancency, &material, &effects, &matCount, &dxmesh ); if( !SUCCEEDED( hres ) ) return false; assert( dxmesh ); if( adjancency ) adjancency->Release(); if( material ) material->Release(); if( effects ) effects->Release(); // // init our mesh assert( !mesh.isCreated() ); // HACK - very limited int formatFlags = 0; DWORD dxFormat = dxmesh->GetFVF(); if( dxFormat & D3DFVF_XYZ ) formatFlags |= CVertexFormat::V_POSITION; if( dxFormat & D3DFVF_NORMAL ) formatFlags |= CVertexFormat::V_NORMAL; if( dxFormat & D3DFVF_TEX1 ) formatFlags |= CVertexFormat::V_UV0_2D; CVertexFormat vertFormat( formatFlags ); // HACK int indexStride = 2; CD3DVertexDecl* vertDecl = RGET_VDECL( CVertexDesc( vertFormat ) ); mesh.createResource( dxmesh->GetNumVertices(), dxmesh->GetNumFaces()*3, vertFormat, indexStride, *vertDecl, CMesh::BUF_STATIC ); // // now, copy data into our mesh void *dxvb, *dxib; dxmesh->LockVertexBuffer( 0, &dxvb ); dxmesh->LockIndexBuffer( 0, &dxib ); void* myvb = mesh.lockVBWrite(); void* myib = mesh.lockIBWrite(); memcpy( myvb, dxvb, mesh.getVertexCount() * mesh.getVertexStride() ); memcpy( myib, dxib, mesh.getIndexCount() * mesh.getIndexStride() ); dxmesh->UnlockVertexBuffer(); dxmesh->UnlockIndexBuffer(); mesh.unlockVBWrite(); mesh.unlockIBWrite(); // // create groups int ngroups; dxmesh->GetAttributeTable( 0, (DWORD*)&ngroups ); D3DXATTRIBUTERANGE *attrs = new D3DXATTRIBUTERANGE[ngroups]; dxmesh->GetAttributeTable( attrs, (DWORD*)&ngroups ); for( int i = 0; i < ngroups; ++i ) { const D3DXATTRIBUTERANGE& a = attrs[i]; mesh.addGroup( CMesh::CGroup( a.VertexStart, a.VertexCount, a.FaceStart, a.FaceCount ) ); } delete[] attrs; // release d3dx mesh dxmesh->Release(); } else { // our own format assert( !mesh.isCreated() ); bool ok = CMeshSerializer::loadMeshFromFile( fullName.getUniqueName().c_str(), mesh ); if( !ok ) return false; } mesh.computeAABBs(); CONSOLE.write( "mesh loaded '" + id.getUniqueName() + "'" ); return true; }