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

OpenGL

开发平台:

Visual C++

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