📄 main.cpp
字号:
//////////////////////////////////////////////////////////////////////////////////////////////
// In this tutorials we're going to cover loading in a standard d3d mesh. D3D supports the
// X-file file format which is actually highly customizable and very versatile. We're going
// to be loading in a standard mesh that comes with the DirectX SDK. Tiny.x - you know, that
// really ugly horribly dressed female that's in some of the samples? Anyway, so we're going
// to load her in and display her.
//
// It's very simple stuff. The D3DX library as usual, comes in very handy when dealing with
// meshes. First off, we'll use their mesh interface to store the mesh data - ID3DXMesh.
// Secondly, we'll use the D3DXLoadMeshFromX function which very easily loads in the xfile
// and stores the data in a ID3DXMesh interface.
//
// Meshes are divided into subsets. For example the head, legs, arms and body might all be
// different subsets of the same mesh. They would each have their own textures and their
// own materials. To render the mesh in its entirety, you'd go through all the subsets, set
// the material and texture for each subset, and the draw it's vertices out.
//
// That's about all we'll be doing in this tutorial, read through the comments in the code
// to better understand exactly what's happening and when it's happening. If you have any
// further questions you're always welcome at the forums: http://www.devmaster.net/forums/
//////////////////////////////////////////////////////////////////////////////////////////////
#include "Main.h"
//---------------------------------------------------------------------------------------------
// This function is used to initialize Tiny.x for rendering. It will load in the x file and
// the associated textures. Follow the comments in this function and you should be able to
// understand everything. It's quite simple.
//---------------------------------------------------------------------------------------------
bool CMain::InitializeTiny()
{
// We'll store the path to the DirectX SDK media folder in this buffer.
char tempPath[MAX_PATH];
// Use the DX utility function. I've included it in Utils.h
if( !DXUTGetDXSDKMediaPathCch( tempPath, MAX_PATH ) )
{
Error( "Couldn't locate media directory" );
return false;
}
// Add the Tiny folder to the media path.
std::string szPath = tempPath;
szPath += "Tiny\\";
// Now we have the path to the Tiny directory.
// nMaterials will hold how many subsets were loaded in
DWORD nMaterials = 0;
// The adjacecny buffer holds face adjacency info, and the material buffer
// holds the information for each subset
ID3DXBuffer *pAdjacency = 0, *pMaterials = 0;
// This will hold the absolute path to the tiny x file.
char pathToTiny[256] = {0};
strcpy( pathToTiny, szPath.c_str() );
strcat( pathToTiny, "Tiny.x" );
// To load in the mesh, we're going to use the D3DX mesh loading helper function. The
// LoadMeshFromX function collapses all meshes in an x file (if there are more then one)
// into one mesh. The first parameter is the path to the file, second is any options
// you want to specify. Don't need or care for any special treatment right now.
//
// Third param is a pointer to the d3d device. Then an adjacency buffer. The adjacency
// data contains an array of three DWORDs per face that specify the three neighbors for
// each face in the mesh. It just specifies which triangles neighbour each face in the
// mesh. This is used for various LOD techniques and mesh optimizations which we wont
// be getting into right now.
//
// Then its the material buffer. This will contain the meshes material information,
// including the textures the mesh uses and the properties of the faces (ie: diffuse
// specular, power - see D3DMATERIAL9 struct)
//
// After that it's a effect instance buffer which we wont be going anywhere near any
// time soon. Then the number of materials returned in our material buffer and finally
// a pointer to a mesh interface pointer that will be initialized with our mesh data.
if( FAILED( D3DXLoadMeshFromX( pathToTiny,
0,
m_pD3DDevice,
&pAdjacency,
&pMaterials,
NULL,
&nMaterials,
&m_pMesh ) ) )
{
return Error( "Failed to load tiny.x" );
}
// Now we dont need our adjacency info, so we'll release it. But we need the material buffer
// info so we need to extract that...
SAFE_RELEASE( pAdjacency );
// The material info is in disquise actually. We got an ID3DXBuffer object back from our
// previous function call. The material info is actually within this buffer. All we need to
// do to retrieve it, is get a pointer to the internal buffer data, and cast it to the
// appropriate type. In this case the appropriate type is the D3DXMATERIAL structure. This
// structure holds the D3DMATERIAL9 information, and it also stores the name of the texture
// that the material uses. Subsets and materials have a one to one relationship. For every
// material, there is one subset and one texture name.
D3DXMATERIAL* pXMats = (D3DXMATERIAL*)pMaterials->GetBufferPointer();
// Now cycle through all the created materials and retirieve the D3DMATERIAL9 structure
// and load in the corresponding texture. We know how many subsets/materials we have because
// the D3DXLoadMeshFromX function gave us back the info when we gave it the address of our
// nMaterials variable. So let's iterate...
for( DWORD i = 0; i < nMaterials; ++i )
{
IDirect3DTexture9* pTex = 0;
// Get the D3DMATERIAL9 structure out.
D3DMATERIAL9 mat9 = pXMats[i].MatD3D;
// Set the ambiant color of the material to the diffuse color.
mat9.Ambient = mat9.Diffuse;
// Create a buffer to store teh absolute path to the texture we need.
char pathToTinySkin[256] = {0};
// First add the path to the tiny directoy to it. This is the directory we loaded the
// xfile form. The texture name (or path) we got back in the pMaterials buffer is
// a relative path. It's relative to the xfile we just loaded.
strcpy( pathToTinySkin, szPath.c_str() );
strcat( pathToTinySkin, pXMats[i].pTextureFilename );
// Now load the texture in.
if( FAILED( D3DXCreateTextureFromFile( m_pD3DDevice, pathToTinySkin, &pTex ) ) )
{
return Error( "Failed to load in texture" );
}
// Add the material and the texture to our vector of stuff.
m_vMaterials.push_back( mat9 );
m_vTextures.push_back( pTex );
}
// We don't need the material buffer anymore, so we can release it.
SAFE_RELEASE( pMaterials );
return true;
}
bool CMain::Render()
{
// To render the mesh, there are actually multiple ways that can be done. We're going to do it
// the simplest way. That is we just call the ID3DXMesh::DrawSubset function which does all the
// work for us. We're going to render the mesh lit. So in the following code, I Turn lighting
// on and set up a light structure and enable it. I setup a little bit of ambient light
m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,23), 1.0f, 0);
m_pD3DDevice->BeginScene();
// Turn lighting on
m_pD3DDevice->SetRenderState( D3DRS_LIGHTING, 1 );
// Set some ambiant value
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0xff080808 );
// Set a directional light and turn it on
D3DLIGHT9 light;
ZeroMemory( &light, sizeof(D3DLIGHT9) );
light.Type = D3DLIGHT_DIRECTIONAL;
light.Direction.y = -1.0f;
light.Direction.x = 1.0f;
light.Direction.z = -1.0f;
light.Diffuse.a = light.Ambient.a = 0.5f;
light.Diffuse.r = light.Ambient.r = 0.5f;
light.Diffuse.g = light.Ambient.g = 0.5f;
light.Diffuse.b = light.Ambient.b = 0.5f;
m_pD3DDevice->SetLight( 0, &light );
m_pD3DDevice->LightEnable( 0, TRUE );
// Set world transformation. We need to rotate the model a bit, because if we use the
// identity matrix it will be rendered flat (as in lying down, not as in Tom & Jerry
// bang into wall flat).
D3DXMATRIX world;
D3DXMatrixRotationX( &world, -D3DX_PI / 2.0f );
m_pD3DDevice->SetTransform( D3DTS_WORLD, &world );
// Now iterate through all the materials/subsets. Set the appropriate material and set
// the appropriate texture and draw the subset.
for( DWORD i = 0; i < m_vMaterials.size(); ++i )
{
m_pD3DDevice->SetMaterial( &(m_vMaterials[i]) );
m_pD3DDevice->SetTexture( 0, m_vTextures[i] );
m_pMesh->DrawSubset( i );
}
// Show our stats.
RenderStats();
m_pD3DDevice->EndScene();
m_pD3DDevice->Present(NULL, NULL, NULL, NULL);
return true;
}
bool CMain::InvalidateObjects()
{
// Delete the mesh and cycle through all the textures in the vector and delete
// those as well. Dont forget to clear the vectors.
SAFE_RELEASE( m_pMesh );
for( DWORD i = 0; i < m_vTextures.size(); ++i )
{
SAFE_RELEASE( m_vTextures[i] );
}
m_vTextures.clear();
m_vMaterials.clear();
return true;
}
bool CMain::RestoreObjects()
{
// Load in tiny.
if( !InitializeTiny() )
{
Error( "Failed to initialize" );
return false;
}
// Move the camera a bit out into the screen
D3DXMATRIX view;
D3DXMatrixLookAtLH( &view,
&D3DXVECTOR3( 0, 0, 800 ),
&D3DXVECTOR3( 0, 0, 0 ),
&D3DXVECTOR3( 0, 1, 0 ) );
m_pD3DDevice->SetTransform( D3DTS_VIEW, &view );
return true;
}
CMain::CMain()
{
m_pMesh = 0;
}
CMain::~CMain()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// //
// A p p l i c a t i o n E n t r y P o i n t //
// //
/////////////////////////////////////////////////////////////////////////////////////////////////
CMain *g_pMain = NULL;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pstrCmdLine, int iShowCmd)
{
g_pMain = new CMain;
g_pMain->Run( hInst, true );
delete g_pMain;
return 0;
}
LRESULT WINAPI MainMessageProcedure(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
return g_pMain->MessageProcedure( hWnd, iMsg, wParam, lParam );
}
//////////////////////////////////////////////////////////////////////////////////////////////
// This file is copyright
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -