1、创建基于MFC单文档例程,本文单文档名称命名为(LIDAR)
2、设置窗口的显示风格
窗口创建之前我们必须设置窗口风格包含
WS_CLIPCHILDREN(创建父窗口使用的Windows风格,用于重绘时裁剪子窗口所覆盖的区域)和WS_CLIPSIBLINGS(创建子窗口使用的Windows风格,用于重绘时剪裁其他子窗口所覆盖的区域),从而避免OpenGL绘制到其他窗口中去。
BOOL CLiDARView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; (在view程序PreCreateWindow函数中添加)
return CView::PreCreateWindow(cs);
}
3、添加链接库
在stdafx.h文件中添加OpenGL的链接库和头文件
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "glut32.lib" )
#pragma comment( lib, "glaux.lib" )
#include <glaux.h>
#include <glut.h>
注:根据编译环境和opengl的安装环境不同,有些例程头文件是#include <gl\glut.h>、#include <gl\glaux.h>
4、利用类向导创建新的类,命名为MyOpenGL(MyOpenGL.cpp、MyOpenGL.h)
在MyOpenGL.h文件中添加以下代码:
class MyOpenGL
{
public:
HGLRC m_hRC; //Rendering Context着色描述表
BOOL InitializeOpenGL(CClientDC *pdc); //初始化 OpenGL
BOOL SetupPixelFormat(CClientDC *pdc); //设置像素格式
void DisplayModeInit(void); //初始化显示的方式(视角、窗口视景等)
void RenderScene(void); //绘制场景函数
void CopyRect(CRect rect); //拷贝窗口客户区的区域函数
void Point(void); //画点函数
void Line(void); //划线函数
void Triangle(void); //画三角形函数
void Square(void); //画正方形
void Esquare(void); //画正方体
void Park(void); //画圆
void Pillar(void); //画圆柱
MyOpenGL();
virtual ~MyOpenGL();
float r;
protected:
private:
CRect OpenGLRect; //显示区域
};
在MyOpenGL.cpp文件中添加以下代码:
#include "stdafx.h"
#include "MyOpenGL.h"
#include "LiDARView.h"
BOOL MyOpenGL::SetupPixelFormat(CClientDC *pdc)
{
static 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 pixelformat;
if ((pixelformat = ChoosePixelFormat(pdc->GetSafeHdc(), &pfd)) == 0)
{
MessageBox(NULL,_T("ChoosePixelFormat failed"),_T("Error"),MB_OK);
return false;
}
if (SetPixelFormat(pdc->GetSafeHdc(),pixelformat,&pfd) == FALSE)
{
MessageBox(NULL, _T("SetPixelFormat failed"), _T("Error"), MB_OK);
return false;
}
return TRUE;
}
BOOL MyOpenGL::InitializeOpenGL(CClientDC *pdc)
{
PIXELFORMATDESCRIPTOR pfd;
int n;
ASSERT(*pdc != NULL);
if (!SetupPixelFormat(pdc))
{
MessageBox(NULL, _T("SetPixelFormat failed"), _T("Error"), MB_OK);
return FALSE;
}
n = ::GetPixelFormat(pdc->GetSafeHdc());
::DescribePixelFormat(pdc->GetSafeHdc(),n,sizeof(pfd),&pfd);
m_hRC = wglCreateContext(pdc->GetSafeHdc());
if (m_hRC == NULL)
{
return FALSE;
}
if (wglMakeCurrent(pdc->GetSafeHdc(), m_hRC) == FALSE)
{
return FALSE;
}
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return TRUE;
}
void MyOpenGL::DisplayModeInit(void)
{
glViewport(0, 0, OpenGLRect.Width(), OpenGLRect.Height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (GLfloat)OpenGLRect.Width() / (GLfloat)OpenGLRect.Height(), 0.1f, 3000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void MyOpenGL::RenderScene(void)
{
glPushMatrix();
glPointSize(4);
glTranslatef(-5, 4, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(1.0f, 0.0f, 0.0f); Point();
glPopMatrix();
glPushMatrix();
glTranslatef(0, 4, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(0.0f, 1.0f, 0.0f); Line();
glPopMatrix();
glPushMatrix();
glTranslatef(5, 4, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(0.0f, 0.0f, 1.0f); Triangle();
glPopMatrix();
glPushMatrix();
glTranslatef(-5, 0, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(1.0f, 1.0f, 0.0f); Square();
glPopMatrix();
glPushMatrix();
glTranslatef(0, 0, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(0.0f, 1.0f, 1.0f); Esquare();
glPopMatrix();
glPushMatrix();
glTranslatef(5, 0, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(1.0f, 0.0f, 1.0f); Park();
glPopMatrix();
glPushMatrix();
glTranslatef(-5, -4, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(1.0f, 1.0f, 1.0f); Pillar();
glPopMatrix();
glPushMatrix();
glTranslatef(0, -4, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(0.7f, 0.7f, 0.7f); auxSolidCone(1, 1);
glPopMatrix();
glPushMatrix();
glTranslatef(5, -4, -13); glRotatef(r, 1.0, 1.0, 1.0);
glColor3f(0.4f, 0.4f, 0.4f); auxWireTeapot(1);
glPopMatrix();
}
void MyOpenGL::CopyRect(CRect rect)
{
OpenGLRect.CopyRect(rect);
}
void MyOpenGL::Point(void)//画点
{
glBegin(GL_POINTS);//
glVertex3f(0.0f, 1.0f, -1.0f);//a点
glVertex3f(-1.0f, -1.0f, 0.0f);//b点
glVertex3f(1.0f, -1.0f, 0.0f);//c点
glEnd();
}
void MyOpenGL::Line(void)//画线
{
glBegin(GL_LINE_LOOP); //
glVertex3f(0.0f, 1.0f, -1.0f);//a点
glVertex3f(-1.0f, -1.0f, 0.0f);//b点
glVertex3f(1.0f, -1.0f, 0.0f);//c点
glEnd();
}
void MyOpenGL::Triangle(void)//画面
{
glBegin(GL_POLYGON);//
glVertex3f(0.0f, 1.0f, -1.0f);//a点
glVertex3f(-1.0f, -1.0f, 0.0f);//b点
glVertex3f(1.0f, -1.0f, 0.0f);//c点
glEnd();
}
void MyOpenGL::Square(void)//画正方面
{
glBegin(GL_POLYGON);//
glVertex3f(0.0f, 0.0f, 0.0f);//a点
glVertex3f(1.0f, 0.0f, 0.0f);//b点
glVertex3f(1.0f, 0.0f, -1.0f);//c点
glVertex3f(0.0f, 0.0f, -1.0f);//d点
glEnd();
}
void MyOpenGL::Esquare(void)//画正方体
{
glBegin(GL_QUAD_STRIP);//
glVertex3f(0.0f, 0.0f, 0.0f);//a0点
glVertex3f(0.0f, 1.0f, 0.0f);//a1点
glVertex3f(1.0f, 0.0f, 0.0f);//b0点
glVertex3f(1.0f, 1.0f, 0.0f);//b1点
glVertex3f(1.0f, 0.0f, -1.0f);//c0点
glVertex3f(1.0f, 1.0f, -1.0f);//c1点
glVertex3f(0.0f, 0.0f, -1.0f);//d0点
glVertex3f(0.0f, 1.0f, -1.0f);//d1点
glVertex3f(0.0f, 0.0f, 0.0f);//a0点
glVertex3f(0.0f, 1.0f, 0.0f);//a1点
glEnd();
glBegin(GL_POLYGON);//
glVertex3f(0.0f, 0.0f, 0.0f);//a0点
glVertex3f(1.0f, 0.0f, 0.0f);//b0点
glVertex3f(1.0f, 0.0f, -1.0f);//c0点
glVertex3f(0.0f, 0.0f, -1.0f);//d0点
glVertex3f(0.0f, 1.0f, 0.0f);//a1点
glVertex3f(1.0f, 1.0f, 0.0f);//b1点
glVertex3f(1.0f, 1.0f, -1.0f);//c1点
glVertex3f(0.0f, 1.0f, -1.0f);//d1点
glEnd();
}
void MyOpenGL::Park(void)//画园
{
glBegin(GL_TRIANGLE_FAN);//
glVertex3f(0, 0, 0.0f);
for (int i = 0; i <= 390; i += 30)
{
float p = (float)(i*3.14 / 180);
glVertex3f((float)sin(p), (float)cos(p), 0.0f);
}
glEnd();
}
void MyOpenGL::Pillar(void) //园柱
{
glBegin(GL_QUAD_STRIP);//
for (int i = 0; i <= 390; i += 30)
{
float p = (float)(i*3.14 / 180);
glVertex3f((float)sin(p) / 2, (float)cos(p) / 2, 1.0f);
glVertex3f((float)sin(p) / 2, (float)cos(p) / 2, 0.0f);
}
glEnd();
}
MyOpenGL::MyOpenGL()
{
m_hRC = NULL;
}
MyOpenGL::~MyOpenGL()
{
}
5、在单文档程序LiDARView.h,class CLiDARView 类中添加变量
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
virtual void OnInitialUpdate();
protected:
afx_msg void OnFilePrintPreview();
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
afx_msg void OnTimer(UINT_PTR nIDEvent);
DECLARE_MESSAGE_MAP()
protected:
MyOpenGL *m_OpenGL; //MyOpenGL 对象
CClientDC *m_pdc;
CRect ClientRect;
private:
UINT_PTR TimerID{1};
6、单文档程序view中添加void CLiDARView::OnTimer(UINT_PTR nIDEvent)函数
记得添加消息宏ON_WM_TIMER(),在OnTimer函数中加入以下代码:
static UINT StartTimer = 0;
++StartTimer;
if (StartTimer >= 2)
{
StartTimer = 0;
InvalidateRect(ClientRect);
}
7、单文档程序view中创建virtual void OnInitialUpdate()函数
函数中加入以下代码:
GetClientRect(ClientRect);
m_OpenGL->CopyRect(ClientRect);
8、单文档程序view中创建int CLiDARView::OnCreate(LPCREATESTRUCT lpCreateStruct)函数
加入以下代码:
// TODO: 在此添加您专用的创建代码
m_OpenGL = new MyOpenGL;
m_pdc = NULL;
m_OpenGL->r = 0;
m_pdc = new CClientDC(this);
if (!(m_OpenGL->InitializeOpenGL(m_pdc)))
{
MessageBox(_T("InitializeOpenGL Error"));
return 0;
}
SetTimer(TimerID, 50, NULL); //启动定时器
9、单文档程序void CLiDARView::OnDraw(CDC* pDC)函数
在该函数中加入以下代码:
// TODO: 在此处为本机数据添加绘制代码
m_OpenGL->DisplayModeInit();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
m_OpenGL->RenderScene();
glFinish();
SwapBuffers(wglGetCurrentDC());
m_OpenGL->r = m_OpenGL->r + 10; //显示中的物体产生旋转的角度用 m_OpenGL->r提供
if ((m_OpenGL->r)>360)
{
m_OpenGL->r = 0;
}
10、单文档程序创建void CLiDARView::OnDestroy()函数
该函数用于当窗口关闭时,销毁已创建的资源
// TODO: 在此处添加消息处理程序代码
HGLRC hrc = ::wglGetCurrentContext();
::wglMakeCurrent(NULL,NULL);
if (hrc)
{
::wglDeleteContext(hrc);
}
11、最后重新编译文档并运行
效果图如下: