基于MFC的OpenGL 绘图例程

所 附 的 程 序 用 M F C 完 成 了 一 个 简 单 的OpenGL 作 图, 用OpenGL 的 辅 助 库 画 了 一 个 有 光 照 的 实 心 圆 球。OpenGL 本 身 的 函 数 这 里 就 不 解 释 了, 仅 对 用MFC 编OpenGL 时 需 要 注 意 的 内 容 做 一 个 简 要 的 说 明:

---- 1. 一 旦 设 定 了 一 个DC 的 位 图 格 式, 该DC 所 联 系 的 窗 口 的 位 图 格 式 随 之 设 定。 该 窗 口 若 含 有 子 窗 口 或 者 有 兄 弟 窗 口, 这 些 兄 弟/ 子 窗 口 的 位 图 格 式 没 有 设 成 与 对 应RC 一 致 的 格 式,OpenGL 在 它 们 上 面 作 图 就 容 易 出 错。 故 而OpenGL 作 图 的 窗 口 必 须 具 有WS_CLIPCHILDREN 和 WS_CLIPSIBLINGS 风 格, 程 序 中 在 主 框 窗 的 构 造 函 数 中 用LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,NULL,NULL ); 指 定 了 主 窗 口 的 风 格。

---- 2. 在ANSI C 的OpenGL 编 程 中, 由auxReshapeFunc 定 义 设 置OpenGL 视 口 大 小 和 作 图 尺 寸 的 回 调 函 数。 在MFC 中 应 该 由WM_SIZ 消 息 的 处 理 函 数 来 完 成。 在ANSI C 的OpenGL 编 程 中, 由EauxMainLoop 定 义 作 图 的 回 调 函 数。 在MFC 中 应 该 由WM_PAINT 消 息 的 处 理 函 数 来 处 理。 相 应 的, 由OpenGL 定 义 的 键 盘、 鼠 标 处 理 函 数 都 应 该 由 相 应 的Windows 处 理 函 数 来 响 应。

---- 3. OpenGL 自 己 有 刷 新 背 景 的 函 数glClear, 故 而 应 禁 止Windows 刷 新 窗 口 背 景。 否 则, 当 窗 口 需 要 重 画 时,Windows 会 自 动 先 发 送WM_ERASEBKGND, 而 缺 省 的 处 理 函 数 使 用 白 色 的 背 景 刷。 当OpenGL 使 用 的 背 景 颜 色 不 是 白 色 时, 作 图 时 有 一 帧 白 色 的 闪 烁。 这 种 现 象 在 做 动 画 时 特 别 明 显。 程 序 中 只 需 要 在WM_ERASEBKGND 的 消 息 处 理 函 数 中 禁 止 父 窗 口 类 的 消 息 处 理, 简 单 的 返 回 一 个TRUE 即 可。

---- 4. 由 于OpenGL 的 跨 平 台 性, 它 必 须 用 操 作 系 统 的 调 色 板。 所 以 如 果GL_INDEX_MODE 作 图 时, 必 须 用VC 自 己 定 义 调 色 板。 不 过 一 般 情 况 下, 用GL_RGBA_MODE 模 式 比 较 方 便, 很 少 用 到GL_INDEX_MODE 模 式。

---- 5. 在OpenGL 作 图 期 间,RC 对 应 的DC 不 能 删 除 或 者 释 放。

---- 6. 由 于OpenGL 作 图 时 需 要 长 时 间 占 用DC, 所 以 最 好 把 作 图 窗 口 类 设 成CS_OWNDC。MFC 缺 省 的 窗 口 类 风 格 中 没 有 设 这 一 属 性, 程 序 中 在 主 窗 口C++ 类 的PreCreateWindow 方 法 中 自 己 注 册 了 一 个 窗 口 类, 除 了 设 定 了CS_OWNDC 属 性 以 外, 还 设 定 了CS_HREDRAW、CS_VREDRAW 和CS_SAVEBITS。 设 定CS_HREDRAW、CS_VREDRAW 是 为 了 让 窗 口 缩 放 时 产 生WM_PAINT 消 息, 修 正OpenGL 视 口 和 作 图 尺 寸; 由 于OpenGL 作 图 需 要 很 多 计 算, 设 定CS_SAVEBITS 是 为 了 在OpenGL 窗 口 被 遮 盖 后 显 现 出 来 时, 不 产 生WM_PAINT 消 息, 用 内 存 存 储 的 图 象 来 填 充, 从 而 用 空 间 消 耗 换 取 计 算 时 间。

---- 7. 本 程 序 中 没 有 对OpenGL 函 数 的 出 错 情 况 作 出 处 理。OpenGL 出 错 后 返 回 错 误 码, 不 会 抛 出 异 常; 而 且 在 某 一 个 函 数 出 错 以 后, 后 继 函 数 也 一 般 不 会 出 现 异 常, 只 是 返 回 错 误 码, 一 不 小 心 就 可 能 忽 略 某 些 错 误。 而 对 每 一 个OpenGL 函 数 都 做 出 错 与 否 的 判 断 比 较 麻 烦, 所 以 编 程 序 时 对OpenGL 的 函 数 应 当 非 常 小 心。

---- 参 考 书 籍:

---- 《OpenGL Programmer's Guide》 SGI inc.

---- 《OpenGL 三 维 图 形 程 序 设 计》 廖 朵 朵、 张 华 军 著, 星 球 地 图 出 版 社

---- 《Visual C++ 5.0 联 机 帮 助》

---- 附 程 序:

---- 程 序 运 行 时 必 须 确 定OpenGL32.dll、glu.dll、glaux.dll 在Windows 的System 目 录 下。 如 果 找 不 到 这 些 文 件, 可 以 从Windows 95 OSR2 的 机 器 上 面 将 这 些 文 件 拷 贝 过 来 即 可。 OpenGL 运 行 不 需 要 注 册 库 信 息。 在VC 的STUDIO 中 运 行 程 序 时, 工 程 文 件 中 必 须 加 入OpenGL.H 、glu.h、glaux.h 以 及OpenGL.lib、glu.lib、glaux.lib, 这 些 文 件 由VC 自 带。

---- 主 窗 口 类 定 义(OpenGLWnd.h):

s#if !defined(AFX_OPENGLWND_H__3FB1AB28_0E70
_11D2_9ACA_48543300E17D__INCLUDED_)
#define AFX_OPENGLWND_H__3FB1AB28_0E70_11D2
_9ACA_48543300E17D__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include < afxwin.h >
#include "SimpleGLApp.h"
#include "resource.h"
// OpenGLWnd.h : header file
//
///
//
// COpenGLWnd frame

class COpenGLWnd : public CFrameWnd
{
	DECLARE_DYNCREATE(COpenGLWnd)
public:
	COpenGLWnd();  
// protected constructor used by dynamic creation
protected:
	HGLRC					m_hrc;
	CClientDC				*m_pDC;
// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(COpenGLWnd)
	protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~COpenGLWnd();

	// Generated message map functions
	//{{AFX_MSG(COpenGLWnd)
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnDestroy();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnPaint();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

///
//

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert 
additional declarations immediately before the previous line.

#endif // !defined(AFX_OPENGLWND_H__3FB1AB28_
0E70_11D2_9ACA_48543300E17D__INCLUDED_)
主窗口类的实现(OpenGLWnd.cpp):
// OpenGLWnd.cpp : implementation file
//

#include "stdafx.h"
#include "OpenGLWnd.h"
#include "SimpleGLApp.h"
#include "gl/glu.h"
#include "gl/gl.h"
#include "gl/glaux.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///
//
// COpenGLWnd

IMPLEMENT_DYNCREATE(COpenGLWnd, CFrameWnd)

COpenGLWnd::COpenGLWnd()
{
	m_pDC = NULL;
	m_hrc = 0;
	LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW
 | WS_CLIPCHILDREN | WS_CLIPSIBLINGS
		,NULL,NULL );
}

COpenGLWnd::~COpenGLWnd()
{
}


BEGIN_MESSAGE_MAP(COpenGLWnd, CFrameWnd)
	//{{AFX_MSG_MAP(COpenGLWnd)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



BOOL COpenGLWnd::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized
 code here and/or call the base class
cs.lpszClass = AfxRegisterWndClass(	CS_DBLCLKS	|
					CS_HREDRAW	|
					CS_VREDRAW	|
					CS_SAVEBITS |
					CS_NOCLOSE	|
                  	CS_OWNDC
					,AfxGetApp( )-
> LoadStandardCursor(IDC_ARROW), 0 ,
AfxGetApp( )- >LoadStandardIcon(IDI_APPLICATION));
	return CFrameWnd::PreCreateWindow(cs);
}


int COpenGLWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
    int pixelformat;

    m_pDC = new CClientDC(this);//在客户区作图
	ASSERT(m_pDC != NULL);

	static PIXELFORMATDESCRIPTOR pfd =
	{
        sizeof(PIXELFORMATDESCRIPTOR),  //固定值
        1,                              //固定值
        PFD_DRAW_TO_WINDOW |            // support window
        PFD_SUPPORT_OPENGL |            // support OpenGL
        PFD_TYPE_RGBA,                  // RGBA模式,不用调色板
        16,                             //程序在16位色彩下运行
        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
        32,                             // 32-bit z-buffer
        0,                              // no stencil buffer
        0,                              // no auxiliary buffer
        PFD_MAIN_PLANE,                 // main layer
        0,                              // reserved
        0, 0, 0                         // layer masks ignored
    };


if ( (pixelformat = ChoosePixelFormat
(m_pDC- >GetSafeHdc(), &pfd)) == 0 )
    {
        MessageBox("在该DC上找不到与PFD接近的位图结构");
        return -1;
    }

if (SetPixelFormat(m_pDC- >
GetSafeHdc(), pixelformat, &pfd) == FALSE)
    {
        MessageBox("无法在该DC上设置位图结构");
        return -1;
    }
    m_hrc = wglCreateContext(m_pDC- >GetSafeHdc());
    wglMakeCurrent(m_pDC- >GetSafeHdc(), m_hrc);
	
    glClearDepth(1.0f);
    glEnable(GL_DEPTH_TEST);


    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
	
	return 0;//OpenGL窗口构造成功
}

void COpenGLWnd::OnSize(UINT nType, int cx, int cy) 
{
	CFrameWnd::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
    if(cy > 0)
    {    
        glViewport(0, 0, cx, cy);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
		if (cx < = cy)
   	glOrtho(-3.0,3.0,-3.0 * (GLfloat)cx/(GLfloat)cy,
		3.0 * (GLfloat)cx/(GLfloat)cy,-3.0,3.0);
		else
	glOrtho(-3.0,3.0,-3.0 * (GLfloat)cy/(GLfloat)cx,
		3.0 * (GLfloat)cy/(GLfloat)cx,-3.0,3.0);
        glMatrixMode(GL_MODELVIEW);
    }
}

void COpenGLWnd::OnDestroy() 
{

	CFrameWnd::OnDestroy();
    ::wglMakeCurrent(NULL,  NULL);
    if (m_hrc)
        ::wglDeleteContext(m_hrc);
	if (m_pDC)
        delete m_pDC;
	// TODO: Add your message handler code here
}

BOOL COpenGLWnd::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message
 handler code here and/or call default
	return TRUE;
	//return CFrameWnd::OnEraseBkgnd(pDC);
}

void COpenGLWnd::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	GLfloat light_position[]={2.0f,0.0f,4.0f,0.0f};
	
	// TODO: Add your message handler code here

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

        glTranslatef(0.0f, 0.0f, -2.0f);
		glLightfv(GL_LIGHT0,GL_POSITION,light_position);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);
		glDepthFunc(GL_LESS);
		glEnable(GL_DEPTH_TEST);
		auxSolidSphere(1.0);

    glPopMatrix();

    glFinish();

	// Do not call CFrameWnd::OnPaint() for painting messages
}
应用程序类的定义(SimpleGLApp.h):
#if !defined(AFX_SIMPLEGLAPP_H__3FB1AB29
_0E70_11D2_9ACA_48543300E17D__INCLUDED_)
#define AFX_SIMPLEGLAPP_H__3FB1AB29_0E70
_11D2_9ACA_48543300E17D__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// SimpleGLApp.h : header file
//
#include < afxwin.h >
#include "OpenGLWnd.h"
#include "resource.h"

///
//
// CSimpleGLApp thread

class CSimpleGLApp : public CWinApp
{
	DECLARE_DYNCREATE(CSimpleGLApp)
public:
	CSimpleGLApp(); 
   // protected constructor used by dynamic creation

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CSimpleGLApp)
	public:
	virtual BOOL InitInstance();
	virtual int ExitInstance();
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CSimpleGLApp();

	// Generated message map functions
	//{{AFX_MSG(CSimpleGLApp)
	afx_msg void OnAppExit();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};

///
//

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert 
additional declarations 
immediately before the previous line.

#endif // !defined(AFX_SIMPLEGLAPP_H__3FB1AB29_
0E70_11D2_9ACA_48543300E17D__INCLUDED_)
应用程序类的实现(SimpleGLApp.cpp):
// SimpleGLApp.cpp : implementation file
//

#include "stdafx.h"
#include "SimpleGLApp.h"
#include "OpenGLWnd.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///
//
// CSimpleGLApp

IMPLEMENT_DYNCREATE(CSimpleGLApp, CWinApp)

CSimpleGLApp::CSimpleGLApp()
{
}

CSimpleGLApp::~CSimpleGLApp()
{
}

BOOL CSimpleGLApp::InitInstance()
{
	// TODO:  perform and per-thread initialization here
	m_pMainWnd = new COpenGLWnd();
	m_pMainWnd- >ShowWindow(m_nCmdShow);
	m_pMainWnd- >UpdateWindow();
	return TRUE;
}

int CSimpleGLApp::ExitInstance()
{
	return CWinApp::ExitInstance();
}

BEGIN_MESSAGE_MAP(CSimpleGLApp, CWinApp)
	//{{AFX_MSG_MAP(CSimpleGLApp)
	ON_COMMAND(ID_APP_EXIT, OnAppExit)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

///
//
// CSimpleGLApp message handlers
void CSimpleGLApp::OnAppExit() 
{
	// TODO: Add your command handler code here
	CWinApp::OnAppExit();
}

CSimpleGLApp SimpleGLApp; 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Matlab绘图例程是用来展示如何使用Matlab软件进行绘图的示例代码。Matlab是一种专业的科学与工程计算软件,其中的plot函数可以用于绘制各种类型的图形,如折线图、散点图、柱状图等。 在绘图例程中,通常会先导入所需的数据,然后使用plot函数进行绘图。例如,要绘制一条简单的折线图,可以使用以下代码: ``` x = 1:10; % x轴数据 y = [2 4 6 8 10 12 14 16 18 20]; % y轴数据 plot(x, y); % 绘制折线图 xlabel('x'); % 设置x轴标签 ylabel('y'); % 设置y轴标签 title('折线图'); % 设置图像标题 ``` 此例程中,首先通过声明x和y数组来定义x轴和y轴的值。然后使用plot函数将x和y作为参数传递,绘制出折线图。接下来,使用xlabel函数设置x轴的标签为"x",ylabel函数设置y轴的标签为"y",title函数设置图像的标题为"折线图"。 除了简单的折线图,Matlab还可以绘制其他类型的图形,如散点图、柱状图等。要根据具体需求绘制不同类型的图形,可以参考Matlab的绘图函数文档,了解不同函数的参数和用法。 通过编写和运行Matlab绘图例程,可以更好地理解和掌握Matlab绘图功能,为后续的数据可视化工作提供基础。 ### 回答2: Matlab绘图例程是一种使用Matlab编程语言编写的脚本文件,用于绘制各种图表和图形。Matlab提供了丰富的绘图函数和工具,可以使用这些函数和工具来自定义图表的样式、坐标轴的范围和标签等。 首先,编写Matlab绘图例程需要明确绘制的图表类型,例如散点图、折线图、条形图等。然后,根据绘制图表的需求,选择合适的绘图函数并传入相应的参数。例如,要绘制散点图,可以使用scatter函数,通过传入数据点的坐标和样式参数来绘制散点图。 在绘制图表之前,还可以设置坐标轴范围、标签、标题等属性。可以使用xlabel和ylabel函数设置x轴和y轴的标签,使用title函数设置图表的标题。还可以通过设置axistight函数来自动调整坐标轴的范围,使图表更加美观。 绘图例程还可以包含一些其他的功能,如添加图例、改变线条的风格、添加网格线等。通过调用legend函数,可以在图表中添加图例,用于说明图表中各个元素的含义。可以使用plot函数来绘制折线图,并通过设置线条的颜色、宽度和样式参数来改变线条的风格。通过设置grid函数,可以在图表中添加网格线,提高图表的可读性。 最后,将编写好的Matlab绘图例程保存为脚本文件,并在Matlab命令行中运行该脚本文件即可生成对应的图表。绘图例程可以帮助我们快速生成各种类型的图表,并实现图表的自定义和美化。在科学研究、工程设计和数据分析等领域中,Matlab绘图例程是非常有用的工具。 ### 回答3: Matlab是一种常用的科学计算和数据可视化软件,它提供了丰富的绘图函数和工具,可以帮助用户快速绘制出各种类型的图表和图像。 在Matlab中,绘图例程是一种用于制作可视化图形的程序或脚本。它由一系列的绘图命令组成,用于指定绘图的数据、图表类型、颜色、标题、标签等信息。 使用Matlab绘图例程的基本步骤如下: 1. 准备数据:首先,需要准备好要绘制的数据。可以使用Matlab提供的函数生成数据,或者从外部源导入数据。 2. 设置绘图参数:在绘图之前,需要设置一些绘图参数,如图表类型、颜色、线型、标题、标签等。可以使用Matlab提供的命令来设置这些参数。 3. 绘制图表:使用Matlab提供的绘图函数,按照准备好的数据和设置好的参数绘制图表。常用的绘图函数有plot、bar、scatter等。 4. 添加额外元素:根据需求,可以添加额外的元素到图表中,如网格、注释、图例等。这些元素可以增强图表的可读性和可视化效果。 5. 显示图表:最后,使用Matlab提供的显示命令将绘制好的图表显示在屏幕上。 绘图例程在科学研究、工程设计、数据分析等领域都有广泛的应用。它可以帮助我们更直观地理解数据,从而做出合理的决策和推断。 总之,Matlab绘图例程是一种有效的数据可视化方法,通过简单的代码实现复杂的图表绘制,为科学研究和数据分析提供了强大的工具。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值