comparison XCodeiPhoneOS/Demos/src/fireworks.c @ 2382:36bcf13ccb48 gsoc2008_iphone

fireworks demo
author Holmes Futrell <hfutrell@umail.ucsb.edu>
date Fri, 18 Jul 2008 20:51:34 +0000
parents
children ac26bd83db1f
comparison
equal deleted inserted replaced
2381:d3952f445f4d 2382:36bcf13ccb48
1 /*
2 * fireworks.c
3 * written by Holmes Futrell
4 * use however you want
5 */
6
7 #include "SDL.h"
8 #include "math.h"
9 #include "common.h"
10 #include <math.h>
11 #include <time.h>
12 #include <OpenGLES/ES1/gl.h>
13
14 #define MILLESECONDS_PER_FRAME 16 /* about 60 frames per second */
15 #define ACCEL 0.0001f
16 #define WIND_RESISTANCE 0.00005f
17 #define MAX_PARTICLES 2000
18 #define VEL_BEFORE_EXPLODE 0.0f
19
20 SDL_TextureID flashTextureID;
21
22
23 enum particleType {
24 emitter = 0,
25 trail,
26 dust
27 };
28
29 struct glformat {
30 int SDL_GL_RED_SIZE;
31 int SDL_GL_GREEN_SIZE;
32 int SDL_GL_BLUE_SIZE;
33 int SDL_GL_ALPHA_SIZE;
34 int SDL_GL_BUFFER_SIZE;
35 int SDL_GL_DOUBLEBUFFER;
36 int SDL_GL_DEPTH_SIZE;
37 int SDL_GL_STENCIL_SIZE;
38 int SDL_GL_ACCUM_RED_SIZE;
39 int SDL_GL_ACCUM_GREEN_SIZE;
40 int SDL_GL_ACCUM_BLUE_SIZE;
41 int SDL_GL_ACCUM_ALPHA_SIZE;
42 int SDL_GL_STEREO;
43 int SDL_GL_MULTISAMPLEBUFFERS;
44 int SDL_GL_MULTISAMPLESAMPLES;
45 int SDL_GL_ACCELERATED_VISUAL;
46 int SDL_GL_RETAINED_BACKING;
47 };
48
49 struct particle {
50
51 GLfloat x;
52 GLfloat y;
53 GLubyte color[4];
54 GLfloat size;
55 GLfloat xvel;
56 GLfloat yvel;
57 int isActive;
58 enum particleType type;
59 int framesSinceEmission;
60 } particles[MAX_PARTICLES];
61
62 void spawnParticleFromEmitter(struct particle *emitter);
63 void explodeEmitter(struct particle *emitter);
64
65 static int num_active_particles;
66
67 static void getError(const char *prefix)
68 {
69 const char *error;
70
71 GLenum result = glGetError();
72 if (result == GL_NO_ERROR)
73 return;
74
75 switch (result) {
76 case GL_NO_ERROR:
77 error = "GL_NO_ERROR";
78 break;
79 case GL_INVALID_ENUM:
80 error = "GL_INVALID_ENUM";
81 break;
82 case GL_INVALID_VALUE:
83 error = "GL_INVALID_VALUE";
84 break;
85 case GL_INVALID_OPERATION:
86 error = "GL_INVALID_OPERATION";
87 break;
88 case GL_STACK_OVERFLOW:
89 error = "GL_STACK_OVERFLOW";
90 break;
91 case GL_STACK_UNDERFLOW:
92 error = "GL_STACK_UNDERFLOW";
93 break;
94 case GL_OUT_OF_MEMORY:
95 error = "GL_OUT_OF_MEMORY";
96 break;
97 default:
98 error = "UNKNOWN";
99 break;
100 }
101 printf("%s: %s\n", prefix, error);
102 }
103
104 void render(void) {
105
106 /* draw the background */
107 glClear(GL_COLOR_BUFFER_BIT);
108
109 struct particle *slot = particles;
110 struct particle *curr = particles;
111 int i;
112 for (i=0; i<num_active_particles; i++) {
113 if (curr->isActive) {
114
115 if (curr->y > SCREEN_HEIGHT) curr->isActive = 0;
116 if (curr->y < 0) curr->isActive = 0;
117 if (curr->x > SCREEN_WIDTH) curr->isActive = 0;
118 if (curr->x < 0) curr->isActive = 0;
119
120 curr->yvel += ACCEL * MILLESECONDS_PER_FRAME;
121 curr->xvel += 0.0f;
122 curr->y += curr->yvel * MILLESECONDS_PER_FRAME;
123 curr->x += curr->xvel * MILLESECONDS_PER_FRAME;
124
125 if (curr->type == emitter) {
126 spawnParticleFromEmitter(curr);
127 curr->framesSinceEmission = 0;
128 if (curr->yvel > -VEL_BEFORE_EXPLODE) {
129 explodeEmitter(curr);
130 }
131 curr->framesSinceEmission++;
132 }
133 else {
134
135 float speed = sqrt(curr->xvel*curr->xvel + curr->yvel*curr->yvel);
136
137 if (WIND_RESISTANCE * MILLESECONDS_PER_FRAME < speed) {
138 float normx = curr->xvel / speed;
139 float normy = curr->yvel / speed;
140 curr->xvel -= normx * WIND_RESISTANCE * MILLESECONDS_PER_FRAME;
141 curr->yvel -= normy * WIND_RESISTANCE * MILLESECONDS_PER_FRAME;
142 }
143 else {
144 curr->xvel = 0;
145 curr->yvel = 0;
146 }
147
148 if (curr->color[3] <= MILLESECONDS_PER_FRAME * 0.0005f * 255) {
149 curr->isActive = 0;
150
151 }
152 else {
153 curr->color[3] -= MILLESECONDS_PER_FRAME * 0.0005f * 255;
154 }
155
156 if (curr->type == dust)
157 curr->size -= MILLESECONDS_PER_FRAME * 0.010f;
158
159 }
160
161 *(slot++) = *curr;
162 }
163 curr++;
164 }
165 num_active_particles = slot - particles;
166
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
169 glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, 1);
170
171 glEnableClientState(GL_VERTEX_ARRAY);
172 glVertexPointer(2, GL_FLOAT, sizeof(struct particle), particles + 0);
173 getError("vertices");
174
175 glEnableClientState(GL_COLOR_ARRAY);
176 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(struct particle), particles[0].color);
177 getError("colors");
178
179 glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
180 getError("enable client state");
181 glPointSizePointerOES(GL_FLOAT, sizeof(struct particle), &(particles[0].size));
182 getError("point size");
183
184 glEnable(GL_POINT_SPRITE_OES);
185 glDrawArrays(GL_POINTS, 0, num_active_particles);
186 getError("glDrawArrays");
187
188
189 /* update screen */
190 SDL_RenderPresent();
191
192 }
193
194 void printOpenGLAttributes(struct glformat *format) {
195 printf("\tSDL_GL_RED_SIZE = %d\n", format->SDL_GL_RED_SIZE);
196 printf("\tSDL_GL_GREEN_SIZE = %d\n", format->SDL_GL_GREEN_SIZE);
197 printf("\tSDL_GL_BLUE_SIZE = %d\n", format->SDL_GL_BLUE_SIZE);
198 printf("\tSDL_GL_ALPHA_SIZE = %d\n", format->SDL_GL_ALPHA_SIZE);
199 printf("\tSDL_GL_BUFFER_SIZE = %d\n", format->SDL_GL_BUFFER_SIZE);
200 printf("\tSDL_GL_DOUBLEBUFFER = %d\n", format->SDL_GL_DOUBLEBUFFER);
201 printf("\tSDL_GL_DEPTH_SIZE = %d\n", format->SDL_GL_DEPTH_SIZE);
202 printf("\tSDL_GL_STENCIL_SIZE = %d\n", format->SDL_GL_STENCIL_SIZE);
203 printf("\tSDL_GL_ACCUM_RED_SIZE = %d\n", format->SDL_GL_ACCUM_RED_SIZE);
204 printf("\tSDL_GL_ACCUM_GREEN_SIZE = %d\n", format->SDL_GL_ACCUM_GREEN_SIZE);
205 printf("\tSDL_GL_ACCUM_BLUE_SIZE = %d\n", format->SDL_GL_ACCUM_BLUE_SIZE);
206 printf("\tSDL_GL_ACCUM_ALPHA_SIZE = %d\n", format->SDL_GL_ACCUM_ALPHA_SIZE);
207 printf("\tSDL_GL_STEREO = %d\n", format->SDL_GL_STEREO);
208 printf("\tSDL_GL_MULTISAMPLEBUFFERS = %d\n", format->SDL_GL_MULTISAMPLEBUFFERS);
209 printf("\tSDL_GL_MULTISAMPLESAMPLES = %d\n", format->SDL_GL_MULTISAMPLESAMPLES);
210 printf("\tSDL_GL_ACCELERATED_VISUAL = %d\n", format->SDL_GL_ACCELERATED_VISUAL);
211 printf("\tSDL_GL_RETAINED_BACKING = %d\n", format->SDL_GL_RETAINED_BACKING);
212 }
213
214 void setOpenGLAttributes(struct glformat *format) {
215 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, format->SDL_GL_RED_SIZE);
216 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, format->SDL_GL_GREEN_SIZE);
217 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, format->SDL_GL_BLUE_SIZE);
218 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, format->SDL_GL_ALPHA_SIZE);
219 SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, format->SDL_GL_BUFFER_SIZE);
220 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, format->SDL_GL_DOUBLEBUFFER);
221 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, format->SDL_GL_DEPTH_SIZE);
222 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, format->SDL_GL_STENCIL_SIZE);
223 SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, format->SDL_GL_ACCUM_RED_SIZE);
224 SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, format->SDL_GL_ACCUM_GREEN_SIZE);
225 SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, format->SDL_GL_ACCUM_BLUE_SIZE);
226 SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, format->SDL_GL_ACCUM_ALPHA_SIZE);
227 SDL_GL_SetAttribute(SDL_GL_STEREO, format->SDL_GL_STEREO);
228 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, format->SDL_GL_MULTISAMPLEBUFFERS);
229 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, format->SDL_GL_MULTISAMPLESAMPLES);
230 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, format->SDL_GL_ACCELERATED_VISUAL);
231 SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, format->SDL_GL_RETAINED_BACKING);
232 }
233
234 void getOpenGLAttributes(struct glformat *format) {
235
236 SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &(format->SDL_GL_RED_SIZE));
237 SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &(format->SDL_GL_GREEN_SIZE));
238 SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &(format->SDL_GL_BLUE_SIZE));
239 SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &(format->SDL_GL_ALPHA_SIZE));
240 SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &(format->SDL_GL_BUFFER_SIZE));
241 SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &(format->SDL_GL_DOUBLEBUFFER));
242 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &(format->SDL_GL_DEPTH_SIZE));
243 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &(format->SDL_GL_STENCIL_SIZE));
244 SDL_GL_GetAttribute(SDL_GL_ACCUM_RED_SIZE, &(format->SDL_GL_ACCUM_RED_SIZE));
245 SDL_GL_GetAttribute(SDL_GL_ACCUM_GREEN_SIZE, &(format->SDL_GL_ACCUM_GREEN_SIZE));
246 SDL_GL_GetAttribute(SDL_GL_ACCUM_BLUE_SIZE, &(format->SDL_GL_ACCUM_BLUE_SIZE));
247 SDL_GL_GetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, &(format->SDL_GL_ACCUM_ALPHA_SIZE));
248 SDL_GL_GetAttribute(SDL_GL_STEREO, &(format->SDL_GL_STEREO));
249 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &(format->SDL_GL_MULTISAMPLEBUFFERS));
250 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &(format->SDL_GL_MULTISAMPLESAMPLES));
251 SDL_GL_GetAttribute(SDL_GL_ACCELERATED_VISUAL, &(format->SDL_GL_ACCELERATED_VISUAL));
252 SDL_GL_GetAttribute(SDL_GL_RETAINED_BACKING, &(format->SDL_GL_RETAINED_BACKING));
253 }
254
255 void explodeEmitter(struct particle *emitter) {
256
257 emitter->isActive = 0;
258
259 int i;
260 for (i=0; i<200; i++) {
261
262 if (num_active_particles >= MAX_PARTICLES) return;
263
264 float theta = randomFloat(0, 2.0f * 3.141592);
265 float max = 3.0f;
266 float speed = randomFloat(0.00, powf(0.17, max));
267 speed = powf(speed, 1.0f / max);
268
269 struct particle *p = &particles[num_active_particles];
270 p->xvel = speed * cos(theta);
271 p->yvel = speed * sin(theta);
272 p->x = emitter->x + emitter->xvel;
273 p->y = emitter->y + emitter->yvel;
274 p->isActive = 1;
275 p->type = dust;
276 p->color[0] = emitter->color[0];
277 p->color[1] = emitter->color[1];
278 p->color[2] = emitter->color[2];
279 p->color[3] = 255;
280
281 p->size = 15;
282
283 num_active_particles++;
284
285 }
286
287 }
288
289 void spawnParticleFromEmitter(struct particle *emitter) {
290
291 if (num_active_particles >= MAX_PARTICLES) return;
292
293 struct particle *p = &particles[num_active_particles];
294 p->x = emitter->x + randomFloat(-3.0, 3.0);
295 p->y = emitter->y + emitter->size / 2.0f;
296 p->xvel = emitter->xvel + randomFloat(-0.005, 0.005);
297 p->yvel = emitter->yvel + 0.1;
298 p->color[0] = (0.8f + randomFloat(-0.1, 0.0)) * 255;
299 p->color[1] = (0.4f + randomFloat(-0.1, 0.1)) * 255;
300 p->color[2] = (0.0f + randomFloat(0.0, 0.2)) * 255;
301 p->color[3] = (0.7f) * 255;
302 p->size = 10;
303 p->type = trail;
304 p->isActive = 1;
305 num_active_particles++;
306
307 }
308
309 void spawnEmitterParticle(int x, int y) {
310
311 if (num_active_particles >= MAX_PARTICLES) return;
312
313 struct particle *p = &particles[num_active_particles];
314 p->x = x;
315 p->y = SCREEN_HEIGHT;
316 p->xvel = 0;
317 p->yvel = -sqrt(2*ACCEL*(SCREEN_HEIGHT-y) + VEL_BEFORE_EXPLODE * VEL_BEFORE_EXPLODE);
318 p->color[0] = 1.0 * 255;
319 p->color[1] = 0.4 * 255;
320 p->color[2] = 0.4 * 255;
321 p->color[3] = 1.0f * 255;
322 p->size = 10;
323 p->type = emitter;
324 p->framesSinceEmission = 0;
325 p->isActive = 1;
326 num_active_particles++;
327 }
328
329 void initializeParticles(void) {
330
331 num_active_particles = 0;
332
333 }
334
335 /*
336 loads the brush texture
337 */
338 void initializeTexture() {
339 SDL_Surface *bmp_surface;
340 bmp_surface = SDL_LoadBMP("stroke.bmp");
341 if (bmp_surface == NULL) {
342 fatalError("could not load stroke.bmp");
343 }
344 flashTextureID = SDL_CreateTextureFromSurface(SDL_PIXELFORMAT_ABGR8888, bmp_surface);
345 SDL_FreeSurface(bmp_surface);
346 if (flashTextureID == 0) {
347 fatalError("could not create brush texture");
348 }
349 glEnable(GL_TEXTURE_2D);
350 glEnable(GL_BLEND);
351 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
352 }
353
354 int main(int argc, char *argv[]) {
355
356 SDL_WindowID windowID; /* ID of main window */
357 Uint32 startFrame; /* time frame began to process */
358 Uint32 endFrame; /* time frame ended processing */
359 Uint32 delay; /* time to pause waiting to draw next frame */
360 int done; /* should we clean up and exit? */
361
362 struct glformat requested, obtained;
363
364 /* initialize SDL */
365 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
366 fatalError("Could not initialize SDL");
367 }
368
369 srand(time(NULL));
370
371 SDL_GL_LoadLibrary(NULL);
372
373 SDL_memset(&requested, 0, sizeof(requested));
374 requested.SDL_GL_RED_SIZE = 5;
375 requested.SDL_GL_GREEN_SIZE = 6;
376 requested.SDL_GL_BLUE_SIZE = 5;
377 requested.SDL_GL_ALPHA_SIZE = 0;
378 requested.SDL_GL_DEPTH_SIZE = 0;
379 requested.SDL_GL_RETAINED_BACKING = 0;
380 requested.SDL_GL_ACCELERATED_VISUAL = 1;
381
382 setOpenGLAttributes(&requested);
383
384 /* create main window and renderer */
385 windowID = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,\
386 SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_BORDERLESS);
387 SDL_CreateRenderer(windowID, 0, 0);
388
389 printf("Requested:\n");
390 printOpenGLAttributes(&requested);
391
392 printf("obtained:\n");
393 getOpenGLAttributes(&obtained);
394 printOpenGLAttributes(&obtained);
395
396 initializeTexture();
397
398 done = 0;
399 /* enter main loop */
400 while(!done) {
401 startFrame = SDL_GetTicks();
402 SDL_Event event;
403 while (SDL_PollEvent(&event)) {
404 if (event.type == SDL_QUIT) {
405 done = 1;
406 }
407 if (event.type == SDL_MOUSEBUTTONDOWN) {
408 printf("mouse down\n");
409 int which = event.button.which;
410 int x, y;
411 SDL_SelectMouse(which);
412 SDL_GetMouseState(&x, &y);
413 spawnEmitterParticle(x, y);
414 }
415 }
416 render();
417 endFrame = SDL_GetTicks();
418
419 /* figure out how much time we have left, and then sleep */
420 delay = MILLESECONDS_PER_FRAME - (endFrame - startFrame);
421 if (delay > MILLESECONDS_PER_FRAME) {
422 delay = MILLESECONDS_PER_FRAME;
423 }
424 if (delay > 0) {
425 SDL_Delay(delay);
426 }
427
428 //SDL_Delay(delay);
429 }
430
431 /* delete textures */
432
433 /* shutdown SDL */
434 SDL_Quit();
435
436 return 0;
437
438 }