History

added extra mode and started prototyping "ribbon" effect

Jeffrey Ventrella committed 13 years ago

Commit 062ee651 parent 90bc3e94 files · +341 −204Browse files

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

Unified · Split

interface/src/ParticleSystem.cpp+182−118
@@ -25,19 +25,16 @@ ParticleSystem::ParticleSystem() { · 24 unmodified lines
25 25
26 for (unsigned int emitterIndex = 0; emitterIndex < MAX_EMITTERS; emitterIndex++) {26 for (unsigned int emitterIndex = 0; emitterIndex < MAX_EMITTERS; emitterIndex++) {
27 27
28 _emitter[emitterIndex].position = glm::vec3(0.0f, 0.0f, 0.0f);28 _emitter[emitterIndex].position = glm::vec3(0.0f, 0.0f, 0.0f);
29 _emitter[emitterIndex].direction = glm::vec3(0.0f, 1.0f, 0.0f);29 _emitter[emitterIndex].direction = glm::vec3(0.0f, 1.0f, 0.0f);
30 _emitter[emitterIndex].visible = false;30 _emitter[emitterIndex].visible = false;
31 _emitter[emitterIndex].particleResolution = DEFAULT_PARTICLE_SPHERE_RESOLUTION;31 _emitter[emitterIndex].particleResolution = DEFAULT_PARTICLE_SPHERE_RESOLUTION;
32 _emitter[emitterIndex].particleLifespan = DEFAULT_PARTICLE_LIFESPAN;32 _emitter[emitterIndex].particleLifespan = DEFAULT_PARTICLE_LIFESPAN;
33 _emitter[emitterIndex].baseParticle.alive = false;33 _emitter[emitterIndex].showingBaseParticle = false;
34 _emitter[emitterIndex].baseParticle.age = 0.0f;34 _emitter[emitterIndex].thrust = 0.0f;
35 _emitter[emitterIndex].thrust = 0.0f;35 _emitter[emitterIndex].rate = 0.0f;
36 _emitter[emitterIndex].rate = 0.0f;36 _emitter[emitterIndex].currentParticle = 0;
37 _emitter[emitterIndex].baseParticle.radius = 0.0f;37 _emitter[emitterIndex].particleRenderStyle = PARTICLE_RENDER_STYLE_SPHERE;
38 _emitter[emitterIndex].baseParticle.emitterIndex = 0;
39 _emitter[emitterIndex].baseParticle.position = glm::vec3(0.0f, 0.0f, 0.0f);
40 _emitter[emitterIndex].baseParticle.velocity = glm::vec3(0.0f, 0.0f, 0.0f);
41 38
42 for (int lifeStage = 0; lifeStage<NUM_PARTICLE_LIFE_STAGES; lifeStage++) {39 for (int lifeStage = 0; lifeStage<NUM_PARTICLE_LIFE_STAGES; lifeStage++) {
43 40
@@ -60,12 +57,13 @@ ParticleSystem::ParticleSystem() { · 16 unmodified lines
60 }; 57 };
61 58
62 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {59 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
63 _particle[p].alive = false;60 _particle[p].alive = false;
64 _particle[p].age = 0.0f;61 _particle[p].age = 0.0f;
65 _particle[p].radius = 0.0f;62 _particle[p].radius = 0.0f;
66 _particle[p].emitterIndex = 0;63 _particle[p].emitterIndex = 0;
67 _particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);64 _particle[p].previousParticle = -1;
68 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);65 _particle[p].position = glm::vec3(0.0f, 0.0f, 0.0f);
66 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
69 } 67 }
70}68}
71 69
@@ -106,15 +104,23 @@ void ParticleSystem::createParticle(int e, glm::vec3 velocity) { · 34 unmodified lines
106 104
107 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {105 for (unsigned int p = 0; p < MAX_PARTICLES; p++) {
108 if (!_particle[p].alive) {106 if (!_particle[p].alive) {
109 107
110 _particle[p].emitterIndex = e; 108 _particle[p].emitterIndex = e;
111 _particle[p].alive = true;109 _particle[p].alive = true;
112 _particle[p].age = 0.0f;110 _particle[p].age = 0.0f;
113 _particle[p].velocity = _emitter[e].direction * _emitter[e].thrust;111 _particle[p].velocity = _emitter[e].direction * _emitter[e].thrust;
114 _particle[p].position = _emitter[e].position;112 _particle[p].position = _emitter[e].position;
115 _particle[p].radius = _emitter[e].particleAttributes[0].radius;113 _particle[p].radius = _emitter[e].particleAttributes[0].radius;
116 _particle[p].color = _emitter[e].particleAttributes[0].color;114 _particle[p].color = _emitter[e].particleAttributes[0].color;
117 115
116 if (( _particle[_emitter[e].currentParticle].alive) && (_particle[_emitter[e].currentParticle].emitterIndex == e )) {
117 _particle[p].previousParticle = _emitter[e].currentParticle;
118 } else {
119 _particle[p].previousParticle = -1;
120 }
121
122 _emitter[e].currentParticle = p;
123
118 _numParticles ++; 124 _numParticles ++;
119 125
120 assert(_numParticles <= MAX_PARTICLES);126 assert(_numParticles <= MAX_PARTICLES);
@@ -164,105 +170,104 @@ void ParticleSystem::setParticleAttributes(int emitterIndex, int lifeStage, Part · 43 unmodified lines
164 170
165void ParticleSystem::updateParticle(int p, float deltaTime) {171void ParticleSystem::updateParticle(int p, float deltaTime) {
166 172
167 assert(_particle[p].age <= _emitter[_particle[p].emitterIndex].particleLifespan);173 if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) {
168 174
169 float ageFraction = _particle[p].age / _emitter[_particle[p].emitterIndex].particleLifespan;175 Emitter myEmitter = _emitter[_particle[p].emitterIndex];
170
171 int lifeStage = (int)( ageFraction * (NUM_PARTICLE_LIFE_STAGES-1) );
172 176
173 float lifeStageFraction = ageFraction * ( NUM_PARTICLE_LIFE_STAGES - 1 ) - lifeStage;177 assert(_particle[p].age <= myEmitter.particleLifespan);
174 178
175 _particle[p].radius179 float ageFraction = _particle[p].age / myEmitter.particleLifespan;
176 = _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction)180
177 + _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage+1].radius * lifeStageFraction;181 int lifeStage = (int)( ageFraction * (NUM_PARTICLE_LIFE_STAGES-1) );
182
183 float lifeStageFraction = ageFraction * ( NUM_PARTICLE_LIFE_STAGES - 1 ) - lifeStage;
184
178 185
179 _particle[p].color186 _particle[p].radius
180 = _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction)187 = myEmitter.particleAttributes[lifeStage ].radius * (1.0f - lifeStageFraction)
181 + _emitter[_particle[p].emitterIndex].particleAttributes[lifeStage+1].color * lifeStageFraction;188 + myEmitter.particleAttributes[lifeStage+1].radius * lifeStageFraction;
189
190 _particle[p].color
191 = myEmitter.particleAttributes[lifeStage ].color * (1.0f - lifeStageFraction)
192 + myEmitter.particleAttributes[lifeStage+1].color * lifeStageFraction;
193
194 // apply random jitter
195 float j = myEmitter.particleAttributes[lifeStage].jitter;
196 _particle[p].velocity +=
197 glm::vec3
198 (
199 -j * ONE_HALF + j * randFloat(),
200 -j * ONE_HALF + j * randFloat(),
201 -j * ONE_HALF + j * randFloat()
202 ) * deltaTime;
182 203
183 Emitter myEmitter = _emitter[_particle[p].emitterIndex];204 // apply attraction to home position
184 205 glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;
185 // apply random jitter206 _particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
186 float j = myEmitter.particleAttributes[lifeStage].jitter;207
187 _particle[p].velocity += 208 // apply neighbor attraction
188 glm::vec3209 int neighbor = p + 1;
189 (210 if (neighbor == _numParticles ) {
190 -j * ONE_HALF + j * randFloat(), 211 neighbor = 0;
191 -j * ONE_HALF + j * randFloat(), 212 }
192 -j * ONE_HALF + j * randFloat()213
193 ) * deltaTime;214 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
194 215 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
195 // apply attraction to home position216
196 glm::vec3 vectorToHome = myEmitter.position - _particle[p].position;217 _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
197 _particle[p].velocity += vectorToHome * myEmitter.particleAttributes[lifeStage].emitterAttraction * deltaTime;
198
199 // apply neighbor attraction
200 int neighbor = p + 1;
201 if (neighbor == _numParticles ) {
202 neighbor = 0;
203 }
204
205 if ( _particle[neighbor].emitterIndex == _particle[p].emitterIndex) {
206 glm::vec3 vectorToNeighbor = _particle[p].position - _particle[neighbor].position;
207
208 _particle[p].velocity -= vectorToNeighbor * myEmitter.particleAttributes[lifeStage].neighborAttraction * deltaTime;
209 218
210 float distanceToNeighbor = glm::length(vectorToNeighbor);219 float distanceToNeighbor = glm::length(vectorToNeighbor);
211 if (distanceToNeighbor > 0.0f) {220 if (distanceToNeighbor > 0.0f) {
212 _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime;221 _particle[neighbor].velocity += (vectorToNeighbor / ( 1.0f + distanceToNeighbor * distanceToNeighbor)) * myEmitter.particleAttributes[lifeStage].neighborRepulsion * deltaTime;
222 }
213 }223 }
214 }224
215 225 // apply tornado force
216 // apply tornado force226 glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.direction);
217 glm::vec3 tornadoDirection = glm::cross(vectorToHome, myEmitter.direction);227 _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;
218 _particle[p].velocity += tornadoDirection * myEmitter.particleAttributes[lifeStage].tornadoForce * deltaTime;228
219 229 // apply air friction
220 // apply air friction230 float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;
221 float drag = 1.0 - myEmitter.particleAttributes[lifeStage].airFriction * deltaTime;231 if (drag < 0.0f) {
222 if (drag < 0.0f) {232 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);
223 _particle[p].velocity = glm::vec3(0.0f, 0.0f, 0.0f);233 } else {
224 } else {234 _particle[p].velocity *= drag;
225 _particle[p].velocity *= drag;235 }
226 }236
227 237 // apply gravity
228 // apply gravity238 _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
229 _particle[p].velocity -= _upDirection * myEmitter.particleAttributes[lifeStage].gravity * deltaTime;
230 239
231 // update position by velocity240 // update position by velocity
232 _particle[p].position += _particle[p].velocity;241 _particle[p].position += _particle[p].velocity;
233
234 // collision with ground
235 if (_particle[p].position.y < _particle[p].radius) {
236 _particle[p].position.y = _particle[p].radius;
237 242
238 if (_particle[p].velocity.y < 0.0f) {243 // collision with ground
239 _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;244 if (_particle[p].position.y < _particle[p].radius) {
245 _particle[p].position.y = _particle[p].radius;
246
247 if (_particle[p].velocity.y < 0.0f) {
248 _particle[p].velocity.y *= -myEmitter.particleAttributes[lifeStage].bounce;
249 }
240 }250 }
241 }
242
243 // collision with sphere
244 if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
245 glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
246 float distanceToSphereCenter = glm::length(vectorToSphereCenter);
247 float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
248 if (distanceToSphereCenter < combinedRadius) {
249 251
250 if (distanceToSphereCenter > 0.0f){252 // collision with sphere
251 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;253 if (myEmitter.particleAttributes[lifeStage].usingCollisionSphere) {
252 _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius; 254 glm::vec3 vectorToSphereCenter = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - _particle[p].position;
255 float distanceToSphereCenter = glm::length(vectorToSphereCenter);
256 float combinedRadius = myEmitter.particleAttributes[lifeStage].collisionSphereRadius + _particle[p].radius;
257 if (distanceToSphereCenter < combinedRadius) {
258
259 if (distanceToSphereCenter > 0.0f){
260 glm::vec3 directionToSphereCenter = vectorToSphereCenter / distanceToSphereCenter;
261 _particle[p].position = myEmitter.particleAttributes[lifeStage].collisionSpherePosition - directionToSphereCenter * combinedRadius;
262 }
253 }263 }
254 }264 }
255 }265 }
256 266
257 // do this at the end...267 // do this at the end...
258 _particle[p].age += deltaTime; 268 _particle[p].age += deltaTime;
259}269}
260 270
261void ParticleSystem::setShowingEmitterBaseParticle(int emitterIndex, bool showing ) {
262
263 _emitter[emitterIndex].baseParticle.alive = true;
264 _emitter[emitterIndex].baseParticle.emitterIndex = emitterIndex;
265}
266 271
267void ParticleSystem::killAllParticles() {272void ParticleSystem::killAllParticles() {
268 273
@@ -277,11 +282,11 @@ void ParticleSystem::render() { · 8 unmodified lines
277 // render the emitters282 // render the emitters
278 for (int e = 0; e < _numEmitters; e++) {283 for (int e = 0; e < _numEmitters; e++) {
279 284
280 if (_emitter[e].baseParticle.alive) {285 if (_emitter[e].showingBaseParticle) {
281 glColor4f(_emitter[e].baseParticle.color.r, _emitter[e].baseParticle.color.g, _emitter[e].baseParticle.color.b, _emitter[e].baseParticle.color.a );286 glColor4f(_particle[0].color.r, _particle[0].color.g, _particle[0].color.b, _particle[0].color.a );
282 glPushMatrix();287 glPushMatrix();
283 glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);288 glTranslatef(_emitter[e].position.x, _emitter[e].position.y, _emitter[e].position.z);
284 glutSolidSphere(_emitter[e].baseParticle.radius, _emitter[e].particleResolution, _emitter[e].particleResolution);289 glutSolidSphere(_particle[0].radius, _emitter[e].particleResolution, _emitter[e].particleResolution);
285 glPopMatrix();290 glPopMatrix();
286 }291 }
287 292
@@ -289,11 +294,13 @@ void ParticleSystem::render() { · 1 unmodified line
289 renderEmitter(e, 0.2f);294 renderEmitter(e, 0.2f);
290 }295 }
291 }; 296 };
292 297
293 // render the particles298 // render the particles
294 for (unsigned int p = 0; p < _numParticles; p++) {299 for (unsigned int p = 0; p < _numParticles; p++) {
295 if (_particle[p].alive) {300 if (_particle[p].alive) {
296 renderParticle(p);301 if (_emitter[_particle[p].emitterIndex].particleLifespan > 0.0) {
302 renderParticle(p);
303 }
297 }304 }
298 }305 }
299}306}
@@ -302,7 +309,7 @@ void ParticleSystem::renderParticle(int p) { · 2 unmodified lines
302 309
303 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );310 glColor4f(_particle[p].color.r, _particle[p].color.g, _particle[p].color.b, _particle[p].color.a );
304 311
305 if (USE_BILLBOARD_RENDERING) {312 if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_BILLBOARD) {
306 glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();313 glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
307 glm::vec3 viewVector = _particle[p].position - cameraPosition;314 glm::vec3 viewVector = _particle[p].position - cameraPosition;
308 float distance = glm::length(viewVector);315 float distance = glm::length(viewVector);
@@ -329,7 +336,7 @@ void ParticleSystem::renderParticle(int p) { · 20 unmodified lines
329 glVertex3f(p3.x, p3.y, p3.z); 336 glVertex3f(p3.x, p3.y, p3.z);
330 glEnd();337 glEnd();
331 }338 }
332 } else {339 } else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_SPHERE) {
333 glPushMatrix();340 glPushMatrix();
334 glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);341 glTranslatef(_particle[p].position.x, _particle[p].position.y, _particle[p].position.z);
335 glutSolidSphere(_particle[p].radius, _emitter[_particle[p].emitterIndex].particleResolution, _emitter[_particle[p].emitterIndex].particleResolution);342 glutSolidSphere(_particle[p].radius, _emitter[_particle[p].emitterIndex].particleResolution, _emitter[_particle[p].emitterIndex].particleResolution);
@@ -343,9 +350,66 @@ void ParticleSystem::renderParticle(int p) { · 7 unmodified lines
343 glVertex3f(end.x, end.y, end.z); 350 glVertex3f(end.x, end.y, end.z);
344 glEnd();351 glEnd();
345 }352 }
353 } else if (_emitter[_particle[p].emitterIndex].particleRenderStyle == PARTICLE_RENDER_STYLE_RIBBON) {
354
355 if (_particle[p].previousParticle != -1) {
356 if (_particle[_particle[p].previousParticle].alive) {
357
358 int pp = _particle[p].previousParticle;
359
360 glm::vec3 v = _particle[p].position - _particle[pp].position;
361 float distance = glm::length(v);
362
363 if (distance > 0.0f) {
364
365 v /= distance;
366
367 glm::vec3 up = glm::normalize(glm::cross(v, _upDirection));
368 glm::vec3 right = glm::normalize(glm::cross(up, v));
369
370 right *= _particle[p].radius;
371 up *= _particle[p].radius;
372
373 glm::vec3 p0Left = _particle[p ].position - right;
374 glm::vec3 p0Right = _particle[p ].position + right;
375 glm::vec3 p0Down = _particle[p ].position - up;
376 glm::vec3 p0Up = _particle[p ].position + up;
377
378 glm::vec3 ppLeft = _particle[pp].position - right;
379 glm::vec3 ppRight = _particle[pp].position + right;
380 glm::vec3 ppDown = _particle[pp].position - up;
381 glm::vec3 ppUp = _particle[pp].position + up;
382
383 glBegin(GL_TRIANGLES);
384 glVertex3f(p0Left.x, p0Left.y, p0Left.z );
385 glVertex3f(p0Right.x, p0Right.y, p0Right.z );
386 glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z );
387 glEnd();
388
389 glBegin(GL_TRIANGLES);
390 glVertex3f(p0Right.x, p0Right.y, p0Right.z );
391 glVertex3f(ppLeft.x, ppLeft.y, ppLeft.z );
392 glVertex3f(ppRight.x, ppRight.y, ppRight.z );
393 glEnd();
394
395 glBegin(GL_TRIANGLES);
396 glVertex3f(p0Up.x, p0Up.y, p0Up.z );
397 glVertex3f(p0Down.x, p0Down.y, p0Down.z );
398 glVertex3f(ppDown.x, ppDown.y, ppDown.z );
399 glEnd();
400
401 glBegin(GL_TRIANGLES);
402 glVertex3f(p0Up.x, p0Up.y, p0Up.z );
403 glVertex3f(ppUp.x, ppUp.y, ppUp.z );
404 glVertex3f(ppDown.x, ppDown.y, ppDown.z );
405 glEnd();
406 }
407 }
408 }
346 }409 }
347}410}
348 411
412
349void ParticleSystem::renderEmitter(int e, float size) {413void ParticleSystem::renderEmitter(int e, float size) {
350 414
351 glLineWidth(2.0f);415 glLineWidth(2.0f);