fountain3d.c
上传用户:kwdpyr1020
上传日期:2022-08-09
资源大小:1363k
文件大小:8k
源码类别:

OpenGL

开发平台:

Visual C++

  1. //三围喷泉
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <time.h>
  6. #include <GL/glut.h>
  7. #include "texture.h"
  8. #define PI 3.14159
  9. struct particle
  10. {
  11.   float t;       // 粒子的寿命
  12.   float v;       // 粒子的运动速度
  13.   float d;       // 粒子的运动方向
  14.   float x, y, z; // 粒子的位置坐标
  15.   float xd, zd;  // X 和 Z 方向上的增量
  16.   char type;     // 粒子的状态(移动或淡化)
  17.   float a;       // 粒子淡化的 alpha 值
  18.   struct particle *next, *prev;
  19. };
  20. struct point
  21. {
  22.   float x, y, z;
  23. };
  24. int WindW, WindH;
  25. unsigned *teximage;    // 粒子的纹理
  26. GLuint texture[2];     // 纹理ID
  27. float a=0;
  28. struct particle *fn[3];   /* Fountains */
  29. char temp[128]="FPS: 0.000000";
  30. // 以下是用于计算帧率的变量
  31. int frame_counter=0;
  32. time_t curtime;
  33. clock_t last_time;
  34. float cur_time;
  35. float total_frames;
  36. struct point upv, cam;        //  摄像机的位置和向上的方向矢量
  37. //  初始化函数
  38. void Init()
  39. {
  40.   fn[0] = NULL;
  41.   fn[1] = NULL;
  42.   fn[2] = NULL;
  43.   upv.x = -5;
  44.   upv.y = 5;
  45.   upv.z = -5;
  46.   cam.x = 200;
  47.   cam.y = 200;
  48.   cam.z = 200;
  49.   glGenTextures(3, texture); 
  50.   glClearColor(0, 0, 0, 0);
  51.   glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  52.   glEnable(GL_BLEND);
  53.   glEnable(GL_TEXTURE_2D);
  54. }
  55. // 在屏幕上绘制字符串
  56. void draw_string(void *font, const char* string) 
  57. {
  58.   while(*string)
  59.     glutStrokeCharacter(font, *string++);
  60. }
  61. static float gettime(void)
  62. {
  63.   clock_t time_new, time_raz;
  64.   time_new=clock();
  65.   time_raz=time_new-last_time;
  66.   last_time=time_new;
  67.   return(time_raz/(float)CLOCKS_PER_SEC);
  68. }
  69. // 装入纹理
  70. void LoadTexture(char *fn, int t_num)
  71. {
  72.   int texwid, texht;
  73.   int texcomps;
  74.  
  75.   teximage = read_texture(fn, &texwid, &texht, &texcomps);
  76.   if (!teximage)
  77.   {
  78.     printf("Sorry, can't read texture file...");
  79.     exit(0);
  80.   }
  81.   glBindTexture(GL_TEXTURE_2D, texture[t_num]);
  82.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  83.   glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, texwid, texht, 0, GL_RGBA, GL_UNSIGNED_BYTE, teximage);
  84.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
  85.   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
  86.   if ((t_num == 0) || (t_num == 2)) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); /* Special for particles */
  87.   if (t_num == 1)
  88.   {
  89.     // 设置地面的重复纹理参数
  90.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
  91.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
  92.   }
  93.   free(teximage);
  94. void Reshape(int width, int height)
  95. {
  96.   glViewport(0, 0, width, height);
  97.   glMatrixMode(GL_PROJECTION);
  98.   glLoadIdentity();
  99.   glFrustum(-0.5, 0.5, -0.5, 0.5, 1, 1000);
  100.   glMatrixMode(GL_MODELVIEW);
  101.   
  102.   WindW = width;
  103.   WindH = height;
  104. }
  105. //添加新的粒子
  106. void AddParticles()
  107. {
  108.   struct particle *tempp;
  109.   int i, j;
  110.   
  111.   for (j=0; j<3; j++)
  112.     for (i=0; i<2; i++)
  113.     {
  114.       tempp = (struct particle *)malloc(sizeof(struct particle));
  115.       if (fn[j]) fn[j]->prev = tempp;
  116.       tempp->next = fn[j];
  117.       fn[j] = tempp;
  118.   
  119.       tempp->t = -9.9;
  120.       tempp->v = (float)(rand() % 200000)/100000+1; // 速度
  121.       tempp->d = (float)(rand() % 400)/100-2;     // 方向角度
  122.       // 开始运动的坐标
  123.       tempp->x = 0;
  124.       tempp->y = 0;
  125.       tempp->z = 0;
  126.       tempp->xd = cos((tempp->d*3.14159)/180)*tempp->v/4;
  127.       tempp->zd = sin((tempp->d*3.14159)/180)*tempp->v;
  128.       tempp->type = 0; // 粒子的状态是运动的
  129.       tempp->a = 1; // 粒子的Alpha初始值是1
  130.     }
  131. }
  132. //  移动粒子
  133. void MoveParticles()
  134. {
  135.   struct particle *tempp;
  136.   int j;
  137.   for (j=0; j<3; j++)
  138.   {
  139.     tempp = fn[j]; // 选择喷泉
  140.     while (tempp)
  141.     {
  142.       if (tempp->type == 0) // 如果粒子是运动的
  143.       {
  144.         tempp->x += tempp->xd;
  145.         tempp->z += tempp->zd;
  146.         tempp->y = -(9.8*(tempp->t*tempp->t/4))/2+122.5; // 计算高度
  147.         tempp->t += 0.1; // 寿命递增
  148.         if (tempp->y < 0) tempp->type = 1; // 如果粒子落到地上,则粒子淡化
  149.       }
  150.       else // 粒子落到地上
  151.       {
  152.         tempp->y = -(9.8*(tempp->t*tempp->t/4))/2+122.5; 
  153.         tempp->a -= 0.1; // 粒子淡化
  154.       }
  155.       tempp = tempp->next; //进行下一个粒子的计算
  156.     }
  157.   }
  158. }
  159. //  删除粒子
  160. void DeleteParticles()
  161. {
  162.   struct particle *tempp, *temp1;
  163.   int j;
  164.   for (j=0; j<3; j++)
  165.   {
  166.     tempp = fn[j];
  167.     while (tempp)
  168.     {
  169.       if ((tempp->type == 1) && (tempp->a <= 0)) // 粒子死亡
  170.       {
  171.         // 删除粒子
  172.         temp1 = tempp->prev;
  173.         tempp->prev->next = tempp->next;
  174.         if (tempp->next) tempp->next->prev = temp1;
  175.         free(tempp);
  176.         tempp = temp1;
  177.       }
  178.       tempp = tempp->next;
  179.     }
  180.   }
  181. }
  182. //求矢量差积 C = A x B 
  183. void vect_mult(struct point *A, struct point *B, struct point *C)
  184. {
  185.   /* Vector multiply */
  186.   C->x = A->y*B->z - A->z*B->y;
  187.   C->y = A->z*B->x - A->x*B->z;
  188.   C->z = A->x*B->y - A->y*B->x;
  189. }
  190. //  矢量单位化
  191. void normalize(struct point *V)
  192. {
  193.   float d;
  194.   // 矢量长度
  195.   d = sqrt(V->x*V->x + V->y*V->y + V->z*V->z);
  196.   // 单位化
  197.   V->x /= d; 
  198.   V->y /= d; 
  199.   V->z /= d; 
  200. }
  201. void DrawFountain()
  202. {
  203.   int j;
  204.   struct particle *tempp;
  205.   struct point vectd, vectl; 
  206.   float alpha, ttx, ttz;
  207.   glBindTexture(GL_TEXTURE_2D, texture[0]);
  208.   AddParticles();
  209.   MoveParticles();
  210.   DeleteParticles();
  211.   
  212.   glPushMatrix();
  213.   for (j=0; j<3; j++)
  214.   {
  215.     glBegin(GL_QUADS);
  216.     tempp = fn[j];
  217.     while (tempp)
  218.     {
  219.       // 旋转喷泉
  220.       alpha = ((j*120+a)*PI)/180;
  221.       ttx = tempp->x*cos(alpha)-tempp->z*sin(alpha);
  222.       ttz = tempp->x*sin(alpha)+tempp->z*cos(alpha);
  223.       // 计算方向矢量A
  224.       vectd.x = ttx - cam.x;
  225.       vectd.y = tempp->y - cam.y;
  226.       vectd.z = ttz - cam.z;
  227.       vect_mult(&vectd, &upv, &vectl);
  228.       normalize(&vectl);
  229.       vectl.x *= 5;
  230.       vectl.y *= 5;
  231.       vectl.z *= 5;
  232.       glColor4f(0.5, 0.5, 1, tempp->a);
  233.       // 绘制粒子及纹理映射
  234.       glTexCoord2f(0, 0); glVertex3f((ttx-vectl.x), (tempp->y-upv.y), (ttz-vectl.z));
  235.       glTexCoord2f(1, 0); glVertex3f((ttx+vectl.x), (tempp->y-upv.y), (ttz+vectl.z));
  236.       glTexCoord2f(1, 1); glVertex3f((ttx+vectl.x), (tempp->y+upv.y), (ttz+vectl.z));
  237.       glTexCoord2f(0, 1); glVertex3f((ttx-vectl.x), (tempp->y+upv.y), (ttz-vectl.z));
  238.       tempp = tempp->next; // 下一个粒子
  239.     }
  240.     glEnd();
  241.   }
  242.   glPopMatrix();
  243. }
  244. //  场景绘制函数
  245. void Draw(void)
  246. {
  247.   glClear(GL_COLOR_BUFFER_BIT);
  248.   
  249.   glLoadIdentity();
  250.   glBindTexture(GL_TEXTURE_2D, texture[1]);
  251.   a += 0.2;
  252.   gluLookAt(cam.x, cam.y, cam.z, 0, 0, 0, upv.x, upv.y, upv.z); 
  253.   
  254.   // 绘制地面
  255.   glColor3f(0.9, 0.9, 1);
  256.   glPushMatrix();
  257.   glRotatef(a, 0, -1, 0);
  258.   glBegin(GL_QUADS);
  259.     glTexCoord2f(0, 0); glVertex3f(-100, 0, -100);
  260.     glTexCoord2f(2, 0); glVertex3f(-100, 0, 100);
  261.     glTexCoord2f(2, 2); glVertex3f(100, 0, 100);
  262.     glTexCoord2f(0, 2); glVertex3f(100, 0, -100);
  263.   glEnd();
  264.   glPopMatrix();
  265.   // 绘制喷泉
  266.   DrawFountain();
  267.   glBindTexture(GL_TEXTURE_2D, texture[2]);
  268.   glColor4f(1, 1, 0, 0.8);
  269.   glPushMatrix();
  270.   glRotatef(a, 0, -1, 0);
  271.   glBegin(GL_QUADS);
  272.     glTexCoord2f(0, 0); glVertex3f(-100, 0, -100);
  273.     glTexCoord2f(1, 0); glVertex3f(-100, 0, 100);
  274.     glTexCoord2f(1, 1); glVertex3f(100, 0, 100);
  275.     glTexCoord2f(0, 1); glVertex3f(100, 0, -100);
  276.   glEnd();
  277.   glPopMatrix();
  278.   // 计算帧率
  279.   frame_counter++;
  280.   if((frame_counter % 40) == 0)
  281.   {
  282.     frame_counter = 0;
  283.     cur_time=gettime();
  284.     sprintf(temp, "FPS: %f", 40.0/cur_time);
  285.   }
  286.   // 绘制显示帧率的字符串
  287.   glColor3f(1, 1, 1);
  288.   glDisable(GL_TEXTURE_2D);
  289.   glLoadIdentity();
  290.   glTranslatef(-4.9, 4.5, -10);
  291.   glScalef(0.003, 0.003, 0.004);
  292.   draw_string(GLUT_STROKE_ROMAN, temp);
  293.   glEnable(GL_TEXTURE_2D);
  294.   
  295.   glFlush();  
  296.   glutSwapBuffers();
  297. }
  298. static void Key(unsigned char key, int x, int y)
  299. {
  300.   switch (key)
  301.   {
  302.     case 27: exit(0);
  303.              break;
  304.   }
  305. }
  306. void timf(int value)
  307. {
  308.   glutPostRedisplay();
  309.   glutTimerFunc(16, timf, 0);
  310. }
  311. int main(int argc, char *argv[])
  312. {
  313.   WindW = 400;
  314.   WindH = 300;
  315.  
  316.   glutInit(&argc, argv);
  317.   glutInitWindowSize(WindW, WindH);
  318.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  319.   (void)glutCreateWindow("三维喷泉");
  320.   Init();
  321.   LoadTexture("particle.rgb", 0);
  322.   LoadTexture("ground1.rgb", 1);
  323.   LoadTexture("ground2.rgb", 2);
  324.   glutReshapeFunc(Reshape);
  325.   glutDisplayFunc(Draw);
  326.   glutKeyboardFunc(Key);
  327.   glutTimerFunc(16, timf, 0); // 设置定时器
  328.   glutSetCursor(GLUT_CURSOR_NONE); // 隐藏光标
  329.   glutMainLoop();
  330.   return 0;
  331. }