MFC+OpenGL三维绘图(一)——简单绘图平台的搭建与实现图像的旋转、缩放
声明:本文章为小白本人第一次创作,文章可能会有诸多不足,希望大家批评指正!
VS2013下载:https://pan.baidu.com/s/1Y7TuZlLaGsbj2KCZV_uckw
OpenGL下载:https://download.csdn.net/download/belence_zhao/10352366
OpenGL的配置方法网上有很多大家可以自行查找。
一、创建项目
1.打开VS2013建立一个单文档工程,项目名字openGLDrawing。
2.添加初始化和终止代码
首先,在打开类COpenGLDrawingView,在其头文件添加“gl.h”“glut.h”“glu.h”三个头文件,然后添加两个记录绘图的成员变量。
#include "Gl/gl.h"
#include "GL/glu.h"
#include "gl/glut.h"
在类COpenGLDrawingView的头文件中添加两个成员变量CClientDC *m_pDC;HGLRC m_hglrc;
protected:// 生成的消息映射函数
protected:DECLARE_MESSAGE_MAP()
public:CClientDC *m_pDC;HGLRC m_hglrc;
然后,给类COpenGLDrawingView分别添加WM_CREATE、WM_SIZE、WM_DESDROY响应函数OnCreate、OnSize和OnDesdory函数。
int COpenGLDrawingView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CView::OnCreate(lpCreateStruct) == -1)return -1;// TODO: 在此添加您专用的创建代码int n;m_pDC = new CClientDC(this);ASSERT(m_pDC != NULL);static PIXELFORMATDESCRIPTOR pfd ={sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type 24, // 24-bit color depth 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 16, // 16-bit z-buffer 0, // no stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored };int m_nPixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);if (m_nPixelFormat == 0){return FALSE;}if (::SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd) == FALSE){return FALSE;}n = ::GetPixelFormat(m_pDC->GetSafeHdc());::DescribePixelFormat(m_pDC->GetSafeHdc(),n,sizeof(pfd),&pfd);//Create Rendering Context m_hglrc = ::wglCreateContext(m_pDC->GetSafeHdc());//Failure to Create Rendering Context if (m_hglrc == 0){MessageBox("Error Creating RC");return FALSE;}//Make the RC Current if (::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hglrc) == FALSE){MessageBox("Error making RC Current");return FALSE;}//Specify Black as the clear color ::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//Specify the back of the buffer as clear depth ::glClearDepth(1.0f);//Enable Depth Testing ::glEnable(GL_DEPTH_TEST);return 0;}
void COpenGLDrawingView::OnDestroy()
{// TODO: 在此处添加消息处理程序代码//Delete the rendering context ::wglMakeCurrent(NULL, NULL);if (m_hglrc)::wglDeleteContext(m_hglrc);if (m_pDC)delete m_pDC;CView::OnDestroy();
}
此外还要再类PreCreateWindow中,还要对窗口风格进行设置。
BOOL COpenGLDrawingView::PreCreateWindow(CREATESTRUCT& cs)
{// TODO: 在此处通过修改// CREATESTRUCT cs 来修改窗口类或样式//cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW);cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MAXIMIZE;return CView::PreCreateWindow(cs);
}
3.根据窗口大小设置场景
在MFC应用中,窗口位置的大小和和位置的改变都会引发一个WM_SIZE消息,执行所在的OnSize函数。
void COpenGLDrawingView::OnSize(UINT nType, int cx, int cy)
{CView::OnSize(nType, cx, cy);if (m_hglrc)wglMakeCurrent(m_pDC->GetSafeHdc(), m_hglrc);elsereturn;// TODO: 在此处添加消息处理程序代码if (0 >= cx || 0 >= cy){return;}//select the full client area ::glViewport(0, 0, cx, cy);::glMatrixMode(GL_PROJECTION);::glLoadIdentity();if (cx < cy)glOrtho(-10.0, 100.0, -10.0*(GLfloat)cy / (GLfloat)cx, 10.0*(GLfloat)cy / (GLfloat)cx, -100.0, 100.0);elseglOrtho(-10.0*(GLfloat)cx / (GLfloat)cy, 10.0*(GLfloat)cx / (GLfloat)cy, -10.0, 10.0, -100.0, 100.0);// switch back to the modelview matrix and clear it ::glMatrixMode(GL_MODELVIEW);::glLoadIdentity();
}
4.添加绘制代码
在MFC中绘图是通过OnDraw函数中执行的,因此OpenGL函数的命令在这里执行。
void COpenGLDrawingView::OnDraw(CDC* /*pDC*/)
{COpenGLDrawingDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码if (m_hglrc)wglMakeCurrent(m_pDC->GetSafeHdc(), m_hglrc);elsereturn;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();glColor3f(1.0,1.0,0.0);Rendenr();::SwapBuffers(m_pDC->GetSafeHdc());}
在这里,我们为了进行简单的说明,采用OpenGL中的glutwireTeapot函数进行快速的茶壶绘制。
这时候,我们就已经完成了一个简单的绘图平台,运行一下程序就会看到一个完美的茶壶图形,如下图:
但是,此时我们所完成的只是一个简单的二维图形,无法想其他专业的三维绘图软件一样,进行图像的旋转、缩放等功能。这个功能的实现我们可以通过添加鼠标消息响应来实现图像的这些功能。
二、实现图像的旋转、平移与缩放
实现图像的旋转、移动、缩放功能是通过鼠标的消息响应函数分别实现的。在MFC中每当鼠标动一下,就会触发消息响应函数,这样绘图区就会重新绘图,正是这种思想,我们才可以简单的实现图形的操作。
通过对类COpenGLDrawingView分别添加WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEWHEEL、WM_MOUSEMOVE和WM_KEYDOWN消息相应的响应函数来实现这些功能。在对鼠标消息命令之前先进设置。
首先在类COpenGLDrawingView的头文件中添加变量:m_yAngle; m_xAngle;m_zAngle; m_xPos; m_yPos; m_zPos;m_MouseDownPoint; m_Scale;分别表示要旋转的角度与位置,代码如下:
public:CClientDC *m_pDC;HGLRC m_hglrc;GLfloat m_yAngle;GLfloat m_xAngle;GLfloat m_zAngle;GLfloat m_xPos;GLfloat m_yPos;GLfloat m_zPos;CPoint m_MouseDownPoint;float m_Scale;
然后在构造函数中对这些变量进行初始化:
COpenGLDrawingView::COpenGLDrawingView()
{// TODO: 在此处添加构造代码m_xPos = 0.0f;m_yPos = 0.0f;m_zPos = 0.0f;m_xAngle = 0.0f;m_yAngle = 0.0f;m_zAngle = 0.0f;m_Scale = 1.0f;}
由于鼠标每次移动都要进行图形的重新绘制,在OnDraw函数中要进行一定的设置。本次工程我们采用OpenGL中的glTranslatef()实现图形的平移,通过glRotatef()函数实现图像的旋转,通过glScalef()函数实现图像的缩放功能,代码如下:
glTranslatef(m_xPos, m_yPos, m_zPos);glRotatef(m_xAngle, 1.0f, 0.0f, 0.0f);glRotatef(m_yAngle, 0.0f, 1.0f, 0.0f);glScalef(m_Scale, m_Scale, m_Scale);glColor3f(1.0,1.0,0.0);
鼠标的移动:
void COpenGLDrawingView::OnMouseMove(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (GetCapture() == this){//Increment the object rotation angles m_xAngle += (point.y - m_MouseDownPoint.y) / 3.6;m_yAngle += (point.x - m_MouseDownPoint.x) / 3.6;//Redraw the view InvalidateRect(NULL, FALSE);//Set the mouse point m_MouseDownPoint = point;};CView::OnMouseMove(nFlags, point);
}
1.实现图像的缩放
图新的缩放功能是通过鼠标中间的转动实现的,当中键向上图形放大,中建向下图形缩小。
BOOL COpenGLDrawingView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{// TODO: 在此添加消息处理程序代码和/或调用默认值if (m_Scale >= 0){m_Scale += 0.05 *zDelta / 120;}else{if (zDelta > 0){m_Scale += 0.05 *zDelta / 120;}}InvalidateRect(NULL, FALSE);return CView::OnMouseWheel(nFlags, zDelta, pt);}
2.实现图像的移动
图像的移动,通过键盘上的箭头来控制的,箭头的上下左右分别控制图形的上下左右平移。
void COpenGLDrawingView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{// TODO: 在此添加消息处理程序代码和/或调用默认值switch (nChar){case VK_UP: m_yPos = m_yPos + 1.0f;break;case VK_DOWN: m_yPos = m_yPos - 1.0f;break;case VK_LEFT: m_xPos = m_xPos - 1.0f;break;case VK_RIGHT: m_xPos = m_xPos + 1.0f;break;default: MessageBox("Press the arrow keys only");break;}InvalidateRect(NULL, FALSE);CView::OnKeyDown(nChar, nRepCnt, nFlags);
3.实现图像的旋转
void COpenGLDrawingView::OnLButtonDown(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值m_MouseDownPoint = point;SetCapture();CView::OnLButtonDown(nFlags, point);
}
void COpenGLDrawingView::OnLButtonUp(UINT nFlags, CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值m_MouseDownPoint = CPoint(0, 0);ReleaseCapture();CView::OnLButtonUp(nFlags, point);
}
此刻,到了我们该欢呼的时刻了,我们已经完成了程序的设计过程,让我们运行一下:
本文代码地址:https://download.csdn.net/download/belence_zhao/10408772
MFC+OpenGL三维绘图(一)——简单绘图平台的搭建与实现图像的旋转、缩放相关推荐
- mfc opengl 三维地形图_衢州三维动画制作传媒企业哪家好2020收费
衢州三维动画制作传媒企业哪家好2020收费 工业动画具有如下优势, 杰出的力.三维技术能够逼真地模拟现实环境或创造常规拍摄所无法实现的场景和事件,从微观世界到宏观世界,从真实空间到想象空间.三维可视化 ...
- mfc opengl 三维地形图_深圳pmax巨影三维扫描仪
深圳pmax巨影三维扫描仪,并首先选择3D打印机项目来开启品牌征程. 深圳pmax巨影三维扫描仪, 雕工精美的红木家具都雕刻着繁复精美的花纹,这都是工匠手工制作,用心思一刀一刀的雕刻的.虽然精美,但是 ...
- 简单绘图软件实现mfc大作业_生产流程图怎么做?简单易上手的流程图工具
生产流程图是什么呢?首先,生产流程指的是在生产的过程中,劳动者通过利用一定的生产设备或工具,将各种原材料.半成品投入,按照一定顺序进行加工,最终得到成品产出的整个过程.而生产流程图则是使用图表符号的形 ...
- Qt使用GDI绘图(仅Windows平台)
绘图引擎 Windows环境下二维绘图引擎有多种选择:GDI.GDI+.DirectDraw.Qt/QPainter.Agg.Cairo.skia.Direct2D.Direct3D.OpenGL等. ...
- [收藏转载]C# GDI+ 简单绘图(一)
最近对GDI+这个东西接触的比较多,也做了些简单的实例,比如绘图板,仿QQ截图等. 废话不多说了,我们先来认识一下这个GDI+,看看它到底长什么样. GDI+:Graphics Device Inte ...
- C#GDI+简单绘图
原文地址:http://www.cnblogs.com/stg609/archive/2008/03/16/1108333.html (一)GDI+ 基础知识 最近对GDI+这个东西接触的比较多,也做 ...
- csvtk:表格处理神器-美化、统计、头表、合并、转置、筛选、取样、去冗余 、分列、分类汇总和简单绘图...
写在前面 CSV/TSV作为数据科学和组学分析的基本格式,其实本质上均为txt格式的表格,CSV是按逗号分隔,TSV是以制表符分隔的表格.这两种格式数据格式应用非常广泛.比较常用的处理软件包括: Ex ...
- TeeChart替代品,MFC下好用的高速绘图控件-(Hight-Speed Charting)
相关链接: C++ GUI 绘图控件目录 MFC VS2010 使用TeeChart绘图控件 - 之一 - 控件和类的导入 VS2010 使用TeeChart绘图控件 - 之二 - 绘制图形(折线图, ...
- c# GDI+简单绘图(一)
最近对GDI+这个东西接触的比较多,也做了些简单的实例,比如绘图板,仿QQ截图等. 最早接触这个类,是因为想做仿QQ截图的效果.巧的很,学会了如何做截图后,.NET课堂上老师也正巧要讲关于c#绘图方面 ...
最新文章
- windows 2012 nps配置
- 念数字python_我是怎样利用python PIL将图片数字读出来的?
- vue中模板编译compiler源码详解
- sqlalchemy基本类型
- Java基础知识——Java常用类的使用
- Python菜鸟入门:day03运算符
- linux grep跨行文本匹配,grep跨行匹配
- 每天一点正则表达式积累之(?=X)和(?!X)测试(七)
- 如何配置可以远程访问linux上mysql
- 卡密社区源码无加密完整版(php源码+mysql脚本)
- 吴孟达《高等工程数学》第一章笔记和部分课后习题答案详解
- 什么是亚线性和超线性?
- 如何打造抖音爆款内容,从而快速热门涨粉丨国仁网络
- mybatis拦截器实现数据脱敏拦截器使用
- 一元二次方程代码c语言,一元二次方程求解程序完整代码
- 六行python代码的爱心曲线_6行python代码的爱心曲线
- Android 双屏异显
- QQ9.4.3版本勋章墙补丁
- 【转帖】追本朔源说COM
- 免重装系统更换AHCI磁盘驱动器模式