Direct3D成长日记(05):简单几何模型绘制

来源:互联网 发布:淘宝装修在线生成 编辑:程序博客网 时间:2024/04/30 12:53

Direct3D成长日记(05):简单几何模型绘制

源程序:

//////////////////////////////////////////////////////////////////////////
//说明        :Direct3D成长日记(05):简单几何模型绘制。
//作者        :shenzi
//完成时间    :2009.05.07
//描述        :绘制简单的立体图形-正方体。可以通过鼠标进行控制几何体,鼠标按
//              下拖动鼠标,旋转几何体,松开鼠标停止。F1控制是否用索引顶点。
//////////////////////////////////////////////////////////////////////////

//包含头文件,相应库:
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#pragma comment(lib,"d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

//全局变量声明:
LPDIRECT3D9            g_pD3D = NULL;        //Direct3D接口指针
LPDIRECT3DDEVICE9    g_pD3DDevice = NULL;//Direct3D设备指针
LPDIRECT3DVERTEXBUFFER9        g_pVBuffer = NULL; //顶点缓存
LPDIRECT3DVERTEXBUFFER9        g_pVBuffer_Indexed = NULL;
LPDIRECT3DINDEXBUFFER9        g_pIndexBuffer = NULL;

#define WINDOW_CLASS_NAME    L"Direct3D"
#define WINDOW_NAME            L"Direct3DBasics Tutorial"

#define SCREEN_WIDTH    800
#define SCREEN_HEIGHT    600

bool g_bUseIndexedGeometry = true;

//鼠标移动控制的旋转
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;

//顶点结构
struct CUSTOMVERTEX
{
    FLOAT X, Y ,Z;
    DWORD COLOR;
};

#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

//函数声明:
HRESULT InitD3D( HWND);            //初始化Direct3D
void RenderFrame( void);        //场景渲染
void CleanD3D( void);            //释放资源
HRESULT InitGraphics(void);        //初始化图形
void SetupMatrices(void);        //模型视图投影矩阵设置

//WINDOWS 消息处理函数:
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM);

//WinMain函数:
int WINAPI WinMain( HINSTANCE hInstance,
                   HINSTANCE hprevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    //变量声明:
    HWND hwnd;
    MSG msg;
    WNDCLASSEX wc;

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    //创建窗口类
    wc.cbClsExtra        = 0;
    wc.cbSize            = sizeof(WNDCLASSEX);
    wc.cbWndExtra        = 0;
    wc.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.hCursor            = LoadCursor( NULL, IDC_ARROW);
    wc.hIcon            = LoadIcon( NULL, IDI_APPLICATION);
    wc.hInstance        = hInstance;
    wc.lpfnWndProc        = WndProc;
    wc.lpszClassName    = WINDOW_CLASS_NAME;
    wc.lpszMenuName        = NULL;
    wc.style            = CS_HREDRAW | CS_VREDRAW;

    //注册窗口类
    RegisterClassEx(&wc);

    //初始化窗口
    hwnd = CreateWindowEx(    NULL,
        WINDOW_CLASS_NAME,
        WINDOW_NAME,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        NULL, NULL, hInstance, NULL);

    //显示,更新窗口:
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    if (SUCCEEDED(InitD3D(hwnd)))
    {
        if (SUCCEEDED(InitGraphics()))
        {
            ZeroMemory(&msg, sizeof(MSG));

            //消息循环:
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    RenderFrame();
            }
        }
       
    }
   
    UnregisterClass( WINDOW_CLASS_NAME, wc.hInstance );
    return 0;

}

LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    static POINT ptLastMousePosit;
    static POINT ptCurrentMousePosit;
    static bool bMousing;
    switch( msg )
    {
    case WM_DESTROY:
        CleanD3D();
        PostQuitMessage( 0 );
        return 0;
    case WM_LBUTTONDOWN:
        {
            ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);
            ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);
            bMousing = true;
        }
        break;

    case WM_LBUTTONUP:
        {
            bMousing = false;
        }
        break;

    case WM_MOUSEMOVE:
        {
            ptCurrentMousePosit.x = LOWORD (lParam);
            ptCurrentMousePosit.y = HIWORD (lParam);

            if( bMousing )
            {
                g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
                g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
            }

            ptLastMousePosit.x = ptCurrentMousePosit.x;
            ptLastMousePosit.y = ptCurrentMousePosit.y;
        }
        break;
    case WM_KEYDOWN:
        switch (wParam)
        {
        case VK_F1:
            g_bUseIndexedGeometry = !g_bUseIndexedGeometry;
            break;
        }
        break;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

HRESULT InitD3D(HWND hwnd)
{
    //创建D3D对象:
    if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
    {
        return E_FAIL;
    }

    //定义窗口的显示信息:
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp));

    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hwnd;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.EnableAutoDepthStencil = TRUE;


    //创建D3D设备:
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,   
        D3DDEVTYPE_HAL,
        hwnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        &d3dpp,
        &g_pD3DDevice)))
    {
        return E_FAIL;
    }

    g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

    g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

    g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

    return S_OK;
}
void RenderFrame(void)
{
    if(NULL == g_pD3DDevice)
        return;
    //清空背景缓冲区:
    g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    if(SUCCEEDED(g_pD3DDevice->BeginScene()))
    {
        //渲染场景:
        //设置顶点结构:
        g_pD3DDevice->SetFVF(CUSTOMFVF);

        SetupMatrices();

        D3DXMATRIX matTrans;
        D3DXMATRIX matRot;
        D3DXMATRIX matWorld;

        D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, 5.0f );

        D3DXMatrixRotationYawPitchRoll( &matRot,
            D3DXToRadian(g_fSpinX),
            D3DXToRadian(g_fSpinY),
            0.0f );
        matWorld = matRot * matTrans;
        g_pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

        if( g_bUseIndexedGeometry == true )
        {
            g_pD3DDevice->SetStreamSource( 0, g_pVBuffer_Indexed, 0, sizeof(CUSTOMVERTEX) );
            g_pD3DDevice->SetIndices( g_pIndexBuffer );
            g_pD3DDevice->SetFVF( CUSTOMFVF );

            g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 8,  0, 2 );
            g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 8,  4, 2 );
            g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 8,  8, 2 );
            g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 8, 12, 2 );
            g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 8, 16, 2 );
            g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLESTRIP, 0, 0, 8, 20, 2 );
        }
        else
        {
            g_pD3DDevice->SetStreamSource( 0, g_pVBuffer, 0, sizeof(CUSTOMVERTEX) );
            g_pD3DDevice->SetFVF( CUSTOMFVF );

            g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,  0, 2 );
            g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,  4, 2 );
            g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,  8, 2 );
            g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 12, 2 );

            //利于观察按F1后,区别用索引顶点绘图。
            //g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 16, 2 );
            //g_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 20, 2 );
        }

        g_pD3DDevice->EndScene();
    }
    //把渲染的场景显示在窗口:
    g_pD3DDevice->Present(NULL, NULL, NULL, NULL);

}
void CleanD3D(void)
{
    //释放资源
    if (NULL != g_pVBuffer)
    {
        g_pVBuffer->Release();
    }
    if (NULL != g_pVBuffer_Indexed)
    {
        g_pVBuffer_Indexed->Release();
    }
    if (NULL !+ g_pIndexBuffer)
    {
        g_pIndexBuffer->Release();
    }
    if(NULL != g_pD3DDevice)
        g_pD3DDevice->Release();
    if(NULL != g_pD3D)
        g_pD3D->Release();

    g_pVBuffer = NULL;
    g_pVBuffer_Indexed = NULL;
    g_pIndexBuffer = NULL;
    g_pD3DDevice = NULL;
    g_pD3D = NULL;
}

HRESULT InitGraphics(void)
{
    //定义顶点数组
    CUSTOMVERTEX vertices[] =
    {
        // Quad 0
        {-1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 0 (unique)
        { 1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 ) }, // 1 (unique)
        {-1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 ) }, // 2 (unique)
        { 1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 ) }, // 3 (unique)

        // Quad 1
        {-1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 ) }, // 4 (unique)
        {-1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 ) }, // 5 (unique)
        { 1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 1.0, 1.0 ) }, // 6 (unique)
        { 1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 7 (unique)

        // Quad 2
        {-1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 ) }, // 4 (start repeating here)
        { 1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 1.0, 1.0 ) }, // 6 (repeat of vertex 6)
        {-1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 0 (repeat of vertex 0... etc.)
        { 1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 ) }, // 1

        // Quad 3
        {-1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 ) }, // 5
        {-1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 ) }, // 2
        { 1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 7
        { 1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 ) }, // 3

        // Quad 4
        { 1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 ) }, // 1
        { 1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 1.0, 1.0 ) }, // 6
        { 1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 ) }, // 3
        { 1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 7

        // Quad 5
        {-1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 0
        {-1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 ) }, // 2
        {-1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 ) }, // 4
        {-1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 ) }  // 5

    };
    //索引顶点数组只需用到以上八个顶点
    CUSTOMVERTEX Vertices_indexed[] =
    {
        {-1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, // 0
        { 1.0f, 1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 ) }, // 1
        {-1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 ) }, // 2
        { 1.0f,-1.0f,-1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 ) }, // 3
        {-1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 ) }, // 4
        {-1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 ) }, // 5
        { 1.0f, 1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 1.0, 1.0, 1.0 ) }, // 6
        { 1.0f,-1.0f, 1.0f,  D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }  // 7
    };
    //索引数组
    WORD Indices[] =
    {
        0, 1, 2, 3, // Quad 0
        4, 5, 6, 7, // Quad 1
        4, 6, 0, 1, // Quad 2
        5, 2, 7, 3, // Quad 3
        1, 6, 3, 7, // Quad 4
        0, 2, 4, 5  // Quad 5
    };

    //建立顶点缓存
    if (FAILED(g_pD3DDevice->CreateVertexBuffer(sizeof(vertices),
                                                0,
                                                CUSTOMFVF,
                                                D3DPOOL_MANAGED,
                                                &g_pVBuffer,
                                                NULL)))
    {
        return E_FAIL;
    }

    //通过Lock,Unlock 为顶点缓存填充数据(顶点信息):
    VOID * pV;

    if(FAILED(g_pVBuffer->Lock(0,
        sizeof(vertices),
        (void**)&pV,
        0)))
    {
        return E_FAIL;
    }

    memcpy(pV, vertices, sizeof(vertices));

    g_pVBuffer->Unlock();

    //同样方法建立顶点缓存

    if(FAILED(g_pD3DDevice->CreateVertexBuffer( 8*sizeof(CUSTOMVERTEX),
                                            0,
                                            CUSTOMFVF,
                                            D3DPOOL_MANAGED,
                                            &g_pVBuffer_Indexed,
                                            NULL )))
    {
        return E_FAIL;
    }
    pV = NULL;

    g_pVBuffer_Indexed->Lock( 0, sizeof(Vertices_indexed), (void**)&pV, 0 );
    memcpy( pV, Vertices_indexed, sizeof(Vertices_indexed) );
    g_pVBuffer_Indexed->Unlock();

    if(FAILED(g_pD3DDevice->CreateIndexBuffer( 24*sizeof(WORD),
                                    0,
                                    D3DFMT_INDEX16,
                                    D3DPOOL_MANAGED,
                                    &g_pIndexBuffer,
                                    NULL )))
    {
        return E_FAIL;
    }
    WORD *pIndices = NULL;

    g_pIndexBuffer->Lock( 0, sizeof(Indices), (void**)&pIndices, 0 );
    memcpy( pIndices, Indices, sizeof(Indices) );
    g_pIndexBuffer->Unlock();

}

void SetupMatrices(void)
{
    //投影变换
    D3DXMATRIX matProjection;

    D3DXMatrixPerspectiveFovLH(&matProjection,
        D3DX_PI/4,
        (FLOAT)SCREEN_WIDTH/(FLOAT)SCREEN_HEIGHT,
        0.1f,
        100.0f);
    g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProjection);

}

结果: