use glam::Vec3;
#[inline(always)]
pub fn modifier_repeat_infinite(point: Vec3, spacing: Vec3) -> Vec3 {
Vec3::new(
spacing.x.mul_add(-(point.x / spacing.x).round(), point.x),
spacing.y.mul_add(-(point.y / spacing.y).round(), point.y),
spacing.z.mul_add(-(point.z / spacing.z).round(), point.z),
)
}
#[inline(always)]
pub fn modifier_repeat_infinite_rk(point: Vec3, spacing: Vec3, recip_spacing: Vec3) -> Vec3 {
Vec3::new(
spacing
.x
.mul_add(-(point.x * recip_spacing.x).round(), point.x),
spacing
.y
.mul_add(-(point.y * recip_spacing.y).round(), point.y),
spacing
.z
.mul_add(-(point.z * recip_spacing.z).round(), point.z),
)
}
#[inline(always)]
pub fn modifier_repeat_finite(point: Vec3, count: [u32; 3], spacing: Vec3) -> Vec3 {
let limit = Vec3::new(count[0] as f32, count[1] as f32, count[2] as f32) * 0.5;
let cell = (point / spacing).round().clamp(-limit, limit);
point - cell * spacing
}
#[inline(always)]
pub fn modifier_repeat_x(point: Vec3, spacing: f32) -> Vec3 {
Vec3::new(
spacing.mul_add(-(point.x / spacing).round(), point.x),
point.y,
point.z,
)
}
#[inline(always)]
pub fn modifier_repeat_y(point: Vec3, spacing: f32) -> Vec3 {
Vec3::new(
point.x,
spacing.mul_add(-(point.y / spacing).round(), point.y),
point.z,
)
}
#[inline(always)]
pub fn modifier_repeat_z(point: Vec3, spacing: f32) -> Vec3 {
Vec3::new(
point.x,
point.y,
spacing.mul_add(-(point.z / spacing).round(), point.z),
)
}
#[inline(always)]
pub fn modifier_repeat_polar(point: Vec3, count: u32) -> Vec3 {
let angle = point.z.atan2(point.x);
let radius = point.x.hypot(point.z);
let sector = std::f32::consts::TAU / count as f32;
let sector_angle = sector.mul_add(-(angle / sector).round(), angle);
let (s, c) = sector_angle.sin_cos();
Vec3::new(radius * c, point.y, radius * s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_repeat_equivalence() {
let p = Vec3::new(3.2, 0.0, 0.0);
let s = Vec3::splat(2.0);
let r = modifier_repeat_infinite(p, s);
assert!((r.x - (-0.8)).abs() < 1e-6);
}
#[test]
fn test_repeat_infinite_origin() {
let spacing = Vec3::splat(2.0);
let result = modifier_repeat_infinite(Vec3::ZERO, spacing);
assert!((result - Vec3::ZERO).length() < 0.0001);
}
#[test]
fn test_repeat_finite_center() {
let count = [3, 3, 3];
let spacing = Vec3::splat(2.0);
let result = modifier_repeat_finite(Vec3::ZERO, count, spacing);
assert!((result - Vec3::ZERO).length() < 0.0001);
}
#[test]
fn test_repeat_x() {
let point = Vec3::new(3.2, 1.0, 2.0);
let result = modifier_repeat_x(point, 2.0);
assert!((result.x - (-0.8)).abs() < 0.0001);
assert!((result.y - 1.0).abs() < 0.0001);
assert!((result.z - 2.0).abs() < 0.0001);
}
#[test]
fn test_repeat_polar() {
let point = Vec3::new(1.0, 0.0, 0.0);
let result = modifier_repeat_polar(point, 6);
assert!((result.y).abs() < 0.0001);
}
}