如何利用OpenGL在MFC中开发出一个简单的喷泉模拟程序探讨
1个回答
展开全部
1 OpenGL绘图环境初始化
OpenGL是一个跨平台的三维图形库,可在Windows、Unix和Mac等平台上运行。而Visual
C++完善的基本类库MFC和应用向导AppWizard使得开发一个复杂的应用程序变得轻松自如。如果将两者结合,便可开发出较高水平的Windows下三维图形应用程序[1]。
在3D游戏的渲染过程中,传统的建模方法一般只适用于外形比较规则的形体,对于那些像雨、雪、瀑布、喷泉以及火焰等没有固定形状,甚至要随着外部环境或者其他因素的改变而改变的物质建模,传统的方法就显得无能为力了[2]。1983年REEVES
W T提出了一种新的建模方法,称为模糊物体建模,该方法就是粒子系统,它的出现正好解决了上述问题[3]。
OpenGL函数库和操作系统无关,它有自己的独特设计,与Windows的图像设备接口GDI模型以及多数MFC应用程序的建立方法不太一致。在Windows系统中,这样的一组函数称为wiggle函数,每个wiggle函数的前缀是“wgl”。
在Win32下,首先必须重新设置画图窗口的像素格式,使其符合OpenGL对像素格式的需要。为此,声明一个PIXELFORMATDESCRIPTOR结构的变量,并适当设置其结构成员的值,使其支持OpenGL及其颜色模式。再以此变量为参数调用ChoosePixelFormat(),分配一个像素格式号,然后调用SetPixelFormat()将其设置为当前像素格式。
完成了像素格式的重新设置后,需要为OpenGL建立绘制描述表(Render
Context)。绘制描述表的作用类似于Windows中的设备描述表(DevICe
Context)。只有建立了绘制描述表RC后,OpenGL才能调用绘图原语在窗口中做出图形。Win32API提供了几个操作绘制描述表的函数,包括建立、复制、使用、删除和查询等,它们都以wgl为词头。RC是以线程为单位的,每一个线程必须使用一个RC作为当前RC才能执行OpenGL绘图原语。
wglCreateContext()是建立绘制描述表的函数,它以一个指向GDI设备描述表的句柄为参数,返回一个与此设备描述表相关联的绘制描述表句柄。在以此2句柄为参数调用函数wglMakeCurrent(),使RC成为线程当前使用的RC,完成Windows下OpenGL绘图环境的初始化过程[4]。
2 建立OpenGL单文档应用程序框架
使用Visual C++的AppWizard和Class Wizard可以很容易地生成一个使用MFC的OpenGL单文档应用程序框架,名称为MyFountain。
2.1 PreCreateWindow方法
BOOL CMySDOpenGLView:: PreCreateWindow(CREATESTRUCT& cs)
{
cs.style|=WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
return CView::PreCreateWindow(cs);
}
使视窗口具有WS_CLIPCHILDREN和WS_CLIPSIBLINGS风格,确保成功地设置像素格式。
2.2 添加消息响应函数
利用MFC ClassWizard为CMySDOpenGLView类添加消息WM_CREATE、WM_DESTROY、WM_SIZE和WM_TIMER的响应函数。
首先在OnCreate方法中初始化OpenGL,并设置定时器。
然后在OnTimer响应函数中添加定时器响应函数和场景更新命令,使得程序按照定时器设置的时间步长进行中断,并调用OnDraw对场景进行更新、渲染。
第三步,添加OnSize函数对用户进行窗口调整的消息进行响应,并即时调整窗口的大小[5]。
最后,当关闭窗口时,将值NULL(或0)赋值给wglMakeCurrent()的参数hRC后,调用wglDeleteContext()删除绘制描述表,并删除调色板和定时器。
3 基于粒子系统的喷泉模拟
构造可视化系统的建模技术大致可以分为两类:几何建模和行为建模。几何建模处理物体的几何和形状的表示,研究图形数据结构等基本问题;行为建模处理物体运动和行为的描述。
一个粒子系统由大量称为粒子的简单体素构成。每个粒子有一组属性,如位置、速度、颜色和生命期。一个粒子究竟有什么样的属性,主要取决于具体的应用。粒子的初值由随机过程产生。粒子往往由位于空间的某个地方的粒子源产生。
粒子系统也利用了随机过程,并常将物体的几何和行为组合在一个有机模型中。
一个粒子系统是不断进化的。在生命期的每一刻,都要完成以下4步工作:
(1)粒子源产生新粒子。产生任意数目的新粒子,它们的初始属性由随机过程控制。每个粒子都有一个生命期,如果某些粒子不应删除,则可以赋予它无限长的生命期。
(2)更新现有粒子属性。例如,若粒子有位置和速度属性,在模拟重力场中的运动时,可以如下更新粒子的位置和速度属性:
v=v+gts=s+vt
在该步中,粒子的生命期递减一个时间步。
(3)删除“死”粒子。检查粒子的生命期,若为0则将粒子从系统中删除。
(4)绘制粒子。显示粒子系统中所有现存的粒子。
在一般情况下,粒子的几何特征十分简单,可以采用一个像素或小的多边形来代表[6]。
3.1 粒子数据结构的定义
粒子数据结构的定义如下:
struct particle
{
float t; //粒子的生命期
float vel; //粒子运动的速度
float dir; //粒子运动的方向
float x,y,z; //粒子的位置坐标
float xd,zd; //粒子的X和Z方向增加值
char type; //粒子类型(运动或淡化)
float a; //淡化alpha值
struct particle*next,*prev;
};
3.2 绘制喷泉
3.2.1 先构造一个场景
由于重点是喷泉,因此简单构造一个模拟的地面能突出喷泉就可以了。实现代码如下:
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D,texture[1]);
a+=0.2;
gluLookAt(cam.x,cam.y,cam.z,0,0,0,upv.x,upv.y, upv.z);
3.2.2 喷泉的渲染处理
喷泉的渲染处理过程主要是利用了OpenGL的特征函数[7]和方法,主要进行了两方面的处理:(1)将喷泉模型渲染成纹理文件[8];(2)采用透明纹理渲染技术[9]。
3.2.3 喷泉的实现
在构造了简单的地面场景后,取以原点为中心的圆周上的均匀点序列作为喷泉的喷射点,按照上述提到的绘制方法[10]即完成了喷泉的动态模拟。喷泉系统模拟的主要关键代码在于向内存中添加渲染粒子,即函数AddParticles(),之后粒子将按照预定的轨道运行,其主要实现代码如下:
//添加新的粒子
void CMyFountainView::AddParticles()
{
struct particle*tempp;
int i, j;
for (j=0;j<18;j++)
for (i=0;i<2;i++)
{
tempp=(struct particle*)malLOC(sizeof(struct particle));
if (fn[j])fn[j]->prev=tempp;
tempp->next=fn[j];
fn[j]=tempp;
tempp->t=-9.9; //粒子的生命期
tempp->v=(float)(rand()%200000)/100000+1;
// 粒子速度
tempp->d=(float)(rand()%400)/100-2;
//粒子方向
tempp->x=20*cos((j*3.14159)/180); //开始位置的坐标
tempp->y=0;
tempp->z=20*sin((j*3.14159)/180);
tempp->xd=cos((tempp->d*3.14159)/180)*tempp->v/4;
tempp->zd=sin((tempp->d*3.14159)/180)*tempp->v;
tempp->type=0; //粒子状态为运动
tempp->a=1; //粒子淡化
}
}
OpenGL是一个跨平台的三维图形库,可在Windows、Unix和Mac等平台上运行。而Visual
C++完善的基本类库MFC和应用向导AppWizard使得开发一个复杂的应用程序变得轻松自如。如果将两者结合,便可开发出较高水平的Windows下三维图形应用程序[1]。
在3D游戏的渲染过程中,传统的建模方法一般只适用于外形比较规则的形体,对于那些像雨、雪、瀑布、喷泉以及火焰等没有固定形状,甚至要随着外部环境或者其他因素的改变而改变的物质建模,传统的方法就显得无能为力了[2]。1983年REEVES
W T提出了一种新的建模方法,称为模糊物体建模,该方法就是粒子系统,它的出现正好解决了上述问题[3]。
OpenGL函数库和操作系统无关,它有自己的独特设计,与Windows的图像设备接口GDI模型以及多数MFC应用程序的建立方法不太一致。在Windows系统中,这样的一组函数称为wiggle函数,每个wiggle函数的前缀是“wgl”。
在Win32下,首先必须重新设置画图窗口的像素格式,使其符合OpenGL对像素格式的需要。为此,声明一个PIXELFORMATDESCRIPTOR结构的变量,并适当设置其结构成员的值,使其支持OpenGL及其颜色模式。再以此变量为参数调用ChoosePixelFormat(),分配一个像素格式号,然后调用SetPixelFormat()将其设置为当前像素格式。
完成了像素格式的重新设置后,需要为OpenGL建立绘制描述表(Render
Context)。绘制描述表的作用类似于Windows中的设备描述表(DevICe
Context)。只有建立了绘制描述表RC后,OpenGL才能调用绘图原语在窗口中做出图形。Win32API提供了几个操作绘制描述表的函数,包括建立、复制、使用、删除和查询等,它们都以wgl为词头。RC是以线程为单位的,每一个线程必须使用一个RC作为当前RC才能执行OpenGL绘图原语。
wglCreateContext()是建立绘制描述表的函数,它以一个指向GDI设备描述表的句柄为参数,返回一个与此设备描述表相关联的绘制描述表句柄。在以此2句柄为参数调用函数wglMakeCurrent(),使RC成为线程当前使用的RC,完成Windows下OpenGL绘图环境的初始化过程[4]。
2 建立OpenGL单文档应用程序框架
使用Visual C++的AppWizard和Class Wizard可以很容易地生成一个使用MFC的OpenGL单文档应用程序框架,名称为MyFountain。
2.1 PreCreateWindow方法
BOOL CMySDOpenGLView:: PreCreateWindow(CREATESTRUCT& cs)
{
cs.style|=WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
return CView::PreCreateWindow(cs);
}
使视窗口具有WS_CLIPCHILDREN和WS_CLIPSIBLINGS风格,确保成功地设置像素格式。
2.2 添加消息响应函数
利用MFC ClassWizard为CMySDOpenGLView类添加消息WM_CREATE、WM_DESTROY、WM_SIZE和WM_TIMER的响应函数。
首先在OnCreate方法中初始化OpenGL,并设置定时器。
然后在OnTimer响应函数中添加定时器响应函数和场景更新命令,使得程序按照定时器设置的时间步长进行中断,并调用OnDraw对场景进行更新、渲染。
第三步,添加OnSize函数对用户进行窗口调整的消息进行响应,并即时调整窗口的大小[5]。
最后,当关闭窗口时,将值NULL(或0)赋值给wglMakeCurrent()的参数hRC后,调用wglDeleteContext()删除绘制描述表,并删除调色板和定时器。
3 基于粒子系统的喷泉模拟
构造可视化系统的建模技术大致可以分为两类:几何建模和行为建模。几何建模处理物体的几何和形状的表示,研究图形数据结构等基本问题;行为建模处理物体运动和行为的描述。
一个粒子系统由大量称为粒子的简单体素构成。每个粒子有一组属性,如位置、速度、颜色和生命期。一个粒子究竟有什么样的属性,主要取决于具体的应用。粒子的初值由随机过程产生。粒子往往由位于空间的某个地方的粒子源产生。
粒子系统也利用了随机过程,并常将物体的几何和行为组合在一个有机模型中。
一个粒子系统是不断进化的。在生命期的每一刻,都要完成以下4步工作:
(1)粒子源产生新粒子。产生任意数目的新粒子,它们的初始属性由随机过程控制。每个粒子都有一个生命期,如果某些粒子不应删除,则可以赋予它无限长的生命期。
(2)更新现有粒子属性。例如,若粒子有位置和速度属性,在模拟重力场中的运动时,可以如下更新粒子的位置和速度属性:
v=v+gts=s+vt
在该步中,粒子的生命期递减一个时间步。
(3)删除“死”粒子。检查粒子的生命期,若为0则将粒子从系统中删除。
(4)绘制粒子。显示粒子系统中所有现存的粒子。
在一般情况下,粒子的几何特征十分简单,可以采用一个像素或小的多边形来代表[6]。
3.1 粒子数据结构的定义
粒子数据结构的定义如下:
struct particle
{
float t; //粒子的生命期
float vel; //粒子运动的速度
float dir; //粒子运动的方向
float x,y,z; //粒子的位置坐标
float xd,zd; //粒子的X和Z方向增加值
char type; //粒子类型(运动或淡化)
float a; //淡化alpha值
struct particle*next,*prev;
};
3.2 绘制喷泉
3.2.1 先构造一个场景
由于重点是喷泉,因此简单构造一个模拟的地面能突出喷泉就可以了。实现代码如下:
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D,texture[1]);
a+=0.2;
gluLookAt(cam.x,cam.y,cam.z,0,0,0,upv.x,upv.y, upv.z);
3.2.2 喷泉的渲染处理
喷泉的渲染处理过程主要是利用了OpenGL的特征函数[7]和方法,主要进行了两方面的处理:(1)将喷泉模型渲染成纹理文件[8];(2)采用透明纹理渲染技术[9]。
3.2.3 喷泉的实现
在构造了简单的地面场景后,取以原点为中心的圆周上的均匀点序列作为喷泉的喷射点,按照上述提到的绘制方法[10]即完成了喷泉的动态模拟。喷泉系统模拟的主要关键代码在于向内存中添加渲染粒子,即函数AddParticles(),之后粒子将按照预定的轨道运行,其主要实现代码如下:
//添加新的粒子
void CMyFountainView::AddParticles()
{
struct particle*tempp;
int i, j;
for (j=0;j<18;j++)
for (i=0;i<2;i++)
{
tempp=(struct particle*)malLOC(sizeof(struct particle));
if (fn[j])fn[j]->prev=tempp;
tempp->next=fn[j];
fn[j]=tempp;
tempp->t=-9.9; //粒子的生命期
tempp->v=(float)(rand()%200000)/100000+1;
// 粒子速度
tempp->d=(float)(rand()%400)/100-2;
//粒子方向
tempp->x=20*cos((j*3.14159)/180); //开始位置的坐标
tempp->y=0;
tempp->z=20*sin((j*3.14159)/180);
tempp->xd=cos((tempp->d*3.14159)/180)*tempp->v/4;
tempp->zd=sin((tempp->d*3.14159)/180)*tempp->v;
tempp->type=0; //粒子状态为运动
tempp->a=1; //粒子淡化
}
}
意法半导体(中国)投资有限公司
2023-06-12 广告
2023-06-12 广告
单片机汇编程序是用汇编语言编写的程序,用于控制单片机的操作。汇编语言是一种比较接近计算机硬件语言的低级语言,相对于高级语言来说更容易理解和实现。下面是单片机汇编程序的基本步骤:1. 将代码和数据汇编到规定的段中。2. 在存储器中用未初始化的...
点击进入详情页
本回答由意法半导体(中国)投资有限公司提供
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询