OpenGLES---模型/观察/投影矩阵

论坛 期权论坛 脚本     
匿名网站用户   2020-12-20 02:45   19   0




#pragma once

#include <Windows.h>
#include <tchar.h>
#include "CELLMath.hpp"
using namespace CELL;

float3 g_cubeVertices[] ={ //4个点组成一个面,一共6个面,
 //前面
    float3(-1.0f,-1.0f, 1.0f ),//前面 左下
    float3( 1.0f,-1.0f, 1.0f ),//前面 右下
    float3( 1.0f, 1.0f, 1.0f ),//前面 右上
    float3(-1.0f, 1.0f, 1.0f ),//前面 左上
 //后面
    float3(-1.0f,-1.0f,-1.0f ),
    float3(-1.0f, 1.0f,-1.0f ),
    float3( 1.0f, 1.0f,-1.0f ),
    float3( 1.0f,-1.0f,-1.0f ),
 //上面
    float3(-1.0f, 1.0f,-1.0f ),
    float3(-1.0f, 1.0f, 1.0f ),
    float3( 1.0f, 1.0f, 1.0f ),
    float3( 1.0f, 1.0f,-1.0f ),
 //下面
    float3(-1.0f,-1.0f,-1.0f ),
    float3( 1.0f,-1.0f,-1.0f ),
    float3( 1.0f,-1.0f, 1.0f ),
    float3(-1.0f,-1.0f, 1.0f ),
 //右侧
    float3( 1.0f,-1.0f,-1.0f ),
    float3( 1.0f, 1.0f,-1.0f ),
    float3( 1.0f, 1.0f, 1.0f ),
    float3( 1.0f,-1.0f, 1.0f ),
 //左侧
    float3(-1.0f,-1.0f,-1.0f ),
    float3(-1.0f,-1.0f, 1.0f ),
    float3(-1.0f, 1.0f, 1.0f ),
    float3(-1.0f, 1.0f,-1.0f )
};

class   Soft3d{
    float2  _viewPort;//视口坐标
    matrix4 _model;//模型矩阵
    matrix4 _proj;//投影矩阵
    matrix4 _view;//视图矩阵(观察矩阵)

    float3  _trans;
    float3  _scale;
    quatr   _quat;
    float   _angel;
public:
    Soft3d(){
        _trans  =   float3(0,0,-5);
        _scale  =   float3(1,1,1);
        _quat   =   angleAxis(float(0),float3(0,0,1));
        _model  =   makeTransform(float3(0,0,0),_scale,_quat);
        _view   =   matrix4(1);
        _angel  =   0;
    }

    void    setTranlate(float3 trans) {
        _trans  =   trans;
    }

    void    setScale(float3 scale){
        _scale  =   scale;
    }
    void    rotate(float angle,float3 axis) {
        _quat    =   CELL::rotate(float(angle),axis);
    }
        

    void    drawLine(HDC hDC,const float3* arData,int length){
        for (int i = 0 ;i < length ; ++ i) {
            float3  pos     =   arData[i];
            float4  world(pos.x,pos.y,pos.z,1); 
            float4  screen;
            worldToScreen(world,screen);

          if (i %4 == 0) {//一共6个面,每个面4个顶点(4个画一组)
  ::MoveToEx(hDC,int(screen.x),int(screen.y),0);//把画笔移到什么位置
    }else{
  ::LineTo(hDC,int(screen.x),int(screen.y));//画到什么地方
    }
        }
            
    }

    void    setViewport(float w,float h) {
        _viewPort   =   float2(w,h);
    }

    void    perspect(){
        _proj   =  perspective<float>(45.0f,_viewPort.x/_viewPort.y,0.1f,1000);
    }

    /**
    *   世界坐标转化为窗口坐标
    */
    bool    worldToScreen( const float4& world, float4& screen ){
        screen  =   (_proj * _view * _model) * world;
        if (screen.w == 0.0f){
            return false;
        }
        screen.x    /=  screen.w;
        screen.y    /=  screen.w;
        screen.z    /=  screen.w;

        // map to range 0 - 1
        screen.x    =   screen.x * 0.5f + 0.5f;
        screen.y    =   screen.y * 0.5f + 0.5f;
        screen.z    =   screen.z * 0.5f + 0.5f;

        // map to viewport
        screen.x    =   screen.x * _viewPort.x;
        screen.y    =   _viewPort.y - (screen.y * _viewPort.y);
        return  true;
    }
    /**
    *   绘制函数
    */
    void   render(HDC hDC,float elapsed){
        _angel  +=  elapsed;
        rotate(_angel,float3(1,1,1));
        _model  =   CELL::makeTransform(_trans,_scale,_quat);
        drawLine(hDC,g_cubeVertices,sizeof(g_cubeVertices)/sizeof(g_cubeVertices[0]));
    }
};

class   CELLWinApp{
public:
    //! 实例句柄
    HINSTANCE   _hInstance;
    //! 窗口句柄
    HWND        _hWnd;
    //! 窗口的高度
    int         _width;
    //! 窗口的宽度
    int         _height;
 
    HDC         _hMemDC;   //内存DC(可以理解成 画板或设备)
    HBITMAP     _hBmp;     //内存位图(可以理解成 一张纸)

    Soft3d      _device;
public:
    CELLWinApp(HINSTANCE hInstance) :_hInstance(hInstance){
        WNDCLASSEX  winClass;
        winClass.lpszClassName  =   _T("CELLWinApp");
        winClass.cbSize         =   sizeof(winClass);
        winClass.style          =   CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        winClass.lpfnWndProc    =   wndProc;
        winClass.hInstance      =   hInstance;
        winClass.hIcon         =   0;
        winClass.hIconSm     =   0;
        winClass.hCursor        =   LoadCursor(hInstance, IDC_ARROW);
        winClass.hbrBackground  =   (HBRUSH)GetStockObject(BLACK_BRUSH);
        winClass.lpszMenuName   =   NULL;
        winClass.cbClsExtra     =   0;
        winClass.cbWndExtra     =   0;
        RegisterClassEx(&winClass);
        _hBmp                   =   0;
        _hMemDC                 =   0;
    }

    virtual ~CELLWinApp() {
        UnregisterClass(_T("CELLWinApp"),_hInstance);
    }
protected:
    static  LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
            
        CELLWinApp*  pThis   =   (CELLWinApp*)GetWindowLong(hWnd,GWL_USERDATA);
        if (pThis)
        {
            return  pThis->onEvent(hWnd,msg,wParam,lParam);
        }
        if (WM_CREATE == msg)
        {
            CREATESTRUCT*   pCreate =   (CREATESTRUCT*)lParam;
            SetWindowLong(hWnd,GWL_USERDATA,(DWORD_PTR)pCreate->lpCreateParams);
        }
        return  DefWindowProc( hWnd, msg, wParam, lParam );
    }
public:
    virtual LRESULT onEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        switch (msg) {
        case WM_CLOSE:
        case WM_DESTROY:
            {
                ::PostQuitMessage(0);
            }
            break;
        case WM_MOUSEMOVE:
            break;
        case WM_SIZE:{//当窗口大小发生改变时
                if (::IsWindow(_hWnd)){//如果窗口存在
                    if (_hBmp){
                        DeleteObject(_hBmp);
                    }
                    RECT    rect;
                    GetClientRect(_hWnd,&rect);
                    HDC     hDC =   GetDC(_hWnd);
                    int     w   =   rect.right - rect.left;
                    int     h   =   rect.bottom - rect.top;

                    _hBmp   =   CreateCompatibleBitmap(hDC,w,h);
                    SelectObject(_hMemDC,_hBmp);//画板和纸关联在一起
                    ReleaseDC(_hWnd,hDC);
                }
            }
            break;
        default:
            return  DefWindowProc( hWnd, msg, wParam, lParam ); 
        }
        return  S_OK;
            
    }
    /**
    *   主函数
    */
    int     main(int width,int height){
        _hWnd   =   CreateWindowEx( NULL,_T("CELLWinApp"),_T("CELLWinApp"),  WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,  width, height,   NULL,  NULL,  _hInstance,  this );

        if (_hWnd == 0) {
            return  -1;
        }
        ShowWindow(_hWnd,SW_SHOW);


        RECT    rect;
        GetClientRect(_hWnd,&rect);
        int     w   =   rect.right - rect.left;
        int     h   =   rect.bottom - rect.top;

  HDC     hDC =   GetDC(_hWnd);//获取系统的画板或设备
  //创建双缓冲区

  _hMemDC =   CreateCompatibleDC(hDC);//创建与当前DC兼容的内存DC
  _hBmp   =   CreateCompatibleBitmap(hDC,w,h);// 创建一块指定大小的位图
        SelectObject(_hMemDC,_hBmp);//画板和纸关联在一起

        HPEN   pen = ::CreatePen(PS_SOLID,1,RGB(255,255,255));//创建画笔,画笔颜色是白颜色
        SelectObject(_hMemDC,pen);///画板和画笔关联在一起

        MSG     msg =   {0};
        while(msg.message != WM_QUIT) {
            if (msg.message == WM_DESTROY ||  msg.message == WM_CLOSE) {
                break;
            }
            if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { // 有消息,处理消息,无消息,则进行渲染绘制
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
                
            HDC     hDC =   GetDC(_hWnd);
            RECT    rect;
            GetClientRect(_hWnd,&rect);
            int     w   =   rect.right - rect.left;
            int     h   =   rect.bottom - rect.top;


   bool isSHC=true;
   if(isSHC){
    FillRect(_hMemDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));

    {
     _device.setViewport(rect.right - rect.left,rect.bottom - rect.top);
     _device.perspect();
     _device.render(_hMemDC,.1f);
    }
    //将双缓冲区图像复制到显示缓冲区
    BitBlt(hDC,0,0,w,h,_hMemDC,0,0,SRCCOPY);//把当前画板上的内容画到当前窗口上
   }else{
    SelectObject(hDC,pen);///画板和画笔关联在一起
    FillRect(hDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));

    {
     _device.setViewport(rect.right - rect.left,rect.bottom - rect.top);
     _device.perspect();
     _device.render(hDC,.1f);
    }
   }
            ReleaseDC(_hWnd,hDC);//释放引用计数
        }

        if (_hMemDC){
            DeleteDC(_hMemDC);
        }

        if (_hBmp) {
            DeleteObject(_hBmp);
        }
        return  0;
    }
        
};

源码地址http://pan.baidu.com/s/1geVargZ

---------
{双缓冲步骤
    1:创建一个画板(内存位图和画笔)
    2:把要显示的东西画的内存位图上
    3:把内存位图上的内容贴到显示器上
        BitBlt(hDC,0,0,w,h,_hMemDC,0,0,SRCCOPY);
}


{具体实现步骤

    1:创建一个画板(内存位图和画笔)
        画板必须关联纸和画笔
            HDC _hMemDC = CreateCompatibleDC(hDC); //创建与当前DC兼容的内存DC
            HBITMAP _hBmp = CreateCompatibleBitmap(hDC,w,h); //创建一块指定大小的位图
            SelectObject(_hMemDC,_hBmp);//画板和纸关联在一起
            HPEN   pen = ::CreatePen(PS_SOLID,1,RGB(255,255,255));//创建画笔,画笔颜色是白颜色
            SelectObject(_hMemDC,pen);//画板和画笔关联在一起
    2:把要显示的东西画的内存位图上
        1:指定画面大小和颜色
            FillRect(_hMemDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));
        2:要画的东西画到画板上
            _device.setViewport(rect.right - rect.left,rect.bottom - rect.top);
            _device.perspect();
            _device.render(_hMemDC,.1f);
    3:把内存位图上的内容贴到显示器上
        BitBlt(hDC,0,0,w,h,_hMemDC,0,0,SRCCOPY);
}





分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP