Merge commit 'origin/master' into gallium-0.2
[mesa.git] / progs / demos / particles.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 <stdlib.h>
10
11 #include "particles.h"
12
13 #define vinit(a,i,j,k) {\
14 (a)[0]=i;\
15 (a)[1]=j;\
16 (a)[2]=k;\
17 }
18
19 #define vadds(a,dt,b) {\
20 (a)[0]+=(dt)*(b)[0];\
21 (a)[1]+=(dt)*(b)[1];\
22 (a)[2]+=(dt)*(b)[2];\
23 }
24
25 #define vequ(a,b) {\
26 (a)[0]=(b)[0];\
27 (a)[1]=(b)[1];\
28 (a)[2]=(b)[2];\
29 }
30
31 #define vinter(a,dt,b,c) {\
32 (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
33 (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
34 (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
35 }
36
37 #define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
38
39 #define vclamp(v) {\
40 (v)[0]=clamp((v)[0]);\
41 (v)[1]=clamp((v)[1]);\
42 (v)[2]=clamp((v)[2]);\
43 }
44
45
46 float rainParticle::min[3];
47 float rainParticle::max[3];
48 float rainParticle::partLength=0.2f;
49
50
51 static float vrnd(void)
52 {
53 return(((float)rand())/RAND_MAX);
54 }
55
56
57 particle::particle()
58 {
59 age=0.0f;
60
61 vinit(acc,0.0f,0.0f,0.0f);
62 vinit(vel,0.0f,0.0f,0.0f);
63 vinit(pos,0.0f,0.0f,0.0f);
64 }
65
66 void particle::elapsedTime(float dt)
67 {
68 age+=dt;
69
70 vadds(vel,dt,acc);
71
72 vadds(pos,dt,vel);
73 }
74
75 /////////////////////////////////////////
76 // Particle System
77 /////////////////////////////////////////
78
79 particleSystem::particleSystem()
80 {
81 t=0.0f;
82
83 part=NULL;
84
85 particleNum=0;
86 }
87
88 particleSystem::~particleSystem()
89 {
90 if(part)
91 free(part);
92 }
93
94 void particleSystem::addParticle(particle *p)
95 {
96 if(!part) {
97 part=(particle **)calloc(1,sizeof(particle *));
98 part[0]=p;
99 particleNum=1;
100 } else {
101 particleNum++;
102 part=(particle **)realloc(part,sizeof(particle *)*particleNum);
103 part[particleNum-1]=p;
104 }
105 }
106
107 void particleSystem::reset(void)
108 {
109 if(part)
110 free(part);
111
112 t=0.0f;
113
114 part=NULL;
115
116 particleNum=0;
117 }
118
119 void particleSystem::draw(void)
120 {
121 if(!part)
122 return;
123
124 part[0]->beginDraw();
125 for(unsigned int i=0;i<particleNum;i++)
126 part[i]->draw();
127 part[0]->endDraw();
128 }
129
130 void particleSystem::addTime(float dt)
131 {
132 if(!part)
133 return;
134
135 for(unsigned int i=0;i<particleNum;i++) {
136 part[i]->elapsedTime(dt);
137 part[i]->checkAge();
138 }
139 }
140
141 /////////////////////////////////////////
142 // Rain
143 /////////////////////////////////////////
144
145 void rainParticle::init(void)
146 {
147 age=0.0f;
148
149 acc[0]=0.0f;
150 acc[1]=-0.98f;
151 acc[2]=0.0f;
152
153 vel[0]=0.0f;
154 vel[1]=0.0f;
155 vel[2]=0.0f;
156
157 oldpos[0]=pos[0]=min[0]+(max[0]-min[0])*vrnd();
158 oldpos[1]=pos[1]=max[1]+0.2f*max[1]*vrnd();
159 oldpos[2]=pos[2]=min[2]+(max[2]-min[2])*vrnd();
160
161 vadds(oldpos,-partLength,vel);
162 }
163
164 rainParticle::rainParticle()
165 {
166 init();
167 }
168
169 void rainParticle::setRainingArea(float minx, float miny, float minz,
170 float maxx, float maxy, float maxz)
171 {
172 vinit(min,minx,miny,minz);
173 vinit(max,maxx,maxy,maxz);
174 }
175
176 void rainParticle::setLength(float l)
177 {
178 partLength=l;
179 }
180
181 void rainParticle::draw(void)
182 {
183 glColor4f(0.7f,0.95f,1.0f,0.0f);
184 glVertex3fv(oldpos);
185
186 glColor4f(0.3f,0.7f,1.0f,1.0f);
187 glVertex3fv(pos);
188 }
189
190 void rainParticle::checkAge(void)
191 {
192 if(pos[1]<min[1])
193 init();
194 }
195
196 void rainParticle::elapsedTime(float dt)
197 {
198 particle::elapsedTime(dt);
199
200 if(pos[0]<min[0])
201 pos[0]=max[0]-(min[0]-pos[0]);
202 if(pos[2]<min[2])
203 pos[2]=max[2]-(min[2]-pos[2]);
204
205 if(pos[0]>max[0])
206 pos[0]=min[0]+(pos[0]-max[0]);
207 if(pos[2]>max[2])
208 pos[2]=min[2]+(pos[2]-max[2]);
209
210 vequ(oldpos,pos);
211 vadds(oldpos,-partLength,vel);
212 }
213
214 void rainParticle::randomHeight(void)
215 {
216 pos[1]=(max[1]-min[1])*vrnd()+min[1];
217
218 oldpos[1]=pos[1]-partLength*vel[1];
219 }