一個簡單的3D立方體C++源碼

來源:互聯網
上載者:User
#include<d3d9.h> //Direct3D程式不需的標頭檔
#include<d3dx9.h>//如果要使用D3DX庫就必須加入這個標頭檔
#include<mmsystem.h>
#include<windows.h>
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")

//4個本程式用到的全域變數
LPDIRECT3D9 g_pD3D = NULL; //Direct3D指標
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;//Direct3D裝置
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;//頂點緩衝區指標
LPDIRECT3DINDEXBUFFER9    g_pIB = NULL;//索引緩衝指標

//定義使用到的頂點結構
struct CUSTOMVERTEX
{
    FLOAT x,y,z;
    DWORD color;
};

//定義上述頂點的FVF結構
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

//初始化Direct3D裝置過程函數
HRESULT InitD3D(HWND hWnd)
{
    //建立Direct3D對象
    if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
    {
        return E_FAIL;
    }

    //填寫建立Direct3D裝置結構體
    D3DPRESENT_PARAMETERS  d3dpp;
    ZeroMemory(&d3dpp,sizeof(d3dpp));

    d3dpp.Windowed = false;//運行在視窗模式
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//最高效的工作方式
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;//螢幕緩衝區資料像素格式

    //建立Direct3D裝置
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pD3DDevice)))
    {
        return E_FAIL;
    }
    return S_OK;
}

//初始化與本程式繪圖相關的資料函數
HRESULT InitDraw()
{
    //建立頂點緩衝區
    g_pD3DDevice->CreateVertexBuffer( 8 * sizeof(CUSTOMVERTEX),
        D3DUSAGE_WRITEONLY,
        D3DFVF_CUSTOMVERTEX,
        D3DPOOL_MANAGED,
        &g_pVB,
        0);
    //建立索引緩衝
    g_pD3DDevice->CreateIndexBuffer(36 * sizeof(WORD),
        D3DUSAGE_WRITEONLY,
        D3DFMT_INDEX16,
        D3DPOOL_MANAGED,
        &g_pIB,
        0);
    //建立立方體的8個頂點,注意每個頂點的顏色都不同
    //在繪製時,Direct3D會根據頂點顏色對三角形內部像素進行插值,所以立方體看起來是彩色的
    CUSTOMVERTEX source_vertices[] = {
        {-1.0f,-1.0f,-1.0f,D3DCOLOR_XRGB(255,0,0)},
        {-1.0f,1.0f,-1.0f,D3DCOLOR_XRGB(0,255,0)},
        {1.0f,1.0f,-1.0f,D3DCOLOR_XRGB(0,0,255)},
        {1.0f,-1.0f,-1.0f,D3DCOLOR_XRGB(255,255,0)},
        {-1.0f,-1.0f,1.0f,D3DCOLOR_XRGB(255,0,255)},
        {-1.0f,1.0f,1.0f,D3DCOLOR_XRGB(0,255,255)},
        {1.0f,1.0f,1.0f,D3DCOLOR_XRGB(0,0,0)},
        {1.0f,-1.0f,1.0f,D3DCOLOR_XRGB(255,255,255)},
    };

    //    把上面的頂點資料複製到建立的緩衝區內
    CUSTOMVERTEX * pVertices;
    if(FAILED(g_pVB->Lock(0,8*sizeof(CUSTOMVERTEX),(VOID **)&pVertices,0)))
    {
        return E_FAIL;
    }

    memcpy(pVertices,source_vertices,8 * sizeof(CUSTOMVERTEX));
    g_pVB->Unlock();
    //定義索引緩衝內容,這裡可以手動定義,也可以用數組設定好,然後內容複寫,向上面頂點緩衝區一樣
    WORD *indices = 0;
    g_pIB->Lock(0,0,(void **) & indices,0);
    //正面
    indices[0]=0;indices[1]=1;indices[2]=2;
    indices[3]=0;indices[4]=2;indices[5]=3;
    //背面
    indices[6]=4;indices[7]=6;indices[8]=5;
    indices[9]=4;indices[10]=7;indices[11]=6;
    //左面
    indices[12]=4;indices[13]=5;indices[14]=1;
    indices[15]=4;indices[16]=1;indices[17]=0;
    //右面
    indices[18]=3;indices[19]=2;indices[20]=6;
    indices[21]=3;indices[22]=6;indices[23]=7;
    //頂面
    indices[24]=1;indices[25]=5;indices[26]=6;
    indices[27]=1;indices[28]=6;indices[29]=2;
    //底面
    indices[30]=4;indices[31]=0;indices[32]=3;
    indices[33]=4;indices[34]=3;indices[35]=7;

    g_pIB->Unlock();

    //設定攝像機
    D3DXVECTOR3 position(0.0f,0.0f,-3.0f);
    D3DXVECTOR3 target(0.0f,0.0f,0.0f);
    D3DXVECTOR3 up(0.0f,1.0f,0.0f);
    D3DXMATRIX V;

    D3DXMatrixLookAtLH(&V,&position,&target,&up);
    g_pD3DDevice->SetTransform(D3DTS_VIEW,&V);

    //設定投影矩陣
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(& proj,
        D3DX_PI * 0.5f,
        (float)800/(float) 600,
        1.0f,
        1000.0f);
    g_pD3DDevice->SetTransform(D3DTS_PROJECTION,&proj);
    //因為沒有使用材質,紋理資訊,所以關閉燈光顯示出本身色彩
    g_pD3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
    return S_OK;
}

void Cleanup()
{
    if(g_pVB != NULL)
    {
        g_pVB->Release();
    }
    if(g_pIB != NULL)
    {
        g_pIB->Release();
    }
    if(g_pD3DDevice != NULL)
    {
        g_pD3DDevice->Release();
    }
    if(g_pD3D != NULL)
    {
        g_pD3D ->Release();
    }
}

//渲染函數
void Render()
{
    //清除螢幕緩衝區到藍色螢幕
    g_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),1.0f,0);
    //開始繪製
    if(SUCCEEDED(g_pD3DDevice->BeginScene()))
    {
        //建立沿3個軸渲染的矩陣
        D3DXMATRIXA16 matWorld_X;
        D3DXMatrixIdentity(&matWorld_X);
        D3DXMatrixRotationX(&matWorld_X,timeGetTime()/500.0f);

        D3DXMATRIXA16 matWorld_Y;
        D3DXMatrixIdentity(&matWorld_Y);
        D3DXMatrixRotationY(&matWorld_Y,timeGetTime()/500.0f);

        D3DXMATRIXA16 matWorld_Z;
        D3DXMatrixIdentity(&matWorld_Z);
        D3DXMatrixRotationZ(&matWorld_Z,timeGetTime()/500.0f);

        //設定物體的世界矩陣

        g_pD3DDevice->SetTransform(D3DTS_WORLD,&(matWorld_X*matWorld_Y*matWorld_Z));

        //掛接渲染流水線,設定FVF值,設定索引,渲染
        g_pD3DDevice->SetStreamSource(0,g_pVB,0,sizeof( CUSTOMVERTEX));
        g_pD3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
        g_pD3DDevice->SetIndices(g_pIB);
        g_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12);

        //結束繪製
        g_pD3DDevice->EndScene();
    }
    //顯示到螢幕
    g_pD3DDevice->Present(NULL,NULL,NULL,NULL);
}
//訊息回呼函數。只處理退出訊息,所以滑鼠一直顯示忙狀態
LRESULT WINAPI MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    switch(msg)
    {
    case WM_DESTROY:
        Cleanup();
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd,msg,wParam,lParam);
}

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE , LPSTR,INT)
{
    //註冊視窗
    WNDCLASSEX wc = {sizeof(WNDCLASSEX),CS_CLASSDC,MsgProc,0L,0L,
                                      GetModuleHandle(NULL),NULL,NULL,NULL,NULL,"D3D Tutorical",NULL
                                       };
    RegisterClassEx(&wc);

    //建立視窗
    HWND hWnd = CreateWindow("D3D Tutorical",
                             "3D立方體",
                             WS_OVERLAPPEDWINDOW,
                             100,
                             100,
                             800,
                             600,
                             GetDesktopWindow(),
                             NULL,
                             wc.hInstance,
                             NULL);
   
    //嵌套if保證全部初始化成功才可以進入迴圈運行
    if(SUCCEEDED (InitD3D(hWnd)))
    {
        if(SUCCEEDED(InitDraw()))
        {
            //顯示視窗
               ShowWindow(hWnd,SW_SHOWDEFAULT);
            UpdateWindow(hWnd);
            //最佳化的訊息迴圈
            MSG msg;
            ZeroMemory(&msg,sizeof(msg));
            while(msg.message != WM_QUIT)
            {
                if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else
                {
                    Render();
                }
            }
        }
    }
    UnregisterClass("D3D Tutorical",wc.hInstance);

    return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.