aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/graphics/particles/particle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/graphics/particles/particle.cpp')
-rw-r--r--src/libjin/graphics/particles/particle.cpp190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/libjin/graphics/particles/particle.cpp b/src/libjin/graphics/particles/particle.cpp
new file mode 100644
index 0000000..74600e0
--- /dev/null
+++ b/src/libjin/graphics/particles/particle.cpp
@@ -0,0 +1,190 @@
+#include "../../utils/log.h"
+#include "../../common/array.hpp"
+#include "../../math/math.h"
+#include "../../math/random.h"
+
+#include "../sprite.h"
+
+#include "particle.h"
+
+using namespace JinEngine::Math;
+
+namespace JinEngine
+{
+ namespace Graphics
+ {
+ namespace Particles
+ {
+
+ static RandomGenerator rng(0xEA44944);
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ // ScaledRangedValue
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ ScaledRangedValue::ScaledRangedValue(Percentage* points, uint n)
+ {
+ for (int i = 0; i < n; ++i)
+ {
+ float x = points[2 * i].value;
+ float y = points[2 * i + 1].value;
+ addPoint(x, y);
+ }
+ }
+
+ void ScaledRangedValue::set(Math::Percentage* points, uint n)
+ {
+ clear();
+ for (int i = 0; i < n; ++i)
+ {
+ float x = points[2 * i].value;
+ float y = points[2 * i + 1].value;
+ addPoint(x, y);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ // GradientColorValue
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ GradientColorValue::GradientColorValue()
+ : mCount(0)
+ {
+ }
+
+ void GradientColorValue::addColor(Color col, Percentage time)
+ {
+ mColors.push_back(col);
+ mTimeline.push_back(time);
+ ++mCount;
+ }
+
+ Color GradientColorValue::getColor(Percentage time)
+ {
+ int endIndex = -1;
+ int n = mCount;
+ for (int i = 1; i < n; i++) {
+ Percentage t = mTimeline[i];
+ if (t.value > time.value) {
+ endIndex = i;
+ break;
+ }
+ }
+ if (endIndex == -1) return mColors[n - 1];
+ int startIndex = endIndex - 1;
+ Color& startValue = mColors[startIndex];
+ Color& endValue = mColors[endIndex];
+ float t = time.value;
+ float start = mTimeline[startIndex].value;
+ float end = mTimeline[endIndex].value;
+ Color c;
+ c.r = startValue.r + (endValue.r - startValue.r) * ((t - start) / (end - start));
+ c.g = startValue.g + (endValue.g - startValue.g) * ((t - start) / (end - start));
+ c.b = startValue.b + (endValue.b - startValue.b) * ((t - start) / (end - start));
+ c.a = startValue.a + (endValue.a - startValue.a) * ((t - start) / (end - start));
+ return c;
+ }
+
+ void GradientColorValue::insertColor(uint i, Color col, Math::Percentage time)
+ {
+ mColors.insert(mColors.begin() + i, col);
+ mTimeline.insert(mTimeline.begin() + i, time);
+ ++mCount;
+ }
+
+ void GradientColorValue::removeColor(uint i)
+ {
+ mColors.erase(mColors.begin() + i);
+ mTimeline.erase(mTimeline.begin() + i);
+ --mCount;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Particle
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ Particle::Particle()
+ {
+ reset();
+ }
+
+ void Particle::reset()
+ {
+ updateFlags = ParticleUpdateMask::NONE;
+ transform.set(0, 0, 1, 1, 0, 0, 0);
+ lifeTime = 1.0f;
+ life = 0.0f;
+ velocity.set(0, 0);
+ linearAcceleration.set(0, 0);
+ radialAcceleration = 0.0f;
+ angularSpeed = 0;
+ color = Color::WHITE;
+ alive = true;
+ spriteIndex = 0;
+ }
+
+ void Particle::update(float dt)
+ {
+ life += dt;
+ alive = life < lifeTime;
+ if (!alive)
+ return;
+ float t = life / lifeTime;
+ if ((updateFlags & UPDATE_COLOR) != 0)
+ color = def->colorDef.overTime.value.getColor(t);
+ // transparency
+ if (def->transparencyDef.overTime.enable)
+ color.a = 0xff * def->transparencyDef.overTime.value.getValue(t);
+ else
+ color.a = 0xff * def->transparencyDef.transparency.value;
+ if ((updateFlags & UPDATE_SCALE) != 0)
+ {
+ // Lerp scale.
+ float scale = def->scaleDef.overTime.value.getValue(t);
+ transform.setScale(scale, scale);
+ }
+ if ((updateFlags & UPDATE_POSITION) != 0)
+ {
+ // Calculate position.
+ if((updateFlags & UPDATE_VELOCITY) != 0)
+ velocity += linearAcceleration * dt;
+ transform.move(velocity * dt);
+ }
+ if ((updateFlags & UPDATE_ROTATION) != 0)
+ {
+ // Calculate rotation.
+ angularSpeed += radialAcceleration * dt;
+ transform.rotate(angularSpeed * dt);
+ }
+ if ((updateFlags & UPDATE_SPRITE) != 0)
+ {
+ int n = def->spritesDef.sprites.size();
+ if (def->spritesDef.mode == SpriteMode::ANIMATED)
+ spriteIndex = lerp<int>(0, n - 1, t);
+ //jin_log_info("sprite index %d", spriteIndex);
+ }
+ }
+
+ void Particle::render()
+ {
+ // Set blend.
+ OpenGL::BlendMode blend = gl.getBlendMode();
+ if(def->blendDef.additive)
+ gl.setBlendMode(OpenGL::BlendMode::ADDITIVE);
+ Color c = gl.getColor();
+ gl.setColor(color);
+ const Sprite* sprite = def->spritesDef.sprites[spriteIndex];
+ if (sprite != nullptr)
+ {
+ Vector2<float>& position = transform.getPosition();
+ Vector2<float>& scale = transform.getScale();
+ float r = transform.getRotation();
+ sprite->render(position.x(), position.y(), scale.x(), scale.y(), r);
+ }
+ gl.setColor(c);
+ gl.setBlendMode(blend);
+ }
+
+ }
+ }
+} \ No newline at end of file