zoukankan      html  css  js  c++  java
  • 绘图对话框基于MFC对话框的OpenGL三维图形开发

    PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘。目前又不当COO,还是得用心记代码哦!

        上文中,,是在对话框的基础上,利用Picture控件停止OpenGL绘制的,,那么当初是基于一个新的类停止的OpenGL绘制,也有一个Demo,,是用GDI和OpenGL分别绘制的,,声明,,这是别人的Demo,拿来试用一下。。示例

        我也是学习了这些资料之后才懂得怎么做的。。

        以三维动态球体模型来讲述基于MFC对话框的OpenGL编程

        1.基本思想

        在Windows98/NT平台下,GDI是原始窗口的图形接口。而GDI实现这些是通过一个设备描述表DC来实现的。当初通过OpenGL绘图需要创建绘图描述表RC。但是RC并不能直接完成绘图,只能与特定的DC联系起来,从而完成详细的绘图工作。最后要注意释放RC和DC。

      2. 编程步骤

        第一步,设置开辟环境

        当初以Windows2000为例,首先将glu.dll,glu32.dll,glut.dll,glut32.dll,opengl32.dll文件拷贝到操纵系统WINNT/System32目录下,将gl.h,glaux.h,glu.h,glut.h拷贝到Microsoft Visual Studio/VC98/Include/GL目录中中,将glaux.lib,glu32.lib,glut32.lib,opengl32.lib拷贝到Microsoft Visual Studio/VC98/Lib目录中;然后在编译程序的时候选择Project|Setting菜单,在Link标签中的Object/library modules编辑框中输入“opengl32.lib, glut32.lib ,glu32.lib,glaux.lib”。到这时候环境就建立好了,可以停止下面的详细编程工作。

        第二步,详细编程

        本实例采取基于对话框的工程。至于用单文档方式和多文档方式其编程原理是一样的,这里不再作独自分析。

        2.1创建项目文件。选择File|New菜单项,新建一个基于对话框的项目文件MyDlgOpenGL;

        2.2 修改对话框模板。删除对话框中的静态文本,调整控件的位置。

        2.3 创建新类,添加消息映射。选择View|ClassWizard菜单项,打开MFC对话框,在Add Class当中选择New,以便添加一个新类COpenGL,且该类的基类选择generic CWnd;最后利用MFC ClassWizard为COpenGL类添加消息WM_CREATE,WM_PAINT的映射。

        2.4 添加代码。

      2.4.1 定义像素格式 ,创建OpenGL表现。

       在OpenGL可以在一个绘图对象中绘图之前,该绘图对象必须初始化。为此引入像素格式的概念。像素格式能告知OpenGL是否使用双缓存,颜色模式,颜色位数,深度位数等等重要信息。它由一个被称作PIXELFORMATDESCRIPTOR的所描述。于是定义在OpenGL.h中定义函数int MySetPixelFormat(HDC hdc)。然后在OpenGL.cpp文件中参加如下代码:

        int COpenGL::MySetPixelFormat(HDC hdc)

        {

        PIXELFORMATDESCRIPTOR pfd = {

            sizeof(PIXELFORMATDESCRIPTOR),   // pfd结构的巨细

            1,                                  // 版本号

            PFD_DRAW_TO_WINDOW |            // 支撑在窗口中绘图

            PFD_SUPPORT_OPENGL |              // 支撑 OpenGL

            PFD_DOUBLEBUFFER,              // 双缓存模式

            PFD_TYPE_RGBA,                  // RGBA 颜色模式

            24,                                // 24 位颜色深度

            0, 0, 0, 0, 0, 0,                         // 忽略颜色位

            0,                                   // 没有非透明度缓存

            0,                                   // 忽略移位位

            0,                                   // 无累计缓存

            0, 0, 0, 0,                             // 忽略累计位

            32,                                  // 32 位深度缓存    

            0,                                   // 无模板缓存

            0,                                   // 无帮助缓存

            PFD_MAIN_PLANE,                   // 主层

            0,                                   // 保存

            0, 0, 0                                // 忽略层,可见性和损毁掩模

        };

       

        int  iPixelFormat;

        // 为设备描述表失掉最匹配的像素格式

        if((iPixelFormat = ChoosePixelFormat(hdc, &pfd)) == 0)

        {

              MessageBox("ChoosePixelFormat Failed", NULL, MB_OK);

              return 0;

        }

         

        // 设置最匹配的像素格式为以后的像素格式

        if(SetPixelFormat(hdc, iPixelFormat, &pfd) == FALSE)

        {

              MessageBox("SetPixelFormat Failed", NULL, MB_OK);

              return 0;

        }

        return 1;

        }

        当初便可以在OnCreate函数中创建绘图描述表。其代码如下:

        int COpenGL::OnCreate(LPCREATESTRUCT lpCreateStruct)

        {

        每日一道理
    书,各种各样的书。书,寄托着人类热切的希望;书,蕴含着人类丰富的感悟。提起书,会有说不完的话语……

        if (CWnd::OnCreate(lpCreateStruct) == -1)

              return -1;

       

        MySetPixelFormat(::GetDC(m_hWnd));       // 设置以后的绘图像素格式

        hdc = ::GetDC(m_hWnd);                  // 取得绘图描述表

        hglrc = wglCreateContext(hdc);              // 创建绘图描述表

        wglMakeCurrent(hdc, hglrc);               // 使绘图描述表为以后调用现程的以后绘图描述表

        return 0;

        }

       2.4.2 停止光照处理,添加OpenGL表现。

        在OpenGL.h中定义函数LightShine函数,作为添加光源和材质属性的函数。在该函数中将创建两个光源,并使其位于不同位置,以产生不同的效果。定义:环境光,散射光,镜面光和镜面反射指数。因为没有一种光源完全由以上三种中的一种光源组成,所以任何一种光源都是由以上三种光源的光照成份组成的,即为混合光源。其成份值由RGBA定义。用材料对光的三原色的反射率来定义材料的颜色,与光源相对应,。代码如下:

        void COpenGL::LightShine(void)

        {

           GLfloat mat_diffuse[4]={1,0.5,0.5,1.0};

           GLfloat mat_specular[4]={1.0,1.0,1.0,1.0};

           GLfloat mat_shininess[1]={100.0};

        //光源 1

           GLfloat light_position0[4]={0,500,500,0};

           glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);

           glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);

           glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);

           glLightfv(GL_LIGHT0,GL_POSITION,light_position0);

           glEnable(GL_LIGHT0);

           //光源 2   

           GLfloat light_position1[4]={1000,-1000,1000,0};

           GLfloat mat_diffuse1[4]={0.5,0.5,1.0,1.0};

           glLightfv(GL_LIGHT1,GL_DIFFUSE,mat_diffuse1);

           glLightfv(GL_LIGHT1,GL_SPECULAR,mat_specular);

           glLightfv(GL_LIGHT1,GL_SHININESS,mat_shininess);

           glLightfv(GL_LIGHT1,GL_POSITION,light_position1);

           glEnable(GL_LIGHT1);

           //使模型能接受光照

           glEnable(GL_LIGHTING); 

        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);

        glDepthFunc(GL_LESS);

        glEnable(GL_DEPTH_TEST);

        //计算定点法线

        glEnable(GL_AUTO_NORMAL);

        glEnable(GL_NORMALIZE);

        }

        2.4.3 定义绘图窗口

      所绘球体在哪个区域内停止绘制以及这个区域的风格是怎样的必须需要停止定义。为下一步的绘图工作打下基础。那么可以在MyDlgOpenGLDlg.cpp的函数OnInitDialog()中参加如下代码:

        CRect rect(7, 7, 300, 300);                  //定义绘图区域的巨细

       m_pDisplay->Create( NULL,               

                                          NULL,

              //定义窗口风格

                     WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_VISIBLE,

                                          rect,  

                                          this,  

                                          0);    

        2.4.4 绘制图象

      在前面的准备之后,当初可以在OnPaint函数中绘制图象。在详细停止绘制物体时,需要注意的是:glPushMatrix()与glPopMatrix()的使用必须成对出现。此外,必须准确使用glScale() 函数和glRatate() 函数以及双缓存技巧,以实现所绘球体的在指定窗口由远及近,由小变大的旋转。代码如下:

        void COpenGL::OnPaint()

        {

                    

       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

      space+=0.005;

      if(space>1.0)

              space=0.1;

       step = step + 1.0;

     if (step > 360.0)

              step = step - 360.0;

      glPushMatrix();

       glScalef(space,space,space);

      glRotatef(step,0.0,1.0,0.0);

      glRotatef(step,0.0,0.0,1.0);

      glRotatef(step,1.0,0.0,0.0);

      LightShine();                             //添加光照属性

       glutSolidSphere(1.0,20,16);                  //绘制球体

      glPopMatrix();

      glFlush();

       SwapBuffers(hdc);                         //使用双缓存技巧实现交换缓冲区

      

        }

        2.4.5 结束运行

        在结束运行时,我们必须将一些环境变量释放。于是应该在添加的类COpenGL的析构函数中停止操纵,以释放DC和删除RC。代码如下:

        COpenGL::~COpenGL()

        {

       wglMakeCurrent(NULL, NULL) ;               

        wglDeleteContext(hglrc);                                  //删除绘图描述表

       ::ReleaseDC (m_hWnd, hdc) ;               //释放设备描述表

        }

        结语

        利用Visual C++强大的窗口功能完成了OpenGL绘制球体的程序的体例工作,上述程序运行正常,其结果是一个动态的球体。理解了上述编程过程,便可以使我们自若地应用MFC停止其他的OpenGL编程。

    文章结束给大家分享下程序员的一些笑话语录: 古鸽是一种搜索隐禽,在中国快绝迹了…初步的研究表明,古鸽的离去,很可能导致另一种长着熊爪,酷似古鸽,却又习性不同的猛禽类——犤毒鸟

    --------------------------------- 原创文章 By
    绘图和对话框
    ---------------------------------

  • 相关阅读:
    如何保证 Redis 缓存与数据库双写一致性?
    如何合理地估算线程池大小?
    不用装工具,一条 Linux 命令就能实现文件上传下载!
    看了 Google 大神 Jeff Dean 的传说,我拜服了~
    div设置水平垂直居中
    "起用"与"启用"
    徇私舞弊
    精选排比金句20例
    一笔画图推
    一笔画
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3102171.html
Copyright © 2011-2022 走看看