Merge branch 'main' into headless-mode

This commit is contained in:
MihailRis
2024-12-24 05:48:02 +03:00
10 changed files with 121 additions and 22 deletions
+1 -2
View File
@@ -104,9 +104,8 @@ void Decorator::update(
void Decorator::update(float delta, const Camera& camera) {
glm::ivec3 pos = camera.position;
pos -= glm::ivec3(UPDATE_AREA_DIAMETER / 2);
for (int i = 0; i < ITERATIONS; i++) {
update(delta, pos, camera.position);
update(delta, pos - glm::ivec3(UPDATE_AREA_DIAMETER / 2), pos);
}
const auto& chunks = *player.chunks;
const auto& indices = *level.content->getIndices();
+21 -2
View File
@@ -19,12 +19,13 @@ Emitter::Emitter(
)
: level(level),
origin(std::move(origin)),
prototype({this, 0, glm::vec3(), preset.velocity, preset.lifetime, region}),
prototype({this, 0, {}, preset.velocity, preset.lifetime, region}),
texture(texture),
count(count),
preset(std::move(preset)) {
random.setSeed(reinterpret_cast<ptrdiff_t>(this));
this->prototype.emitter = this;
timer = preset.spawnInterval;
timer = preset.spawnInterval * random.randFloat();
}
const Texture* Emitter::getTexture() const {
@@ -76,6 +77,10 @@ void Emitter::update(
count = std::max(0, count - skipped);
timer -= skipped * spawnInterval;
}
if (count < 0) {
int skipped = timer / spawnInterval;
timer -= skipped * spawnInterval;
}
return;
}
while (count && timer > spawnInterval) {
@@ -83,6 +88,15 @@ void Emitter::update(
Particle particle = prototype;
particle.emitter = this;
particle.random = random.rand32();
if (glm::abs(preset.angleSpread) >= 0.005f) {
particle.angle =
random.randFloat() * preset.angleSpread * glm::pi<float>() * 2;
}
particle.angularVelocity =
(preset.minAngularVelocity +
random.randFloat() *
(preset.maxAngularVelocity - preset.minAngularVelocity)) *
((random.rand() % 2) * 2 - 1);
glm::vec3 spawnOffset = generate_coord(preset.spawnShape);
spawnOffset *= preset.spawnSpread;
@@ -103,6 +117,7 @@ void Emitter::update(
if (count > 0) {
count--;
}
refCount++;
}
}
@@ -114,6 +129,10 @@ bool Emitter::isDead() const {
return count == 0;
}
bool Emitter::isReferred() const {
return refCount > 0;
}
const EmitterOrigin& Emitter::getOrigin() const {
return origin;
}
+11 -1
View File
@@ -27,6 +27,10 @@ struct Particle {
float lifetime;
/// @brief UV region
UVRegion region;
/// @brief Current rotation angle
float angle;
/// @brief Angular velocity
float angularVelocity;
};
class Texture;
@@ -39,7 +43,7 @@ class Emitter {
EmitterOrigin origin;
/// @brief Particle prototype
Particle prototype;
/// @brief Particle
/// @brief Particle texture
const Texture* texture;
/// @brief Number of particles should be spawned before emitter deactivation.
/// -1 is infinite.
@@ -50,6 +54,9 @@ class Emitter {
util::PseudoRandom random;
public:
/// @brief Number of references (alive particles)
int refCount = 0;
/// @brief Particle settings
ParticlesPreset preset;
Emitter(
@@ -82,6 +89,9 @@ public:
/// @return true if the emitter has spawned all particles
bool isDead() const;
/// @return true if there is at least one alive referring particle left
bool isReferred() const;
const EmitterOrigin& getOrigin() const;
void setOrigin(const EmitterOrigin& origin);
+49 -16
View File
@@ -36,12 +36,14 @@ static inline void update_particle(
const auto& preset = particle.emitter->preset;
auto& pos = particle.position;
auto& vel = particle.velocity;
auto& angle = particle.angle;
vel += delta * preset.acceleration;
if (preset.collision && chunks.isObstacleAt(pos + vel * delta)) {
vel *= 0.0f;
}
pos += vel * delta;
angle += particle.angularVelocity * delta;
particle.lifetime -= delta;
}
@@ -65,7 +67,8 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
auto iter = vec.begin();
while (iter != vec.end()) {
auto& particle = *iter;
auto& preset = particle.emitter->preset;
auto& emitter = *particle.emitter;
auto& preset = emitter.preset;
if (!preset.frames.empty()) {
float time = preset.lifetime - particle.lifetime;
@@ -86,19 +89,52 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
}
update_particle(particle, delta, chunks);
float scale = 1.0f + ((particle.random ^ 2628172) % 1000) *
0.001f * preset.sizeSpread;
glm::vec4 light(1, 1, 1, 0);
if (preset.lighting) {
light = MainBatch::sampleLight(
particle.position, chunks, backlight
particle.position,
chunks,
backlight
);
auto size = glm::max(glm::vec3(0.5f), preset.size * scale);
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int z = -1; z <= 1; z++) {
light = glm::max(
light,
MainBatch::sampleLight(
particle.position -
size * glm::vec3(x, y, z),
chunks,
backlight
)
);
}
}
}
light *= 0.9f + (particle.random % 100) * 0.001f;
}
float scale = 1.0f + ((particle.random ^ 2628172) % 1000) *
0.001f * preset.sizeSpread;
glm::vec3 localRight = right;
glm::vec3 localUp = preset.globalUpVector ? glm::vec3(0, 1, 0) : up;
float angle = particle.angle;
if (glm::abs(angle) >= 0.005f) {
glm::vec3 rotatedRight(glm::cos(angle), -glm::sin(angle), 0.0f);
glm::vec3 rotatedUp(glm::sin(angle), glm::cos(angle), 0.0f);
localRight = right * rotatedRight.x + localUp * rotatedRight.y +
camera.front * rotatedRight.z;
localUp = right * rotatedUp.x + localUp * rotatedUp.y +
camera.front * rotatedUp.z;
}
batch->quad(
particle.position,
right,
preset.globalUpVector ? glm::vec3(0, 1, 0) : up,
localRight,
localUp,
preset.size * scale,
light,
glm::vec3(1.0f),
@@ -106,6 +142,7 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
);
if (particle.lifetime <= 0.0f) {
iter = vec.erase(iter);
emitter.refCount--;
} else {
iter++;
}
@@ -128,19 +165,15 @@ void ParticlesRenderer::render(const Camera& camera, float delta) {
auto iter = emitters.begin();
while (iter != emitters.end()) {
auto& emitter = *iter->second;
if (emitter.isDead() && !emitter.isReferred()) {
// destruct Emitter only when there is no particles spawned by it
iter = emitters.erase(iter);
continue;
}
auto texture = emitter.getTexture();
const auto& found = particles.find(texture);
std::vector<Particle>* vec;
if (found == particles.end()) {
if (emitter.isDead()) {
// destruct Emitter only when there is no particles spawned by it
iter = emitters.erase(iter);
continue;
}
vec = &particles[texture];
} else {
vec = &found->second;
}
vec = &particles[texture];
emitter.update(delta, camera.position, *vec);
iter++;
}