Skip to content

Commit

Permalink
scene: basic support on rope particle
Browse files Browse the repository at this point in the history
  • Loading branch information
catsout committed May 4, 2022
1 parent a62bf81 commit e47e723
Show file tree
Hide file tree
Showing 23 changed files with 614 additions and 296 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ make
- [ ] Visualization
- [x] Particle System
- [x] Renderers
- [ ] Rope
- [x] Emitters
- [ ] Duration
- [x] Initializers
Expand Down
35 changes: 19 additions & 16 deletions src/backend_scene/wallpaper/Particle/Particle.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
#pragma once

namespace wallpaper {
namespace wallpaper
{

struct Particle {
float position[3] {0.0f};
float position[3] { 0.0f };

float color[3] {1.0f, 1.0f, 1.0f};
float colorInit[3] {1.0f, 1.0f, 1.0f};
float color[3] { 1.0f, 1.0f, 1.0f };
float colorInit[3] { 1.0f, 1.0f, 1.0f };

float alpha {1.0f};
float alphaInit {1.0f};
float alpha { 1.0f };
float alphaInit { 1.0f };

float size {20};
float sizeInit {20};
float size { 20 };
float sizeInit { 20 };

float lifetime {1.0f};
float lifetimeInit {1.0f};
float lifetime { 1.0f };
float lifetimeInit { 1.0f };

float rotation[3] {0.0f, 0.0f, 0.0f}; // radian z x y
float velocity[3] {0.0f, 0.0f, 0.0f};
float acceleration[3] {0.0f, 0.0f, 0.0f};
float angularVelocity[3] {0.0f, 0.0f, 0.0f};
float angularAcceleration[3] {0.0f, 0.0f, 0.0f};
float rotation[3] { 0.0f, 0.0f, 0.0f }; // radian z x y
float velocity[3] { 0.0f, 0.0f, 0.0f };
float acceleration[3] { 0.0f, 0.0f, 0.0f };
float angularVelocity[3] { 0.0f, 0.0f, 0.0f };
float angularAcceleration[3] { 0.0f, 0.0f, 0.0f };

bool mark_new { true };
};
}
} // namespace wallpaper
191 changes: 116 additions & 75 deletions src/backend_scene/wallpaper/Particle/ParticleEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,95 +4,136 @@
#include "Utils/Logging.h"
#include <random>
#include <array>
#include <tuple>

using namespace wallpaper;

static float GetRandomIn(float min, float max, float random) {
return min + (max - min)*random;
}

typedef std::function<Particle()> GenParticleOp;
typedef std::function<Particle()> SpwanOp;

int32_t FindLastParticle(const std::vector<Particle>& ps, int32_t last) {
for(int32_t i=last;i<ps.size();i++) {
if(!ParticleModify::LifetimeOk(ps[i]))
return i;
}
return -1;
namespace
{
inline float GetRandomIn(float min, float max, float random) { return min + (max - min) * random; }

inline std::tuple<uint32_t, bool> FindLastParticle(Span<const Particle> ps, uint32_t last) {
for (uint32_t i = last; i < ps.size(); i++) {
if (! ParticleModify::LifetimeOk(ps[i])) return { i, true };
}
return { 0, false };
}
uint32_t GetEmitNum(double& timer, float speed) {
double emitDur = 1.0f / speed;
if(emitDur > timer) return 0;
uint32_t num = timer / emitDur;
while(emitDur < timer) timer -= emitDur;
if(timer < 0) timer = 0;
return num;

inline uint32_t GetEmitNum(double& timer, float speed) {
double emitDur = 1.0f / speed;
if (emitDur > timer) return 0;
uint32_t num = timer / emitDur;
while (emitDur < timer) timer -= emitDur;
if (timer < 0) timer = 0;
return num;
}
uint32_t Emitt(std::vector<Particle>& particles, uint32_t num, uint32_t maxcount, SpwanOp Spwan) {
int32_t lastPartcle = 0;
uint32_t i = 0;
for(i=0;i<num;i++) {
lastPartcle = FindLastParticle(particles, lastPartcle);
if(lastPartcle == -1) {
lastPartcle = 0;
if(maxcount == particles.size()) break;
particles.push_back(Spwan());
} else {
particles[lastPartcle] = Spwan();
}
}
return i + 1;
inline uint32_t Emitt(std::vector<Particle>& particles, uint32_t num, uint32_t maxcount, bool sort,
SpwanOp Spwan) {
uint32_t lastPartcle = 0;
bool has_dead = true;
uint32_t i = 0;

for (i = 0; i < num; i++) {
if (has_dead) {
auto [r1, r2] = FindLastParticle(particles, lastPartcle);
lastPartcle = r1;
has_dead = r2;
}
if (has_dead) {
particles[lastPartcle] = Spwan();

} else {
if (maxcount == particles.size()) break;
particles.push_back(Spwan());
}
}

if (sort) {
// old << new << dead
std::stable_sort(particles.begin(), particles.end(), [](const auto& a, const auto& b) {
bool l_a = ParticleModify::LifetimeOk(a);
bool l_b = ParticleModify::LifetimeOk(b);

return (l_a && ! l_b) ||
(l_a && l_b && ! ParticleModify::IsNew(a) && ParticleModify::IsNew(b));
});
}

return i + 1;
}

Particle Spwan(GenParticleOp gen, std::vector<ParticleInitOp>& inis, double duration) {
auto particle = gen();
for(auto& el:inis) el(particle, duration);
return particle;
inline Particle Spwan(GenParticleOp gen, std::vector<ParticleInitOp>& inis, double duration) {
auto particle = gen();
for (auto& el : inis) el(particle, duration);
return particle;
}
} // namespace

ParticleEmittOp ParticleBoxEmitterArgs::MakeEmittOp(ParticleBoxEmitterArgs a) {
double timer {0.0f};
return [a, timer](std::vector<Particle>& ps, std::vector<ParticleInitOp>& inis, uint32_t maxcount, double timepass) mutable {
timer += timepass;
auto GenBox = [&]() {
std::array<float, 3> pos;
for(int32_t i=0;i<3;i++)
pos[i] = GetRandomIn(a.minDistance[i], a.maxDistance[i], (a.randomFn()-0.5f)*2.0f);
auto p = Particle();
ParticleModify::MoveTo(p, pos[0], pos[1], pos[2]);
ParticleModify::MoveMultiply(p, a.directions[0], a.directions[1], a.directions[2]);
ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]);
return p;
};
Emitt(ps, GetEmitNum(timer, a.emitSpeed), maxcount, [&]() {
return Spwan(GenBox, inis, 1.0f/a.emitSpeed);
});
};
double timer { 0.0f };
return [a, timer](std::vector<Particle>& ps,
std::vector<ParticleInitOp>& inis,
uint32_t maxcount,
double timepass) mutable {
timer += timepass;
auto GenBox = [&]() {
std::array<float, 3> pos;
for (int32_t i = 0; i < 3; i++)
pos[i] =
GetRandomIn(a.minDistance[i], a.maxDistance[i], (a.randomFn() - 0.5f) * 2.0f);
auto p = Particle();
ParticleModify::MoveTo(p, pos[0], pos[1], pos[2]);
ParticleModify::MoveMultiply(p, a.directions[0], a.directions[1], a.directions[2]);
ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]);
return p;
};
uint32_t emit_num = GetEmitNum(timer, a.emitSpeed);
emit_num = a.one_per_frame ? 1 : emit_num;
Emitt(ps, emit_num, maxcount, a.sort, [&]() {
return Spwan(GenBox, inis, 1.0f / a.emitSpeed);
});
};
}

ParticleEmittOp ParticleSphereEmitterArgs::MakeEmittOp(ParticleSphereEmitterArgs a) {
using namespace Eigen;
double timer {0.0f};
return [a, timer](std::vector<Particle>& ps, std::vector<ParticleInitOp>& inis, uint32_t maxcount, double timepass) mutable {
timer += timepass;
auto GenSphere = [&]() {
auto p = Particle();
float r = GetRandomIn(a.minDistance, a.maxDistance, a.randomFn());
std::array<double, 3> sp = algorism::GenSphere(a.randomFn);
ParticleModify::MoveTo(p, sp[0], sp[1], sp[2]);
{
ParticleModify::SphereDirectOffset(p, Vector3f::UnitX(), std::asin(p.position[0]) - std::asin(p.position[0]*a.directions[0]));
ParticleModify::SphereDirectOffset(p, Vector3f::UnitY(), std::asin(p.position[1]) - std::asin(p.position[1]*a.directions[1]));
ParticleModify::SphereDirectOffset(p, Vector3f::UnitZ(), std::asin(p.position[2]) - std::asin(p.position[2]*a.directions[2]));
}
ParticleModify::MoveMultiply(p, r, r, r);
ParticleModify::MoveApplySign(p, a.sign[0], a.sign[1], a.sign[2]);
ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]);
return p;
};
Emitt(ps, GetEmitNum(timer, a.emitSpeed), maxcount, [&]() {
return Spwan(GenSphere, inis, 1.0f/a.emitSpeed);
});
};
using namespace Eigen;
double timer { 0.0f };
return [a, timer](std::vector<Particle>& ps,
std::vector<ParticleInitOp>& inis,
uint32_t maxcount,
double timepass) mutable {
timer += timepass;
auto GenSphere = [&]() {
auto p = Particle();
float r = GetRandomIn(a.minDistance, a.maxDistance, a.randomFn());
std::array<double, 3> sp = algorism::GenSphere(a.randomFn);
ParticleModify::MoveTo(p, sp[0], sp[1], sp[2]);
{
ParticleModify::SphereDirectOffset(p,
Vector3f::UnitX(),
std::asin(p.position[0]) -
std::asin(p.position[0] * a.directions[0]));
ParticleModify::SphereDirectOffset(p,
Vector3f::UnitY(),
std::asin(p.position[1]) -
std::asin(p.position[1] * a.directions[1]));
ParticleModify::SphereDirectOffset(p,
Vector3f::UnitZ(),
std::asin(p.position[2]) -
std::asin(p.position[2] * a.directions[2]));
}
ParticleModify::MoveMultiply(p, r, r, r);
ParticleModify::MoveApplySign(p, a.sign[0], a.sign[1], a.sign[2]);
ParticleModify::Move(p, a.orgin[0], a.orgin[1], a.orgin[2]);
return p;
};
uint32_t emit_num = GetEmitNum(timer, a.emitSpeed);
emit_num = a.one_per_frame ? 1 : emit_num;
Emitt(ps, emit_num, maxcount, a.sort, [&]() {
return Spwan(GenSphere, inis, 1.0f / a.emitSpeed);
});
};
}
4 changes: 4 additions & 0 deletions src/backend_scene/wallpaper/Particle/ParticleEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ struct ParticleBoxEmitterArgs {
float emitSpeed;
std::array<float, 3> orgin;
std::function<float()> randomFn;
bool one_per_frame;
bool sort;

static ParticleEmittOp MakeEmittOp(ParticleBoxEmitterArgs);
};
Expand All @@ -45,6 +47,8 @@ struct ParticleSphereEmitterArgs {
std::array<float, 3> orgin;
std::array<int32_t, 3> sign;
std::function<float()> randomFn;
bool one_per_frame;
bool sort;

static ParticleEmittOp MakeEmittOp(ParticleSphereEmitterArgs);
};
Expand Down
3 changes: 3 additions & 0 deletions src/backend_scene/wallpaper/Particle/ParticleModify.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,8 @@ inline void Reset(Particle& p) {
p.size = p.sizeInit;
std::memcpy(p.color, p.colorInit, 3 * sizeof(float));
}
inline void MarkOld(Particle& p) { p.mark_new = false; }

inline bool IsNew(const Particle& p) { return p.mark_new; }
}; // namespace ParticleModify
} // namespace wallpaper
1 change: 1 addition & 0 deletions src/backend_scene/wallpaper/Particle/ParticleSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void ParticleSubSystem::Emitt() {
.time_pass = particleTime };

for (auto& p : info.particles) {
ParticleModify::MarkOld(p);
if (! ParticleModify::LifetimeOk(p)) {
i++;
continue;
Expand Down
Loading

0 comments on commit e47e723

Please sign in to comment.