• 3D游戏编程入门(十六)索引缓存绘制立方体


    T T本想和刚才那个帖在一起的,可是新浪日志限制每帖1万字,呼,再单独的发个立方体代码吧
    运行后效果图应当如下:
    3D游戏编程入门(十六)索引缓存绘制立方体


    头文件就不再给出包含了,其他完整代码如下,另部分关于旋转和视角的东西大家暂时先不用管,我以后会慢慢说明的。


    // 全局变量:
    HINSTANCE hInst;    // 当前实例
    TCHAR szTitle[20];    // 标题栏文本
    TCHAR szWindowClass[20];   // 主窗口类名
    LPDIRECT3D9 g_pD3D = NULL;
    LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
    LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;

    // 此代码模块中包含的函数的前向声明:
    ATOM    MyRegisterClass(HINSTANCE hInstance);
    BOOL    InitInstance(HINSTANCE, int);
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);

    //定义定点信息的结构体
    struct CUSTOMVERTEX
    {
        FLOAT x, y, z;   
        DWORD colour;
    };

    //自由定点格式的宏定义
    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

    //COM对象释放的宏定义
    #define SafeRelease(pObject) if(pObject != NULL) {pObject->Release(); pObject=NULL;}

    //初始化D3D设备
    HRESULT InitialiseD3D(HWND hWnd)
    {
        //得到一个D3D9的对象
        g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
        if(g_pD3D == NULL)
        {
            return E_FAIL;
        }

     //得到当前的显示模式
        D3DDISPLAYMODE d3ddm;
        if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
        {
            return E_FAIL;
        }

        //建立一个存储设备设置的结构体
        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));

        d3dpp.Windowed = TRUE;//为窗口还是全屏
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //
        d3dpp.BackBufferFormat = d3ddm.Format;//显示模式

     //创建D3D设备
        if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                       D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice)))
        {
            return E_FAIL;
        }
       
     //设置渲染时的剔出模式
        g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

     //关闭灯光
        g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

        return S_OK;
    }

    HRESULT InitialiseVertexBuffer()
    {
        VOID* pVertices;
     
        CUSTOMVERTEX cvVertices[] =
        { 
      //顶面
      {-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 255),}, 
            {-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 255, 0),},
            {5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(255, 255, 0),}, 
      {5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 255),},  

      //侧面 1
      {-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 255),}, 
            {-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 255),}, 
            {5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 255, 0),}, 
      {5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 255),},  

      //侧面 2
      {5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 255),},  
            {5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 255, 0),},  
      
      //侧面 3
            {-5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(255, 255, 0),}, 
      {-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 255),},  

      //侧面 4
            {-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 255, 0),}, 
            {-5.0f, 5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 255),}, 

      //底面
      {5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(0, 255, 255),}, 
            {5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 255),}, 
            {-5.0f, -5.0f, -5.0f, D3DCOLOR_XRGB(255, 0, 255),}, 
      {-5.0f, -5.0f, 5.0f, D3DCOLOR_XRGB(255, 255, 0),}, 
        };

        //通过D3D设备指针获得一个定点缓冲的指针
        if(FAILED(g_pD3DDevice->CreateVertexBuffer(sizeof(cvVertices),
                                                   0, D3DFVF_CUSTOMVERTEX,
                                                   D3DPOOL_DEFAULT, &g_pVertexBuffer,NULL)))
        {
            return E_FAIL;
        }


        //锁定定点缓冲区并得到一个存放顶点信息缓冲区的指针
        if(FAILED(g_pVertexBuffer->Lock(0, sizeof(cvVertices), (void**)&pVertices, 0)))
        {
            return E_FAIL;
        }

        //将顶点数组当中的顶点信息复制到顶点缓冲当中
        memcpy(pVertices, cvVertices, sizeof(cvVertices));

        //解锁顶点缓冲
        g_pVertexBuffer->Unlock();

        return S_OK;
    }

    //设置旋转、移动和缩放,即设置世界变换, 暂时无需管
    void SetupRotation() 
    {
     D3DXMATRIX matWorld;
     D3DXMATRIX matScaling;
     D3DXMATRIX matTranslation;
     
     D3DXMatrixRotationX(&matWorld,70);
     D3DXMatrixScaling(&matScaling,1.5,1.5,1.5);
     D3DXMatrixTranslation(&matTranslation,5,0,0);

     D3DXMatrixMultiply(&matWorld,&matWorld,&matScaling);
     D3DXMatrixMultiply(&matWorld,&matWorld,&matTranslation);
     g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
    }

    //设置摄像机
    void SetupCamera()
    {

        D3DXMATRIX matView;
        D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(-30.0f, 0.0f,-25.0f),  //摄像机的位置
                                     &D3DXVECTOR3(0.0f, 0.0f, 0.0f),  //摄像机的朝向
                                     &D3DXVECTOR3(0.0f, 1.0f, 0.0f));  //摄像机的顶方向
        g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
    }

    void SetupPerspective()
    {
     //Here we specify the field of view, aspect ration and near and far clipping planes.
        D3DXMATRIX matProj;
        D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);
        g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);
    }


    void Render()
    {
        if(g_pD3DDevice == NULL)
        {
            return;
        }

        //将后备缓冲区全部清空为黑色
        g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
       
        //开始绘制场景
        g_pD3DDevice->BeginScene();
       

     //设置世界变换、视图变换和投影变换
        SetupRotation();
     SetupCamera();
     SetupPerspective();


        //渲染立方体
        g_pD3DDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX));   //设置顶点缓冲区
        g_pD3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);                  //设置自由顶点格式
        g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);  //渲染顶面
     g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 8);  //渲染侧面
     g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 2); //渲染底面

        //结束绘制场景
        g_pD3DDevice->EndScene();
       
        //翻页,显示后备缓冲区的内容
        g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
    }

    //释放COM对象
    void CleanUp()
    {
        SafeRelease(g_pVertexBuffer);
        SafeRelease(g_pD3DDevice);
        SafeRelease(g_pD3D);
    }

    void GameLoop()
    {
        //进入游戏循环
        MSG msg;
        BOOL fMessage;

        PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
       
        while(msg.message != WM_QUIT)
        {
            fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);

            if(fMessage)
            {
                //处理消息
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {
                //没有消息处理的时候,渲染当前的场景
                Render();
            }

        }
    }

    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
        //注册窗口类
        WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
                         GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                         "D3DDrawCube", NULL};
        RegisterClassEx(&wc);

        //建立一个应用程序的窗口
        HWND hWnd = CreateWindow("D3DDrawCube", "D3D绘制立方体",
                                  WS_OVERLAPPEDWINDOW, 50, 50, 500, 500,
                                  GetDesktopWindow(), NULL, wc.hInstance, NULL);

        //初始化 Direct3D
        if(SUCCEEDED(InitialiseD3D(hWnd)))
        {
            //显示窗口
            ShowWindow(hWnd, SW_SHOWDEFAULT);
            UpdateWindow(hWnd);

            //初始化顶点缓冲(Vertex Buffer)
            if(SUCCEEDED(InitialiseVertexBuffer()))
            {
                //开始执行游戏: 进入游戏循环
                GameLoop();
            }
        }
       
     //游戏结束,执行清理工作
        CleanUp();

     //注销窗口类
        UnregisterClass("D3DDrawCube", wc.hInstance);
       
        return 0;
    }

     


    //  注册窗口类。

    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
     WNDCLASSEX wcex;

     wcex.cbSize = sizeof(WNDCLASSEX);

     wcex.style   = CS_HREDRAW | CS_VREDRAW;
     wcex.lpfnWndProc = (WNDPROC)WndProc;
     wcex.cbClsExtra  = 0;
     wcex.cbWndExtra  = 0;
     wcex.hInstance  = hInstance;
     wcex.hIcon   = LoadIcon(hInstance, (LPCTSTR)IDI_MY);
     wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
     wcex.lpszMenuName = (LPCTSTR)IDC_MY;
     wcex.lpszClassName = szWindowClass;
     wcex.hIconSm  = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

     return RegisterClassEx(&wcex);
    }


    //    保存实例句柄并创建主窗口

    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       HWND hWnd;

       hInst = hInstance; // 将实例句柄存储在全局变量中

       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

       if (!hWnd)
       {
          return FALSE;
       }

       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);

       return TRUE;
    }


    // 处理主窗口的消息。

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch(message)
        {
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
            break;
            case WM_KEYUP:
                switch (wParam)
                {
                    case VK_ESCAPE:
                        //当用户按下ESC键的时候,关闭窗口
                        DestroyWindow(hWnd);
                        return 0;
                    break;
                }
            break;

        }

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

  • 相关阅读:
    [转]给C++初学者的50个忠告
    [转]代理模式——代理模式的核心思想
    [转]单例模式——C++实现自动释放单例类的实例
    [转]代理模式——何时使用代理模式
    观察者模式——生动的气象信息订阅服务图示
    [转]单例模式——Java中互斥访问单一实例
    [转]C++ const变量使用技巧总结
    [转]用C++设计一个不能被继承的类
    ExtJs2.0学习系列(14)Ext.TreePanel之第三式(可增删改的树)
    ExtJs2.0学习系列(7)Ext.FormPanel之第四式(其他组件示例篇)
  • 原文地址:https://www.cnblogs.com/Anzhongliu/p/6092049.html
Copyright © 2020-2023  润新知