From 39893ee940d36acc18beaf0ea35cc6e8eba1e4ff Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 3 Nov 2024 17:14:30 +0300 Subject: [PATCH] add 'spawn_spread' and 'spawn_shape' --- res/content/base/scripts/world.lua | 5 ++++- src/graphics/render/Emitter.cpp | 19 ++++++++++++++++++- src/presets/ParticlesPreset.cpp | 27 +++++++++++++++++++++++++++ src/presets/ParticlesPreset.hpp | 19 +++++++++++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/res/content/base/scripts/world.lua b/res/content/base/scripts/world.lua index 61e1086a..d8e76967 100644 --- a/res/content/base/scripts/world.lua +++ b/res/content/base/scripts/world.lua @@ -4,6 +4,9 @@ function on_block_broken(id, x, y, z, playerid) spawn_interval=0.0001, explosion={4, 4, 4}, texture="blocks:"..block.get_textures(id)[1], - random_sub_uv=0.1 + random_sub_uv=0.1, + size={0.1, 0.1, 0.1}, + spawn_shape="box", + spawn_spread={0.4, 0.4, 0.4} }) end diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index c2763574..96bcb96d 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -30,6 +30,19 @@ const Texture* Emitter::getTexture() const { return texture; } +static inline glm::vec3 generate_coord(ParticleSpawnShape shape) { + switch (shape) { + case ParticleSpawnShape::BALL: + return glm::ballRand(1.0f); + case ParticleSpawnShape::SPHERE: + return glm::sphericalRand(1.0f); + case ParticleSpawnShape::BOX: + return glm::linearRand(glm::vec3(-1.0f), glm::vec3(1.0f)); + default: + return {}; + } +} + void Emitter::update( float delta, const glm::vec3& cameraPosition, @@ -66,7 +79,11 @@ void Emitter::update( Particle particle = prototype; particle.emitter = this; particle.random = random.rand32(); - particle.position = position; + + glm::vec3 spawnOffset = generate_coord(preset.spawnShape); + spawnOffset *= preset.spawnSpread; + + particle.position = position + spawnOffset; particle.lifetime *= 1.0f - preset.lifetimeSpread * random.randFloat(); particle.velocity += glm::ballRand(1.0f) * preset.explosion; if (preset.randomSubUV < 1.0f) { diff --git a/src/presets/ParticlesPreset.cpp b/src/presets/ParticlesPreset.cpp index 490e7cc9..7d9f86ab 100644 --- a/src/presets/ParticlesPreset.cpp +++ b/src/presets/ParticlesPreset.cpp @@ -2,6 +2,25 @@ #include "data/dv_util.hpp" +std::string to_string(ParticleSpawnShape shape) { + static std::string names[] = { + "ball", + "sphere", + "box" + }; + return names[static_cast(shape)]; +} + +ParticleSpawnShape ParticleSpawnShape_from(std::string_view s) { + if (s == "ball") { + return ParticleSpawnShape::BALL; + } else if (s == "sphere") { + return ParticleSpawnShape::SPHERE; + } else { + return ParticleSpawnShape::BOX; + } +} + dv::value ParticlesPreset::serialize() const { auto root = dv::object(); root["texture"] = texture; @@ -14,6 +33,8 @@ dv::value ParticlesPreset::serialize() const { root["acceleration"] = dv::to_value(acceleration); root["explosion"] = dv::to_value(explosion); root["size"] = dv::to_value(size); + root["spawn_spread"] = dv::to_value(size); + root["spawn_shape"] = to_string(spawnShape); root["random_sub_uv"] = randomSubUV; return root; } @@ -33,7 +54,13 @@ void ParticlesPreset::deserialize(const dv::value& src) { if (src.has("size")) { dv::get_vec(src["size"], size); } + if (src.has("spawn_spread")) { + dv::get_vec(src["spawn_spread"], spawnSpread); + } if (src.has("explosion")) { dv::get_vec(src["explosion"], explosion); } + if (src.has("spawn_shape")) { + spawnShape = ParticleSpawnShape_from(src["spawn_shape"].asString()); + } } diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index 48658f8c..38fc1214 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -4,6 +4,21 @@ #include "interfaces/Serializable.hpp" +enum ParticleSpawnShape { + /// @brief Coordinates are regulary distributed within + /// the volume of a ball. + BALL = 0, + /// @brief Coordinates are regulary distributed on + /// a sphere. + SPHERE, + /// @brief Coordinates are uniform distributed within + /// the volume of a box. + BOX +}; + +std::string to_string(ParticleSpawnShape shape); +ParticleSpawnShape ParticleSpawnShape_from(std::string_view s); + struct ParticlesPreset : public Serializable { /// @brief Collision detection bool collision = true; @@ -25,6 +40,10 @@ struct ParticlesPreset : public Serializable { glm::vec3 explosion {2.0f}; /// @brief Particle size glm::vec3 size {0.1f}; + /// @brief Spawn spread shape + ParticleSpawnShape spawnShape; + /// @brief Spawn spread + glm::vec3 spawnSpread {}; /// @brief Texture name std::string texture = ""; /// @brief Size of random sub-uv region