MFC+OpenGL 编程入门.docx

上传人:b****6 文档编号:6794976 上传时间:2023-01-10 格式:DOCX 页数:13 大小:19.67KB
下载 相关 举报
MFC+OpenGL 编程入门.docx_第1页
第1页 / 共13页
MFC+OpenGL 编程入门.docx_第2页
第2页 / 共13页
MFC+OpenGL 编程入门.docx_第3页
第3页 / 共13页
MFC+OpenGL 编程入门.docx_第4页
第4页 / 共13页
MFC+OpenGL 编程入门.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

MFC+OpenGL 编程入门.docx

《MFC+OpenGL 编程入门.docx》由会员分享,可在线阅读,更多相关《MFC+OpenGL 编程入门.docx(13页珍藏版)》请在冰豆网上搜索。

MFC+OpenGL 编程入门.docx

MFC+OpenGL编程入门

标题:

MFC+OpenGL编程入门发信人:

qhchen(老道),信区:

VR_3D

发信站:

BBS水木清华站(MonAug917:

55:

551999)

MFC+OpenGL编程入门

1998-09-08

中国科技大学数学系计算专业老道

E-mail:

qhchen@

OpenGL作图非常方便,故日益流行,但对许多人来说,是在微机上

进行的,首先碰到的问题是,如何适应微机环境。

这往往是最关键的一步,

虽然也是最初级的。

下面介绍如何在VC++上进行OpenGL编程。

其实相当简单明快,只

因国内缺少这方面的资料与例子,致使许多小细节要一个一个地试,耗去

大量时间。

希望各位有什么心得体会,也公布出来,从而节省每个人都要

试试的时间。

言归正传,下面以画一条Bezier曲线为例,详细介绍VC++上OpenGL

编程的方法。

这里实际上也给出了个C++良好封装性编程的范例。

文中给

出了详细注释,以便给初学者明确的指引。

一步一步地按所述去做,你将顺

利地画出第一个OpenGL平台上的图形来。

(本文例子以VC++5.0为背景)

一、产生程序框架Test.dsw

NewProject|MFCApplicationWizard(EXE)|"Test"|OK

*注*:

加“”者指要手工敲入的字串

二、导入Bezier曲线类的文件。

用下面方法产生BezierCurve.h

BezierCurve.cpp两个文件:

WorkSpace|ClassView|TestClasses|<右击弹出>NewClass

|GenericClass(不用MFC类)|"CBezierCurve"|OK

三、编辑好Bezier曲线类的定义与实现。

写好下面两个文件:

BezierCurve.h

BezierCurve.cpp

四、设置编译环境:

1.在BezierCurve.h和TestView.h内各加上:

#include

#include

#include

2.在集成环境中,Project|Settings|Link|Object/librarymodule

|"opengl32.libglu32.libglaux.lib"|OK

五、设置OpenGL工作环境:

(下面各个操作,均针对TestView.cpp)

1.处理PreCreateWindow():

设置OpenGL绘图窗口的风格

cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN|CS_OWNDC;

2.处理OnCreate():

创建OpenGL的绘图设备。

OpenGL绘图的机制

是:

先用OpenGL的绘图上下文RenderingContext(简称为RC)

把图画好,再把所绘结果通过SwapBuffer()函数传给Window的

绘图上下文DeviceContext(简记为DC).要注意的是,程序运行

过程中,可以有多个DC,但只能有一个RC。

因此当一个DC画完图

后,要立即释放RC,以便其它的DC也使用。

在后面的代码中,将有

详细注释。

intCTestView:

:

OnCreate(LPCREATESTRUCTlpCreateStruct)

{

if(CView:

:

OnCreate(lpCreateStruct)==-1)

return-1;

Init();

return0;

}

voidCTestView:

:

Init()

{

m_pDC=newCClientDC(this);//创建DC

ASSERT(m_pDC!

=NULL);

if(!

bSetupPixelFormat())//设定绘图的位图格式,函数下面列出

return;

m_hRC=wglCreateContext(m_pDC->m_hDC);//创建RC

wglMakeCurrent(m_pDC->m_hDC,m_hRC);//RC与当前DC相关联

}//CClient*m_pDC;HGLRCm_hRC;是CTestView的成员变量

BOOLCTestView:

:

bSetupPixelFormat()

{

staticPIXELFORMATDESCRIPTORpfd=

{

sizeof(PIXELFORMATDESCRIPTOR),//sizeofthispfd

1,//versionnumber

PFD_DRAW_TO_WINDOW|//supportwindow

PFD_SUPPORT_OPENGL|//supportOpenGL

PFD_DOUBLEBUFFER,//doublebuffered

PFD_TYPE_RGBA,//RGBAtype

24,//24-bitcolordepth

0,0,0,0,0,0,//colorbitsignored

0,//noalphabuffer

0,//shiftbitignored

0,//noaccumulationbuffer

0,0,0,0,//accumbitsignored

32,//32-bitz-buffer

0,//nostencilbuffer

0,//noauxiliarybuffer

PFD_MAIN_PLANE,//mainlayer

0,//reserved

0,0,0//layermasksignored

};

intpixelformat;

if((pixelformat=ChoosePixelFormat(m_pDC->m_hDC,&pfd))==0)

{

MessageBox("ChoosePixelFormatfailed");

returnFALSE;

}

if(SetPixelFormat(m_pDC->m_hDC,pixelformat,&pfd)==FALSE)

{

MessageBox("SetPixelFormatfailed");

returnFALSE;

}

returnTRUE;

}

3.处理OnDestroy()

voidCTestView:

:

OnDestroy()

{

wglMakeCurrent(m_pDC->m_hDC,NULL);//释放与m_hDC对应的RC

wglDeleteContext(m_hRC);//删除RC

if(m_pDC)

deletem_pDC;//删除当前View拥有的DC

CView:

:

OnDestroy();

}

4.处理OnEraseBkgnd()

BOOLCTestView:

:

OnEraseBkgnd(CDC*pDC)

{

//TODO:

Addyourmessagehandlercodehereand/orcalldefault

//returnCView:

:

OnEraseBkgnd(pDC);//把这句话注释掉,若不然,Window

//会用白色北景来刷新,导致画面闪烁

returnTRUE;//只要空返回即可。

}

5.处理OnDraw()

voidCTestView:

:

OnDraw(CDC*pDC)

{

wglMakeCurrent(m_pDC->m_hDC,m_hRC);//使RC与当前DC相关联

DrawScene();//具体的绘图函数,在RC中绘制

SwapBuffers(m_pDC->m_hDC);//把RC中所绘传到当前的DC上,从而

//在屏幕上显示

wglMakeCurrent(m_pDC->m_hDC,NULL);//释放RC,以便其它DC进行绘图

}

voidCTestView:

:

DrawScene()

{

glClearColor(0.0f,0.0f,0.0f,1.0f);//设置背景颜色为黑色

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glTranslated(0.0f,0.0f,-3.0f);//把物体沿(0,0,-1)方向平移

//以便投影时可见。

因为缺省的视点在(0,0,0),只有移开

//物体才能可见。

//本例是为了演示平面Bezier曲线的,只要作一个旋转

//变换,可更清楚的看到其3D效果。

//如?

glRotated(30,1.0f,0.0f,0.0f);//绕X轴转30度

//glRotated(30,0.0f,1.0f,0.0f);//绕Y轴转30度

glBegin(GL_LINES);//画坐标系,由三条线段组成

glColor3f(1,0,0);

glVertex3f(0,0,0);

glVertex3f(1,0,0);//X坐标

glColor3f(0,1,0);

glVertex3f(0,0,0);

glVertex3f(0,1,0);//Y坐标

glColor3f(0,0,1);

glVertex3f(0,0,0);

glVertex3f(0,0,1);//Z坐标

glEnd();//enddrawthe3Daxis

//下面画一条Bezier曲线

bezier_curve.myPolygon();//画Bezier曲线的控制多边形

bezier_curve.myDraw();//CBezierCurvebezier_curve

//是CTestView的成员变量

//具体的函数见附录

glPopMatrix();

glFinish();//结束RC绘图

return;

}

6.处理OnSize()

voidCTestView:

:

OnSize(UINTnType,intcx,intcy)

{

CView:

:

OnSize(nType,cx,cy);

VERIFY(wglMakeCurrent(m_pDC->m_hDC,m_hRC));//确认RC与当前DC关联

GLResize(cx,cy);//具体的响应WM_SIZE消息,对投影进行修正

VERIFY(wglMakeCurrent(NULL,NULL));//确认DC释放RC

}

voidGLResize(GLsizeiw,GLsizeih)//GLResize()是一个全局函数

{

//Preventadividebyzero

if(h==0)

h=1;

glViewport(0,0,w,h);//设置视口

glMatrixMode(GL_PROJECTION);//进入投影变换状态

glLoadIdentity();

//重新进行投影变换

gluPerspective(20.0f,(GLdouble)w/(GLdouble)h,1.0,40.0f);

glMatrixMode(GL_MODELVIEW);//结束投影变换

glLoadIdentity();

}

7处理OnLButtonDown()

voidCTestView:

:

OnLButtonDown(UINTnFlags,CPointpoint)

{

CView:

:

OnLButtonDown(nFlags,point);

if(bezier_curve.m_N>MAX-1)

{

MessageBox("顶点个数超过了最大数MAX=50");

return;

}

//以下为坐标变换作准备,

//说明:

OpenGL有一个更有力处理方式,即用gluUnProject()

//这里为了证券交易起见,自己处理。

GetClientRect(&m_ClientRect);//获取视口区域大小

w=m_ClientRect.right-m_ClientRect.left;//视口宽度w

h=m_ClientRect.bottom-m_ClientRect.top;//视口高度h

//w,h是CTestView的成员变量

centerx=(m_ClientRect.left+m_ClientRect.right)/2;//中心位置,

centery=(m_ClientRect.top+m_ClientRect.bottom)/2;//取之作原点

//centerx,centery是CTestView的成员变量

GLdoubletmpx,tmpy;

tmpx=scrx2glx(point.x);//屏幕上点坐标转化为OpenGL画图的规范坐标

tmpy=scry2gly(point.y);

bezier_curve.m_Vertex[bezier_curve.m_N].x=tmpx;//加一个顶点

bezier_curve.m_Vertex[bezier_curve.m_N].y=tmpy;

bezier_curve.m_N++;//顶点数加一

InvalidateRect(NULL,TRUE);//发送刷新重绘消息

}

doubleCTestView:

:

scrx2glx(intscrx)//可能有毛病,因为点到的位置总

{//总画不到,望指正

return(double)(scrx-centerx)/double(h);

}

doubleCTestView:

:

scry2gly(intscry)

{

return(double)(centery-scry)/double(h);

}

附录:

1.CBezierCurve的声明:

(BezierCurve.h)

classCBezierCurve

{

public:

CBezierCurve();

virtual~CBezierCurve();

voidbezier_generation(myPOINT2DP[MAX],intlevel);

//算法的具体实现

voidmyDraw();//画曲线函数

public:

voidmyPolygon();//画控制多边形

myPOINT2Dm_Vertex[MAX];//控制顶点,以数组存储

//myPOINT2D是一个存二维点的结构

//成员为Gldoublex,y

intm_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()

{

}

voidCBezierCurve:

:

myDraw()

{

bezier_generation(m_Vertex,LEVEL);

}

voidCBezierCurve:

:

bezier_generation(myPOINT2DP[MAX],intlevel)

{//算法的具体描述,请参考相关书本

inti,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;//递归到了最底层,跳出递归

}

myPOINT2DQ[MAX],R[MAX];

for(i=0;i

{

Q[i].x=P[i].x;

Q[i].y=P[i].y;

}

for(i=1;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);

}

voidCBezierCurve:

:

myPolygon()

{

glBegin(GL_LINE_STRIP);//画出连线段

glColor3f(0.2f,0.4f,0.4f);

for(inti=0;i

{

glVertex2d(m_Vertex[i].x,m_Vertex[i].y);

}

glEnd();//结束画连线段

}

*************本文结束****************************

--

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 幼儿读物

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1