博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转]浮动窗体中的OpenGL多视图的实现
阅读量:6836 次
发布时间:2019-06-26

本文共 3284 字,大约阅读时间需要 10 分钟。

由于在工作中需要结合浮动窗体实现的多视图,用于得到实体的三视图观察效果,通过参考其它资料,设计了一个程序框架,在此基础之上大家可以根据自己的需要进行扩充,实现需要的功能。 

  程序实现效果图:

关键技术实现介绍:

  一、OpenGL多视图的实现
  平常我们的程序大部分都是建立一OpenGL设备上下文,但在本程序中,由于要实现三维实体的多视图观察功能,因此,需要建立多OpenGL设备上下文,并在需要的时候进行切换。
  同一般的OpenGL程序一样,我们在每个视图类中都定义了每个视图所对应的设备描述上下文并在视图创建的时候建立了这个设备描述上下文。 

//add in the header file of view class public:CClientDC* m_pDC; HGLRC m_hRC;//add in the init() function of view classm_hRC = wglCreateContext(m_pDC->GetSafeHdc());

接着在某个视图需要更新的时候(一般在每个视图的OnDraw()函数中),将这个视图的设备上下文设为OpenGL当前的渲染上下文(OpenGL Rendering context)

//add in the OnDraw() function of view class//set current devicewglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);

二、视图类型的切换及当前视图类型的判断

  由于同一视图在不同的时刻根据用户的需要可能有不同的功能,因此需要在几个视图之间进行功能的切换。本程序选取一个视图作为主视图,而另外两个视图作为子视图。视图的类有一下几种:上、下视图,前、后视图,左、右视图。为此设计了枚举类型变量用于指示视图的类型。为了保证不同视图类型之间的有效切换,即不会产生重复的类型,设计了一个类用于操作视图之间的类型切换。
  为了减小程序编制的负担,所有子视图共享一个视图类,而每个视图的当前类型是存储在这个视图类之外的,因此在每个视图绘制的时候都需要判断自己的类型。这样便出现了无法在子视图类中判断自己当前的视图类型的情况。为此在子视图类中增加了一个成员变量用于记录自己的类型。

//add in the header file of child view class//view ID, it will be assigned by parentframe when this program begin//[childviewA id = 1; childviewB id = 2] int m_ViewID

然后在程序运行之初,浮动窗体创建之后,对每个浮动窗体所包含的子视图的类型进行设置。

//add in the OnCreate() function of CMainFrame classAssignViewID();//the definition of AssignViewID()void CMainFrame::AssignViewID(){ CEdit3DMDoc* pdoc = (CEdit3DMDoc*)m_pMainView->GetDocument(); if(pdoc) {  POSITION pos = pdoc->GetFirstViewPosition();  CView* pview;  int tempid = 1;  while (pos != NULL)  {   pview = pdoc->GetNextView(pos);   if (pview->IsKindOf(RUNTIME_CLASS(CChildOGLView)))   {    CChildOGLView* pchildview = (CChildOGLView*)pview;    pchildview->m_ViewID = tempid;    tempid += 1;   }  } }}

我们看到这里需要从文档类中检索出所有子视图(CChildOGLView),因此,在子视图创建的时候需要把自己加入到文档中。 

//add in the OnCreate() function of child view classAddMetoDoc();//the definition of AddMetoDoc()void CChildOGLView::AddMetoDoc(){ CEdit3DMDoc* pdoc = (CEdit3DMDoc*)GetDocument(); if(pdoc != NULL) {  pdoc->AddView(this); }}

至此,本程序的关键功能已经实现,在主视图和子视图的绘制函数部分便可以通过判断当前视图的类型进行不同内容的绘制。 

//in the DrawScene() function of main view//To get the current view typeViewType currentviewtype;CMainFrame* pframe = (CMainFrame*)GetParentFrame();currentviewtype = pframe->m_ViewArrange.m_MainViewType;glViewport(0, 0, m_oldRect.right, m_oldRect.bottom);glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);CEdit3DMDoc* pdoc = GetDocument();if(pdoc != NULL){ pdoc->m_3DMani.SetProjection(currentviewtype, 0); pdoc->m_3DMani.DrawBound(currentviewtype);}glFinish();SwapBuffers(wglGetCurrentDC());//in the DrawScene() function of child viewViewType currentviewtype;CMainFrame* pframe = (CMainFrame*)AfxGetMainWnd();if(m_ViewID == 1){ currentviewtype = pframe->m_ViewArrange.m_ChildViewAType;}else if(m_ViewID == 2){ currentviewtype = pframe->m_ViewArrange.m_ChildViewBType;}glViewport(0, 0, m_oldRect.right, m_oldRect.bottom);glClearColor(0.0f, 0.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);CEdit3DMDoc* pdoc = GetDocument();if(pdoc != NULL){ pdoc->m_3DMani.SetProjection(currentviewtype, 0); pdoc->m_3DMani.DrawBound(currentviewtype);}glFinish();SwapBuffers(wglGetCurrentDC());

各位读者可以在此基础之上根据各自的需要实现不同的功能。需要指出的是,程序中包含了我们在系统开发中所需要的三维实体模型类,你可以对它进行修改或者替换为自己的数据结构,欢迎大家对本文提出建议,期待与大家进行合作!

(作者:胡卓玮责任编辑:方舟)

转载地址:http://bqqkl.baihongyu.com/

你可能感兴趣的文章
Eslint配置文件 `.eslintrc.js`
查看>>
Linux系统详解 系统的启动、登录、注销与开关机
查看>>
CentOS 6.0 VNC远程桌面配置
查看>>
Ubuntu 14.04环境变量修改
查看>>
Start Developing iOS Apps Today系列(十二)
查看>>
简单的冒泡排序
查看>>
Oracle锁表 行级锁 表级锁 行级锁
查看>>
Linux下如何把时间转成秒数,或把秒数转换成标准时间
查看>>
操作系统---Systemd
查看>>
JS中定义式函数与变量时函数的差别
查看>>
JSON字符串的解析
查看>>
LDAP之LDAP服务器搭建
查看>>
vmware redhat5.4 磁盘阵列 RIDA
查看>>
python学习--DAY2
查看>>
mysql5.6创建用户并授予指定数据库或表权限
查看>>
sql的使用详解(针对oeacle)之select(上)
查看>>
在CentOS/RHEL 7.X安装 EPEL repo 的方法
查看>>
oracle安装文档
查看>>
AD域中NTP服务器的配置
查看>>
我的友情链接
查看>>