using StereoKit; using System; namespace slash; static class VFX { public static ParticleSystem ps = new(64); public static ParticleSystem leafs = new(64); public static ParticleSystem ripples = new(64); public static void Init() { ps.Init(); leafs.Init(); ripples.Init(); } public static void Play(Vec3 pos) { for (int i = 0; i < 8; i++) { ps.index = (ps.index + 1) % ps.count; Particle particle = ps.particles[ps.index]; particle.pos = pos; particle.vel = Quat.FromAngles(Noise.u_scalar * 360, 0, 0) * Quat.FromAngles(0, Noise.u_scalar * 360, 0) * Vec3.Forward * 3.0f; particle.ori = Quat.Identity; particle.scl = (1.0f / 3) * Maths.smooth_start(Noise.u_scalar); } } public static void Leaf(Vec3 pos) { leafs.index = (leafs.index + 1) % leafs.count; Particle particle = leafs.particles[leafs.index]; particle.state.Step(true); particle.pos = pos; particle.vel = V.XYZ(0, 0, 0); // Quat.FromAngles(Noise.u_scalar * 360, 0, 0) * Quat.FromAngles(0, Noise.u_scalar * 360, 0) * Vec3.Forward * 3.0f; particle.ori = Quat.FromAngles(Noise.s_scalar * 180, 0, 0) * Quat.FromAngles(0, Noise.s_scalar * 180, 0); particle.scl = 0.1f; // (1.0f / 3) * Maths.smooth_start(Noise.u_scalar); } static void Ripple(Vec3 pos) { ripples.index = (ripples.index + 1) % ripples.count; Particle particle = ripples.particles[ripples.index]; particle.state.Step(true); particle.pos = pos; particle.vel = V.XYZ(0, 0, 0); // Quat.FromAngles(Noise.u_scalar * 360, 0, 0) * Quat.FromAngles(0, Noise.u_scalar * 360, 0) * Vec3.Forward * 3.0f; particle.ori = Quat.Identity; particle.scl = 0.1f; // (1.0f / 3) * Maths.smooth_start(Noise.u_scalar); } public static void Frame() { for (int i = 0; i < ps.count; i++) { Particle particle = ps.particles[i]; if (particle.vel.MagnitudeSq > float.Epsilon) { particle.pos += particle.vel * Time.Stepf; particle.vel *= 1 - (3 * Time.Stepf); particle.scl *= 1 - (3 * Time.Stepf); // float scl_rad = particle.scl * 0.5f * 0.333f; // Vec3 next_pos = V.XYZ( // Maths.s_clamp(particle.pos.x, 2 - scl_rad), // Maths.s_clamp(particle.pos.y, 2 - scl_rad), // Maths.s_clamp(particle.pos.z, 2 - scl_rad) // ); // if (next_pos.x != particle.pos.x || next_pos.y != particle.pos.y || next_pos.z != particle.pos.z) // { // particle.pos = next_pos; // particle.vel = Vec3.Zero; // } } } for (int i = 0; i < leafs.count; i++) { Particle particle = leafs.particles[i]; particle.state.Step(particle.pos.y > 0); if (particle.state.state) { particle.pos += particle.vel * Time.Stepf; float x_wind = Maths.smooth_stop(Maths.u_scalar(SKMath.Sin((particle.pos.x * 0.5f) - Time.Totalf))); particle.vel.x += x_wind * Time.Stepf; particle.vel += Vec3.Up * -9.81f * 0.1f * Time.Stepf; particle.ori = Quat.LookDir(particle.vel) * Quat.FromAngles(0, 0, 90); } else { particle.pos.y = 0; particle.vel = Vec3.Zero; if (particle.state.delta == -1) { Ripple(particle.pos); } } } } } public class Particle { public DeltaBool state; public Vec3 pos, vel; public Quat ori; public float scl; public Color col; public Particle() { this.state = new(false); this.pos = Vec3.Zero; this.vel = Vec3.Zero; this.ori = Quat.Identity; this.scl = 0.0f; this.col = Color.White; } } public class ParticleSystem { public Particle[] particles; public int count; public int index; public ParticleSystem(int count) { this.particles = new Particle[count]; this.count = count; this.index = 0; } public void Init() { for (int i = 0; i < particles.Length; i++) { particles[i] = new(); } } }