History

Merge branch 'master' of https://github.com/worklist/hifi into dev4

Eric Johnston committed 13 years ago

Commit 57c2f162 parents aa0cab2 0bc0f3c4 files · +253 −105Browse files

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

Unified · Split

interface/src/ParticleSystem.cpp+175−69
@@ -11,34 +11,47 @@ · 10 unmodified lines
1111 #include "ParticleSystem.h"
1212 #include "Application.h"
1313
14+const float DEFAULT_PARTICLE_RADIUS = 0.01f;
1415 const float DEFAULT_PARTICLE_BOUNCE = 1.0f;
1516 const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f;
1617
1718 ParticleSystem::ParticleSystem() {
1819
19− _timer = 0.0f;
2020 _numEmitters = 0;
2121 _numParticles = 0;
2222 _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
23−
23+
2424 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;
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].visible = false;
31+ _emitter[e].baseParticle.alive = false;
32+ _emitter[e].baseParticle.age = 0.0f;
33+ _emitter[e].baseParticle.lifespan = 0.0f;
34+ _emitter[e].baseParticle.radius = 0.0f;
35+ _emitter[e].baseParticle.emitterIndex = 0;
36+ _emitter[e].baseParticle.position = glm::vec3(0.0f, 0.0f, 0.0f);
37+ _emitter[e].baseParticle.velocity = glm::vec3(0.0f, 0.0f, 0.0f);
38+
39+
40+ for (int s = 0; s<NUM_PARTICLE_LIFE_STAGES; s++) {
41+ _emitter[e].particleAttributes[s].radius = DEFAULT_PARTICLE_RADIUS;
42+ _emitter[e].particleAttributes[s].color = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
43+ _emitter[e].particleAttributes[s].bounce = DEFAULT_PARTICLE_BOUNCE;
44+ _emitter[e].particleAttributes[s].airFriction = DEFAULT_PARTICLE_AIR_FRICTION;
45+ _emitter[e].particleAttributes[s].gravity = 0.0f;
46+ _emitter[e].particleAttributes[s].jitter = 0.0f;
47+ _emitter[e].particleAttributes[s].emitterAttraction = 0.0f;
48+ _emitter[e].particleAttributes[s].tornadoForce = 0.0f;
49+ _emitter[e].particleAttributes[s].neighborAttraction = 0.0f;
50+ _emitter[e].particleAttributes[s].neighborRepulsion = 0.0f;
51+ _emitter[e].particleAttributes[s].collisionSphereRadius = 0.0f;
52+ _emitter[e].particleAttributes[s].collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);
53+ _emitter[e].particleAttributes[s].usingCollisionSphere = false;
54+ }
4255 };
4356
4457 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
@@ -52,7 +65,6 @@ ParticleSystem::ParticleSystem() { · 7 unmodified lines
5265 }
5366 }
5467
55−
5668 int ParticleSystem::addEmitter() {
5769
5870 _numEmitters ++;
@@ -75,11 +87,16 @@ void ParticleSystem::simulate(float deltaTime) { · 16 unmodified lines
7587 // update particles
7688 for (unsigned int p = 0; p < _numParticles; p++) {
7789 if (_particle[p].alive) {
78− updateParticle(p, deltaTime);
90+ if (_particle[p].age > _particle[p].lifespan) {
91+ killParticle(p);
92+ } else {
93+ updateParticle(p, deltaTime);
94+ }
7995 }
8096 }
8197 }
8298
99+
83100 void ParticleSystem::updateEmitter(int e, float deltaTime) {
84101
85102 _emitter[e].front = _emitter[e].rotation * IDENTITY_FRONT;
@@ -106,9 +123,11 @@ void ParticleSystem::createParticle(int e, glm::vec3 position, glm::vec3 velocit · 20 unmodified lines
106123 _particle[p].age = 0.0f;
107124 _particle[p].position = position;
108125 _particle[p].velocity = velocity;
109− _particle[p].radius = radius;
110126 _particle[p].color = color;
111127
128+ _particle[p].radius = _emitter[e].particleAttributes[0].radius;
129+ _particle[p].color = _emitter[e].particleAttributes[0].color;
130+
112131 _numParticles ++;
113132
114133 assert(_numParticles <= MAX_PARTICLES);
@@ -146,45 +165,72 @@ void ParticleSystem::setOrangeBlueColorPalette() { · 31 unmodified lines
146165 }
147166
148167
149−void ParticleSystem::setParticleAttributesForEmitter(int emitterIndex, ParticleAttributes attributes) {
168+void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) {
150169
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;
170+ for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) {
171+ setParticleAttributes(emitterIndex, lifeStage, attributes);
172+ }
162173 }
163174
175+void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, ParticleAttributes attributes) {
176+
177+ ParticleAttributes * a = &_emitter[emitterIndex].particleAttributes[lifeStage];
178+
179+ a->radius = attributes.radius;
180+ a->color = attributes.color;
181+ a->bounce = attributes.bounce;
182+ a->gravity = attributes.gravity;
183+ a->airFriction = attributes.airFriction;
184+ a->jitter = attributes.jitter;
185+ a->emitterAttraction = attributes.emitterAttraction;
186+ a->tornadoForce = attributes.tornadoForce;
187+ a->neighborAttraction = attributes.neighborAttraction;
188+ a->neighborRepulsion = attributes.neighborRepulsion;
189+ a->usingCollisionSphere = attributes.usingCollisionSphere;
190+ a->collisionSpherePosition = attributes.collisionSpherePosition;
191+ a->collisionSphereRadius = attributes.collisionSphereRadius;
192+}
164193
165194
166195 void ParticleSystem::updateParticle(int p, float deltaTime) {
167196
168− _particle[p].age += deltaTime;
197+ assert(_particle[p].age <= _particle[p].lifespan);
198+
199+ float ageFraction = _particle[p].age / _particle[p].lifespan;
200+
201+ int lifeStage = (int)( ageFraction * (NUM_PARTICLE_LIFE_STAGES-1) );
202+
203+ float lifeStageFraction = ageFraction * ( NUM_PARTICLE_LIFE_STAGES - 1 ) - lifeStage;
169204
170− if (_particle[p].age > _particle[p].lifespan) {
171− killParticle(p);
205+ /*
206+ if ( p == 0 ) {
207+ printf( "lifespan = %f ageFraction = %f lifeStage = %d lifeStageFraction = %f\n", _particle[p].lifespan, ageFraction, lifeStage, lifeStageFraction );
172208 }
209+ */
173210
211+ _particle[p].radius
212+ = _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction)
213+ + _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage+1].radius * lifeStageFraction;
214+
215+ _particle[p].color
216+ = _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction)
217+ + _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage+1].color * lifeStageFraction;
218+
174219 Emitter myEmitter = _emitter[_particle[p].emitterIndex];
175220
176221 // apply random jitter
222+ float j = myEmitter.particleAttributes[lifeStage].jitter;
177223 _particle[p].velocity +=
178224 glm::vec3
179225 (
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()
226+ -j * ONE_HALF + j * randFloat(),
227+ -j * ONE_HALF + j * randFloat(),
228+ -j * ONE_HALF + j * randFloat()
183229 ) * deltaTime;
184230
185231 // apply attraction to home position
186232 glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;
187− _particle[p].velocity += vectorToHome * myEmitter.particleAttributes.emitterAttraction * deltaTime;
233+ _particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
188234
189235 // apply neighbor attraction
190236 int neighbor = p + 1;
@@ -195,20 +241,20 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 4 unmodified lines
195241 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
196242 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
197243
198− _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes.neighborAttraction * deltaTime;
244+ _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
199245
200246 float distanceToNeighbor = glm::length(vectorToNeighbor);
201247 if (distanceToNeighbor > 0.0f) {
202− _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes.neighborRepulsion * deltaTime;
248+ _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime;
203249 }
204250 }
205251
206252 // apply tornado force
207253 glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.up);
208− _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes.tornadoForce * deltaTime;
254+ _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
209255
210256 // apply air friction
211− float drag = 1.0 - myEmitter.particleAttributes.airFriction * deltaTime;
257+ float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
212258 if (drag < 0.0f) {
213259 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
214260 } else {
@@ -216,7 +262,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 1 unmodified line
216262 }
217263
218264 // apply gravity
219− _particle[p].velocity -= _upDirection * myEmitter.particleAttributes.gravity * deltaTime;
265+ _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
220266
221267 // update position by velocity
222268 _particle[p].position += _particle[p].velocity;
@@ -226,36 +272,66 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 3 unmodified lines
226272 _particle[p].position.y = _particle[p].radius;
227273
228274 if (_particle[p].velocity.y < 0.0f) {
229− _particle[p].velocity.y *= -myEmitter.particleAttributes.bounce;
275+ _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
230276 }
231277 }
232278
233279 // collision with sphere
234− if (myEmitter.particleAttributes.usingCollisionSphere) {
235− glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes.collisionSpherePosition - _particle[p].position;
280+ if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
281+ glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
236282 float distanceToSphereCenter = glm::length(vectorToSphereCenter);
237− float combinedRadius = myEmitter.particleAttributes.collisionSphereRadius + _particle[p].radius;
283+ float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
238284 if (distanceToSphereCenter < combinedRadius) {
239285
240286 if (distanceToSphereCenter > 0.0f){
241287 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
242− _particle[p].position = myEmitter.particleAttributes.collisionSpherePosition - directionToSphereCenter * combinedRadius;
288+ _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
243289 }
244290 }
245291 }
292+
293+ // do this at the end...
294+ _particle[p].age += deltaTime;
246295 }
247296
248297 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;
298+
299+ int lifeStage = 0;
300+
301+ _emitter[e].particleAttributes[lifeStage].usingCollisionSphere = true;
302+ _emitter[e].particleAttributes[lifeStage].collisionSpherePosition = position;
303+ _emitter[e].particleAttributes[lifeStage].collisionSphereRadius = radius;
252304 }
253305
306+void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing ) {
307+
308+ _emitter[emitterIndex].baseParticle.alive = true;
309+ _emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
310+}
311+
312+void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing, float radius, glm::vec4 color ) {
313+
314+ _emitter[emitterIndex].baseParticle.alive = true;
315+ _emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
316+ _emitter[emitterIndex].baseParticle.radius = radius;
317+ _emitter[emitterIndex].baseParticle.color = color;
318+}
319+
320+
254321 void ParticleSystem::render() {
255322
256323 // render the emitters
257− for (unsigned int e = 0; e < _numEmitters; e++) {
258− if (_emitter[e].showingEmitter) {
324+ for (int e = 0; e < _numEmitters; e++) {
325+
326+ if (_emitter[e].baseParticle.alive) {
327+ glColor4f(_emitter[e].baseParticle.color.r, _emitter[e].baseParticle.color.g, _emitter[e].baseParticle.color.b, _emitter[e].baseParticle.color.a );
328+ glPushMatrix();
329+ glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
330+ glutSolidSphere(_emitter[e].baseParticle.radius, 6, 6);
331+ glPopMatrix();
332+ }
333+
334+ if (_emitter[e].visible) {
259335 renderEmitter(e, 0.2f);
260336 }
261337 };
@@ -271,19 +347,49 @@ void ParticleSystem::render() { · 9 unmodified lines
271347 void ParticleSystem::renderParticle(int p) {
272348
273349 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();
350+
351+ if (USE_BILLBOARD_RENDERING) {
352+ glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
353+ glm::vec3 viewVector = _particle[p].position - cameraPosition;
354+ float distance = glm::length(viewVector);
355+
356+ if (distance >= 0.0f) {
357+ viewVector /= distance;
358+ glm::vec3 up = glm::vec3(viewVector.y, viewVector.z, viewVector.x);
359+ glm::vec3 right = glm::vec3(viewVector.z, viewVector.x, viewVector.y);
360+
361+ glm::vec3 p0 = _particle[p].position - right * _particle[p].radius - up * _particle[p].radius;
362+ glm::vec3 p1 = _particle[p].position + right * _particle[p].radius - up * _particle[p].radius;
363+ glm::vec3 p2 = _particle[p].position + right * _particle[p].radius + up * _particle[p].radius;
364+ glm::vec3 p3 = _particle[p].position - right * _particle[p].radius + up * _particle[p].radius;
365+
366+ glBegin(GL_TRIANGLES);
367+ glVertex3f(p0.x, p0.y, p0.z);
368+ glVertex3f(p1.x, p1.y, p1.z);
369+ glVertex3f(p2.x, p2.y, p2.z);
370+ glEnd();
371+
372+ glBegin(GL_TRIANGLES);
373+ glVertex3f(p0.x, p0.y, p0.z);
374+ glVertex3f(p2.x, p2.y, p2.z);
375+ glVertex3f(p3.x, p3.y, p3.z);
376+ glEnd();
377+ }
378+ } else {
379+ glPushMatrix();
380+ glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
381+ glutSolidSphere(_particle[p].radius, 6, 6);
382+ glPopMatrix();
383+
384+ if (SHOW_VELOCITY_TAILS) {
385+ glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);
386+ glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;
387+ glBegin(GL_LINES);
388+ glVertex3f(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
389+ glVertex3f(end.x, end.y, end.z);
390+ glEnd();
391+ }
392+ }
287393 }
288394
289395