#![allow(dead_code)]
pub struct ProximityDeformer {
pub source_positions: Vec<[f32; 3]>,
pub influence_radius: f32,
pub strength: f32,
}
pub fn new_proximity_deformer(source: Vec<[f32; 3]>, radius: f32) -> ProximityDeformer {
ProximityDeformer {
source_positions: source,
influence_radius: radius,
strength: 1.0,
}
}
pub fn proximity_nearest_distance(d: &ProximityDeformer, p: [f32; 3]) -> f32 {
d.source_positions
.iter()
.map(|s| ((p[0] - s[0]).powi(2) + (p[1] - s[1]).powi(2) + (p[2] - s[2]).powi(2)).sqrt())
.fold(f32::MAX, f32::min)
}
pub fn proximity_influence(d: &ProximityDeformer, point: [f32; 3]) -> f32 {
if d.influence_radius <= 0.0 {
return 0.0;
}
let dist = proximity_nearest_distance(d, point);
(1.0 - dist / d.influence_radius).clamp(0.0, 1.0)
}
pub fn proximity_deform_vertex(
d: &ProximityDeformer,
p: [f32; 3],
target_normal: [f32; 3],
) -> [f32; 3] {
let infl = proximity_influence(d, p);
let amount = infl * d.strength;
[
p[0] + target_normal[0] * amount,
p[1] + target_normal[1] * amount,
p[2] + target_normal[2] * amount,
]
}
pub fn proximity_count_influenced(d: &ProximityDeformer, points: &[[f32; 3]]) -> usize {
points
.iter()
.filter(|&&p| proximity_influence(d, p) > 0.0)
.count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_proximity_deformer() {
let src = vec![[0.0f32, 0.0, 0.0]];
let d = new_proximity_deformer(src, 2.0);
assert!((d.influence_radius - 2.0).abs() < 1e-6);
}
#[test]
fn test_proximity_nearest_distance_zero() {
let d = new_proximity_deformer(vec![[1.0f32, 0.0, 0.0]], 1.0);
assert!(proximity_nearest_distance(&d, [1.0, 0.0, 0.0]) < 1e-6);
}
#[test]
fn test_proximity_influence_at_source() {
let d = new_proximity_deformer(vec![[0.0f32, 0.0, 0.0]], 2.0);
assert!((proximity_influence(&d, [0.0, 0.0, 0.0]) - 1.0).abs() < 1e-5);
}
#[test]
fn test_proximity_influence_beyond_radius() {
let d = new_proximity_deformer(vec![[0.0f32, 0.0, 0.0]], 1.0);
assert!(proximity_influence(&d, [5.0, 0.0, 0.0]) < 1e-6);
}
#[test]
fn test_proximity_deform_vertex() {
let d = new_proximity_deformer(vec![[0.0f32, 0.0, 0.0]], 2.0);
let out = proximity_deform_vertex(&d, [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
assert!(out[1] > 0.0);
}
#[test]
fn test_proximity_count_influenced() {
let d = new_proximity_deformer(vec![[0.0f32, 0.0, 0.0]], 2.0);
let pts = vec![[0.5f32, 0.0, 0.0], [5.0, 0.0, 0.0]];
assert_eq!(proximity_count_influenced(&d, &pts), 1);
}
}