diff options
Diffstat (limited to 'src/libjin/graphics/particles/particle.cpp')
-rw-r--r-- | src/libjin/graphics/particles/particle.cpp | 190 |
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 |