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);
	else
		return;

	// 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);
	else
		glOrtho(-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);
	else
		return;
	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


  • 29
    点赞
  • 219
    收藏
    觉得还不错? 一键收藏
  • 31
    评论
### 回答1: 使用MFCOpenGL来读取并显示STL三维模型需要以下几个步骤: 1. 创建一个新的MFC项目,选择对话框应用程序作为模板。 2. 将OpenGL库文件添加到项目中,并进行相关配置,以便在对话框中使用OpenGL绘图。 3. 在对话框中添加一个静态文本框和一个自定义的OpenGL绘图区域。 4. 创建一个自定义的OpenGL绘图类,用于在绘图区域中显示STL模型。在该类中,定义一个透视投影矩阵、模型矩阵和视图矩阵,通过OpenGL函数来加载和渲染STL文件中的三角形。 5. 在对话框类中,添加一个自定义的OpenGL绘图类的成员变量,并在OnInitDialog()函数中对其进行初始化。 6. 在OnInitDialog()函数中,调用自定义OpenGL绘图类的初始化函数,传入STL模型文件的路径,将模型加载到内存中。 7. 在OnPaint()函数中,调用自定义OpenGL绘图类的绘制函数,将模型渲染到OpenGL绘图区域。 8. 处理对话框中的事件,例如按钮点击事件,调用自定义OpenGL绘图类的相应函数进行操作,如旋转、平移等。 9. 在应用程序类的InitInstance()函数中,创建对话框类的对象,并显示对话框。 通过以上步骤,可以实现MFC应用程序中读取并显示STL三维模型。 ### 回答2: MFC是Microsoft Foundation Classes的缩写,是一种用于Windows平台的C++应用程序框架。OpenGL是一种跨平台的图形API,用于开发图形和计算机视觉应用程序。STL(Standard Template Library)是C++的一部分,提供了一组通用的数据结构和算法。 要在MFC应用程序中读取并显示STL三维模型,可以按照以下步骤进行操作: 1. 首先,创建一个MFC应用程序项目,并在项目中添加OpenGL支持。这可以通过在项目属性中启用OpenGL选项来实现。 2. 在MFC应用程序中创建一个窗口,用于显示3D模型。这可以通过创建一个自定义的CStatic控件,并在其上绘制OpenGL图形来实现。 3. 接下来,编写代码来读取STL文件的数据。STL文件中包含三角形网格的顶点和法线信息。可以使用标准的文件处理函数来读取和解析STL文件的内容,并将其存储在一个适当的数据结构中。 4. 通过OpenGL的API函数,将STL模型数据绘制到窗口中。可以使用OpenGL的顶点数组和绘制函数来绘制三角形网格的各个面。 5. 最后,将OpenGL绘制的结果显示在MFC窗口中。可以通过重载绘图消息处理函数,并在其中调用OpenGL的绘制函数来实现。 需要注意的是,由于MFCOpenGL都是底层的图形库,对于初学者来说,可能需要一定的编程经验和对图形编程的理解。这个过程可能需要一些时间和尝试来完善和调试。 ### 回答3: 在 MFC 中使用 OpenGL 来读取并显示 STL 三维模型可以通过以下步骤实现: 1. 添加准备创建 OpenGL 窗口的代码。在 MFC 的窗体类中,可以使用 `COpenGLControl` 类或 `CView` 类来实现 OpenGL 窗口。 2. 创建一个函数来读取 STL 三维模型文件。你可以使用 STL 文件解析库,例如 `std::ifstream` 类来读取 STL 文件的内容。 3. 在创建的 OpenGL 窗口中,使用 OpenGL 函数来绘制三维模型。你可以使用 `glBegin`、`glEnd` 和 `glVertex3f` 等函数来绘制模型的顶点和三角面片。 4. 在 OpenGL 窗口中,将读取到的 STL 三维模型数据传入 OpenGL 函数来进行绘制。你可以使用 `glColor3f` 函数来设置模型的颜色。 5. 在 MFC 的窗体类中,实现绘制 OpenGL 窗口的函数。通过重写 `OnDraw` 或 `OnPaint` 函数,调用 OpenGL 窗口的绘制函数。 6. 在 MFC 的窗体类中,重写 `OnCreate` 函数来初始化 OpenGL 窗口,调用读取和显示 STL 模型的函数。 7. 在 MFC 的窗体类中,为了在窗口中显示 OpenGL 窗口,重写 `OnSize` 函数,并调用 OpenGL 窗口的调整大小函数。 通过上述步骤,你可以在 MFC 中使用 OpenGL 来读取并显示 STL 三维模型。你可以进一步优化代码,例如添加相机控制、光照设置等来增强模型的显示效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值