TDME2  1.9.200
PointsParticleSystemInternal.cpp
Go to the documentation of this file.
2 
3 #include <memory>
4 #include <string>
5 #include <vector>
6 
7 #include <tdme/tdme.h>
8 #include <tdme/engine/Texture.h>
10 #include <tdme/engine/Color4.h>
18 #include <tdme/engine/Engine.h>
19 #include <tdme/engine/Timing.h>
20 #include <tdme/engine/Transform.h>
21 #include <tdme/math/Math.h>
22 #include <tdme/math/Matrix4x4.h>
23 #include <tdme/math/Vector3.h>
24 #include <tdme/utilities/Console.h>
25 
26 using std::make_unique;
27 using std::string;
28 using std::unique_ptr;
29 using std::vector;
30 
45 using tdme::math::Math;
49 
50 PointsParticleSystemInternal::PointsParticleSystemInternal(const string& id, ParticleEmitter* emitter, int32_t maxPoints, float pointSize, bool autoEmit, Texture* texture, int32_t textureHorizontalSprites, int32_t textureVerticalSprites, float fps)
51 {
52  this->id = id;
53  this->enabled = true;
54  // will be activated on emit and auto unactivated if no more active particles
55  this->active = false;
56  this->emitter = unique_ptr<ParticleEmitter>(emitter);
57  particles.resize(maxPoints);
58  this->maxPoints = maxPoints;
59  this->effectColorMul.set(1.0f, 1.0f, 1.0f, 1.0f);
60  this->effectColorAdd.set(0.0f, 0.0f, 0.0f, 0.0f);
61  this->pickable = false;
62  this->pointSize = pointSize;
63  this->pointSizeScale = 1.0f;
64  this->autoEmit = autoEmit;
65  this->particlesToSpawnRemainder = 0.0f;
66  this->pointsRenderPool = nullptr;
67  this->texture = texture;
68  this->textureHorizontalSprites = textureHorizontalSprites;
69  this->textureVerticalSprites = textureVerticalSprites;
70  this->fps = fps;
71  this->pointsRenderPool = make_unique<TransparentRenderPointsPool>(maxPoints);
72  this->texture = texture != nullptr?texture:TextureReader::read("resources/engine/textures", "point.png");
74 }
75 
77  if (texture != nullptr) texture->releaseReference();
78 }
79 
81 }
82 
84 {
86  //
87  auto entityTransform = parentTransform * (*this);
88  entityTransformMatrix = entityTransform.getTransformMatrix();
89  //
91 }
92 
94 {
95  Transform::setTransform(transform);
96  //
97  auto entityTransform = parentTransform * (*this);
98  entityTransformMatrix = entityTransform.getTransformMatrix();
99  //
100  updateInternal();
101 }
102 
104 {
105  if (enabled == false || active == false)
106  return;
107 
108  //
109  Vector3 center;
110  const auto& localTransformMatrix = localTransform.getTransformMatrix();
111  localTransformMatrix.getTranslation(center);
112  center.add(emitter->getCenter());
113  //
114  Vector3 point;
115  Vector3 velocityForTime;
116  //
117  auto first = false;
118  // compute distance from camera
119  float distanceFromCamera;
120  // process particles
121  pointsRenderPool->reset();
122  auto activeParticles = 0;
123  auto timeDelta = engine->getTiming()->getDeltaTime();
124  for (auto i = 0; i < particles.size(); i++) {
125  auto& particle = particles[i];
126  if (particle.active == false)
127  continue;
128 
129  // life time
130  particle.lifeTimeCurrent += timeDelta;
131  // crop to max life time
132  if (particle.lifeTimeCurrent >= particle.lifeTimeMax) {
133  particle.active = false;
134  continue;
135  }
136  // sprite index
137  particle.spriteIndex+= (static_cast<float>(timeDelta) / 1000.0f) * fps;
138  // add gravity if our particle have a noticeable mass
139  if (particle.mass > Math::EPSILON)
140  particle.velocity.sub(Vector3(0.0f, 0.5f * Math::G * static_cast<float>(timeDelta) / 1000.0f, 0.0f));
141  // TODO:
142  // maybe take air resistance into account like a huge paper needs more time to fall than a sphere of paper
143  // or heat for smoke or fire, whereas having no mass for those particles works around this problem for now
144  // translation
145  particle.position.add(velocityForTime.set(particle.velocity).scale(static_cast<float>(timeDelta) / 1000.0f));
146  // color
147  auto& color = particle.color;
148  const auto& colorAdd = particle.colorAdd;
149  color[0] += colorAdd[0] * static_cast<float>(timeDelta);
150  color[1] += colorAdd[1] * static_cast<float>(timeDelta);
151  color[2] += colorAdd[2] * static_cast<float>(timeDelta);
152  color[3] += colorAdd[3] * static_cast<float>(timeDelta);
153  //
154  activeParticles++;
155  // set up bounding box
156  point = localTransformMatrix.multiply(particle.position);
157  point.add(center);
158  //
159  if (first == false) {
160  boundingBox.getMin().set(point);
161  boundingBox.getMax().set(point);
162  first = true;
163  } else {
164  boundingBox.extend(point);
165  }
166  // transform particle according to its transform
167  point = entityTransformMatrix.multiply(point);
168  // add to render points pool
169  pointsRenderPool->addPoint(point, static_cast<uint16_t>(particle.spriteIndex) % (textureHorizontalSprites * textureVerticalSprites), color, 0, this);
170  }
171  // auto disable particle system if no more active particles
172  if (activeParticles == 0) {
173  active = false;
174  return;
175  }
176  // scale a bit up to make picking work better
182 }
183 
185 {
186  pointsRenderPool = nullptr;
187 }
188 
190 {
191  // enable particle system
192  active = true;
193  // delta time
194  auto timeDelta = engine->getTiming()->getDeltaTime();
195  // determine particles to spawn
196  auto particlesToSpawn = 0;
197  {
198  if (autoEmit == true) {
199  auto particlesToSpawnWithFraction = emitter->getCount() * engine->getTiming()->getDeltaTime() / 1000.0f;
200  particlesToSpawn = static_cast<int32_t>(particlesToSpawnWithFraction);
201  particlesToSpawnRemainder += particlesToSpawnWithFraction - particlesToSpawn;
202  if (particlesToSpawnRemainder > 1.0f) {
203  particlesToSpawn++;
205  }
206  } else {
207  particlesToSpawn = emitter->getCount();
208  }
209  }
210  // skip if nothing to spawn
211  if (particlesToSpawn == 0) return 0;
212  //
213  Vector3 velocityForTime;
214  // spawn
215  auto particlesSpawned = 0;
216  for (auto i = 0; i < particles.size(); i++) {
217  auto& particle = particles[i];
218  if (particle.active == true)
219  continue;
220  // emit particle
221  emitter->emit(&particle);
222  // add gravity if our particle have a noticable mass, add translation
223  // add some movement with a min of 0 time delta and a max of engine time delta
224  auto timeDeltaRnd = static_cast<int64_t>((Math::random() * timeDelta));
225  if (particle.mass > Math::EPSILON)
226  particle.velocity.sub(Vector3(0.0f, 0.5f * Math::G * static_cast<float>(timeDeltaRnd) / 1000.0f, 0.0f));
227  particle.position.add(velocityForTime.set(particle.velocity).scale(timeDeltaRnd / 1000.0f));
228  //
229  particlesSpawned++;
230  // finished?
231  if (particlesSpawned == particlesToSpawn) break;
232 
233  }
234  return particlesSpawned;
235 }
Color 4 definition class.
Definition: Color4.h:18
void set(float r, float g, float b, float a)
Sets this color by its components.
Definition: Color4.h:66
Engine main class.
Definition: Engine.h:131
Timing * getTiming()
Definition: Engine.h:1064
Texture entity.
Definition: Texture.h:24
Timing class.
Definition: Timing.h:16
int64_t getDeltaTime()
Gets the time passed between last and current frame.
Definition: Timing.h:85
Transform which contain scale, rotations and translation.
Definition: Transform.h:29
virtual void setTransform(const Transform &transform)
Set transform.
Definition: Transform.h:177
virtual void update()
Computes transform matrix.
Definition: Transform.cpp:33
const Matrix4x4 & getTransformMatrix() const
Definition: Transform.h:169
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:26
void extend(BoundingBox *boundingBox)
Extend bounding box with given bounding box.
Definition: BoundingBox.h:158
void fromBoundingVolumeWithTransformMatrix(BoundingBox *original, const Matrix4x4 &transformMatrix)
Create bounding volume from given original(of same type) with applied transform matrix.
Definition: BoundingBox.cpp:79
void update()
Updates this bounding box.
void setTransform(const Transform &transform) override
Set transform.
int emitParticles() override
Adds particles to this particle entity at given position.
Standard math functions.
Definition: Math.h:19
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
Matrix4x4 & identity()
Creates identity matrix.
Definition: Matrix4x4.h:158
Vector3 multiply(const Vector3 &vector3) const
Multiplies this matrix with vector3.
Definition: Matrix4x4.h:225
void getTranslation(Vector3 &translation) const
Get translation.
Definition: Matrix4x4.h:433
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
Vector3 & add(float scalar)
Adds a scalar.
Definition: Vector3.h:153
Vector3 & sub(float scalar)
Subtracts a scalar.
Definition: Vector3.h:177
Vector3 & scale(float scalar)
Scales by scalar.
Definition: Vector3.h:201
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.
Definition: Vector3.h:70
Console class.
Definition: Console.h:29
virtual void releaseReference()
Releases a reference, thus decrementing the counter and delete it if reference counter is zero.
Definition: Reference.h:38