Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
//--------------------------------------------------------------------------------------
// 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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 7
0
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, &center, &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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}