home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / demos / pointblast.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  12KB  |  507 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1997.  */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. /* This example demonstrates how to render particle effects
  9.    with OpenGL.  A cloud of pinkish/orange particles explodes with the
  10.    particles bouncing off the ground.  When the EXT_point_parameters
  11.    is present , the particle size is attenuated based on eye distance. */
  12.  
  13.  
  14. /*
  15.  * $Log: pointblast.c,v $
  16.  * Revision 1.1.1.1  1999/08/19 00:55:40  jtg
  17.  * Imported sources
  18.  *
  19.  * Revision 3.3  1998/07/26 01:24:27  brianp
  20.  * removed include of gl.h
  21.  *
  22.  * Revision 3.2  1998/02/14 18:51:46  brianp
  23.  * fixed a small compiler warning
  24.  *
  25.  * Revision 3.1  1998/02/14 18:45:25  brianp
  26.  * optimized to use flat shading, don't blend ground polygon
  27.  *
  28.  * Revision 3.0  1998/02/14 18:42:29  brianp
  29.  * initial rev
  30.  *
  31.  */
  32.  
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <math.h>       /* for cos(), sin(), and sqrt() */
  38. #include <GL/glut.h>
  39.  
  40. /* Some <math.h> files do not define M_PI... */
  41. #ifndef M_PI
  42. #define M_PI 3.14159265
  43. #endif
  44.  
  45. #if 0  /* For debugging. */
  46. #undef GL_EXT_point_parameters
  47. #endif
  48.  
  49. static GLfloat angle = -150;   /* in degrees */
  50. static int spin = 0;
  51. static int moving, begin;
  52. static int newModel = 1;
  53. static float theTime;
  54. static int repeat = 1;
  55. static int blend = 1;
  56. int useMipmaps = 1;
  57. int linearFiltering = 1;
  58.  
  59. static GLfloat constant[3] = { 1/5.0, 0.0, 0.0 };
  60. static GLfloat linear[3] = { 0.0, 1/5.0, 0.0 };
  61. static GLfloat theQuad[3] = { 0.25, 0.0, 1/60.0 };
  62.  
  63. #define MAX_POINTS 2000
  64.  
  65. static int numPoints = 200;
  66.  
  67. static GLfloat pointList[MAX_POINTS][3];
  68. static GLfloat pointTime[MAX_POINTS];
  69. static GLfloat pointVelocity[MAX_POINTS][2];
  70. static GLfloat pointDirection[MAX_POINTS][2];
  71. static int colorList[MAX_POINTS];
  72. static int animate = 1, motion = 0;
  73.  
  74. static GLfloat colorSet[][4] = {
  75.   /* Shades of red. */
  76.   { 0.7, 0.2, 0.4, 0.5 },
  77.   { 0.8, 0.0, 0.7, 0.5 },
  78.   { 1.0, 0.0, 0.0, 0.5 },
  79.   { 0.9, 0.3, 0.6, 0.5 },
  80.   { 1.0, 0.4, 0.0, 0.5 },
  81.   { 1.0, 0.0, 0.5, 0.5 },
  82. };
  83.  
  84. #define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0]))
  85.  
  86. #define DEAD (NUM_COLORS+1)
  87.  
  88.  
  89. #if 0  /* drand48 might be better on Unix machines */
  90. #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48())
  91. #else
  92. static float float_rand(void) { return rand() / (float) RAND_MAX; }
  93. #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand())
  94. #endif
  95.  
  96. #define MEAN_VELOCITY 3.0
  97. #define GRAVITY 2.0
  98. #define TIME_DELTA 0.025  /* The speed of time. */
  99.  
  100. /* Modeling units of ground extent in each X and Z direction. */
  101. #define EDGE 12
  102.  
  103. void
  104. makePointList(void)
  105. {
  106.   float angle, velocity, direction;
  107.   int i;
  108.  
  109.   motion = 1;
  110.   for (i=0; i<numPoints; i++) {
  111.     pointList[i][0] = 0.0;
  112.     pointList[i][1] = 0.0;
  113.     pointList[i][2] = 0.0;
  114.     pointTime[i] = 0.0;
  115.     angle = (RANDOM_RANGE(60.0, 70.0)) * M_PI/180.0;
  116.     direction = RANDOM_RANGE(0.0, 360.0) * M_PI/180.0;
  117.     pointDirection[i][0] = cos(direction);
  118.     pointDirection[i][1] = sin(direction);
  119.     velocity = MEAN_VELOCITY + RANDOM_RANGE(-0.8, 1.0);
  120.     pointVelocity[i][0] = velocity * cos(angle);
  121.     pointVelocity[i][1] = velocity * sin(angle);
  122.     colorList[i] = rand() % NUM_COLORS;
  123.   }
  124.   theTime = 0.0;
  125. }
  126.  
  127. void
  128. updatePointList(void)
  129. {
  130.   float distance;
  131.   int i;
  132.  
  133.   motion = 0;
  134.   for (i=0; i<numPoints; i++) {
  135.     distance = pointVelocity[i][0] * theTime;
  136.  
  137.     /* X and Z */
  138.     pointList[i][0] = pointDirection[i][0] * distance;
  139.     pointList[i][2] = pointDirection[i][1] * distance;
  140.  
  141.     /* Z */
  142.     pointList[i][1] =
  143.       (pointVelocity[i][1] - 0.5 * GRAVITY * pointTime[i])*pointTime[i];
  144.  
  145.     /* If we hit the ground, bounce the point upward again. */
  146.     if (pointList[i][1] <= 0.0) {
  147.       if (distance > EDGE) {
  148.         /* Particle has hit ground past the distance duration of
  149.           the particles.  Mark particle as dead. */
  150.        colorList[i] = NUM_COLORS;  /* Not moving. */
  151.        continue;
  152.       }
  153.  
  154.       pointVelocity[i][1] *= 0.8;  /* 80% of previous up velocity. */
  155.       pointTime[i] = 0.0;  /* Reset the particles sense of up time. */
  156.     }
  157.     motion = 1;
  158.     pointTime[i] += TIME_DELTA;
  159.   }
  160.   theTime += TIME_DELTA;
  161.   if (!motion && !spin) {
  162.     if (repeat) {
  163.       makePointList();
  164.     } else {
  165.       glutIdleFunc(NULL);
  166.     }
  167.   }
  168. }
  169.  
  170. void
  171. idle(void)
  172. {
  173.   updatePointList();
  174.   if (spin) {
  175.     angle += 0.3;
  176.     newModel = 1;
  177.   }
  178.   glutPostRedisplay();
  179. }
  180.  
  181. void
  182. visible(int vis)
  183. {
  184.   if (vis == GLUT_VISIBLE) {
  185.     if (animate && (motion || spin)) {
  186.       glutIdleFunc(idle);
  187.     }
  188.   } else {
  189.     glutIdleFunc(NULL);
  190.   }
  191. }
  192.  
  193. void
  194. recalcModelView(void)
  195. {
  196.   glPopMatrix();
  197.   glPushMatrix();
  198.   glRotatef(angle, 0.0, 1.0, 0.0);
  199.   newModel = 0;
  200. }
  201.  
  202. void
  203. redraw(void)
  204. {
  205.   int i;
  206.  
  207.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  208.   if (newModel)
  209.     recalcModelView();
  210.  
  211.   glDepthMask(GL_FALSE);
  212.  
  213.   /* Draw the floor. */
  214. /*  glEnable(GL_TEXTURE_2D);*/
  215.   glColor3f(0.5, 1.0, 0.5);
  216.   glBegin(GL_QUADS);
  217.     glTexCoord2f(0.0, 0.0);
  218.     glVertex3f(-EDGE, -0.05, -EDGE);
  219.     glTexCoord2f(20.0, 0.0);
  220.     glVertex3f(EDGE, -0.05, -EDGE);
  221.     glTexCoord2f(20.0, 20.0);
  222.     glVertex3f(EDGE, -0.05, EDGE);
  223.     glTexCoord2f(0.0, 20.0);
  224.     glVertex3f(-EDGE, -0.05, EDGE);
  225.   glEnd();
  226.  
  227.   /* Allow particles to blend with each other. */
  228.   glDepthMask(GL_TRUE);
  229.  
  230.   if (blend)
  231.      glEnable(GL_BLEND);
  232.  
  233.   glDisable(GL_TEXTURE_2D);
  234.   glBegin(GL_POINTS);
  235.     for (i=0; i<numPoints; i++) {
  236.       /* Draw alive particles. */
  237.       if (colorList[i] != DEAD) {
  238.         glColor4fv(colorSet[colorList[i]]);
  239.         glVertex3fv(pointList[i]);
  240.       }
  241.     }
  242.   glEnd();
  243.  
  244.   glDisable(GL_BLEND);
  245.  
  246.   glutSwapBuffers();
  247. }
  248.  
  249. /* ARGSUSED2 */
  250. void
  251. mouse(int button, int state, int x, int y)
  252. {
  253.   /* Scene can be spun around Y axis using left
  254.      mouse button movement. */
  255.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  256.     moving = 1;
  257.     begin = x;
  258.   }
  259.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  260.     moving = 0;
  261.   }
  262. }
  263.  
  264. /* ARGSUSED1 */
  265. void
  266. mouseMotion(int x, int y)
  267. {
  268.   if (moving) {
  269.     angle = angle + (x - begin);
  270.     begin = x;
  271.     newModel = 1;
  272.     glutPostRedisplay();
  273.   }
  274. }
  275.  
  276. void
  277. menu(int option)
  278. {
  279.   switch (option) {
  280.   case 0:
  281.     makePointList();
  282.     break;
  283. #if GL_EXT_point_parameters
  284.   case 1:
  285.     glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, constant);
  286.     break;
  287.   case 2:
  288.     glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, linear);
  289.     break;
  290.   case 3:
  291.     glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, theQuad);
  292.     break;
  293. #endif
  294.   case 4:
  295.     blend = 1;
  296.     break;
  297.   case 5:
  298.     blend = 0;
  299.     break;
  300. #if GL_EXT_point_parameters
  301.   case 6:
  302.     glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 1.0);
  303.     break;
  304.   case 7:
  305.     glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT, 10.0);
  306.     break;
  307. #endif
  308.   case 8:
  309.     glEnable(GL_POINT_SMOOTH);
  310.     break;
  311.   case 9:
  312.     glDisable(GL_POINT_SMOOTH);
  313.     break;
  314.   case 10:
  315.     glPointSize(2.0);
  316.     break;
  317.   case 11:
  318.     glPointSize(4.0);
  319.     break;
  320.   case 12:
  321.     glPointSize(8.0);
  322.     break;
  323.   case 13:
  324.     spin = 1 - spin;
  325.     if (animate && (spin || motion)) {
  326.       glutIdleFunc(idle);
  327.     } else {
  328.       glutIdleFunc(NULL);
  329.     }
  330.     break;
  331.   case 14:
  332.     numPoints = 200;
  333.     break;
  334.   case 15:
  335.     numPoints = 500;
  336.     break;
  337.   case 16:
  338.     numPoints = 1000;
  339.     break;
  340.   case 17:
  341.     numPoints = 2000;
  342.     break;
  343.   case 666:
  344.     exit(0);
  345.   }
  346.   glutPostRedisplay();
  347. }
  348.  
  349. /* ARGSUSED1 */
  350. void
  351. key(unsigned char c, int x, int y)
  352. {
  353.   switch (c) {
  354.   case 13:
  355.     animate = 1 - animate;  /* toggle. */
  356.     if (animate && (motion || spin)) {
  357.       glutIdleFunc(idle);
  358.     } else {
  359.       glutIdleFunc(NULL);
  360.     }
  361.     break;
  362.   case ' ':
  363.     animate = 1;
  364.     makePointList();
  365.     glutIdleFunc(idle);
  366.     break;
  367.   case 27:
  368.     exit(0);
  369.   }
  370. }
  371.  
  372. /* Nice floor texture tiling pattern. */
  373. static char *circles[] = {
  374.   "....xxxx........",
  375.   "..xxxxxxxx......",
  376.   ".xxxxxxxxxx.....",
  377.   ".xxx....xxx.....",
  378.   "xxx......xxx....",
  379.   "xxx......xxx....",
  380.   "xxx......xxx....",
  381.   "xxx......xxx....",
  382.   ".xxx....xxx.....",
  383.   ".xxxxxxxxxx.....",
  384.   "..xxxxxxxx......",
  385.   "....xxxx........",
  386.   "................",
  387.   "................",
  388.   "................",
  389.   "................",
  390. };
  391.  
  392. static void
  393. makeFloorTexture(void)
  394. {
  395.   GLubyte floorTexture[16][16][3];
  396.   GLubyte *loc;
  397.   int s, t;
  398.  
  399.   /* Setup RGB image for the texture. */
  400.   loc = (GLubyte*) floorTexture;
  401.   for (t = 0; t < 16; t++) {
  402.     for (s = 0; s < 16; s++) {
  403.       if (circles[t][s] == 'x') {
  404.         /* Nice blue. */
  405.         loc[0] = 0x1f;
  406.         loc[1] = 0x1f;
  407.         loc[2] = 0x8f;
  408.       } else {
  409.         /* Light gray. */
  410.         loc[0] = 0xca;
  411.         loc[1] = 0xca;
  412.         loc[2] = 0xca;
  413.       }
  414.       loc += 3;
  415.     }
  416.   }
  417.  
  418.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  419.  
  420.   if (useMipmaps) {
  421.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  422.       GL_LINEAR_MIPMAP_LINEAR);
  423.     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16,
  424.       GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
  425.   } else {
  426.     if (linearFiltering) {
  427.       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  428.     } else {
  429.       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  430.     }
  431.     glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
  432.       GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
  433.   }
  434. }
  435.  
  436. int
  437. main(int argc, char **argv)
  438. {
  439.   int i;
  440.   glutInit(&argc, argv);
  441.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  442.  
  443.   for (i=1; i<argc; i++) {
  444.     if(!strcmp("-noms", argv[i])) {
  445.       glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  446.       printf("forcing no multisampling\n");
  447.     } else if(!strcmp("-nomipmaps", argv[i])) {
  448.       useMipmaps = 0;
  449.     } else if(!strcmp("-nearest", argv[i])) {
  450.       linearFiltering = 0;
  451.     }
  452.   }
  453.  
  454.   glutCreateWindow("point burst");
  455.   glutDisplayFunc(redraw);
  456.   glutMouseFunc(mouse);
  457.   glutMotionFunc(mouseMotion);
  458.   glutVisibilityFunc(visible);
  459.   glutKeyboardFunc(key);
  460.   glutCreateMenu(menu);
  461.   glutAddMenuEntry("Reset time", 0);
  462.   glutAddMenuEntry("Constant", 1);
  463.   glutAddMenuEntry("Linear", 2);
  464.   glutAddMenuEntry("Quadratic", 3);
  465.   glutAddMenuEntry("Blend on", 4);
  466.   glutAddMenuEntry("Blend off", 5);
  467.   glutAddMenuEntry("Threshold 1", 6);
  468.   glutAddMenuEntry("Threshold 10", 7);
  469.   glutAddMenuEntry("Point smooth on", 8);
  470.   glutAddMenuEntry("Point smooth off", 9);
  471.   glutAddMenuEntry("Point size 2", 10);
  472.   glutAddMenuEntry("Point size 4", 11);
  473.   glutAddMenuEntry("Point size 8", 12);
  474.   glutAddMenuEntry("Toggle spin", 13);
  475.   glutAddMenuEntry("200 points ", 14);
  476.   glutAddMenuEntry("500 points ", 15);
  477.   glutAddMenuEntry("1000 points ", 16);
  478.   glutAddMenuEntry("2000 points ", 17);
  479.   glutAddMenuEntry("Quit", 666);
  480.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  481.  
  482.   glShadeModel(GL_FLAT);
  483.   glEnable(GL_DEPTH_TEST);
  484.   glEnable(GL_POINT_SMOOTH);
  485.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  486.   glPointSize(8.0);
  487. #if GL_EXT_point_parameters
  488.   glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, theQuad);
  489. #endif
  490.   glMatrixMode(GL_PROJECTION);
  491.   gluPerspective( /* field of view in degree */ 40.0,
  492.   /* aspect ratio */ 1.0,
  493.     /* Z near */ 0.5, /* Z far */ 40.0);
  494.   glMatrixMode(GL_MODELVIEW);
  495.   gluLookAt(0.0, 1.0, 8.0, /* eye location */
  496.     0.0, 1.0, 0.0,      /* center is at (0,0,0) */
  497.     0.0, 1.0, 0.);      /* up is in postivie Y direction */
  498.   glPushMatrix();       /* dummy push so we can pop on model
  499.                            recalc */
  500.  
  501.   makePointList();
  502.   makeFloorTexture();
  503.  
  504.   glutMainLoop();
  505.   return 0;             /* ANSI C requires main to return int. */
  506. }
  507.