MFC+OpenGL 编程入门
下面介绍如何在 VC++ 上进行 OpenGL 编程,下面以画一条 Bezier 曲线为例,详细介绍VC++ 上 OpenGL
编程的方法。这里实际上也给出了个 C++ 良好封装性编程的范例。文中给出了详细注释,以便给初学者明确的指引。一步一步地按所述去做,你将顺利地画出第一个 OpenGL 平台上的图形来。
一、产生程序框架 Test.dsw
New Project | MFC Application Wizard (EXE) | "Test" | OK
*注* : 加“”者指要手工敲入的字串
二、导入 Bezier 曲线类的文件。用下面方法产生 BezierCurve.h,BezierCurve.cpp 两个文件:
WorkSpace | ClassView | Test Classes| <右击弹出> New Class | Generic Class(不用MFC类) | "CBezierCurve" | OK
三、编辑好 Bezier 曲线类的定义与实现。写好下面两个文件:
四、设置编译环境:
1. 在 BezierCurve.h 和 TestView.h 内各加上:
2. 在集成环境中,Project | Settings | Link | Object/library module | "opengl32.lib glu32.lib glaux.lib" | OK.同样可以用预编译命令pragma设置,效果相同,代码如下。
五、设置 OpenGL 工作环境:(下面各个操作,均针对 TestView.cpp )
1. 处理 PreCreateWindow(): 设置 OpenGL 绘图窗口的风格
2. 处理 OnCreate():创建 OpenGL 的绘图设备。 OpenGL 绘图的机制是: 先用 OpenGL 的绘图上下文 Rendering Context (简称为 RC ) 把图画好,再把所绘结果通过 SwapBuffer() 函数传给 Window 的绘图上下文 Device Context (简记为 DC).要注意的是,程序运行过程中,可以有多个 DC,但只能有一个 RC。因此当一个 DC 画完图后,要立即释放 RC,以便其它的 DC 也使用。在后面的代码中,将有详细注释。
3. 处理 OnDestroy()
4. 处理 OnEraseBkgnd()
5. 处理 OnDraw()
6. 处理 OnSize()
7 处理 OnLButtonDown()
double CTestView::scrx2glx(int scrx) //可能有毛病,因为点到的位置总
{ //总画不到,望指正
return (double)(scrx-centerx)/double(h);
}
double CTestView::scry2gly(int scry)
{
return (double)(centery-scry)/double(h);
}
附录:
1.CBezierCurve 的声明: (BezierCurve.h)
class CBezierCurve
{
public:
CBezierCurve();
virtual ~CBezierCurve();
void bezier_generation(myPOINT2D P[MAX],int level);
//算法的具体实现
void myDraw();//画曲线函数
public:
void myPolygon(); //画控制多边形
myPOINT2D m_Vertex[MAX];//控制顶点,以数组存储
//myPOINT2D 是一个存二维点的结构
//成员为Gldouble x,y
int m_N; //控制顶点的个数
};
2. CBezierCurve 的实现: (BezierCurve.cpp)
CBezierCurve::CBezierCurve()
{
m_N=4;
m_Vertex[0].x=-0.5f;
m_Vertex[0].y=-0.5f;
m_Vertex[1].x=-0.5f;
m_Vertex[1].y=0.5f;
m_Vertex[2].x=0.5f;
m_Vertex[2].y=0.5f;
m_Vertex[3].x=0.5f;
m_Vertex[3].y=-0.5f;
}
CBezierCurve::~CBezierCurve()
{
}
void CBezierCurve::myDraw()
{
bezier_generation(m_Vertex,LEVEL);
}
void CBezierCurve::bezier_generation(myPOINT2D P[MAX], int level)
{ //算法的具体描述,请参考相关书本
int i,j;
level--;
if(level<0)return;
if(level==0) //不要写成level=0!!!
{
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINES); //画出线段
glVertex2d(P[0].x,P[0].y);
glVertex2d(P[m_N-1].x,P[m_N-1].y);
glEnd();//结束画线段
return; //递归到了最底层,跳出递归
}
myPOINT2D Q[MAX],R[MAX];
for(i=0;i<m_N;i++)
{
Q[i].x=P[i].x;
Q[i].y=P[i].y;
}
for(i=1;i<m_N;i++)
{
R[m_N-i].x=Q[m_N-1].x;
R[m_N-i].y=Q[m_N-1].y;
for(j=m_N-1;j>=i;j--)
{
Q[j].x=(Q[j-1].x+Q[j].x)/double(2);
Q[j].y=(Q[j-1].y+Q[j].y)/double(2);
}
}
R[0].x=Q[m_N-1].x;
R[0].y=Q[m_N-1].y;
bezier_generation(Q,level);
bezier_generation(R,level);
}
void CBezierCurve::myPolygon()
{
glBegin(GL_LINE_STRIP); //画出连线段
glColor3f(0.2f,0.4f,0.4f);
for(int i=0;i<m_N;i++)
{
glVertex2d(m_Vertex[i].x,m_Vertex[i].y);
}
glEnd();//结束画连线段
}
*************本文结束****************************
--
平生不见陈近南,便称英雄亦惘然