火焰 粒子系统 OpenGL - 图文
更新时间:2023-11-14 15:44:01 阅读量: 教育文库 文档下载
- 火焰视频推荐度:
- 相关推荐
课 程 设 计 报告
题 目 基于openGL的粒子系统——模拟火焰 系 (部) 专 业 班 级 学生姓名 学 号
起止时间:
指导教师(签字) 系 主 任(签字)
提交时间:
一、设计任务及要求: 设计任务:
要 求: 此次课程设计的课题为通过编程,实现火焰的绘制。实现交互控制火焰颜色、火焰燃烧方向、贴图形状,通过实验得到火焰贴图大小与火焰效果的关系,并给出代码和结果截图。 指导教师签名: 年 月 日 二、指导教师评语: 指导教师签名: 年 月 日 三、成绩
计算机图形学课程设计报告
1.课程设计目的
本学期系统学习了《计算机图形学》这门专业课,在学期期末按课程要求进行实验。粒子系统由Reeves于1983年首次提出,此后越来越受到重视,它的主要优点是可以利用非常简单的体素来构造复杂的物体,为自然现象(如火焰、雨、雪、树林等)的造型提供了强有力的技术手段。
该课程设计以培养我们算法设计与实现的能力为目标,通过实践,使我们了解、掌握计算机图形学的基本知识和关键技术、了解和熟悉计算机图形学的方法、工具和环境,同时培养我们的思维能力和团队合作能力。 2.课程设计描述及要求
粒子系统的基本思想是用许多形状简单且赋予生命的微小粒子作为基本元素来表示基本物体,侧重于物体的总体形态和特征的动态变化。把物体定义为许多不规则、随机分布的粒子,且每个粒子均有一定的生命周期。随着时间的推移,旧的粒子不断消失(死亡),新的粒子不断加入(生长)。粒子的这种出生、成长、衰老、死亡的过程,能够较好的反应模糊物体的动态特征。一个粒子系统是不断进化的,在生命周期的每一刻,都要完成以下四步:
初始化粒子 更新粒子 删除死粒子 绘制粒子 第一步产生5000个新粒子,他们的每个粒子都有生命周期为2; 第二步根据情况更新,递减一个随机的时间步;
第三步检查粒子的生命期,若为零,则将粒子从系统中删除; 第四步显示粒子系统中的粒子。 要求:
此次课程设计的课题为通过编程,实现火焰的绘制。实现交互控制火焰颜色、火焰燃烧方向、
贴图形状,通过实验得到火焰贴图大小与火焰效果的关系,并给出代码和结果截图。 3.系统开发环境 开发工具:VC 6.0
操作系统:Microsoft Windows 7 4、粒子系统(火焰)的算法原理
4.1 定义粒子的属性
宏定义粒子的最大数目5000,并定义结构体来设置粒子属性,代码如下: #define MAX_PARTICLES 5000 typedef struct { } particles;
bool float float float float float float float float float float float float float float
active; life; fade; r; g; b; x; y; z; xi; yi; zi; xg; yg; zg;
//
// 粒子数的数目
// 创建结构体
// 粒子生命周期
// 消失的速度 // 坐标 // 坐标 // 坐标
// X轴加速度 // Y轴加速度 // Z轴加速度
particles particle[MAX_PARTICLES]; // 创建粒子数组 4.2 初始化粒子
利用循环变量loop,loop小于等于最大粒子数目时,则初始化每一个粒子,代码如下: for (loop=0;loop { particle[loop].active=true; particle[loop].life=2.0f; //生命期 particle[loop].fade=float(rand()0)/1500.0f+0.002f; //消失速度(随机) particle[loop].r=colors[loop*(4/MAX_PARTICLES)][0]; } particle[loop].g=colors[loop*(4/MAX_PARTICLES)][1]; particle[loop].b=colors[loop*(4/MAX_PARTICLES)][2]; particle[loop].xg=0.0f; particle[loop].yg=0.3f; particle[loop].zg=0.0f; 4.3 粒子消失的过程 (1)定义消失变量,使粒子的生命期递减一个随机的生命步,代码如下: particle[loop].fade=float(rand()0)/1500.0f+0.002f; (2)粒子的颜色透明度随着生命期的减少而降低,最终消失,代码如下: glColor4f(particle[loop].r,particle[loop].g,particle[loop].b,particle[loop].life); 4.4 绘制及更新粒子 (1)设置粒子的运动状态,代码如下: particle[loop].x+=particle[loop].xi/(slowdown*1050); //X的坐标随X轴速度变化 particle[loop].y+=particle[loop].yi/(slowdown*1050); particle[loop].z+=particle[loop].zi/(slowdown*1050); particle[loop].xi+=particle[loop].xg; // X轴的速度随X轴的加速度变化 particle[loop].yi+=particle[loop].yg; particle[loop].zi+=particle[loop].zg; // 周期衰减 particle[loop].life-=particle[loop].fade; (2)当粒子生命期衰减为0时,更新粒子,代码如下: if (particle[loop].life<0.0f) { particle[loop].life=2.0f; particle[loop].fade=float(rand()0)/1500.0f+0.002f; particle[loop].x=0.0f; particle[loop].y=0.0f; particle[loop].z=0.0f; particle[loop].xi=float((rand()`)-30.0f); particle[loop].yi=float((rand()`)-30.0f); particle[loop].zi=float((rand()`)-30.0f); particle[loop].r=colors[col][0]; //渲染 particle[loop].g=colors[col][1]; //渲染 particle[loop].b=colors[col][2]; //渲染 particle[loop].xg=xg1; particle[loop].yg=yg1; } particle[loop].zg=0.0f; 5、实现交互的原理 5.1 键盘和鼠标主菜单控制火焰颜色 (1)定义颜色数组及设置火焰颜色: static GLfloat colors[8][3]= // 颜色数组 { {0.0f,0.0f,0.0f},{0.5f,0.75f,1.0f},{1.0f,0.75f,0.5f},{0.75f,1.0f,0.5f}, {1.0f,0.5f,0.75f}, {0.35f,0.8f,0.5f}, {0.55f,0.25f,0.75f},{0.5f,0.5f,0.75f}, }; particle[loop].r=colors[col][0]; particle[loop].g=colors[col][1]; particle[loop].b=colors[col][2]; //渲染 //渲染 //渲染 (2)用键盘的“q”“w”“a”“s”“z”键和主菜单选择数组中相应行的RGB值来改变火焰颜色,代码如下: void keyboard(unsigned char key,int x,int y) //定义键盘功能 { switch(key) { case 'q': { col=3; xg1+=0.05; glutPostRedisplay(); //重绘函数 } break; case 'w': { col=4; yg1+=0.05; glutPostRedisplay(); } break; case 'a': { col=5; xg1-=0.05; glutPostRedisplay(); }break; case 's': { col=6; yg1-=0.05; glutPostRedisplay(); } break; case 'z': { col=7; glutPostRedisplay(); } break; default: break; } } void MainMenuHandler(int option) //{ switch(option) { case 0: { exit(0); LoadGLTextures(); } break; case 1: { col=1; 定义主菜单功能 } break; case 2: }break; { col=2; default: break; } glutPostRedisplay(); } void MenuHandler() // 主菜单 { int mainMenu; mainMenu = glutCreateMenu(MainMenuHandler); glutSetMenu(mainMenu); glutAddMenuEntry(\ glutAddMenuEntry(\ glutAddMenuEntry(\ glutAttachMenu(GLUT_RIGHT_BUTTON); } 5.2 键盘控制火焰燃烧方向 (代码可参照键盘控制火焰颜色) 5.3 选择贴图纹理 用键盘输入选择纹理所对应的编号,代码可参照附录源代码中int LoadGLTextures()函数。 6、程序运行结果 图6.1 图6.2 例如:选择2号:五角星火焰(图6.1) 贴图纹理:五角星(图6.2) 图6.3.1 图6.3.2 例如:选择4号:火焰(图6.3.1) 贴图纹理:火焰(图6.3.2) 图6.4.1 图6.4.2 图6.4.3 按键改变的火焰颜色(图6.4.1 图6.4.2 图6.4.3 ) 图6.5.1 图6.5.2 鼠标主菜单,改变火焰颜色,和退出。例如选择“bright blue”,结果如图6.5.1 与图6.5.2 图6.6.1 图6.6.2 通过改变粒子X与Y轴的初速度和加速度,来改变火焰的燃烧方向,如图6.6.1与图6.6.2 7、总结 在完成基于粒子系统的火焰模拟实验的过程中,我们小组各成员通过分工与合作多种形式,查阅和检索相关文献及资料,最终通过学习基本原理、讨论实验方案、研究重点难点及验证预期结果等过程完成了本次实验。我们实验的特色在于使用键盘和鼠标控制火焰颜色的交互变化,以及使用 键盘控制火焰加速度的变化。在本次实验中我们学习并掌握了相关知识,同时也深刻的体会到了合作的重要性。今后,我们一定会更加认真学习。 8、参考资料: 《计算机图形学基础(第2版)》 陆枫 何云峰 编著 太原工业学院精品课程 9、附录:源程序代码清单 #include \#include float slowdown=3.0f; float xspeed; float yspeed; float zoom=-40.0f; int a; float xg1; float yg1=0.2f; GLuint loop; GLuint col=5; GLuint texture[1]; typedef struct { bool active; float life; float fade; // 粒子数的数目 // X轴速度 // Y轴速度 // 循环变量 // 初始颜色 // 创建数组存储纹理 // 创建结构体 // // 粒子生命周期 // 消失的速度 } float r; float g; float b; float x; float y; float z; float xi; float yi; float zi; float xg; float yg; float zg; // 坐标 // 坐标 // 坐标 // X轴加速度 // Y轴加速度 // Z轴加速度 particles; particles particle[MAX_PARTICLES]; // 创建粒子数组 static GLfloat colors[8][3]= { }; AUX_RGBImageRec *LoadBMP(char *Filename) { FILE *File=NULL; if (!Filename) { return NULL; // 载入位图图像 {0.0f,0.0f,0.0f},{0.5f,0.75f,1.0f},{1.0f,0.75f,0.5f},{0.75f,1.0f,0.5f}, {1.0f,0.5f,0.75f}, {0.35f,0.8f,0.5f}, {0.55f,0.25f,0.75f},{0.5f,0.5f,0.75f}, // 颜色数组 } File=fopen(Filename,\ if (File) { fclose(File); return auxDIBImageLoad(Filename); } return NULL; } int LoadGLTextures() 成纹理 { int Status=FALSE; // 载入位图(调用上面的代码)并转换 AUX_RGBImageRec *TextureImage[1]; memset(TextureImage,0,sizeof(void *)*1); printf(\键 xg1+=0.05;(X轴加速度) 荧光黄色\\n\printf(\键 yg1+=0.05;(X轴加速度) 玫瑰粉\\n\printf(\键 xg1-=0.05;(X轴加速度) 荧光绿\\n\printf(\键 yg1-=0.05;(X轴加速度) 亮紫\\n\ printf(\键 yg1-=0.05;(X轴加速度) 藕荷色\\n\ printf(\ printf(\选择纹理 printf(\ Triangle---\\n\\n\ Hexagon---\\n\\n\ printf(\scanf(\ if(a>6) { printf(\exit(0); } switch(a) { case 1: { if (TextureImage[0]=LoadBMP(\ { glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, Status=TRUE; glGenTextures(1, &texture[0]); TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); } } break; case 2: { if (TextureImage[0]=LoadBMP(\ { glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); Status=TRUE; glGenTextures(1, &texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); } }break; case 3: { if (TextureImage[0]=LoadBMP(\ { glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 0, 3, TextureImage[0]->sizeX, Status=TRUE; glGenTextures(1, &texture[0]); glTexImage2D(GL_TEXTURE_2D, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); } }break; case 4: { if (TextureImage[0]=LoadBMP(\ { glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 0, 3, TextureImage[0]->sizeX, Status=TRUE; glGenTextures(1, &texture[0]); glTexImage2D(GL_TEXTURE_2D, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); } }break; case 5: { if (TextureImage[0]=LoadBMP(\ { glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 0, 3, TextureImage[0]->sizeX, Status=TRUE; glGenTextures(1, &texture[0]); glTexImage2D(GL_TEXTURE_2D, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); case 6: { if (TextureImage[0]=LoadBMP(\ } }break; { glBindTexture(GL_TEXTURE_2D, texture[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 0, 3, TextureImage[0]->sizeX, Status=TRUE; glGenTextures(1, &texture[0]); glTexImage2D(GL_TEXTURE_2D, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); } }break; } if (TextureImage[0]) { } if (TextureImage[0]->data) { } free(TextureImage[0]); free(TextureImage[0]->data); return Status; } void ReSizeGLScene(GLsizei width, GLsizei height) { } void InitGL(GLvoid) { glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // 调整并初始化GL窗口 gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,200.0f); // OpenGL的设置 } glClearColor(0.0f,0.0f,0.0f,0.0f); glShadeModel(GL_SMOOTH); glClearDepth(1.0f); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); glHint(GL_POINT_SMOOTH_HINT,GL_NICEST); glEnable(GL_TEXTURE_2D); LoadGLTextures(); glBindTexture(GL_TEXTURE_2D,texture[0]); for (loop=0;loop particle[loop].xg=0.0f; particle[loop].yg=0.3f; particle[loop].zg=0.0f; particle[loop].active=true; particle[loop].life=2.0f; particle[loop].fade=float(rand()0)/1500.0f+0.002f; particle[loop].r=colors[loop*(4/MAX_PARTICLES)][0]; particle[loop].g=colors[loop*(4/MAX_PARTICLES)][1]; particle[loop].b=colors[loop*(4/MAX_PARTICLES)][2]; void DrawGLScene(GLvoid) // 绘制 { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0,0,5, for (loop=0;loop if (particle[loop].active) { float x=particle[loop].x; float y=particle[loop].y; 0,1.5,0, 0,1,0); float z=particle[loop].z+zoom; ); particle[loop].x+=particle[loop].xi/(slowdown*1050); //X的坐标随X轴速度 glBegin(GL_TRIANGLE_STRIP); glColor4f(particle[loop].r,particle[loop].g,particle[loop].b,particle[loop].life glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z); glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z); glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z); glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z); glEnd(); 变化 particle[loop].y+=particle[loop].yi/(slowdown*1050); particle[loop].z+=particle[loop].zi/(slowdown*1050); 化 } { } particle[loop].life=2.0f; if (particle[loop].life<0.0f) particle[loop].yi+=particle[loop].yg; particle[loop].zi+=particle[loop].zg; // 周期衰减 particle[loop].xi+=particle[loop].xg; // X轴的速度随X轴的加速度变 particle[loop].life-=particle[loop].fade; particle[loop].fade=float(rand()0)/1500.0f+0.002f; particle[loop].x=0.0f; particle[loop].y=0.0f; particle[loop].z=0.0f; particle[loop].xi=float((rand()`)-30.0f); particle[loop].yi=float((rand()`)-30.0f); particle[loop].zi=float((rand()`)-30.0f); particle[loop].r=colors[col][0]; particle[loop].g=colors[col][1]; particle[loop].b=colors[col][2]; particle[loop].xg=xg1; particle[loop].yg=yg1; particle[loop].zg=0.0f; //渲染 //渲染 //渲染 } } glutSwapBuffers(); void MainMenuHandler(int option) //{ switch(option) { case 0: { exit(0); LoadGLTextures(); } break; case 1: { col=1; } break; case 2: { col=2; }break; default: break; } glutPostRedisplay(); } 定义主菜单功能 void MenuHandler() // 主菜单 { int mainMenu; mainMenu = glutCreateMenu(MainMenuHandler); glutSetMenu(mainMenu); glutAddMenuEntry(\ glutAddMenuEntry(\ glutAddMenuEntry(\ glutAttachMenu(GLUT_RIGHT_BUTTON); } void keyboard(unsigned char key,int x,int y) //{ 定义键盘功能 switch(key) { case 'q': { col=3; //xg1+=0.05; glutPostRedisplay(); //重绘函数 } break; case 'w': { col=4; // yg1+=0.05; glutPostRedisplay(); } break; case 'a': { col=5; // xg1-=0.05; glutPostRedisplay(); }break; case 's': { col=6; //yg1-=0.05; glutPostRedisplay(); } break; case 'z': { col=7; glutPostRedisplay(); } break; default: break; } } int main(int argc, char* argv[]) { InitGL(); glutReshapeFunc(ReSizeGLScene); glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH); glutInitWindowSize(500,650); glutInitWindowPosition(800,50); glutCreateWindow(\ } glutDisplayFunc(DrawGLScene); glutIdleFunc(DrawGLScene); MenuHandler(); glutKeyboardFunc(keyboard); glutMainLoop(); return 0;
正在阅读:
火焰 粒子系统 OpenGL - 图文11-14
8 离心压缩机08-18
2018年周口市继续教育综合考试“一带一路”战略发展全部试题与答03-17
最新高中化学高考总复习资料03-08
最常见的近红外光谱的预处理技术的综述07-04
食品10-24
低碳与生活教案10-12
综合智商测试二01-15
后厨操作规范04-17
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 粒子
- 火焰
- 图文
- OpenGL
- 系统
- 党课讲稿:不忘初心抉择无悔铸就对党绝对忠诚的政治品格
- 贞丰县永丰街道必克小学留守儿童之家建设报告
- 西安交通大学16年9月课程考试《工程热力学》作业考核试题
- (灵)苏教版四年级数学上册《认识垂直》教学设计
- 西南财经大学科研管理规范
- 国家专项研发资金、补助资金会计核算的指导性意见(开发支出、无形资产、研发费用、递延收益)
- 2014奥鹏《地方政府学》模拟练习题答案
- 致远小学五年级课外阅读知识练习
- 4、勤读
- 2016年下半年福建省内审师《内部审计基础》:底稿编制技术考试试卷
- 安徽省六安市第一中学2018届高三下学期第三次模拟考试文综-历史试题含解析
- Domino数据迁移解决方案
- 恒父摄影作品欣赏 - 图文
- 中石油18年8月《石油钻采设备及工艺》第一次在线作业
- 国家鼓励类项目确认书
- PCB常用元件名称
- 中职物流与配送试题
- 先进基层党组织事迹材料
- 植物生理学(名词+符号)
- 裙楼地下结构逆作法施工工程监理实施细则