#![allow(dead_code)]
use std::f32::consts::PI;
pub fn vec3_add(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
[a[0] + b[0], a[1] + b[1], a[2] + b[2]]
}
pub fn vec3_sub(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
[a[0] - b[0], a[1] - b[1], a[2] - b[2]]
}
pub fn vec3_scale(a: [f32; 3], s: f32) -> [f32; 3] {
[a[0] * s, a[1] * s, a[2] * s]
}
pub fn vec3_dot(a: [f32; 3], b: [f32; 3]) -> f32 {
a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
}
pub fn vec3_cross(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
[
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]
}
pub fn vec3_len(a: [f32; 3]) -> f32 {
(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]).sqrt()
}
pub fn vec3_norm(a: [f32; 3]) -> [f32; 3] {
let len = vec3_len(a);
if len < 1e-12 {
[0.0, 0.0, 0.0]
} else {
vec3_scale(a, 1.0 / len)
}
}
pub fn vec3_lerp(a: [f32; 3], b: [f32; 3], t: f32) -> [f32; 3] {
[
a[0] + (b[0] - a[0]) * t,
a[1] + (b[1] - a[1]) * t,
a[2] + (b[2] - a[2]) * t,
]
}
pub fn vec3_angle(a: [f32; 3], b: [f32; 3]) -> f32 {
let dot = vec3_dot(a, b);
let lens = vec3_len(a) * vec3_len(b);
if lens < 1e-12 {
return 0.0;
}
(dot / lens).clamp(-1.0, 1.0).acos()
}
pub fn vec3_reflect(a: [f32; 3], n: [f32; 3]) -> [f32; 3] {
let d = 2.0 * vec3_dot(a, n);
vec3_sub(a, vec3_scale(n, d))
}
pub fn vec3_max(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
[a[0].max(b[0]), a[1].max(b[1]), a[2].max(b[2])]
}
pub fn vec3_perp(a: [f32; 3]) -> [f32; 3] {
if a[0].abs() <= a[1].abs() && a[0].abs() <= a[2].abs() {
vec3_cross(a, [1.0, 0.0, 0.0])
} else if a[1].abs() <= a[2].abs() {
vec3_cross(a, [0.0, 1.0, 0.0])
} else {
vec3_cross(a, [0.0, 0.0, 1.0])
}
}
pub fn vec3_neg(a: [f32; 3]) -> [f32; 3] {
[-a[0], -a[1], -a[2]]
}
pub fn vec3_pi() -> f32 {
PI
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec3_add() {
let r = vec3_add([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);
assert!((r[0] - 5.0).abs() < 1e-6);
assert!((r[1] - 7.0).abs() < 1e-6);
assert!((r[2] - 9.0).abs() < 1e-6);
}
#[test]
fn test_vec3_sub() {
let r = vec3_sub([10.0, 5.0, 3.0], [1.0, 2.0, 3.0]);
assert!((r[0] - 9.0).abs() < 1e-6);
assert!((r[1] - 3.0).abs() < 1e-6);
assert!((r[2]).abs() < 1e-6);
}
#[test]
fn test_vec3_scale() {
let r = vec3_scale([1.0, 2.0, 3.0], 2.0);
assert!((r[0] - 2.0).abs() < 1e-6);
assert!((r[1] - 4.0).abs() < 1e-6);
assert!((r[2] - 6.0).abs() < 1e-6);
}
#[test]
fn test_vec3_dot() {
let d = vec3_dot([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
assert!(d.abs() < 1e-6);
let d2 = vec3_dot([1.0, 2.0, 3.0], [4.0, 5.0, 6.0]);
assert!((d2 - 32.0).abs() < 1e-6);
}
#[test]
fn test_vec3_cross() {
let r = vec3_cross([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
assert!((r[0]).abs() < 1e-6);
assert!((r[1]).abs() < 1e-6);
assert!((r[2] - 1.0).abs() < 1e-6);
}
#[test]
fn test_vec3_len() {
let l = vec3_len([3.0, 4.0, 0.0]);
assert!((l - 5.0).abs() < 1e-6);
}
#[test]
fn test_vec3_norm() {
let n = vec3_norm([3.0, 0.0, 0.0]);
assert!((n[0] - 1.0).abs() < 1e-6);
let z = vec3_norm([0.0, 0.0, 0.0]);
assert!(z[0].abs() < 1e-6);
}
#[test]
fn test_vec3_lerp() {
let r = vec3_lerp([0.0, 0.0, 0.0], [2.0, 4.0, 6.0], 0.5);
assert!((r[0] - 1.0).abs() < 1e-6);
assert!((r[1] - 2.0).abs() < 1e-6);
assert!((r[2] - 3.0).abs() < 1e-6);
}
#[test]
fn test_vec3_angle() {
use std::f32::consts::FRAC_PI_2;
let a = vec3_angle([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
assert!((a - FRAC_PI_2).abs() < 1e-5);
}
#[test]
fn test_vec3_reflect() {
let r = vec3_reflect([0.0, -1.0, 0.0], [0.0, 1.0, 0.0]);
assert!((r[1] - 1.0).abs() < 1e-6);
}
}