⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 load .x file to application
💻 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 + -