📄 meshloader.cpp
字号:
WCHAR strName[MAX_PATH] = {0};
InFile >> strName;
bool bFound = false;
for( int iMaterial=0; iMaterial < m_Materials.GetSize(); iMaterial++ )
{
Material* pCurMaterial = m_Materials.GetAt( iMaterial );
if( 0 == wcscmp( pCurMaterial->strName, strName ) )
{
bFound = true;
dwCurSubset = iMaterial;
break;
}
}
if( !bFound )
{
pMaterial = new Material();
if( pMaterial == NULL )
return E_OUTOFMEMORY;
dwCurSubset = m_Materials.GetSize();
InitMaterial( pMaterial );
StringCchCopy( pMaterial->strName, MAX_PATH-1, strName );
m_Materials.Add( pMaterial );
}
}
else
{
// Unimplemented or unrecognized command
}
InFile.ignore( 1000, '\n' );
}
// Cleanup
InFile.close();
DeleteCache();
// If an associated material file was found, read that in as well.
if( strMaterialFilename[0] )
{
V_RETURN( LoadMaterialsFromMTL( strMaterialFilename ) );
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc:
//-----------------------------------------------------------------------------
DWORD CMeshLoader::AddVertex( UINT hash, VERTEX* pVertex )
{
// If this vertex doesn't already exist in the Vertices list, create a new entry.
// Add the index of the vertex to the Indices list.
bool bFoundInList = false;
DWORD index = 0;
// Since it's very slow to check every element in the vertex list, a hashtable stores
// vertex indices according to the vertex position's index as reported by the OBJ file
if( (UINT)m_VertexCache.GetSize() > hash )
{
CacheEntry* pEntry = m_VertexCache.GetAt( hash );
while( pEntry != NULL )
{
VERTEX* pCacheVertex = m_Vertices.GetData() + pEntry->index;
// If this vertex is identical to the vertex already in the list, simply
// point the index buffer to the existing vertex
if( 0 == memcmp( pVertex, pCacheVertex, sizeof(VERTEX) ) )
{
bFoundInList = true;
index = pEntry->index;
break;
}
pEntry = pEntry->pNext;
}
}
// Vertex was not found in the list. Create a new entry, both within the Vertices list
// and also within the hashtable cache
if( !bFoundInList )
{
// Add to the Vertices list
index = m_Vertices.GetSize();
m_Vertices.Add( *pVertex );
// Add this to the hashtable
CacheEntry* pNewEntry = new CacheEntry;
if( pNewEntry == NULL )
return E_OUTOFMEMORY;
pNewEntry->index = index;
pNewEntry->pNext = NULL;
// Grow the cache if needed
while( (UINT)m_VertexCache.GetSize() <= hash )
{
m_VertexCache.Add( NULL );
}
// Add to the end of the linked list
CacheEntry* pCurEntry = m_VertexCache.GetAt( hash );
if( pCurEntry == NULL )
{
// This is the head element
m_VertexCache.SetAt( hash, pNewEntry );
}
else
{
// Find the tail
while( pCurEntry->pNext != NULL )
{
pCurEntry = pCurEntry->pNext;
}
pCurEntry->pNext = pNewEntry;
}
}
return index;
}
//-----------------------------------------------------------------------------
// Desc:
//-----------------------------------------------------------------------------
void CMeshLoader::DeleteCache()
{
// Iterate through all the elements in the cache and subsequent linked lists
for( int i=0; i < m_VertexCache.GetSize(); i++ )
{
CacheEntry* pEntry = m_VertexCache.GetAt( i );
while( pEntry != NULL )
{
CacheEntry* pNext = pEntry->pNext;
SAFE_DELETE( pEntry );
pEntry = pNext;
}
}
m_VertexCache.RemoveAll();
}
//-----------------------------------------------------------------------------
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMeshLoader::LoadMaterialsFromMTL( const WCHAR* strFileName )
{
HRESULT hr;
// Set the current directory based on where the mesh was found
WCHAR wstrOldDir[MAX_PATH] = {0};
GetCurrentDirectory( MAX_PATH, wstrOldDir );
SetCurrentDirectory( m_strMediaDir );
// Find the file
WCHAR strPath[MAX_PATH];
char cstrPath[MAX_PATH];
V_RETURN( DXUTFindDXSDKMediaFileCch( strPath, MAX_PATH, strFileName ) );
WideCharToMultiByte( CP_ACP, 0, strPath, -1, cstrPath, MAX_PATH, NULL, NULL );
// File input
WCHAR strCommand[256] = {0};
wifstream InFile( cstrPath );
if( !InFile )
return DXTRACE_ERR( L"wifstream::open", E_FAIL );
// Restore the original current directory
SetCurrentDirectory( wstrOldDir );
Material* pMaterial = NULL;
for(;;)
{
InFile >> strCommand;
if( !InFile )
break;
if( 0 == wcscmp( strCommand, L"newmtl" ) )
{
// Switching active materials
WCHAR strName[MAX_PATH] = {0};
InFile >> strName;
pMaterial = NULL;
for( int i=0; i < m_Materials.GetSize(); i++ )
{
Material* pCurMaterial = m_Materials.GetAt( i );
if( 0 == wcscmp( pCurMaterial->strName, strName ) )
{
pMaterial = pCurMaterial;
break;
}
}
}
// The rest of the commands rely on an active material
if( pMaterial == NULL )
continue;
if( 0 == wcscmp( strCommand, L"#" ) )
{
// Comment
}
else if( 0 == wcscmp( strCommand, L"Ka" ) )
{
// Ambient color
float r, g, b;
InFile >> r >> g >> b;
pMaterial->vAmbient = D3DXVECTOR3(r, g, b);
}
else if( 0 == wcscmp( strCommand, L"Kd" ) )
{
// Diffuse color
float r, g, b;
InFile >> r >> g >> b;
pMaterial->vDiffuse = D3DXVECTOR3(r, g, b);
}
else if( 0 == wcscmp( strCommand, L"Ks" ) )
{
// Specular color
float r, g, b;
InFile >> r >> g >> b;
pMaterial->vSpecular = D3DXVECTOR3(r, g, b);
}
else if( 0 == wcscmp( strCommand, L"d" ) ||
0 == wcscmp( strCommand, L"Tr" ) )
{
// Alpha
InFile >> pMaterial->fAlpha;
}
else if( 0 == wcscmp( strCommand, L"Ns" ) )
{
// Shininess
int nShininess;
InFile >> nShininess;
pMaterial->nShininess = nShininess;
}
else if( 0 == wcscmp( strCommand, L"illum" ) )
{
// Specular on/off
int illumination;
InFile >> illumination;
pMaterial->bSpecular = (illumination == 2);
}
else if( 0 == wcscmp( strCommand, L"map_Kd" ) )
{
// Texture
InFile >> pMaterial->strTexture;
}
else
{
// Unimplemented or unrecognized command
}
InFile.ignore( 1000, L'\n' );
}
InFile.close();
return S_OK;
}
//-----------------------------------------------------------------------------
// Desc: 初始化材质
//-----------------------------------------------------------------------------
void CMeshLoader::InitMaterial( Material* pMaterial )
{
ZeroMemory( pMaterial, sizeof(Material) );
pMaterial->vAmbient = D3DXVECTOR3(0.2f, 0.2f, 0.2f);
pMaterial->vDiffuse = D3DXVECTOR3(0.8f, 0.8f, 0.8f);
pMaterial->vSpecular = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
pMaterial->nShininess = 0;
pMaterial->fAlpha = 1.0f;
pMaterial->bSpecular = false;
pMaterial->pTexture = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -