📄 d3dfile.cpp
字号:
//-----------------------------------------------------------------------------
// File: D3DFile.cpp
//
// Desc: Support code for loading DirectX .X files.
//
// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#define D3D_OVERLOADS
#include <stdio.h>
#include <tchar.h>
#include "D3DUtil.h"
#include "D3DMath.h"
#include "D3DTextr.h"
#include "dxfile.h"
#include "rmxfguid.h"
#include "rmxftmpl.h"
#include "D3DFile.h"
//-----------------------------------------------------------------------------
// Name: GetFace
// Desc: Get the nth face
//-----------------------------------------------------------------------------
DWORD* GetFace( DWORD* pFaceData, DWORD dwFace )
{
for( DWORD i=0; i<dwFace; i++ )
pFaceData += (*pFaceData) + 1;
return pFaceData;
}
//-----------------------------------------------------------------------------
// Name: GetNumIndices
// Desc: Get number of indices from face data
//-----------------------------------------------------------------------------
DWORD GetNumIndices( DWORD* pFaceData, DWORD dwNumFaces )
{
DWORD dwNumIndices = 0;
while( dwNumFaces-- > 0 )
{
dwNumIndices += (*pFaceData-2)*3;
pFaceData += *pFaceData + 1;
}
return dwNumIndices;
}
//-----------------------------------------------------------------------------
// Name: CD3DFileBaseObject()
// Desc:
//-----------------------------------------------------------------------------
CD3DFileObject::CD3DFileObject( TCHAR* strName )
{
m_pNext = NULL;
m_pChild = NULL;
m_strName[0] = 0;
m_bHasMeshData = FALSE;
if( strName )
lstrcpy( m_strName, strName );
// Set a default matrix
D3DUtil_SetIdentityMatrix( m_mat );
// Set a default material
D3DUtil_InitMaterial( m_Material[0].m_mtrl, 1.0f, 1.0f, 1.0f );
ZeroMemory( m_Material, sizeof(m_Material) );
m_dwNumMaterials = 0;
m_bHasAlpha = FALSE;
// Clear out vertex data
m_dwNumVertices = 0L;
m_pVertices = NULL;
m_dwNumIndices = 0L;
m_pIndices = NULL;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CD3DFileObject::~CD3DFileObject()
{
SAFE_DELETE( m_pChild );
SAFE_DELETE( m_pNext );
for( DWORD i=0; i<m_dwNumMaterials; i++ )
D3DTextr_DestroyTexture( m_Material[i].m_strTexture );
SAFE_DELETE( m_pVertices );
SAFE_DELETE( m_pIndices );
}
//-----------------------------------------------------------------------------
// Name: SetMeshGeometry()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DFileObject::SetMeshGeometry( D3DVECTOR* pVertexData,
DWORD dwNumVertices, DWORD* pFaceData,
DWORD dwNumFaces )
{
// Set up vertices
m_dwNumVertices = dwNumVertices;
m_pVertices = new D3DVERTEX[m_dwNumVertices];
if( NULL == m_pVertices )
return E_FAIL;
for( DWORD i=0; i< m_dwNumVertices; i++ )
{
ZeroMemory( &m_pVertices[i], sizeof(D3DVERTEX) );
m_pVertices[i].x = pVertexData[i].x;
m_pVertices[i].y = pVertexData[i].y;
m_pVertices[i].z = pVertexData[i].z;
}
// Count the number of indices (converting n-sided faces to triangles)
m_dwNumIndices = GetNumIndices( pFaceData, dwNumFaces );
// Allocate memory for the indices, you must call AddFace() to set the vertices
m_pIndices = new WORD[m_dwNumIndices];
if( NULL == m_pIndices )
return E_FAIL;
m_bHasMeshData = TRUE;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
VOID CD3DFileObject::AddChild( CD3DFileObject* pChild )
{
if( m_pChild )
m_pChild->AddNext( pChild );
else
m_pChild = pChild;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
VOID CD3DFileObject::AddNext( CD3DFileObject* pNext )
{
if( m_pNext )
m_pNext->AddNext( pNext );
else
m_pNext = pNext;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
VOID CD3DFileObject::Render( LPDIRECT3DDEVICE7 pd3dDevice, BOOL bAlpha )
{
if( m_bHasMeshData )
{
// Render the mesh
WORD* pIndices = m_pIndices;
for( DWORD i=0; i <= m_dwNumMaterials; i++ )
{
// Skip materials with no references
if( 0L == m_Material[i].m_dwNumIndices )
continue;
// Render opaque and transparent meshes during separate passes
if( bAlpha == m_bHasAlpha )
{
TCHAR* strTexture = m_Material[i].m_strTexture;
DWORD dwNumIndices = m_Material[i].m_dwNumIndices;
if( strTexture[0] )
pd3dDevice->SetTexture( 0, D3DTextr_GetSurface( strTexture ) );
pd3dDevice->SetMaterial( &m_Material[i].m_mtrl );
pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX,
m_pVertices, m_dwNumVertices,
pIndices, dwNumIndices, NULL );
}
pIndices += m_Material[i].m_dwNumIndices;
}
}
else
{
if( m_pChild )
{
// Save the old matrix sate
D3DMATRIX matWorldOld, matWorldNew;
pd3dDevice->GetTransform( D3DTRANSFORMSTATE_WORLD, &matWorldOld );
// Concat the frame matrix with the current world matrix
matWorldNew = m_mat * matWorldOld;
pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorldNew );
// Render the child nodes
m_pChild->Render( pd3dDevice, bAlpha );
// Restore the old matrix state
pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorldOld );
}
}
// Render the remaining sibling nodes
if( m_pNext )
m_pNext->Render( pd3dDevice, bAlpha );
}
//-----------------------------------------------------------------------------
// Name: SetMaterialData()
// Desc: Sets the material structure for the mesh
//-----------------------------------------------------------------------------
VOID CD3DFileObject::SetMaterialData( DWORD dwMaterial, D3DMATERIAL7* pmtrl,
TCHAR* strName )
{
if( dwMaterial < MAX_MATERIAL )
{
m_Material[dwMaterial].m_mtrl = *pmtrl;
lstrcpyn( m_Material[dwMaterial].m_strTexture, strName, MAX_TEXTURE_NAME );
if( pmtrl->diffuse.a < 1.0f )
m_bHasAlpha = TRUE;
}
}
//-----------------------------------------------------------------------------
// Name: AddFace()
// Desc: Adds one or more faces to a material slot in a Mesh. Note: this must
// be called in order (material 0 first, then 1, ...)
//-----------------------------------------------------------------------------
VOID CD3DFileObject::AddFace( DWORD dwMaterial, DWORD* pFaceData,
DWORD dwNumFaces )
{
// Make sure dwMaterial is in range
if( dwMaterial >= MAX_MATERIAL)
return;
// Update the material count
if( m_dwNumMaterials < dwMaterial+1 )
m_dwNumMaterials = dwMaterial+1;
// add indices to the end
WORD* pIndices = m_pIndices;
for( DWORD i=0; i<=dwMaterial; i++ )
pIndices += m_Material[i].m_dwNumIndices;
// Assign the indices (build a triangle fan for high-order polygons)
while( dwNumFaces-- )
{
DWORD dwNumVerticesPerFace = *pFaceData++;
for( DWORD i=2; i<dwNumVerticesPerFace; i++ )
{
m_Material[dwMaterial].m_dwNumIndices += 3;
*pIndices++ = (WORD)pFaceData[0];
*pIndices++ = (WORD)pFaceData[i-1];
*pIndices++ = (WORD)pFaceData[i];
}
pFaceData += dwNumVerticesPerFace;
}
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DFileObject::GetMeshGeometry( D3DVERTEX** ppVertices, DWORD* pdwNumVertices,
WORD** ppIndices, DWORD* pdwNumIndices )
{
if( ppVertices ) *ppVertices = m_pVertices;
if( pdwNumVertices ) *pdwNumVertices = m_dwNumVertices;
if( ppIndices ) *ppIndices = m_pIndices;
if( pdwNumIndices ) *pdwNumIndices = m_dwNumIndices;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DFileObject::ComputeNormals()
{
D3DVECTOR* pNormals = new D3DVECTOR[m_dwNumVertices];
ZeroMemory( pNormals, sizeof(D3DVECTOR)*m_dwNumVertices );
for( DWORD i=0; i<m_dwNumIndices; i+=3 )
{
WORD a = m_pIndices[i+0];
WORD b = m_pIndices[i+1];
WORD c = m_pIndices[i+2];
D3DVECTOR* v1 = (D3DVECTOR*)&m_pVertices[a];
D3DVECTOR* v2 = (D3DVECTOR*)&m_pVertices[b];
D3DVECTOR* v3 = (D3DVECTOR*)&m_pVertices[c];
D3DVECTOR n = Normalize( CrossProduct( *v2-*v1, *v3-*v2 ) );
pNormals[a] += n;
pNormals[b] += n;
pNormals[c] += n;
}
// Assign the newly computed normals back to the vertices
for( i=0; i<m_dwNumVertices; i++ )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -