add particles collision detection

This commit is contained in:
MihailRis
2024-11-03 01:59:41 +03:00
parent 1974298c82
commit b944f257f7
7 changed files with 58 additions and 22 deletions
+3 -1
View File
@@ -15,7 +15,8 @@ Emitter::Emitter(
prototype(std::move(prototype)),
texture(texture),
spawnInterval(spawnInterval),
count(count) {
count(count),
behaviour() {
this->prototype.emitter = this;
}
@@ -37,6 +38,7 @@ void Emitter::update(float delta, std::vector<Particle>& particles) {
while (count && timer > spawnInterval) {
// spawn particle
Particle particle = prototype;
particle.emitter = this;
particle.position = position;
particle.velocity += glm::ballRand(1.0f) * explosion;
particles.push_back(std::move(particle));
+10 -1
View File
@@ -26,6 +26,11 @@ struct Particle {
class Texture;
struct ParticleBehaviour {
bool collision = true;
glm::vec3 gravity {0.0f, -16.0f, 0.0f};
};
class Emitter {
/// @brief Static position or entity
std::variant<glm::vec3, entityid_t> origin;
@@ -42,8 +47,10 @@ class Emitter {
/// to spawn on update. May be innacurate.
float timer = 0.0f;
/// @brief Random velocity magnitude applying to spawned particles
glm::vec3 explosion {1.0f};
glm::vec3 explosion {8.0f};
public:
ParticleBehaviour behaviour;
Emitter(
std::variant<glm::vec3, entityid_t> origin,
Particle prototype,
@@ -52,6 +59,8 @@ public:
int count
);
explicit Emitter(const Emitter&) = delete;
/// @return Emitter particles texture
const Texture* getTexture() const;
+23 -9
View File
@@ -6,22 +6,38 @@
#include "graphics/core/Texture.hpp"
#include "graphics/render/MainBatch.hpp"
#include "window/Camera.hpp"
#include "world/Level.hpp"
#include "voxels/Chunks.hpp"
size_t ParticlesRenderer::visibleParticles = 0;
size_t ParticlesRenderer::aliveEmitters = 0;
ParticlesRenderer::ParticlesRenderer(const Assets& assets)
: batch(std::make_unique<MainBatch>(1024)) {
ParticlesRenderer::ParticlesRenderer(const Assets& assets, const Level& level)
: batch(std::make_unique<MainBatch>(1024)), level(level) {
auto region = util::get_texture_region(assets, "blocks:grass_side", "");
Emitter emitter(glm::vec3(0, 100, 0), Particle {
auto region = util::get_texture_region(assets, "blocks:bazalt", "");
emitters.push_back(std::make_unique<Emitter>(glm::vec3(0, 100, 0), Particle {
nullptr, glm::vec3(), glm::vec3(), 5.0f, region.region
},region.texture, 0.001f, 1000);
emitters.push_back(std::make_unique<Emitter>(emitter));
},region.texture, 0.002f, -1));
}
ParticlesRenderer::~ParticlesRenderer() = default;
static inline void update_particle(
Particle& particle, float delta, const Chunks& chunks
) {
const auto& behave = particle.emitter->behaviour;
auto& pos = particle.position;
auto& vel = particle.velocity;
vel += delta * behave.gravity;
if (behave.collision && chunks.isObstacleAt(pos + vel * delta)) {
vel *= 0.0f;
}
pos += vel * delta;
particle.lifetime -= delta;
}
void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
const auto& right = camera.right;
const auto& up = camera.up;
@@ -41,7 +57,7 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
while (iter != vec.end()) {
auto& particle = *iter;
particle.position += particle.velocity * delta;
update_particle(particle, delta, *level.chunks);
batch->quad(
particle.position,
@@ -52,8 +68,6 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
glm::vec3(1.0f),
particle.region
);
particle.lifetime -= delta;
if (particle.lifetime <= 0.0f) {
iter = vec.erase(iter);
} else {
+3 -1
View File
@@ -10,15 +10,17 @@ class Texture;
class Assets;
class Camera;
class MainBatch;
class Level;
class ParticlesRenderer {
const Level& level;
std::unordered_map<const Texture*, std::vector<Particle>> particles;
std::vector<std::unique_ptr<Emitter>> emitters;
std::unique_ptr<MainBatch> batch;
void renderParticles(const Camera& camera, float delta);
public:
ParticlesRenderer(const Assets& assets);
ParticlesRenderer(const Assets& assets, const Level& level);
~ParticlesRenderer();
void render(const Camera& camera, float delta);
+3 -2
View File
@@ -62,8 +62,9 @@ WorldRenderer::WorldRenderer(
level->chunks.get(),
&engine->getSettings()
)),
particles(std::make_unique<ParticlesRenderer>(*engine->getAssets())) {
particles(std::make_unique<ParticlesRenderer>(
*engine->getAssets(), *frontend->getLevel()
)) {
renderer = std::make_unique<ChunksRenderer>(
level, frontend->getContentGfxCache(), &engine->getSettings()
);