blob: d19f049c5f3fadef39c0c023e4ebfa0689b1dcff [file] [log] [blame]
Brian Paul5b0a7f32000-06-27 16:52:38 +00001/*
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>
Karl Schultz164ce122002-01-16 00:48:43 +000014#ifndef M_PI
15#define M_PI 3.14159265
16#endif
Brian Paul5b0a7f32000-06-27 16:52:38 +000017
18#include "particles.h"
19extern "C" {
Karl Schultz164ce122002-01-16 00:48:43 +000020#include "readtex.h"
Brian Paul5b0a7f32000-06-27 16:52:38 +000021}
22
Karl Schultz164ce122002-01-16 00:48:43 +000023#ifdef _WIN32
Brian Paul5b0a7f32000-06-27 16:52:38 +000024#include <windows.h>
25#include <mmsystem.h>
Karl Schultz164ce122002-01-16 00:48:43 +000026#include "particles.cxx"
27#include "readtex.c"
Brian Paul5b0a7f32000-06-27 16:52:38 +000028#endif
29
30#ifdef XMESA
31#include "GL/xmesa.h"
32static int fullscreen=1;
33#endif
34
35static int WIDTH=640;
36static int HEIGHT=480;
37static int NUMPART=7500;
38
39#define FRAME 50
40
41static float fogcolor[4]={1.0,1.0,1.0,1.0};
42
43#define DIMP 40.0
44#define DIMTP 32.0
45
46static 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
53static float qt[4][2]={
54 {-DIMTP,-DIMTP},
55 {DIMTP,-DIMTP},
56 {DIMTP,DIMTP},
57 {-DIMTP,DIMTP}
58};
59
60static int win=0;
61
62static int fog=1;
63static int help=1;
64
65static GLuint groundid;
66
67static float obs[3]={2.0,1.0,0.0};
68static float dir[3];
69static float v=0.0;
70static float alpha=-90.0;
71static float beta=90.0;
72
73static particleSystem *ps;
74
75static 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
89static 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
103static 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
116static 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
125static 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
137static 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);
Brian Paulc39a4bc2005-04-04 20:06:40 +0000149 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Toggle Help");
Brian Paul5b0a7f32000-06-27 16:52:38 +0000150
151 glRasterPos2i(60,360);
Brian Paulc39a4bc2005-04-04 20:06:40 +0000152 printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Toggle Fog");
Brian Paul5b0a7f32000-06-27 16:52:38 +0000153 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
165static 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
249static 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
267static 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
303static void inittextures(void)
304{
Karl Schultz164ce122002-01-16 00:48:43 +0000305 GLubyte *img;
306 GLint width,height;
307 GLenum format;
Brian Paul5b0a7f32000-06-27 16:52:38 +0000308 GLenum gluerr;
309
310 glGenTextures(1,&groundid);
311 glBindTexture(GL_TEXTURE_2D,groundid);
312
Karl Schultz164ce122002-01-16 00:48:43 +0000313 if(!(img=LoadRGBImage("../images/s128.rgb",&width,&height,&format))){
314 fprintf(stderr,"Error reading a texture.\n");
315 exit(-1);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000316 }
Brian Paul5b0a7f32000-06-27 16:52:38 +0000317 glPixelStorei(GL_UNPACK_ALIGNMENT,4);
Karl Schultz164ce122002-01-16 00:48:43 +0000318 if((gluerr=(GLenum)gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGB,
319 GL_UNSIGNED_BYTE, (GLvoid *)(img)))) {
Brian Paul5b0a7f32000-06-27 16:52:38 +0000320 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
333static 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
347int 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}