-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParticleSystem.cpp
131 lines (107 loc) · 3.15 KB
/
ParticleSystem.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Kevin M.Smith - CS 134 SJSU
#include "ParticleSystem.h"
void ParticleSystem::add(const Particle &p) {
particles.push_back(p);
}
void ParticleSystem::addForce(ParticleForce *f) {
forces.push_back(f);
}
void ParticleSystem::remove(int i) {
particles.erase(particles.begin() + i);
}
void ParticleSystem::setLifespan(float l) {
for (int i = 0; i < particles.size(); i++) {
particles[i].lifespan = l;
}
}
void ParticleSystem::reset() {
for (int i = 0; i < forces.size(); i++) {
forces[i]->applied = false;
}
}
void ParticleSystem::update() {
// check if empty and just return
if (particles.size() == 0) return;
vector<Particle>::iterator p = particles.begin();
vector<Particle>::iterator tmp;
// check which particles have exceed their lifespan and delete
// from list. When deleting multiple objects from a vector while
// traversing at the same time, we need to use an iterator.
//
while (p != particles.end()) {
if (p->lifespan != -1 && p->age() > p->lifespan) {
tmp = particles.erase(p);
p = tmp;
}
else p++;
}
// update forces on all particles first
//
for (int i = 0; i < particles.size(); i++) {
for (int k = 0; k < forces.size(); k++) {
if (!forces[k]->applied)
forces[k]->updateForce( &particles[i] );
}
}
// update all forces only applied once to "applied"
// so they are not applied again.
//
for (int i = 0; i < forces.size(); i++) {
if (forces[i]->applyOnce)
forces[i]->applied = true;
}
// integrate all the particles in the store
//
for (int i = 0; i < particles.size(); i++)
particles[i].integrate();
}
// remove all particlies within "dist" of point (not implemented as yet)
//
int ParticleSystem::removeNear(const ofVec3f & point, float dist) { return 0; }
// draw the particle cloud
//
void ParticleSystem::draw() {
for (int i = 0; i < particles.size(); i++) {
particles[i].draw();
}
}
// Gravity Force Field
//
GravityForce::GravityForce(const ofVec3f &g) {
gravity = g;
}
void GravityForce::updateForce(Particle * particle) {
//
// f = mg
//
particle->forces += gravity * particle->mass;
}
// Turbulence Force Field
//
TurbulenceForce::TurbulenceForce(const ofVec3f &min, const ofVec3f &max) {
tmin = min;
tmax = max;
}
void TurbulenceForce::updateForce(Particle * particle) {
//
// We are going to add a little "noise" to a particles
// forces to achieve a more natual look to the motion
//
particle->forces.x += ofRandom(tmin.x, tmax.x);
particle->forces.y += ofRandom(tmin.y, tmax.y);
particle->forces.z += ofRandom(tmin.z, tmax.z);
}
// Impulse Radial Force - this is a "one shot" force that
// eminates radially outward in random directions.
//
ImpulseRadialForce::ImpulseRadialForce(float magnitude) {
this->magnitude = magnitude;
applyOnce = true;
}
void ImpulseRadialForce::updateForce(Particle * particle) {
// we basically create a random direction for each particle
// the force is only added once after it is triggered.
//
ofVec3f dir = ofVec3f(ofRandom(-1, 1), ofRandom(-1, 1), ofRandom(-1, 1));
particle->forces += dir.getNormalized() * magnitude;
}