-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathParticleSystem.cpp
200 lines (172 loc) · 4.8 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include "ParticleSystem.h"
#include "SOIL.h"
ParticleSystem::ParticleSystem(Vector3 pos, int nParticles, double lifetime, char* spriteName, Shader* partShader)
{
// create space for all for the particles
particles = new Particle[nParticles];
numParticles = nParticles;
position = pos;
globalLifetime = lifetime;
particleSprite = SOIL_load_OGL_texture
(
spriteName,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
if (0 == particleSprite)
{
printf("SOIL loading error: '%s'\n", SOIL_last_result());
}
particleShader = partShader;
}
ParticleSystem::~ParticleSystem()
{
// deallocate particle array
delete[] particles;
}
/*********************GETTERS AND SETTERSi*******************/
// gets position of system
Vector3 ParticleSystem::getPosition()
{
return position;
}
// sets position
void ParticleSystem::setPosition(Vector3 pos)
{
position = pos;
}
// gets particle in the particle array
Particle& ParticleSystem::getParticle(int particleNum)
{
return particles[particleNum];
}
// sets particle in the array to the given particle
void ParticleSystem::setParticle(int particleNum, Particle newValue)
{
particles[particleNum] = newValue;
}
// gets number of particles
int ParticleSystem::getNumParticles()
{
return numParticles;
}
// gets the reference point for all the lifetimes of the particles
int ParticleSystem::getGlobalLifetime()
{
return globalLifetime;
}
// sets the reference point for lifetimes of the particles
void ParticleSystem::setGlobalLifetime(int newLifetime)
{
globalLifetime = newLifetime;
}
// TODO: optimize this!!
// finds next available spot in the particle array and returns its index
// returns -1 if no spot was found
int ParticleSystem::findNext()
{
for (int i = 0; i < numParticles; i++)
{
if (particles[i].state == DEAD)
{
return i;
}
}
// no available spots right now
return -1;
}
// finds next avaialbe spot and makes it into new emitter
void ParticleSystem::triggerEmitter(Vector3 direction)
{
// find next available spot
int index = findNext();
// if there WAS an available spot
if (index != -1)
{
particles[index].state = ALIVE;
particles[index].p0 = position;
particles[index].lifetime = globalLifetime + rand() % 500;
particles[index].time = 0;
particles[index].v0 = direction;
}
}
/*
* draw
*
* overidden draw method from Node.
* updates each particles lifetimes,
* draws all of the children
* and passes them to the vertex shader
*/
void ParticleSystem::draw(Matrix4, Frustum, bool)
{
// turning on flag in shader
particleShader->uniform1i("particle", 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, particleSprite);
particleShader->uniform1i("tex", 2);
glEnable(GL_POINT_SPRITE);
// get the current time
int currentTime = frameTimer.getElapsedTimeInMilliSec();
// array of vertices to pass to shader
float* vertices = new float[numParticles * 3];
float* initialVel = new float[numParticles * 3];
float* time = new float[numParticles];
glPointSize(7);
//glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
// update particles' existence time
for (int i = 0; i < numParticles; i++)
{
// initial position of current point
Vector3 currPoint = particles[i].p0;
// initial vel of current point
Vector3 currVel = particles[i].v0;
particles[i].time += currentTime - prevFrameTime;
// check if particle exceeds its lifetime
if (particles[i].time > particles[i].lifetime)
particles[i].reset();
else
{
if (particles[i].state == ALIVE)
{
// draw particles' vertices
glBegin(GL_POINTS);
glColor4f(1, 1, 1, 1);
Vector3 g(0, -9.8 * 30, 0);
float t = particles[i].time / 1000.0;
g.scale(0.5 * t * t);
currVel.scale(t);
currPoint += currVel + g;
glVertex3f(currPoint[0], currPoint[1], currPoint[2]);
glEnd();
}
else{
// draw particles' vertices
/* glBegin(GL_POINTS);
glColor4f(0,0,0,0);
glVertex3f(currPoint[0], currPoint[1], currPoint[2]);
glEnd();*/
}
}
glBindTexture(GL_TEXTURE_2D, 0);
// set initial position for vertex shader
vertices[i * 3] = currPoint[0];
vertices[i * 3 + 1] = currPoint[1];
vertices[i * 3 + 2] = currPoint[2];
// initial velocity for shader
initialVel[i * 3] = currVel[0];
initialVel[i * 3 + 1] = currVel[1];
initialVel[i * 3 + 2] = currVel[2];
// set time for shader
time[i] = particles[i].time;
}
// update prevTime
prevFrameTime = currentTime;
//
particleShader->uniform1i("particle", 0);
}
// overidden bounding sphere method from Node
void ParticleSystem::computeBoundingSphere(Matrix4)
{
}