Skip to main content

proof_engine/math/
mod.rs

1//! Mathematical primitives: functions, force fields, attractors.
2//!
3//! Every visual property in Proof Engine is driven by a `MathFunction`.
4//! Every spatial interaction is modeled as a `ForceField`.
5//! No keyframes. No tweens. Only functions.
6
7pub mod eval;
8pub mod attractors;
9pub mod noise;
10pub mod springs;
11pub mod fields;
12pub mod color;
13pub mod complex;
14pub mod curves;
15pub mod numerical;
16pub mod geometry;
17pub mod statistics;
18pub mod simulation;
19
20pub use eval::MathFunction;
21pub use fields::{ForceField, Falloff, FieldTarget};
22pub use attractors::AttractorType;
23pub use springs::{SpringDamper, Spring3D, SpringDamper3};
24
25
26/// Evaluate a scalar function of time.
27/// `t` = elapsed seconds since engine start.
28/// `input` = chained input value (for composed functions).
29pub fn evaluate(f: &MathFunction, t: f32, input: f32) -> f32 {
30    f.evaluate(t, input)
31}
32
33/// Map a value from [in_min, in_max] to [out_min, out_max].
34#[inline]
35pub fn remap(v: f32, in_min: f32, in_max: f32, out_min: f32, out_max: f32) -> f32 {
36    let t = (v - in_min) / (in_max - in_min);
37    out_min + t * (out_max - out_min)
38}
39
40/// Smooth step (3t² - 2t³).
41#[inline]
42pub fn smoothstep(t: f32) -> f32 {
43    let t = t.clamp(0.0, 1.0);
44    t * t * (3.0 - 2.0 * t)
45}
46
47/// Smoother step (6t⁵ - 15t⁴ + 10t³).
48#[inline]
49pub fn smootherstep(t: f32) -> f32 {
50    let t = t.clamp(0.0, 1.0);
51    t * t * t * (t * (t * 6.0 - 15.0) + 10.0)
52}
53
54/// Lerp two colors.
55#[inline]
56pub fn lerp_color(a: (u8, u8, u8), b: (u8, u8, u8), t: f32) -> (u8, u8, u8) {
57    let t = t.clamp(0.0, 1.0);
58    (
59        (a.0 as f32 + (b.0 as f32 - a.0 as f32) * t) as u8,
60        (a.1 as f32 + (b.1 as f32 - a.1 as f32) * t) as u8,
61        (a.2 as f32 + (b.2 as f32 - a.2 as f32) * t) as u8,
62    )
63}
64
65/// Hsv to RGB.
66pub fn hsv_to_rgb(h: f32, s: f32, v: f32) -> (f32, f32, f32) {
67    if s == 0.0 { return (v, v, v); }
68    let h = h % 360.0;
69    let i = (h / 60.0) as u32;
70    let f = h / 60.0 - i as f32;
71    let p = v * (1.0 - s);
72    let q = v * (1.0 - s * f);
73    let t = v * (1.0 - s * (1.0 - f));
74    match i {
75        0 => (v, t, p),
76        1 => (q, v, p),
77        2 => (p, v, t),
78        3 => (p, q, v),
79        4 => (t, p, v),
80        _ => (v, p, q),
81    }
82}