Skip to main content

kvas_engine/
procedural.rs

1//! Systems that build or simulate procedural geometry (cloth, voxel smoke and clouds, grass).
2//! They write a `DynamicMesh` that the renderer uploads.
3
4use kvas_ecs::World;
5use serde::Serialize;
6
7/// Stable hash of a component's serialized parameters; used to detect edits that need a rebuild.
8pub fn signature<T: Serialize>(value: &T) -> u64 {
9    serde_json::to_string(value)
10        .unwrap_or_default()
11        .bytes()
12        .fold(0xcbf2_9ce4_8422_2325u64, |h, b| (h ^ b as u64).wrapping_mul(0x0100_0000_01b3))
13}
14
15/// Tiny deterministic random generator (xorshift64*).
16#[derive(Clone)]
17pub struct Rng(u64);
18
19impl Rng {
20    /// Creates a nonzero generator state from any seed, including zero.
21    pub fn new(seed: u64) -> Self {
22        Self(seed.wrapping_mul(0x9e37_79b9_7f4a_7c15) | 1)
23    }
24
25    /// Returns the next deterministic 64-bit pseudorandom value.
26    /// This generator is for procedural content, not cryptographic use.
27    pub fn next_u64(&mut self) -> u64 {
28        self.0 ^= self.0 >> 12;
29        self.0 ^= self.0 << 25;
30        self.0 ^= self.0 >> 27;
31        self.0.wrapping_mul(0x2545_f491_4f6c_dd1d)
32    }
33
34    /// Uniform in 0..1.
35    pub fn f32(&mut self) -> f32 {
36        (self.next_u64() >> 40) as f32 / 16_777_216.0
37    }
38}
39
40/// Runs every procedural system. `simulate` is false in the editor outside Play mode: simulations
41/// then only show their initial state.
42pub fn update(world: &mut World, time: f32, dt: f32, simulate: bool) {
43    crate::meshmod::update(world);
44    crate::paint::update(world, crate::meshmod::assets().as_ref());
45    crate::grass::update(world);
46    crate::tree::update(world);
47    crate::voxel::update_clouds(world, dt, simulate);
48    crate::voxel::update_smoke(world, dt, simulate);
49    crate::cloth::update(world, time, dt, simulate);
50    crate::particles::update(world, time, dt, simulate);
51    crate::water::update_water(world, time);
52    crate::mesh_edit::update(world);
53}