move initialization code aroudn so glPointParameter isn't called before checking...
[mesa.git] / progs / demos / rain.cxx
1 /*
2 * This program is under the GNU GPL.
3 * Use at your own risk.
4 *
5 * written by David Bucciarelli (humanware@plus.it)
6 * Humanware s.r.l.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <time.h>
13 #include <GL/glut.h>
14 #ifndef M_PI
15 #define M_PI 3.14159265
16 #endif
17
18 #include "particles.h"
19 extern "C" {
20 #include "readtex.h"
21 }
22
23 #ifdef _WIN32
24 #include <windows.h>
25 #include <mmsystem.h>
26 #include "particles.cxx"
27 #include "readtex.c"
28 #endif
29
30 #ifdef XMESA
31 #include "GL/xmesa.h"
32 static int fullscreen=1;
33 #endif
34
35 static int WIDTH=640;
36 static int HEIGHT=480;
37 static int NUMPART=7500;
38
39 #define FRAME 50
40
41 static float fogcolor[4]={1.0,1.0,1.0,1.0};
42
43 #define DIMP 40.0
44 #define DIMTP 32.0
45
46 static float q[4][3]={
47 {-DIMP,0.0,-DIMP},
48 {DIMP,0.0,-DIMP},
49 {DIMP,0.0,DIMP},
50 {-DIMP,0.0,DIMP}
51 };
52
53 static float qt[4][2]={
54 {-DIMTP,-DIMTP},
55 {DIMTP,-DIMTP},
56 {DIMTP,DIMTP},
57 {-DIMTP,DIMTP}
58 };
59
60 static int win=0;
61
62 static int fog=1;
63 static int help=1;
64
65 static GLuint groundid;
66
67 static float obs[3]={2.0,1.0,0.0};
68 static float dir[3];
69 static float v=0.0;
70 static float alpha=-90.0;
71 static float beta=90.0;
72
73 static particleSystem *ps;
74
75 static float gettime()
76 {
77 static clock_t told=0;
78 clock_t tnew,ris;
79
80 tnew=clock();
81
82 ris=tnew-told;
83
84 told=tnew;
85
86 return(ris/(float)CLOCKS_PER_SEC);
87 }
88
89 static float gettimerain()
90 {
91 static clock_t told=0;
92 clock_t tnew,ris;
93
94 tnew=clock();
95
96 ris=tnew-told;
97
98 told=tnew;
99
100 return(ris/(float)CLOCKS_PER_SEC);
101 }
102
103 static void calcposobs(void)
104 {
105 dir[0]=sin(alpha*M_PI/180.0);
106 dir[2]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
107 dir[1]=cos(beta*M_PI/180.0);
108
109 obs[0]+=v*dir[0];
110 obs[1]+=v*dir[1];
111 obs[2]+=v*dir[2];
112
113 rainParticle::setRainingArea(obs[0]-7.0f,-0.2f,obs[2]-7.0f,obs[0]+7.0f,8.0f,obs[2]+7.0f);
114 }
115
116 static void printstring(void *font, char *string)
117 {
118 int len,i;
119
120 len=(int)strlen(string);
121 for(i=0;i<len;i++)
122 glutBitmapCharacter(font,string[i]);
123 }
124
125 static void reshape(int width, int height)
126 {
127 WIDTH=width;
128 HEIGHT=height;
129 glViewport(0,0,(GLint)width,(GLint)height);
130 glMatrixMode(GL_PROJECTION);
131 glLoadIdentity();
132 gluPerspective(70.0,width/(float)height,0.1,30.0);
133
134 glMatrixMode(GL_MODELVIEW);
135 }
136
137 static void printhelp(void)
138 {
139 glEnable(GL_BLEND);
140 glColor4f(0.0,0.0,0.0,0.5);
141 glRecti(40,40,600,440);
142 glDisable(GL_BLEND);
143
144 glColor3f(1.0,0.0,0.0);
145 glRasterPos2i(300,420);
146 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
147
148 glRasterPos2i(60,390);
149 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Toggle Help");
150
151 glRasterPos2i(60,360);
152 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Toggle Fog");
153 glRasterPos2i(60,330);
154 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
155 glRasterPos2i(60,300);
156 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
157 glRasterPos2i(60,270);
158 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
159 glRasterPos2i(60,240);
160 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"l - Increase rain length");
161 glRasterPos2i(60,210);
162 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"k - Increase rain length");
163 }
164
165 static void drawrain(void)
166 {
167 static int count=0;
168 static char frbuf[80];
169 float fr;
170
171 glEnable(GL_DEPTH_TEST);
172
173 if(fog)
174 glEnable(GL_FOG);
175 else
176 glDisable(GL_FOG);
177
178 glDepthMask(GL_TRUE);
179 glClearColor(1.0,1.0,1.0,1.0);
180 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
181
182 glPushMatrix();
183 calcposobs();
184 gluLookAt(obs[0],obs[1],obs[2],
185 obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
186 0.0,1.0,0.0);
187
188 glColor4f(1.0,1.0,1.0,1.0);
189
190 glEnable(GL_TEXTURE_2D);
191
192 glBindTexture(GL_TEXTURE_2D,groundid);
193 glBegin(GL_QUADS);
194 glTexCoord2fv(qt[0]);
195 glVertex3fv(q[0]);
196 glTexCoord2fv(qt[1]);
197 glVertex3fv(q[1]);
198 glTexCoord2fv(qt[2]);
199 glVertex3fv(q[2]);
200 glTexCoord2fv(qt[3]);
201 glVertex3fv(q[3]);
202 glEnd();
203
204 // Particle System
205
206 glDisable(GL_TEXTURE_2D);
207 glShadeModel(GL_SMOOTH);
208 glEnable(GL_BLEND);
209
210 ps->draw();
211 ps->addTime(gettimerain());
212
213 glShadeModel(GL_FLAT);
214
215
216 if((count % FRAME)==0) {
217 fr=gettime();
218 sprintf(frbuf,"Frame rate: %f",FRAME/fr);
219 }
220
221 glDisable(GL_TEXTURE_2D);
222 glDisable(GL_DEPTH_TEST);
223 glDisable(GL_FOG);
224
225 glMatrixMode(GL_PROJECTION);
226 glLoadIdentity();
227 glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
228 glMatrixMode(GL_MODELVIEW);
229 glLoadIdentity();
230
231 glColor3f(1.0,0.0,0.0);
232 glRasterPos2i(10,10);
233 printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
234 glRasterPos2i(350,470);
235 printstring(GLUT_BITMAP_HELVETICA_10,"Rain V1.0 Written by David Bucciarelli (humanware@plus.it)");
236
237 if(help)
238 printhelp();
239
240 reshape(WIDTH,HEIGHT);
241 glPopMatrix();
242
243 glutSwapBuffers();
244
245 count++;
246 }
247
248
249 static void special(int key, int x, int y)
250 {
251 switch (key) {
252 case GLUT_KEY_LEFT:
253 alpha+=2.0;
254 break;
255 case GLUT_KEY_RIGHT:
256 alpha-=2.0;
257 break;
258 case GLUT_KEY_DOWN:
259 beta-=2.0;
260 break;
261 case GLUT_KEY_UP:
262 beta+=2.0;
263 break;
264 }
265 }
266
267 static void key(unsigned char key, int x, int y)
268 {
269 switch (key) {
270 case 27:
271 exit(0);
272 break;
273
274 case 'a':
275 v+=0.01;
276 break;
277 case 'z':
278 v-=0.01;
279 break;
280
281 case 'l':
282 rainParticle::setLength(rainParticle::getLength()+0.025f);
283 break;
284 case 'k':
285 rainParticle::setLength(rainParticle::getLength()-0.025f);
286 break;
287
288 case 'h':
289 help=(!help);
290 break;
291 case 'f':
292 fog=(!fog);
293 break;
294 #ifdef XMESA
295 case ' ':
296 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
297 fullscreen=(!fullscreen);
298 break;
299 #endif
300 }
301 }
302
303 static void inittextures(void)
304 {
305 GLubyte *img;
306 GLint width,height;
307 GLenum format;
308 GLenum gluerr;
309
310 glGenTextures(1,&groundid);
311 glBindTexture(GL_TEXTURE_2D,groundid);
312
313 if(!(img=LoadRGBImage("../images/s128.rgb",&width,&height,&format))){
314 fprintf(stderr,"Error reading a texture.\n");
315 exit(-1);
316 }
317 glPixelStorei(GL_UNPACK_ALIGNMENT,4);
318 if((gluerr=(GLenum)gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGB,
319 GL_UNSIGNED_BYTE, (GLvoid *)(img)))) {
320 fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
321 exit(-1);
322 }
323
324 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
325 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
326
327 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
328 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
329
330 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
331 }
332
333 static void initparticle(void)
334 {
335 ps=new particleSystem;
336
337 rainParticle::setRainingArea(-7.0f,-0.2f,-7.0f,7.0f,8.0f,7.0f);
338
339 for(int i=0;i<NUMPART;i++) {
340 rainParticle *p=new rainParticle;
341 p->randomHeight();
342
343 ps->addParticle((particle *)p);
344 }
345 }
346
347 int main(int ac,char **av)
348 {
349 fprintf(stderr,"Rain V1.0\nWritten by David Bucciarelli (humanware@plus.it)\n");
350
351 /* Default settings */
352
353 WIDTH=640;
354 HEIGHT=480;
355
356 glutInitWindowPosition(0,0);
357 glutInitWindowSize(WIDTH,HEIGHT);
358 glutInit(&ac,av);
359
360 glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
361
362 if(!(win=glutCreateWindow("Rain"))) {
363 fprintf(stderr,"Error opening a window.\n");
364 exit(-1);
365 }
366
367 reshape(WIDTH,HEIGHT);
368
369 inittextures();
370
371 glShadeModel(GL_FLAT);
372 glEnable(GL_DEPTH_TEST);
373
374 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
375
376 glEnable(GL_FOG);
377 glFogi(GL_FOG_MODE,GL_EXP);
378 glFogfv(GL_FOG_COLOR,fogcolor);
379 glFogf(GL_FOG_DENSITY,0.1);
380 #ifdef FX
381 glHint(GL_FOG_HINT,GL_NICEST);
382 #endif
383
384 initparticle();
385
386 glutKeyboardFunc(key);
387 glutSpecialFunc(special);
388 glutDisplayFunc(drawrain);
389 glutIdleFunc(drawrain);
390 glutReshapeFunc(reshape);
391 glutMainLoop();
392
393 return(0);
394 }