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
1616
1717 ParticleSystem::ParticleSystem() {
1818
19− _timer = 0.0f;
2019 _numEmitters = 0;
2120 _numParticles = 0;
2221 _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
2322
2423 for (unsigned int e = 0; e < MAX_EMITTERS; e++) {
25− _emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
26− _emitter[e].rotation = glm::quat();
27− _emitter[e].right = IDENTITY_RIGHT;
28− _emitter[e].up = IDENTITY_UP;
29− _emitter[e].front = IDENTITY_FRONT;
30− _emitter[e].showingEmitter = false;
31− _emitter[e].particleAttributes.bounce = DEFAULT_PARTICLE_BOUNCE;
32− _emitter[e].particleAttributes.airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
33− _emitter[e].particleAttributes.gravity = 0.0f;
34− _emitter[e].particleAttributes.jitter = 0.0f;
35− _emitter[e].particleAttributes.emitterAttraction = 0.0f;
36− _emitter[e].particleAttributes.tornadoForce = 0.0f;
37− _emitter[e].particleAttributes.neighborAttraction = 0.0f;
38− _emitter[e].particleAttributes.neighborRepulsion = 0.0f;
39− _emitter[e].particleAttributes.collisionSphereRadius = 0.0f;
40− _emitter[e].particleAttributes.collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
41− _emitter[e].particleAttributes.usingCollisionSphere = false;
24+ _emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
25+ _emitter[e].rotation = glm::quat();
26+ _emitter[e].right = IDENTITY_RIGHT;
27+ _emitter[e].up = IDENTITY_UP;
28+ _emitter[e].front = IDENTITY_FRONT;
29+ _emitter[e].visible = false;
30+
31+ for (int s = 0; s<NUM_PARTICLE_LIFE_STAGES; s++) {
32+ _emitter[e].particleAttributes[s].bounce = DEFAULT_PARTICLE_BOUNCE;
33+ _emitter[e].particleAttributes[s].airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
34+ _emitter[e].particleAttributes[s].gravity = 0.0f;
35+ _emitter[e].particleAttributes[s].jitter = 0.0f;
36+ _emitter[e].particleAttributes[s].emitterAttraction = 0.0f;
37+ _emitter[e].particleAttributes[s].tornadoForce = 0.0f;
38+ _emitter[e].particleAttributes[s].neighborAttraction = 0.0f;
39+ _emitter[e].particleAttributes[s].neighborRepulsion = 0.0f;
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+ }
4244 };
4345
4446 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
@@ -52,7 +54,6 @@ ParticleSystem::ParticleSystem() { · 7 unmodified lines
5254 }
5355 }
5456
55−
5657 int ParticleSystem::addEmitter() {
5758
5859 _numEmitters ++;
@@ -75,11 +76,16 @@ void ParticleSystem::simulate(float deltaTime) { · 16 unmodified lines
7576 // update particles
7677 for (unsigned int p = 0; p < _numParticles; p++) {
7778 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+ }
7984 }
8085 }
8186 }
8287
88+
8389 void ParticleSystem::updateEmitter(int e, float deltaTime) {
8490
8591 _emitter[e].front = _emitter[e].rotation * IDENTITY_FRONT;
@@ -146,45 +152,54 @@ void ParticleSystem::setOrangeBlueColorPalette() { · 60 unmodified lines
146152 }
147153
148154
149−void ParticleSystem::setParticleAttributesForEmitter(int emitterIndex, ParticleAttributes attributes) {
155+void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) {
150156
151− _emitter[emitterIndex].particleAttributes.bounce = attributes.bounce;
152− _emitter[emitterIndex].particleAttributes.gravity = attributes.gravity;
153− _emitter[emitterIndex].particleAttributes.airFriction = attributes.airFriction;
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;
157+ for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) {
158+ setParticleAttributes(emitterIndex, lifeStage, attributes);
159+ }
162160 }
163161
162+void 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+}
164178
165179
166180 void ParticleSystem::updateParticle(int p, float deltaTime) {
167181
168− _particle[p].age += deltaTime;
182+ assert(_particle[p].age <= _particle[p].lifespan);
183+
184+ float ageFraction = _particle[p].age / _particle[p].lifespan;
169185
170− if (_particle[p].age > _particle[p].lifespan) {
171− killParticle(p);
172− }
186+ int lifeStage = (int)( ageFraction * NUM_PARTICLE_LIFE_STAGES );
173187
174188 Emitter myEmitter = _emitter[_particle[p].emitterIndex];
175189
176190 // apply random jitter
191+ float j = myEmitter.particleAttributes[lifeStage].jitter;
177192 _particle[p].velocity +=
178193 glm::vec3
179194 (
180− -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat(),
181− -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat(),
182− -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat()
195+ -j * ONE_HALF + j * randFloat(),
196+ -j * ONE_HALF + j * randFloat(),
197+ -j * ONE_HALF + j * randFloat()
183198 ) * deltaTime;
184199
185200 // apply attraction to home position
186201 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;
188203
189204 // apply neighbor attraction
190205 int neighbor = p + 1;
@@ -195,20 +210,20 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 4 unmodified lines
195210 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
196211 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
197212
198− _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes.neighborAttraction * deltaTime;
213+ _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
199214
200215 float distanceToNeighbor = glm::length(vectorToNeighbor);
201216 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;
203218 }
204219 }
205220
206221 // apply tornado force
207222 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;
209224
210225 // apply air friction
211− float drag = 1.0 - myEmitter.particleAttributes.airFriction * deltaTime;
226+ float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
212227 if (drag < 0.0f) {
213228 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
214229 } else {
@@ -216,7 +231,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 1 unmodified line
216231 }
217232
218233 // apply gravity
219− _particle[p].velocity -= _upDirection * myEmitter.particleAttributes.gravity * deltaTime;
234+ _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
220235
221236 // update position by velocity
222237 _particle[p].position += _particle[p].velocity;
@@ -226,36 +241,42 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 3 unmodified lines
226241 _particle[p].position.y = _particle[p].radius;
227242
228243 if (_particle[p].velocity.y < 0.0f) {
229− _particle[p].velocity.y *= -myEmitter.particleAttributes.bounce;
244+ _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
230245 }
231246 }
232247
233248 // collision with sphere
234− if (myEmitter.particleAttributes.usingCollisionSphere) {
235− glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes.collisionSpherePosition - _particle[p].position;
249+ if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
250+ glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
236251 float distanceToSphereCenter = glm::length(vectorToSphereCenter);
237− float combinedRadius = myEmitter.particleAttributes.collisionSphereRadius + _particle[p].radius;
252+ float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
238253 if (distanceToSphereCenter < combinedRadius) {
239254
240255 if (distanceToSphereCenter > 0.0f){
241256 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
242− _particle[p].position = myEmitter.particleAttributes.collisionSpherePosition - directionToSphereCenter * combinedRadius;
257+ _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
243258 }
244259 }
245260 }
261+
262+ // do this at the end...
263+ _particle[p].age += deltaTime;
246264 }
247265
248266 void ParticleSystem::setCollisionSphere(int e, glm::vec3 position, float radius) {
249− _emitter[e].particleAttributes.usingCollisionSphere = true;
250− _emitter[e].particleAttributes.collisionSpherePosition = position;
251− _emitter[e].particleAttributes.collisionSphereRadius = radius;
267+
268+ int lifeStage = 0;
269+
270+ _emitter[e].particleAttributes[lifeStage].usingCollisionSphere = true;
271+ _emitter[e].particleAttributes[lifeStage].collisionSpherePosition = position;
272+ _emitter[e].particleAttributes[lifeStage].collisionSphereRadius = radius;
252273 }
253274
254275 void ParticleSystem::render() {
255276
256277 // render the emitters
257278 for (unsigned int e = 0; e < _numEmitters; e++) {
258− if (_emitter[e].showingEmitter) {
279+ if (_emitter[e].visible) {
259280 renderEmitter(e, 0.2f);
260281 }
261282 };
@@ -271,19 +292,49 @@ void ParticleSystem::render() { · 9 unmodified lines
271292 void ParticleSystem::renderParticle(int p) {
272293
273294 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );
274− glPushMatrix();
275− glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
276− glutSolidSphere(_particle[p].radius, 6, 6);
277− glPopMatrix();
278−
279− // render velocity lines
280− glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
281− glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
282− glBegin(GL_LINES);
283− glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
284− glVertex3f(end.x, end.y, end.z);
285−
286− glEnd();
295+
296+ if (USE_BILLBOARD_RENDERING) {
297+ glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
298+ glm::vec3 viewVector = _particle[p].position - cameraPosition;
299+ float distance = glm::length(viewVector);
300+
301+ if (distance >= 0.0f) {
302+ viewVector /= distance;
303+ glm::vec3 up = glm::vec3(viewVector.y, viewVector.z, viewVector.x);
304+ glm::vec3 right = glm::vec3(viewVector.z, viewVector.x, viewVector.y);
305+
306+ glm::vec3 p0 = _particle[p].position - right * _particle[p].radius - up * _particle[p].radius;
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+ }
287338 }
288339
289340
@@ -293,7 +344,7 @@ void ParticleSystem::renderEmitter(int e, float size) { · 3 unmodified lines
293344 glm::vec3 r = _emitter[e].right * size;
294345 glm::vec3 u = _emitter[e].up * size;
295346 glm::vec3 f = _emitter[e].front * size;
296−
347+
297348 glLineWidth(2.0f);
298349
299350 glColor3f(0.8f, 0.4, 0.4);