add particles.emit(...) (WIP)
This commit is contained in:
parent
9728c674fc
commit
c8187c5f25
8
res/content/base/scripts/world.lua
Normal file
8
res/content/base/scripts/world.lua
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
function on_block_broken(id, x, y, z, playerid)
|
||||||
|
particles.emit({x+0.5, y+0.5, z+0.5}, 100, {
|
||||||
|
lifetime=1.0,
|
||||||
|
spawn_interval=0.0001,
|
||||||
|
explosion={4, 4, 4},
|
||||||
|
texture="blocks:"..block.get_textures(id)[1]
|
||||||
|
})
|
||||||
|
end
|
||||||
@ -66,7 +66,7 @@ void LevelScreen::initializeContent() {
|
|||||||
for (auto& entry : content->getPacks()) {
|
for (auto& entry : content->getPacks()) {
|
||||||
initializePack(entry.second.get());
|
initializePack(entry.second.get());
|
||||||
}
|
}
|
||||||
scripting::on_frontend_init(hud.get());
|
scripting::on_frontend_init(hud.get(), worldRenderer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
||||||
|
|||||||
@ -12,18 +12,17 @@
|
|||||||
Emitter::Emitter(
|
Emitter::Emitter(
|
||||||
const Level& level,
|
const Level& level,
|
||||||
std::variant<glm::vec3, entityid_t> origin,
|
std::variant<glm::vec3, entityid_t> origin,
|
||||||
Particle prototype,
|
ParticlesPreset preset,
|
||||||
const Texture* texture,
|
const Texture* texture,
|
||||||
float spawnInterval,
|
const UVRegion& region,
|
||||||
int count
|
int count
|
||||||
)
|
)
|
||||||
: level(level),
|
: level(level),
|
||||||
origin(std::move(origin)),
|
origin(std::move(origin)),
|
||||||
prototype(std::move(prototype)),
|
prototype({this, 0, glm::vec3(), preset.velocity, preset.lifetime, region}),
|
||||||
texture(texture),
|
texture(texture),
|
||||||
spawnInterval(spawnInterval),
|
|
||||||
count(count),
|
count(count),
|
||||||
preset() {
|
preset(std::move(preset)) {
|
||||||
this->prototype.emitter = this;
|
this->prototype.emitter = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +35,7 @@ void Emitter::update(
|
|||||||
const glm::vec3& cameraPosition,
|
const glm::vec3& cameraPosition,
|
||||||
std::vector<Particle>& particles
|
std::vector<Particle>& particles
|
||||||
) {
|
) {
|
||||||
|
const float spawnInterval = preset.spawnInterval;
|
||||||
if (count == 0 || (count == -1 && spawnInterval < FLT_EPSILON)) {
|
if (count == 0 || (count == -1 && spawnInterval < FLT_EPSILON)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ void Emitter::update(
|
|||||||
particle.emitter = this;
|
particle.emitter = this;
|
||||||
particle.random = random.rand32();
|
particle.random = random.rand32();
|
||||||
particle.position = position;
|
particle.position = position;
|
||||||
particle.velocity += glm::ballRand(1.0f) * explosion;
|
particle.velocity += glm::ballRand(1.0f) * preset.explosion;
|
||||||
particles.push_back(std::move(particle));
|
particles.push_back(std::move(particle));
|
||||||
timer -= spawnInterval;
|
timer -= spawnInterval;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
@ -76,10 +76,6 @@ void Emitter::update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emitter::setExplosion(const glm::vec3& magnitude) {
|
|
||||||
explosion = magnitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Emitter::isDead() const {
|
bool Emitter::isDead() const {
|
||||||
return count == 0;
|
return count == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,24 +31,22 @@ struct Particle {
|
|||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
|
using EmitterOrigin = std::variant<glm::vec3, entityid_t>;
|
||||||
|
|
||||||
class Emitter {
|
class Emitter {
|
||||||
const Level& level;
|
const Level& level;
|
||||||
/// @brief Static position or entity
|
/// @brief Static position or entity
|
||||||
std::variant<glm::vec3, entityid_t> origin;
|
EmitterOrigin origin;
|
||||||
/// @brief Particle prototype
|
/// @brief Particle prototype
|
||||||
Particle prototype;
|
Particle prototype;
|
||||||
/// @brief Particle
|
/// @brief Particle
|
||||||
const Texture* texture;
|
const Texture* texture;
|
||||||
/// @brief Particles spawn interval
|
|
||||||
float spawnInterval;
|
|
||||||
/// @brief Number of particles should be spawned before emitter deactivation.
|
/// @brief Number of particles should be spawned before emitter deactivation.
|
||||||
/// -1 is infinite.
|
/// -1 is infinite.
|
||||||
int count;
|
int count;
|
||||||
/// @brief Spawn timer used to determine number of particles
|
/// @brief Spawn timer used to determine number of particles
|
||||||
/// to spawn on update. May be innacurate.
|
/// to spawn on update. May be innacurate.
|
||||||
float timer = 0.0f;
|
float timer = 0.0f;
|
||||||
/// @brief Random velocity magnitude applying to spawned particles.
|
|
||||||
glm::vec3 explosion {8.0f};
|
|
||||||
|
|
||||||
util::PseudoRandom random;
|
util::PseudoRandom random;
|
||||||
public:
|
public:
|
||||||
@ -57,9 +55,9 @@ public:
|
|||||||
Emitter(
|
Emitter(
|
||||||
const Level& level,
|
const Level& level,
|
||||||
std::variant<glm::vec3, entityid_t> origin,
|
std::variant<glm::vec3, entityid_t> origin,
|
||||||
Particle prototype,
|
ParticlesPreset preset,
|
||||||
const Texture* texture,
|
const Texture* texture,
|
||||||
float spawnInterval,
|
const UVRegion& region,
|
||||||
int count
|
int count
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,10 +75,7 @@ public:
|
|||||||
const glm::vec3& cameraPosition,
|
const glm::vec3& cameraPosition,
|
||||||
std::vector<Particle>& particles
|
std::vector<Particle>& particles
|
||||||
);
|
);
|
||||||
|
|
||||||
/// @brief Set initial random velocity magitude
|
|
||||||
void setExplosion(const glm::vec3& magnitude);
|
|
||||||
|
|
||||||
/// @return true if the emitter has spawned all particles
|
/// @return true if the emitter has spawned all particles
|
||||||
bool isDead() const;
|
bool isDead() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#include "ParticlesRenderer.hpp"
|
#include "ParticlesRenderer.hpp"
|
||||||
|
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
#include "assets/assets_util.hpp"
|
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/core/Texture.hpp"
|
#include "graphics/core/Texture.hpp"
|
||||||
#include "graphics/render/MainBatch.hpp"
|
#include "graphics/render/MainBatch.hpp"
|
||||||
@ -18,17 +17,7 @@ ParticlesRenderer::ParticlesRenderer(
|
|||||||
)
|
)
|
||||||
: batch(std::make_unique<MainBatch>(1024)),
|
: batch(std::make_unique<MainBatch>(1024)),
|
||||||
level(level),
|
level(level),
|
||||||
settings(settings) {
|
settings(settings) {}
|
||||||
auto region = util::get_texture_region(assets, "blocks:grass_side", "");
|
|
||||||
emitters.push_back(std::make_unique<Emitter>(
|
|
||||||
level,
|
|
||||||
glm::vec3(0, 80, 0),
|
|
||||||
Particle {nullptr, 0, glm::vec3(), glm::vec3(), 5.0f, region.region},
|
|
||||||
region.texture,
|
|
||||||
0.002f,
|
|
||||||
-1
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
ParticlesRenderer::~ParticlesRenderer() = default;
|
ParticlesRenderer::~ParticlesRenderer() = default;
|
||||||
|
|
||||||
@ -68,21 +57,22 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
|
|||||||
auto iter = vec.begin();
|
auto iter = vec.begin();
|
||||||
while (iter != vec.end()) {
|
while (iter != vec.end()) {
|
||||||
auto& particle = *iter;
|
auto& particle = *iter;
|
||||||
|
auto& preset = particle.emitter->preset;
|
||||||
|
|
||||||
update_particle(particle, delta, chunks);
|
update_particle(particle, delta, chunks);
|
||||||
|
|
||||||
glm::vec4 light(1, 1, 1, 0);
|
glm::vec4 light(1, 1, 1, 0);
|
||||||
if (particle.emitter->preset.lighting) {
|
if (preset.lighting) {
|
||||||
light = MainBatch::sampleLight(
|
light = MainBatch::sampleLight(
|
||||||
particle.position, chunks, backlight
|
particle.position, chunks, backlight
|
||||||
);
|
);
|
||||||
light *= 0.8f + (particle.random % 200) * 0.001f;
|
light *= 0.9f + (particle.random % 100) * 0.001f;
|
||||||
}
|
}
|
||||||
batch->quad(
|
batch->quad(
|
||||||
particle.position,
|
particle.position,
|
||||||
right,
|
right,
|
||||||
up,
|
up,
|
||||||
glm::vec2(0.3f),
|
preset.size,
|
||||||
light,
|
light,
|
||||||
glm::vec3(1.0f),
|
glm::vec3(1.0f),
|
||||||
particle.region
|
particle.region
|
||||||
@ -128,3 +118,7 @@ void ParticlesRenderer::render(const Camera& camera, float delta) {
|
|||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticlesRenderer::add(std::unique_ptr<Emitter> emitter) {
|
||||||
|
emitters.push_back(std::move(emitter));
|
||||||
|
}
|
||||||
|
|||||||
@ -31,6 +31,8 @@ public:
|
|||||||
|
|
||||||
void render(const Camera& camera, float delta);
|
void render(const Camera& camera, float delta);
|
||||||
|
|
||||||
|
void add(std::unique_ptr<Emitter> emitter);
|
||||||
|
|
||||||
static size_t visibleParticles;
|
static size_t visibleParticles;
|
||||||
static size_t aliveEmitters;
|
static size_t aliveEmitters;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
#include "ChunksRenderer.hpp"
|
#include "ChunksRenderer.hpp"
|
||||||
#include "ModelBatch.hpp"
|
#include "ModelBatch.hpp"
|
||||||
#include "Skybox.hpp"
|
#include "Skybox.hpp"
|
||||||
|
#include "Emitter.hpp"
|
||||||
|
|
||||||
bool WorldRenderer::showChunkBorders = false;
|
bool WorldRenderer::showChunkBorders = false;
|
||||||
bool WorldRenderer::showEntitiesDebug = false;
|
bool WorldRenderer::showEntitiesDebug = false;
|
||||||
@ -534,6 +535,10 @@ void WorldRenderer::drawBorders(
|
|||||||
lineBatch->flush();
|
lineBatch->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldRenderer::addEmitter(std::unique_ptr<Emitter> emitter) {
|
||||||
|
particles->add(std::move(emitter));
|
||||||
|
}
|
||||||
|
|
||||||
void WorldRenderer::clear() {
|
void WorldRenderer::clear() {
|
||||||
renderer->clear();
|
renderer->clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,6 @@
|
|||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Emitter.hpp"
|
|
||||||
|
|
||||||
class Level;
|
class Level;
|
||||||
class Player;
|
class Player;
|
||||||
class Camera;
|
class Camera;
|
||||||
@ -27,6 +25,7 @@ class PostProcessing;
|
|||||||
class DrawContext;
|
class DrawContext;
|
||||||
class ModelBatch;
|
class ModelBatch;
|
||||||
class Assets;
|
class Assets;
|
||||||
|
class Emitter;
|
||||||
struct EngineSettings;
|
struct EngineSettings;
|
||||||
|
|
||||||
namespace model {
|
namespace model {
|
||||||
@ -109,5 +108,7 @@ public:
|
|||||||
bool pause
|
bool pause
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void addEmitter(std::unique_ptr<Emitter> emitter);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -31,6 +31,7 @@ extern const luaL_Reg itemlib[];
|
|||||||
extern const luaL_Reg jsonlib[];
|
extern const luaL_Reg jsonlib[];
|
||||||
extern const luaL_Reg mat4lib[];
|
extern const luaL_Reg mat4lib[];
|
||||||
extern const luaL_Reg packlib[];
|
extern const luaL_Reg packlib[];
|
||||||
|
extern const luaL_Reg particleslib[];
|
||||||
extern const luaL_Reg playerlib[];
|
extern const luaL_Reg playerlib[];
|
||||||
extern const luaL_Reg quatlib[]; // quat.cpp
|
extern const luaL_Reg quatlib[]; // quat.cpp
|
||||||
extern const luaL_Reg timelib[];
|
extern const luaL_Reg timelib[];
|
||||||
|
|||||||
44
src/logic/scripting/lua/libs/libparticles.cpp
Normal file
44
src/logic/scripting/lua/libs/libparticles.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "api_lua.hpp"
|
||||||
|
|
||||||
|
#include "logic/scripting/scripting_hud.hpp"
|
||||||
|
#include "graphics/render/WorldRenderer.hpp"
|
||||||
|
#include "graphics/render/Emitter.hpp"
|
||||||
|
#include "assets/assets_util.hpp"
|
||||||
|
#include "engine.hpp"
|
||||||
|
|
||||||
|
using namespace scripting;
|
||||||
|
|
||||||
|
static int l_emit(lua::State* L) {
|
||||||
|
EmitterOrigin origin;
|
||||||
|
if (lua::istable(L, 1)) {
|
||||||
|
origin = lua::tovec3(L, 1);
|
||||||
|
} else {
|
||||||
|
origin = static_cast<entityid_t>(lua::tointeger(L, 1));
|
||||||
|
}
|
||||||
|
int count = lua::tointeger(L, 2);
|
||||||
|
auto preset = lua::tovalue(L, 3);
|
||||||
|
auto extension = lua::tovalue(L, 4);
|
||||||
|
|
||||||
|
ParticlesPreset particlesPreset {};
|
||||||
|
particlesPreset.deserialize(preset);
|
||||||
|
if (extension != nullptr) {
|
||||||
|
particlesPreset.deserialize(extension);
|
||||||
|
}
|
||||||
|
auto& assets = *engine->getAssets();
|
||||||
|
auto region = util::get_texture_region(assets, particlesPreset.texture, "");
|
||||||
|
auto emitter = std::make_unique<Emitter>(
|
||||||
|
*level,
|
||||||
|
std::move(origin),
|
||||||
|
std::move(particlesPreset),
|
||||||
|
region.texture,
|
||||||
|
region.region,
|
||||||
|
count
|
||||||
|
);
|
||||||
|
renderer->addEmitter(std::move(emitter));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg particleslib[] = {
|
||||||
|
{"emit", lua::wrap<l_emit>},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
@ -4,6 +4,7 @@
|
|||||||
#include "engine.hpp"
|
#include "engine.hpp"
|
||||||
#include "files/files.hpp"
|
#include "files/files.hpp"
|
||||||
#include "frontend/hud.hpp"
|
#include "frontend/hud.hpp"
|
||||||
|
#include "graphics/render/WorldRenderer.hpp"
|
||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "lua/libs/api_lua.hpp"
|
#include "lua/libs/api_lua.hpp"
|
||||||
#include "lua/lua_engine.hpp"
|
#include "lua/lua_engine.hpp"
|
||||||
@ -14,10 +15,14 @@ using namespace scripting;
|
|||||||
static debug::Logger logger("scripting-hud");
|
static debug::Logger logger("scripting-hud");
|
||||||
|
|
||||||
Hud* scripting::hud = nullptr;
|
Hud* scripting::hud = nullptr;
|
||||||
|
WorldRenderer* scripting::renderer = nullptr;
|
||||||
|
|
||||||
void scripting::on_frontend_init(Hud* hud) {
|
void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) {
|
||||||
scripting::hud = hud;
|
scripting::hud = hud;
|
||||||
|
scripting::renderer = renderer;
|
||||||
|
|
||||||
lua::openlib(lua::get_main_state(), "hud", hudlib);
|
lua::openlib(lua::get_main_state(), "hud", hudlib);
|
||||||
|
lua::openlib(lua::get_main_state(), "particles", particleslib);
|
||||||
|
|
||||||
for (auto& pack : engine->getContentPacks()) {
|
for (auto& pack : engine->getContentPacks()) {
|
||||||
lua::emit_event(
|
lua::emit_event(
|
||||||
|
|||||||
@ -8,20 +8,20 @@
|
|||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
class Hud;
|
class Hud;
|
||||||
|
class WorldRenderer;
|
||||||
|
|
||||||
namespace scripting {
|
namespace scripting {
|
||||||
extern Hud *hud;
|
extern Hud *hud;
|
||||||
|
extern WorldRenderer* renderer;
|
||||||
|
|
||||||
void on_frontend_init(Hud *hud);
|
void on_frontend_init(Hud* hud, WorldRenderer* renderer);
|
||||||
void on_frontend_render();
|
void on_frontend_render();
|
||||||
void on_frontend_close();
|
void on_frontend_close();
|
||||||
|
|
||||||
/**
|
/// @brief Load package-specific hud script
|
||||||
* Load package-specific hud script
|
/// @param env environment id
|
||||||
* @param env environment id
|
/// @param packid content-pack id
|
||||||
* @param packid content-pack id
|
/// @param file script file path
|
||||||
* @param file script file path
|
|
||||||
*/
|
|
||||||
void load_hud_script(
|
void load_hud_script(
|
||||||
const scriptenv &env, const std::string &packid, const fs::path &file
|
const scriptenv &env, const std::string &packid, const fs::path &file
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,17 +4,32 @@
|
|||||||
|
|
||||||
dv::value ParticlesPreset::serialize() const {
|
dv::value ParticlesPreset::serialize() const {
|
||||||
auto root = dv::object();
|
auto root = dv::object();
|
||||||
|
root["texture"] = texture;
|
||||||
root["collision"] = collision;
|
root["collision"] = collision;
|
||||||
root["lighting"] = lighting;
|
root["lighting"] = lighting;
|
||||||
root["max_distance"] = maxDistance;
|
root["max_distance"] = maxDistance;
|
||||||
|
root["spawn_interval"] = spawnInterval;
|
||||||
|
root["lifetime"] = lifetime;
|
||||||
root["acceleration"] = dv::to_value(acceleration);
|
root["acceleration"] = dv::to_value(acceleration);
|
||||||
|
root["explosion"] = dv::to_value(explosion);
|
||||||
|
root["size"] = dv::to_value(size);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticlesPreset::deserialize(const dv::value& src) {
|
void ParticlesPreset::deserialize(const dv::value& src) {
|
||||||
|
src.at("texture").get(texture);
|
||||||
src.at("collision").get(collision);
|
src.at("collision").get(collision);
|
||||||
src.at("lighting").get(lighting);
|
src.at("lighting").get(lighting);
|
||||||
|
src.at("max_distance").get(maxDistance);
|
||||||
|
src.at("spawn_interval").get(spawnInterval);
|
||||||
|
src.at("lifetime").get(lifetime);
|
||||||
if (src.has("acceleration")) {
|
if (src.has("acceleration")) {
|
||||||
dv::get_vec(src["acceleration"], acceleration);
|
dv::get_vec(src["acceleration"], acceleration);
|
||||||
}
|
}
|
||||||
|
if (src.has("size")) {
|
||||||
|
dv::get_vec(src["size"], size);
|
||||||
|
}
|
||||||
|
if (src.has("explosion")) {
|
||||||
|
dv::get_vec(src["explosion"], explosion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,20 @@ struct ParticlesPreset : public Serializable {
|
|||||||
bool lighting = true;
|
bool lighting = true;
|
||||||
/// @brief Max distance of actually spawning particles.
|
/// @brief Max distance of actually spawning particles.
|
||||||
float maxDistance = 32.0f;
|
float maxDistance = 32.0f;
|
||||||
|
/// @brief Particles spawn interval
|
||||||
|
float spawnInterval = 0.1f;
|
||||||
|
/// @brief Particle life time
|
||||||
|
float lifetime = 5.0f;
|
||||||
|
/// @brief Initial velocity
|
||||||
|
glm::vec3 velocity {};
|
||||||
/// @brief Velocity acceleration
|
/// @brief Velocity acceleration
|
||||||
glm::vec3 acceleration {0.0f, -16.0f, 0.0f};
|
glm::vec3 acceleration {0.0f, -16.0f, 0.0f};
|
||||||
|
/// @brief Random velocity magnitude applying to spawned particles.
|
||||||
|
glm::vec3 explosion {2.0f};
|
||||||
|
/// @brief Particle size
|
||||||
|
glm::vec3 size {0.1f};
|
||||||
|
/// @brief Texture name
|
||||||
|
std::string texture = "";
|
||||||
|
|
||||||
dv::value serialize() const override;
|
dv::value serialize() const override;
|
||||||
void deserialize(const dv::value& src) override;
|
void deserialize(const dv::value& src) override;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user