基于Viusal C++ 2015 MFC单文档程序中搭建OpenGL框架

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、最后重新编译文档并运行

效果图如下:

猜你喜欢

转载自blog.csdn.net/qq_34911636/article/details/86666112
今日推荐