History

adding more behavior to the particle system

Jeffrey Ventrella committed 13 years ago

Commit 5a0fcb71 parent 1aa06114 files · +149 −98Browse files

Showing the changes to interface/src/ParticleSystem.cpp (1 of 4 files). Show all

Unified · Split

interface/src/ParticleSystem.cpp+119−68
@@ -16,29 +16,31 @@ const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f; · 15 unmodified lines
16 16
17ParticleSystem::ParticleSystem() {17ParticleSystem::ParticleSystem() {
18 18
19 _timer = 0.0f;
20 _numEmitters = 0;19 _numEmitters = 0;
21 _numParticles = 0;20 _numParticles = 0;
22 _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default21 _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
23 22
24 for (unsigned int e = 0; e < MAX_EMITTERS; e++) {23 for (unsigned int e = 0; e < MAX_EMITTERS; e++) {
25 _emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);24 _emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
26 _emitter[e].rotation = glm::quat();25 _emitter[e].rotation = glm::quat();
27 _emitter[e].right = IDENTITY_RIGHT;26 _emitter[e].right = IDENTITY_RIGHT;
28 _emitter[e].up = IDENTITY_UP;27 _emitter[e].up = IDENTITY_UP;
29 _emitter[e].front = IDENTITY_FRONT;28 _emitter[e].front = IDENTITY_FRONT;
30 _emitter[e].showingEmitter = false;29 _emitter[e].visible = false;
31 _emitter[e].particleAttributes.bounce = DEFAULT_PARTICLE_BOUNCE;30
32 _emitter[e].particleAttributes.airFriction = DEFAULT_PARTICLE_AIR_FRICTION;31 for (int s = 0; s<NUM_PARTICLE_LIFE_STAGES; s++) {
33 _emitter[e].particleAttributes.gravity = 0.0f;32 _emitter[e].particleAttributes[s].bounce = DEFAULT_PARTICLE_BOUNCE;
34 _emitter[e].particleAttributes.jitter = 0.0f;33 _emitter[e].particleAttributes[s].airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
35 _emitter[e].particleAttributes.emitterAttraction = 0.0f;34 _emitter[e].particleAttributes[s].gravity = 0.0f;
36 _emitter[e].particleAttributes.tornadoForce = 0.0f;35 _emitter[e].particleAttributes[s].jitter = 0.0f;
37 _emitter[e].particleAttributes.neighborAttraction = 0.0f;36 _emitter[e].particleAttributes[s].emitterAttraction = 0.0f;
38 _emitter[e].particleAttributes.neighborRepulsion = 0.0f;37 _emitter[e].particleAttributes[s].tornadoForce = 0.0f;
39 _emitter[e].particleAttributes.collisionSphereRadius = 0.0f;38 _emitter[e].particleAttributes[s].neighborAttraction = 0.0f;
40 _emitter[e].particleAttributes.collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);39 _emitter[e].particleAttributes[s].neighborRepulsion = 0.0f;
41 _emitter[e].particleAttributes.usingCollisionSphere = false;40 _emitter[e].particleAttributes[s].collisionSphereRadius = 0.0f;
41 _emitter[e].particleAttributes[s].collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
42 _emitter[e].particleAttributes[s].usingCollisionSphere = false;
43 }
42 }; 44 };
43 45
44 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {46 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
@@ -52,7 +54,6 @@ ParticleSystem::ParticleSystem() { · 7 unmodified lines
52 } 54 }
53}55}
54 56
55
56int ParticleSystem::addEmitter() {57int ParticleSystem::addEmitter() {
57 58
58 _numEmitters ++;59 _numEmitters ++;
@@ -75,11 +76,16 @@ void ParticleSystem::simulate(float deltaTime) { · 16 unmodified lines
75 // update particles76 // update particles
76 for (unsigned int p = 0; p < _numParticles; p++) {77 for (unsigned int p = 0; p < _numParticles; p++) {
77 if (_particle[p].alive) {78 if (_particle[p].alive) {
78 updateParticle(p, deltaTime);79 if (_particle[p].age > _particle[p].lifespan) {
80 killParticle(p);
81 } else {
82 updateParticle(p, deltaTime);
83 }
79 }84 }
80 }85 }
81}86}
82 87
88
83void ParticleSystem::updateEmitter(int e, float deltaTime) {89void ParticleSystem::updateEmitter(int e, float deltaTime) {
84 90
85 _emitter[e].front = _emitter[e].rotation * IDENTITY_FRONT;91 _emitter[e].front = _emitter[e].rotation * IDENTITY_FRONT;
@@ -146,45 +152,54 @@ void ParticleSystem::setOrangeBlueColorPalette() { · 60 unmodified lines
146}152}
147 153
148 154
149void ParticleSystem::setParticleAttributesForEmitter(int emitterIndex, ParticleAttributes attributes) {155void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) {
150 156
151 _emitter[emitterIndex].particleAttributes.bounce = attributes.bounce;157 for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) {
152 _emitter[emitterIndex].particleAttributes.gravity = attributes.gravity;158 setParticleAttributes(emitterIndex, lifeStage, attributes);
153 _emitter[emitterIndex].particleAttributes.airFriction = attributes.airFriction;159 }
154 _emitter[emitterIndex].particleAttributes.jitter = attributes.jitter;
155 _emitter[emitterIndex].particleAttributes.emitterAttraction = attributes.emitterAttraction;
156 _emitter[emitterIndex].particleAttributes.tornadoForce = attributes.tornadoForce;
157 _emitter[emitterIndex].particleAttributes.neighborAttraction = attributes.neighborAttraction;
158 _emitter[emitterIndex].particleAttributes.neighborRepulsion = attributes.neighborRepulsion;
159 _emitter[emitterIndex].particleAttributes.usingCollisionSphere = attributes.usingCollisionSphere;
160 _emitter[emitterIndex].particleAttributes.collisionSpherePosition = attributes.collisionSpherePosition;
161 _emitter[emitterIndex].particleAttributes.collisionSphereRadius = attributes.collisionSphereRadius;
162}160}
163 161
162void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, ParticleAttributes attributes) {
163
164 ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
165
166 a->bounce = attributes.bounce;
167 a->gravity = attributes.gravity;
168 a->airFriction = attributes.airFriction;
169 a->jitter = attributes.jitter;
170 a->emitterAttraction = attributes.emitterAttraction;
171 a->tornadoForce = attributes.tornadoForce;
172 a->neighborAttraction = attributes.neighborAttraction;
173 a->neighborRepulsion = attributes.neighborRepulsion;
174 a->usingCollisionSphere = attributes.usingCollisionSphere;
175 a->collisionSpherePosition = attributes.collisionSpherePosition;
176 a->collisionSphereRadius = attributes.collisionSphereRadius;
177}
164 178
165 179
166void ParticleSystem::updateParticle(int p, float deltaTime) {180void ParticleSystem::updateParticle(int p, float deltaTime) {
167 181
168 _particle[p].age += deltaTime;182 assert(_particle[p].age <= _particle[p].lifespan);
183
184 float ageFraction = _particle[p].age / _particle[p].lifespan;
169 185
170 if (_particle[p].age > _particle[p].lifespan) {186 int lifeStage = (int)( ageFraction * NUM_PARTICLE_LIFE_STAGES );
171 killParticle(p);
172 }
173 187
174 Emitter myEmitter = _emitter[_particle[p].emitterIndex];188 Emitter myEmitter = _emitter[_particle[p].emitterIndex];
175 189
176 // apply random jitter190 // apply random jitter
191 float j = myEmitter.particleAttributes[lifeStage].jitter;
177 _particle[p].velocity += 192 _particle[p].velocity +=
178 glm::vec3193 glm::vec3
179 (194 (
180 -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat(), 195 -j * ONE_HALF + j * randFloat(),
181 -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat(), 196 -j * ONE_HALF + j * randFloat(),
182 -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat()197 -j * ONE_HALF + j * randFloat()
183 ) * deltaTime;198 ) * deltaTime;
184 199
185 // apply attraction to home position200 // apply attraction to home position
186 glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;201 glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;
187 _particle[p].velocity += vectorToHome * myEmitter.particleAttributes.emitterAttraction * deltaTime;202 _particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
188 203
189 // apply neighbor attraction204 // apply neighbor attraction
190 int neighbor = p + 1;205 int neighbor = p + 1;
@@ -195,20 +210,20 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 4 unmodified lines
195 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {210 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
196 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;211 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
197 212
198 _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes.neighborAttraction * deltaTime;213 _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
199 214
200 float distanceToNeighbor = glm::length(vectorToNeighbor);215 float distanceToNeighbor = glm::length(vectorToNeighbor);
201 if (distanceToNeighbor > 0.0f) {216 if (distanceToNeighbor > 0.0f) {
202 _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes.neighborRepulsion * deltaTime;217 _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime;
203 }218 }
204 }219 }
205 220
206 // apply tornado force221 // apply tornado force
207 glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.up);222 glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.up);
208 _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes.tornadoForce * deltaTime;223 _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
209 224
210 // apply air friction225 // apply air friction
211 float drag = 1.0 - myEmitter.particleAttributes.airFriction * deltaTime;226 float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
212 if (drag < 0.0f) {227 if (drag < 0.0f) {
213 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);228 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
214 } else {229 } else {
@@ -216,7 +231,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 1 unmodified line
216 }231 }
217 232
218 // apply gravity233 // apply gravity
219 _particle[p].velocity -= _upDirection * myEmitter.particleAttributes.gravity * deltaTime; 234 _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
220 235
221 // update position by velocity236 // update position by velocity
222 _particle[p].position += _particle[p].velocity;237 _particle[p].position += _particle[p].velocity;
@@ -226,36 +241,42 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 3 unmodified lines
226 _particle[p].position.y = _particle[p].radius;241 _particle[p].position.y = _particle[p].radius;
227 242
228 if (_particle[p].velocity.y < 0.0f) {243 if (_particle[p].velocity.y < 0.0f) {
229 _particle[p].velocity.y *= -myEmitter.particleAttributes.bounce;244 _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
230 }245 }
231 }246 }
232 247
233 // collision with sphere248 // collision with sphere
234 if (myEmitter.particleAttributes.usingCollisionSphere) {249 if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
235 glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes.collisionSpherePosition - _particle[p].position;250 glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
236 float distanceToSphereCenter = glm::length(vectorToSphereCenter);251 float distanceToSphereCenter = glm::length(vectorToSphereCenter);
237 float combinedRadius = myEmitter.particleAttributes.collisionSphereRadius + _particle[p].radius;252 float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
238 if (distanceToSphereCenter < combinedRadius) {253 if (distanceToSphereCenter < combinedRadius) {
239 254
240 if (distanceToSphereCenter > 0.0f){255 if (distanceToSphereCenter > 0.0f){
241 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;256 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
242 _particle[p].position = myEmitter.particleAttributes.collisionSpherePosition - directionToSphereCenter * combinedRadius; 257 _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
243 }258 }
244 }259 }
245 }260 }
261
262 // do this at the end...
263 _particle[p].age += deltaTime;
246}264}
247 265
248void ParticleSystem::setCollisionSphere(int e, glm::vec3 position, float radius) {266void ParticleSystem::setCollisionSphere(int e, glm::vec3 position, float radius) {
249 _emitter[e].particleAttributes.usingCollisionSphere = true;267
250 _emitter[e].particleAttributes.collisionSpherePosition = position; 268 int lifeStage = 0;
251 _emitter[e].particleAttributes.collisionSphereRadius = radius;269
270 _emitter[e].particleAttributes[lifeStage].usingCollisionSphere = true;
271 _emitter[e].particleAttributes[lifeStage].collisionSpherePosition = position;
272 _emitter[e].particleAttributes[lifeStage].collisionSphereRadius = radius;
252}273}
253 274
254void ParticleSystem::render() {275void ParticleSystem::render() {
255 276
256 // render the emitters277 // render the emitters
257 for (unsigned int e = 0; e < _numEmitters; e++) {278 for (unsigned int e = 0; e < _numEmitters; e++) {
258 if (_emitter[e].showingEmitter) {279 if (_emitter[e].visible) {
259 renderEmitter(e, 0.2f);280 renderEmitter(e, 0.2f);
260 }281 }
261 }; 282 };
@@ -271,19 +292,49 @@ void ParticleSystem::render() { · 9 unmodified lines
271void ParticleSystem::renderParticle(int p) {292void ParticleSystem::renderParticle(int p) {
272 293
273 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );294 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );
274 glPushMatrix();295
275 glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);296 if (USE_BILLBOARD_RENDERING) {
276 glutSolidSphere(_particle[p].radius, 6, 6);297 glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
277 glPopMatrix();298 glm::vec3 viewVector = _particle[p].position - cameraPosition;
278 299 float distance = glm::length(viewVector);
279 // render velocity lines300
280 glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);301 if (distance >= 0.0f) {
281 glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;302 viewVector /= distance;
282 glBegin(GL_LINES);303 glm::vec3 up = glm::vec3(viewVector.y, viewVector.z, viewVector.x);
283 glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);304 glm::vec3 right = glm::vec3(viewVector.z, viewVector.x, viewVector.y);
284 glVertex3f(end.x, end.y, end.z);305
285 306 glm::vec3 p0 = _particle[p].position - right * _particle[p].radius - up * _particle[p].radius;
286 glEnd();307 glm::vec3 p1 = _particle[p].position + right * _particle[p].radius - up * _particle[p].radius;
308 glm::vec3 p2 = _particle[p].position + right * _particle[p].radius + up * _particle[p].radius;
309 glm::vec3 p3 = _particle[p].position - right * _particle[p].radius + up * _particle[p].radius;
310
311 glBegin(GL_TRIANGLES);
312 glVertex3f(p0.x, p0.y, p0.z);
313 glVertex3f(p1.x, p1.y, p1.z);
314 glVertex3f(p2.x, p2.y, p2.z);
315 glEnd();
316
317 glBegin(GL_TRIANGLES);
318 glVertex3f(p0.x, p0.y, p0.z);
319 glVertex3f(p2.x, p2.y, p2.z);
320 glVertex3f(p3.x, p3.y, p3.z);
321 glEnd();
322 }
323 } else {
324 glPushMatrix();
325 glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
326 glutSolidSphere(_particle[p].radius, 6, 6);
327 glPopMatrix();
328
329 // render velocity lines
330 glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
331 glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
332 glBegin(GL_LINES);
333 glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
334 glVertex3f(end.x, end.y, end.z);
335
336 glEnd();
337 }
287}338}
288 339
289 340
@@ -293,7 +344,7 @@ void ParticleSystem::renderEmitter(int e, float size) { · 3 unmodified lines
293 glm::vec3 r = _emitter[e].right * size;344 glm::vec3 r = _emitter[e].right * size;
294 glm::vec3 u = _emitter[e].up * size;345 glm::vec3 u = _emitter[e].up * size;
295 glm::vec3 f = _emitter[e].front * size;346 glm::vec3 f = _emitter[e].front * size;
296 347
297 glLineWidth(2.0f);348 glLineWidth(2.0f);
298 349
299 glColor3f(0.8f, 0.4, 0.4);350 glColor3f(0.8f, 0.4, 0.4);