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
11#include "ParticleSystem.h"11#include "ParticleSystem.h"
12#include "Application.h"12#include "Application.h"
13 13
14const float DEFAULT_PARTICLE_RADIUS = 0.01f;
14const float DEFAULT_PARTICLE_BOUNCE = 1.0f;15const float DEFAULT_PARTICLE_BOUNCE = 1.0f;
15const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f;16const float DEFAULT_PARTICLE_AIR_FRICTION = 2.0f;
16 17
17ParticleSystem::ParticleSystem() {18ParticleSystem::ParticleSystem() {
18 19
19 _timer = 0.0f;
20 _numEmitters = 0;20 _numEmitters = 0;
21 _numParticles = 0;21 _numParticles = 0;
22 _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default22 _upDirection = glm::vec3(0.0f, 1.0f, 0.0f); // default
23 23
24 for (unsigned int e = 0; e < MAX_EMITTERS; e++) {24 for (unsigned int e = 0; e < MAX_EMITTERS; e++) {
25 _emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);25 _emitter[e].position = glm::vec3(0.0f, 0.0f, 0.0f);
26 _emitter[e].rotation = glm::quat();26 _emitter[e].rotation = glm::quat();
27 _emitter[e].right = IDENTITY_RIGHT;27 _emitter[e].right = IDENTITY_RIGHT;
28 _emitter[e].up = IDENTITY_UP;28 _emitter[e].up = IDENTITY_UP;
29 _emitter[e].front = IDENTITY_FRONT;29 _emitter[e].front = IDENTITY_FRONT;
30 _emitter[e].showingEmitter = false;30 _emitter[e].visible = false;
31 _emitter[e].particleAttributes.bounce = DEFAULT_PARTICLE_BOUNCE;31 _emitter[e].baseParticle.alive = false;
32 _emitter[e].particleAttributes.airFriction = DEFAULT_PARTICLE_AIR_FRICTION;32 _emitter[e].baseParticle.age = 0.0f;
33 _emitter[e].particleAttributes.gravity = 0.0f;33 _emitter[e].baseParticle.lifespan = 0.0f;
34 _emitter[e].particleAttributes.jitter = 0.0f;34 _emitter[e].baseParticle.radius = 0.0f;
35 _emitter[e].particleAttributes.emitterAttraction = 0.0f;35 _emitter[e].baseParticle.emitterIndex = 0;
36 _emitter[e].particleAttributes.tornadoForce = 0.0f;36 _emitter[e].baseParticle.position = glm::vec3(0.0f, 0.0f, 0.0f);
37 _emitter[e].particleAttributes.neighborAttraction = 0.0f;37 _emitter[e].baseParticle.velocity = glm::vec3(0.0f, 0.0f, 0.0f);
38 _emitter[e].particleAttributes.neighborRepulsion = 0.0f;38
39 _emitter[e].particleAttributes.collisionSphereRadius = 0.0f;39
40 _emitter[e].particleAttributes.collisionSpherePosition = glm::vec3(0.0f, 0.0f, 0.0f);40 for (int s = 0; s<NUM_PARTICLE_LIFE_STAGES; s++) {
41 _emitter[e].particleAttributes.usingCollisionSphere = false;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 }
42 }; 55 };
43 56
44 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {57 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
@@ -52,7 +65,6 @@ ParticleSystem::ParticleSystem() { · 7 unmodified lines
52 } 65 }
53}66}
54 67
55
56int ParticleSystem::addEmitter() {68int ParticleSystem::addEmitter() {
57 69
58 _numEmitters ++;70 _numEmitters ++;
@@ -75,11 +87,16 @@ void ParticleSystem::simulate(float deltaTime) { · 16 unmodified lines
75 // update particles87 // update particles
76 for (unsigned int p = 0; p < _numParticles; p++) {88 for (unsigned int p = 0; p < _numParticles; p++) {
77 if (_particle[p].alive) {89 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 }
79 }95 }
80 }96 }
81}97}
82 98
99
83void ParticleSystem::updateEmitter(int e, float deltaTime) {100void ParticleSystem::updateEmitter(int e, float deltaTime) {
84 101
85 _emitter[e].front = _emitter[e].rotation * IDENTITY_FRONT;102 _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
106 _particle[p].age = 0.0f;123 _particle[p].age = 0.0f;
107 _particle[p].position = position;124 _particle[p].position = position;
108 _particle[p].velocity = velocity;125 _particle[p].velocity = velocity;
109 _particle[p].radius = radius;
110 _particle[p].color = color;126 _particle[p].color = color;
111 127
128 _particle[p].radius = _emitter[e].particleAttributes[0].radius;
129 _particle[p].color = _emitter[e].particleAttributes[0].color;
130
112 _numParticles ++; 131 _numParticles ++;
113 132
114 assert(_numParticles <= MAX_PARTICLES);133 assert(_numParticles <= MAX_PARTICLES);
@@ -146,45 +165,72 @@ void ParticleSystem::setOrangeBlueColorPalette() { · 31 unmodified lines
146}165}
147 166
148 167
149void ParticleSystem::setParticleAttributesForEmitter(int emitterIndex, ParticleAttributes attributes) {168void ParticleSystem::setParticleAttributes(int emitterIndex, ParticleAttributes attributes) {
150 169
151 _emitter[emitterIndex].particleAttributes.bounce = attributes.bounce;170 for (int lifeStage = 0; lifeStage < NUM_PARTICLE_LIFE_STAGES; lifeStage ++ ) {
152 _emitter[emitterIndex].particleAttributes.gravity = attributes.gravity;171 setParticleAttributes(emitterIndex, lifeStage, attributes);
153 _emitter[emitterIndex].particleAttributes.airFriction = attributes.airFriction;172 }
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}173}
163 174
175void 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}
164 193
165 194
166void ParticleSystem::updateParticle(int p, float deltaTime) {195void ParticleSystem::updateParticle(int p, float deltaTime) {
167 196
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;
169 204
170 if (_particle[p].age > _particle[p].lifespan) {205 /*
171 killParticle(p);206 if ( p == 0 ) {
207 printf( "lifespan = %f ageFraction = %f lifeStage = %d lifeStageFraction = %f\n", _particle[p].lifespan, ageFraction, lifeStage, lifeStageFraction );
172 }208 }
209 */
173 210
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
174 Emitter myEmitter = _emitter[_particle[p].emitterIndex];219 Emitter myEmitter = _emitter[_particle[p].emitterIndex];
175 220
176 // apply random jitter221 // apply random jitter
222 float j = myEmitter.particleAttributes[lifeStage].jitter;
177 _particle[p].velocity += 223 _particle[p].velocity +=
178 glm::vec3224 glm::vec3
179 (225 (
180 -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat(), 226 -j * ONE_HALF + j * randFloat(),
181 -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat(), 227 -j * ONE_HALF + j * randFloat(),
182 -myEmitter.particleAttributes.jitter * ONE_HALF + myEmitter.particleAttributes.jitter * randFloat()228 -j * ONE_HALF + j * randFloat()
183 ) * deltaTime;229 ) * deltaTime;
184 230
185 // apply attraction to home position231 // apply attraction to home position
186 glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;232 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;
188 234
189 // apply neighbor attraction235 // apply neighbor attraction
190 int neighbor = p + 1;236 int neighbor = p + 1;
@@ -195,20 +241,20 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 4 unmodified lines
195 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {241 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
196 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;242 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
197 243
198 _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes.neighborAttraction * deltaTime;244 _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
199 245
200 float distanceToNeighbor = glm::length(vectorToNeighbor);246 float distanceToNeighbor = glm::length(vectorToNeighbor);
201 if (distanceToNeighbor > 0.0f) {247 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;
203 }249 }
204 }250 }
205 251
206 // apply tornado force252 // apply tornado force
207 glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.up);253 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;
209 255
210 // apply air friction256 // apply air friction
211 float drag = 1.0 - myEmitter.particleAttributes.airFriction * deltaTime;257 float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
212 if (drag < 0.0f) {258 if (drag < 0.0f) {
213 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);259 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
214 } else {260 } else {
@@ -216,7 +262,7 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 1 unmodified line
216 }262 }
217 263
218 // apply gravity264 // apply gravity
219 _particle[p].velocity -= _upDirection * myEmitter.particleAttributes.gravity * deltaTime; 265 _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
220 266
221 // update position by velocity267 // update position by velocity
222 _particle[p].position += _particle[p].velocity;268 _particle[p].position += _particle[p].velocity;
@@ -226,36 +272,66 @@ void ParticleSystem::updateParticle(int p, float deltaTime) { · 3 unmodified lines
226 _particle[p].position.y = _particle[p].radius;272 _particle[p].position.y = _particle[p].radius;
227 273
228 if (_particle[p].velocity.y < 0.0f) {274 if (_particle[p].velocity.y < 0.0f) {
229 _particle[p].velocity.y *= -myEmitter.particleAttributes.bounce;275 _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
230 }276 }
231 }277 }
232 278
233 // collision with sphere279 // collision with sphere
234 if (myEmitter.particleAttributes.usingCollisionSphere) {280 if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
235 glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes.collisionSpherePosition - _particle[p].position;281 glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
236 float distanceToSphereCenter = glm::length(vectorToSphereCenter);282 float distanceToSphereCenter = glm::length(vectorToSphereCenter);
237 float combinedRadius = myEmitter.particleAttributes.collisionSphereRadius + _particle[p].radius;283 float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
238 if (distanceToSphereCenter < combinedRadius) {284 if (distanceToSphereCenter < combinedRadius) {
239 285
240 if (distanceToSphereCenter > 0.0f){286 if (distanceToSphereCenter > 0.0f){
241 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;287 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
242 _particle[p].position = myEmitter.particleAttributes.collisionSpherePosition - directionToSphereCenter * combinedRadius; 288 _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
243 }289 }
244 }290 }
245 }291 }
292
293 // do this at the end...
294 _particle[p].age += deltaTime;
246}295}
247 296
248void ParticleSystem::setCollisionSphere(int e, glm::vec3 position, float radius) {297void ParticleSystem::setCollisionSphere(int e, glm::vec3 position, float radius) {
249 _emitter[e].particleAttributes.usingCollisionSphere = true;298
250 _emitter[e].particleAttributes.collisionSpherePosition = position; 299 int lifeStage = 0;
251 _emitter[e].particleAttributes.collisionSphereRadius = radius;300
301 _emitter[e].particleAttributes[lifeStage].usingCollisionSphere = true;
302 _emitter[e].particleAttributes[lifeStage].collisionSpherePosition = position;
303 _emitter[e].particleAttributes[lifeStage].collisionSphereRadius = radius;
252}304}
253 305
306void ParticleSystem::setEmitterBaseParticle(int emitterIndex, bool showing ) {
307
308 _emitter[emitterIndex].baseParticle.alive = true;
309 _emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
310}
311
312void 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
254void ParticleSystem::render() {321void ParticleSystem::render() {
255 322
256 // render the emitters323 // render the emitters
257 for (unsigned int e = 0; e < _numEmitters; e++) {324 for (int e = 0; e < _numEmitters; e++) {
258 if (_emitter[e].showingEmitter) {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) {
259 renderEmitter(e, 0.2f);335 renderEmitter(e, 0.2f);
260 }336 }
261 }; 337 };
@@ -271,19 +347,49 @@ void ParticleSystem::render() { · 9 unmodified lines
271void ParticleSystem::renderParticle(int p) {347void ParticleSystem::renderParticle(int p) {
272 348
273 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );349 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );
274 glPushMatrix();350
275 glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);351 if (USE_BILLBOARD_RENDERING) {
276 glutSolidSphere(_particle[p].radius, 6, 6);352 glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
277 glPopMatrix();353 glm::vec3 viewVector = _particle[p].position - cameraPosition;
278 354 float distance = glm::length(viewVector);
279 // render velocity lines355
280 glColor4f( _particle[p].color.x, _particle[p].color.y, _particle[p].color.z, 0.5f);356 if (distance >= 0.0f) {
281 glm::vec3 end = _particle[p].position - _particle[p].velocity * 2.0f;357 viewVector /= distance;
282 glBegin(GL_LINES);358 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);359 glm::vec3 right = glm::vec3(viewVector.z, viewVector.x, viewVector.y);
284 glVertex3f(end.x, end.y, end.z);360
285 361 glm::vec3 p0 = _particle[p].position - right * _particle[p].radius - up * _particle[p].radius;
286 glEnd();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 }
287}393}
288 394
289 395