#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
pub struct FlowVector {
pub direction: [f32; 3],
pub magnitude: f32,
}
#[allow(dead_code)]
pub struct FlowField {
pub vectors: Vec<FlowVector>,
}
#[allow(dead_code)]
pub fn new_flow_field(n: usize) -> FlowField {
FlowField {
vectors: vec![
FlowVector {
direction: [1.0, 0.0, 0.0],
magnitude: 0.0
};
n
],
}
}
#[allow(dead_code)]
pub fn set_flow_vector(field: &mut FlowField, i: usize, dir: [f32; 3], magnitude: f32) {
if i < field.vectors.len() {
let len = (dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]).sqrt();
let d = if len < 1e-10 {
[1.0, 0.0, 0.0]
} else {
[dir[0] / len, dir[1] / len, dir[2] / len]
};
field.vectors[i] = FlowVector {
direction: d,
magnitude,
};
}
}
#[allow(dead_code)]
pub fn flow_at_vertex(field: &FlowField, i: usize) -> FlowVector {
if i < field.vectors.len() {
field.vectors[i]
} else {
FlowVector {
direction: [1.0, 0.0, 0.0],
magnitude: 0.0,
}
}
}
#[allow(dead_code)]
pub fn advect_point_on_surface(
point: [f32; 3],
field: &FlowField,
positions: &[[f32; 3]],
dt: f32,
) -> [f32; 3] {
let mut best_idx = 0;
let mut best_dist = f32::MAX;
for (i, &p) in positions.iter().enumerate() {
let dx = point[0] - p[0];
let dy = point[1] - p[1];
let dz = point[2] - p[2];
let d = dx * dx + dy * dy + dz * dz;
if d < best_dist {
best_dist = d;
best_idx = i;
}
}
let fv = flow_at_vertex(field, best_idx);
[
point[0] + fv.direction[0] * fv.magnitude * dt,
point[1] + fv.direction[1] * fv.magnitude * dt,
point[2] + fv.direction[2] * fv.magnitude * dt,
]
}
#[allow(dead_code)]
pub fn smooth_flow_field(field: &FlowField, iterations: usize) -> FlowField {
let mut result = FlowField {
vectors: field.vectors.clone(),
};
let n = result.vectors.len();
for _ in 0..iterations {
let prev = result.vectors.clone();
for i in 0..n {
let left = if i == 0 { n - 1 } else { i - 1 };
let right = (i + 1) % n;
let dx =
(prev[left].direction[0] + prev[i].direction[0] + prev[right].direction[0]) / 3.0;
let dy =
(prev[left].direction[1] + prev[i].direction[1] + prev[right].direction[1]) / 3.0;
let dz =
(prev[left].direction[2] + prev[i].direction[2] + prev[right].direction[2]) / 3.0;
let len = (dx * dx + dy * dy + dz * dz).sqrt().max(1e-10);
result.vectors[i].direction = [dx / len, dy / len, dz / len];
result.vectors[i].magnitude =
(prev[left].magnitude + prev[i].magnitude + prev[right].magnitude) / 3.0;
}
}
result
}
#[allow(dead_code)]
pub fn flow_magnitude_at(field: &FlowField, i: usize) -> f32 {
flow_at_vertex(field, i).magnitude
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_flow_field_size() {
let f = new_flow_field(5);
assert_eq!(f.vectors.len(), 5);
}
#[test]
fn test_set_and_get_flow_vector() {
let mut f = new_flow_field(3);
set_flow_vector(&mut f, 1, [1.0, 0.0, 0.0], 2.5);
let v = flow_at_vertex(&f, 1);
assert!((v.magnitude - 2.5).abs() < 1e-5);
}
#[test]
fn test_flow_direction_normalized() {
let mut f = new_flow_field(3);
set_flow_vector(&mut f, 0, [3.0, 0.0, 0.0], 1.0);
let v = flow_at_vertex(&f, 0);
assert!((v.direction[0] - 1.0).abs() < 1e-5);
}
#[test]
fn test_flow_magnitude_at() {
let mut f = new_flow_field(2);
set_flow_vector(&mut f, 0, [0.0, 1.0, 0.0], 3.0);
assert!((flow_magnitude_at(&f, 0) - 3.0).abs() < 1e-5);
}
#[test]
fn test_advect_point_moves() {
let mut f = new_flow_field(1);
set_flow_vector(&mut f, 0, [1.0, 0.0, 0.0], 1.0);
let pos = vec![[0.0f32, 0.0, 0.0]];
let p = advect_point_on_surface([0.0, 0.0, 0.0], &f, &pos, 1.0);
assert!((p[0] - 1.0).abs() < 1e-5);
}
#[test]
fn test_smooth_flow_field_count() {
let f = new_flow_field(4);
let s = smooth_flow_field(&f, 1);
assert_eq!(s.vectors.len(), 4);
}
#[test]
fn test_flow_at_vertex_oob() {
let f = new_flow_field(2);
let v = flow_at_vertex(&f, 100);
assert!((v.magnitude).abs() < 1e-5);
}
#[test]
fn test_flow_vector_default_magnitude() {
let f = new_flow_field(3);
for v in &f.vectors {
assert!((v.magnitude).abs() < 1e-5);
}
}
#[test]
fn test_smooth_flow_preserves_direction_unit() {
let mut f = new_flow_field(3);
set_flow_vector(&mut f, 0, [1.0, 0.0, 0.0], 1.0);
set_flow_vector(&mut f, 1, [1.0, 0.0, 0.0], 1.0);
set_flow_vector(&mut f, 2, [1.0, 0.0, 0.0], 1.0);
let s = smooth_flow_field(&f, 2);
let v = s.vectors[1];
let len = (v.direction[0] * v.direction[0]
+ v.direction[1] * v.direction[1]
+ v.direction[2] * v.direction[2])
.sqrt();
assert!((len - 1.0).abs() < 1e-4);
}
}