TDME2 1.9.121
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PointsParticleSystemInternal.cpp
Go to the documentation of this file.
2
3#include <string>
4#include <vector>
5
6#include <tdme/tdme.h>
17#include <tdme/engine/Engine.h>
18#include <tdme/engine/Timing.h>
20#include <tdme/math/Math.h>
21#include <tdme/math/Matrix4x4.h>
22#include <tdme/math/Vector3.h>
24
25using std::string;
26using std::vector;
27
46
47PointsParticleSystemInternal::PointsParticleSystemInternal(const string& id, ParticleEmitter* emitter, int32_t maxPoints, float pointSize, bool autoEmit, Texture* texture, int32_t textureHorizontalSprites, int32_t textureVerticalSprites, float fps)
48{
49 this->id = id;
50 this->enabled = true;
51 // will be activated on emit and auto unactivated if no more active particles
52 this->active = false;
53 this->emitter = emitter;
54 particles.resize(maxPoints);
55 this->maxPoints = maxPoints;
56 this->effectColorMul.set(1.0f, 1.0f, 1.0f, 1.0f);
57 this->effectColorAdd.set(0.0f, 0.0f, 0.0f, 0.0f);
58 this->pickable = false;
59 this->pointSize = pointSize;
60 this->pointSizeScale = 1.0f;
61 this->autoEmit = autoEmit;
62 this->particlesToSpawnRemainder = 0.0f;
63 this->pointsRenderPool = nullptr;
64 this->texture = texture;
65 this->textureId = 0;
66 this->textureHorizontalSprites = textureHorizontalSprites;
67 this->textureVerticalSprites = textureVerticalSprites;
68 this->fps = fps;
70 if (this->texture != nullptr) this->texture->acquireReference();
71}
72
74 delete emitter;
75 if (pointsRenderPool != nullptr) delete pointsRenderPool;
77 if (this->texture != nullptr) this->texture->releaseReference();
78}
79
81 this->textureId = this->texture == nullptr?engine->getTextureManager()->addTexture(this->texture = TextureReader::read("resources/engine/textures", "point.png"), renderer->CONTEXTINDEX_DEFAULT):engine->getTextureManager()->addTexture(this->texture, renderer->CONTEXTINDEX_DEFAULT);
82}
83
85{
88}
89
91{
94}
95
97{
98 if (enabled == false || active == false)
99 return;
100
101 //
102 Vector3 center;
103 auto& localTransformationsMatrix = localTransformations.getTransformationsMatrix();
104 localTransformationsMatrix.getTranslation(center);
105 center.add(emitter->getCenter());
106 //
107 Vector3 point;
108 Vector3 velocityForTime;
109 // bounding box transformed min, max xyz
110 auto& bbMinXYZ = boundingBox.getMin().getArray();
111 auto& bbMaxXYZ = boundingBox.getMax().getArray();
112 //
113 auto haveBoundingBox = false;
114 // compute distance from camera
115 float distanceFromCamera;
116 // transformations
118 // process particles
120 auto activeParticles = 0;
121 auto timeDelta = engine->getTiming()->getDeltaTime();
122 for (auto i = 0; i < particles.size(); i++) {
123 auto& particle = particles[i];
124 if (particle.active == false)
125 continue;
126
127 // life time
128 particle.lifeTimeCurrent += timeDelta;
129 // crop to max life time
130 if (particle.lifeTimeCurrent >= particle.lifeTimeMax) {
131 particle.active = false;
132 continue;
133 }
134 // sprite index
135 particle.spriteIndex+= (static_cast<float>(timeDelta) / 1000.0f) * fps;
136 // add gravity if our particle have a noticeable mass
137 if (particle.mass > Math::EPSILON)
138 particle.velocity.sub(Vector3(0.0f, 0.5f * Math::g * static_cast<float>(timeDelta) / 1000.0f, 0.0f));
139 // TODO:
140 // maybe take air resistance into account like a huge paper needs more time to fall than a sphere of paper
141 // or heat for smoke or fire, whereas having no mass for those particles works around this problem for now
142 // translation
143 particle.position.add(velocityForTime.set(particle.velocity).scale(static_cast<float>(timeDelta) / 1000.0f));
144 // color
145 auto& color = particle.color.getArray();
146 auto& colorAdd = particle.colorAdd.getArray();
147 color[0] += colorAdd[0] * static_cast<float>(timeDelta);
148 color[1] += colorAdd[1] * static_cast<float>(timeDelta);
149 color[2] += colorAdd[2] * static_cast<float>(timeDelta);
150 color[3] += colorAdd[3] * static_cast<float>(timeDelta);
151 //
152 activeParticles++;
153 // set up bounding box
154 point = localTransformationsMatrix.multiply(particle.position);
155 point.add(center);
156 //
157 auto& pointXYZ = point.getArray();
158 if (haveBoundingBox == false) {
159 bbMinXYZ = pointXYZ;
160 bbMaxXYZ = pointXYZ;
161 haveBoundingBox = true;
162 } else {
163 if (pointXYZ[0] < bbMinXYZ[0]) bbMinXYZ[0] = pointXYZ[0];
164 if (pointXYZ[1] < bbMinXYZ[1]) bbMinXYZ[1] = pointXYZ[1];
165 if (pointXYZ[2] < bbMinXYZ[2]) bbMinXYZ[2] = pointXYZ[2];
166 if (pointXYZ[0] > bbMaxXYZ[0]) bbMaxXYZ[0] = pointXYZ[0];
167 if (pointXYZ[1] > bbMaxXYZ[1]) bbMaxXYZ[1] = pointXYZ[1];
168 if (pointXYZ[2] > bbMaxXYZ[2]) bbMaxXYZ[2] = pointXYZ[2];
169 }
170 // transform particle according to its transformations
171 point = transformationsMatrix.multiply(point);
172 // add to render points pool
173 pointsRenderPool->addPoint(point, static_cast<uint16_t>(particle.spriteIndex) % (textureHorizontalSprites * textureVerticalSprites), color, 0, this);
174 }
175 // auto disable particle system if no more active particles
176 if (activeParticles == 0) {
177 active = false;
178 return;
179 }
180 // scale a bit up to make picking work better
186}
187
189{
190}
191
193{
194 // enable particle system
195 active = true;
196 // delta time
197 auto timeDelta = engine->getTiming()->getDeltaTime();
198 // determine particles to spawn
199 auto particlesToSpawn = 0;
200 {
201 if (autoEmit == true) {
202 auto particlesToSpawnWithFraction = emitter->getCount() * engine->getTiming()->getDeltaTime() / 1000.0f;
203 particlesToSpawn = static_cast< int32_t >(particlesToSpawnWithFraction);
204 particlesToSpawnRemainder += particlesToSpawnWithFraction - particlesToSpawn;
205 if (particlesToSpawnRemainder > 1.0f) {
206 particlesToSpawn++;
208 }
209 } else {
210 particlesToSpawn = emitter->getCount();
211 }
212 }
213 // skip if nothing to spawn
214 if (particlesToSpawn == 0) return 0;
215 //
216 Vector3 velocityForTime;
217 //
218 auto& center = emitter->getCenter();
219 // spawn
220 auto particlesSpawned = 0;
221 for (auto i = 0; i < particles.size(); i++) {
222 auto& particle = particles[i];
223 if (particle.active == true)
224 continue;
225 // emit particle
226 emitter->emit(&particle);
227 // add gravity if our particle have a noticable mass, add translation
228 // add some movement with a min of 0 time delta and a max of engine time delta
229 auto timeDeltaRnd = static_cast< int64_t >((Math::random() * timeDelta));
230 if (particle.mass > Math::EPSILON)
231 particle.velocity.sub(Vector3(0.0f, 0.5f * Math::g * static_cast<float>(timeDeltaRnd) / 1000.0f, 0.0f));
232 particle.position.add(velocityForTime.set(particle.velocity).scale(timeDeltaRnd / 1000.0f));
233 //
234 particlesSpawned++;
235 // finished?
236 if (particlesSpawned == particlesToSpawn) break;
237
238 }
239 return particlesSpawned;
240}
241
243{
244 return pointsRenderPool;
245}
Engine main class.
Definition: Engine.h:122
Timing * getTiming()
Definition: Engine.h:900
static TextureManager * getTextureManager()
Definition: Engine.h:564
Timing class.
Definition: Timing.h:17
int64_t getDeltaTime()
Gets the time passed between last and current frame.
Definition: Timing.h:83
Transformations which contain scale, rotations and translation.
const Matrix4x4 & getTransformationsMatrix() const
virtual void fromTransformations(const Transformations &transformations)
Set up this transformations from given transformations.
virtual void update()
Computes transformation matrix.
const string & getId() const
Definition: Texture.h:60
void set(const array< float, 4 > &color)
Set up color.
Definition: Color4Base.h:68
Color 4 definition.
Definition: Color4.h:20
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:25
void fromBoundingVolumeWithTransformations(BoundingBox *original, const Transformations &transformations)
Create bounding volume from given original(of same type) with applied transformations.
Definition: BoundingBox.cpp:79
void update()
Updates this bounding box.
void removeTexture(const string &textureId)
Removes a texture from manager / open gl stack.
TextureManager_TextureManaged * addTexture(const string &id, bool &created)
Adds a texture to manager.
void fromTransformations(const Transformations &transformations) override
Set up this transformations from given transformations.
int32_t emitParticles() override
Adds particles to this particle entity at given position.
void addPoint(const Vector3 &point, uint16_t spriteIndex, const Color4 &color, int particleSystemType, void *particleSystem)
Creates an transparent render point entity in pool.
Standard math functions.
Definition: Math.h:21
4x4 3D Matrix class
Definition: Matrix4x4.h:24
void getTranslation(Vector3 &translation) const
Get translation.
Definition: Matrix4x4.h:261
Vector3 multiply(const Vector3 &v) const
Multiplies a vector3 with this matrix into destination vector.
Definition: Matrix4x4.h:351
3D vector 3 class
Definition: Vector3.h:22
Vector3 & set(float x, float y, float z)
Set up vector.
Definition: Vector3.h:73
Vector3 & sub(const Vector3 &v)
Subtracts a vector.
Definition: Vector3.h:325
Vector3 & add(const Vector3 &v)
Adds a vector.
Definition: Vector3.h:301
Vector3 & scale(float scale)
Scale this vector.
Definition: Vector3.h:349
array< float, 3 > & getArray() const
Definition: Vector3.h:171
Console class.
Definition: Console.h:26
void releaseReference()
releases a reference, thus decrementing the counter and delete it if reference counter is zero
Definition: Reference.cpp:20
void acquireReference()
acquires a reference, incrementing the counter
Definition: Reference.cpp:16
virtual void emit(Particle *particle)=0
Emits particles.