2 /* Copyright (c) Mark J. Kilgard, 1997. */
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. */
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. */
15 * $Log: pointblast.c,v $
16 * Revision 1.1 1999/08/19 00:55:40 jtg
19 * Revision 3.3 1998/07/26 01:24:27 brianp
20 * removed include of gl.h
22 * Revision 3.2 1998/02/14 18:51:46 brianp
23 * fixed a small compiler warning
25 * Revision 3.1 1998/02/14 18:45:25 brianp
26 * optimized to use flat shading, don't blend ground polygon
28 * Revision 3.0 1998/02/14 18:42:29 brianp
37 #include <math.h> /* for cos(), sin(), and sqrt() */
40 /* Some <math.h> files do not define M_PI... */
42 #define M_PI 3.14159265
45 #if 0 /* For debugging. */
46 #undef GL_EXT_point_parameters
49 static GLfloat angle
= -150; /* in degrees */
51 static int moving
, begin
;
52 static int newModel
= 1;
54 static int repeat
= 1;
57 int linearFiltering
= 1;
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 };
63 #define MAX_POINTS 2000
65 static int numPoints
= 200;
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;
74 static GLfloat colorSet
[][4] = {
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 },
84 #define NUM_COLORS (sizeof(colorSet)/sizeof(colorSet[0]))
86 #define DEAD (NUM_COLORS+1)
89 #if 0 /* drand48 might be better on Unix machines */
90 #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * drand48())
92 static float float_rand(void) { return rand() / (float) RAND_MAX
; }
93 #define RANDOM_RANGE(lo, hi) ((lo) + (hi - lo) * float_rand())
96 #define MEAN_VELOCITY 3.0
98 #define TIME_DELTA 0.025 /* The speed of time. */
100 /* Modeling units of ground extent in each X and Z direction. */
106 float angle
, velocity
, direction
;
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;
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
;
128 updatePointList(void)
134 for (i
=0; i
<numPoints
; i
++) {
135 distance
= pointVelocity
[i
][0] * theTime
;
138 pointList
[i
][0] = pointDirection
[i
][0] * distance
;
139 pointList
[i
][2] = pointDirection
[i
][1] * distance
;
143 (pointVelocity
[i
][1] - 0.5 * GRAVITY
* pointTime
[i
])*pointTime
[i
];
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. */
154 pointVelocity
[i
][1] *= 0.8; /* 80% of previous up velocity. */
155 pointTime
[i
] = 0.0; /* Reset the particles sense of up time. */
158 pointTime
[i
] += TIME_DELTA
;
160 theTime
+= TIME_DELTA
;
161 if (!motion
&& !spin
) {
184 if (vis
== GLUT_VISIBLE
) {
185 if (animate
&& (motion
|| spin
)) {
194 recalcModelView(void)
198 glRotatef(angle
, 0.0, 1.0, 0.0);
207 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
211 glDepthMask(GL_FALSE
);
213 /* Draw the floor. */
214 /* glEnable(GL_TEXTURE_2D);*/
215 glColor3f(0.5, 1.0, 0.5);
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
);
227 /* Allow particles to blend with each other. */
228 glDepthMask(GL_TRUE
);
233 glDisable(GL_TEXTURE_2D
);
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
]);
251 mouse(int button
, int state
, int x
, int y
)
253 /* Scene can be spun around Y axis using left
254 mouse button movement. */
255 if (button
== GLUT_LEFT_BUTTON
&& state
== GLUT_DOWN
) {
259 if (button
== GLUT_LEFT_BUTTON
&& state
== GLUT_UP
) {
266 mouseMotion(int x
, int y
)
269 angle
= angle
+ (x
- begin
);
283 #if GL_EXT_point_parameters
285 glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT
, constant
);
288 glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT
, linear
);
291 glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT
, theQuad
);
300 #if GL_EXT_point_parameters
302 glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT
, 1.0);
305 glPointParameterfEXT(GL_POINT_FADE_THRESHOLD_SIZE_EXT
, 10.0);
309 glEnable(GL_POINT_SMOOTH
);
312 glDisable(GL_POINT_SMOOTH
);
325 if (animate
&& (spin
|| motion
)) {
351 key(unsigned char c
, int x
, int y
)
355 animate
= 1 - animate
; /* toggle. */
356 if (animate
&& (motion
|| spin
)) {
372 /* Nice floor texture tiling pattern. */
373 static char *circles
[] = {
393 makeFloorTexture(void)
395 GLubyte floorTexture
[16][16][3];
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') {
418 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
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
);
426 if (linearFiltering
) {
427 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
429 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
431 glTexImage2D(GL_TEXTURE_2D
, 0, 3, 16, 16, 0,
432 GL_RGB
, GL_UNSIGNED_BYTE
, floorTexture
);
437 main(int argc
, char **argv
)
440 glutInit(&argc
, argv
);
441 glutInitDisplayMode(GLUT_RGB
| GLUT_DOUBLE
| GLUT_DEPTH
| GLUT_MULTISAMPLE
);
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
])) {
449 } else if(!strcmp("-nearest", argv
[i
])) {
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
);
482 glShadeModel(GL_FLAT
);
483 glEnable(GL_DEPTH_TEST
);
484 glEnable(GL_POINT_SMOOTH
);
485 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
487 #if GL_EXT_point_parameters
488 glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT
, theQuad
);
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
505 return 0; /* ANSI C requires main to return int. */