use rustraight::prelude::*;
fn approx_eq(a: f32, b: f32) -> bool {
(a - b).abs() < 1e-4
}
fn main() {
log_info!("--- Vec3 の基本演算 ---");
let a = Vec3::new(1.0, 0.0, 0.0);
let b = Vec3::new(0.0, 1.0, 0.0);
let z = Vec3::new(0.0, 0.0, 1.0);
assert_eq!(a + b, Vec3::new(1.0, 1.0, 0.0), "加算が不正");
assert_eq!(a - b, Vec3::new(1.0, -1.0, 0.0), "減算が不正");
assert_eq!(a * 2.0, Vec3::new(2.0, 0.0, 0.0), "スカラー倍が不正");
assert_eq!(-a, Vec3::new(-1.0, 0.0, 0.0), "単項マイナスが不正");
assert_eq!(a + Vec3::ZERO, a, "ZEROが加算の単位元でない");
log_info!("加減算・スカラー倍・単項マイナス OK");
log_info!("--- dot / cross / length サニティチェック ---");
assert_eq!(a.dot(b), 0.0, "直交ベクトルのdotが0でない");
assert_eq!(a.cross(b), z, "x cross y が z にならない");
assert_eq!(a.length(), 1.0, "単位ベクトルのlengthが1でない");
log_info!("dot/cross/length OK");
log_info!("--- normalize ---");
let v = Vec3::new(3.0, 4.0, 0.0);
assert_eq!(v.length(), 5.0, "3-4-5三角形のlengthが5でない");
assert!(approx_eq(v.normalize().length(), 1.0), "normalize後のlengthが1に近くない");
log_info!("normalize OK");
log_info!("--- icosphere(頂点/面の重複排除チェック) ---");
for n in 0..=3u32 {
let mesh = icosphere(n);
let factor = 4u32.pow(n) as usize;
let expected_vertices = 2 + 10 * factor;
let expected_faces = 20 * factor;
assert_eq!(
mesh.vertices.len(),
expected_vertices,
"subdivisions={n}: 頂点数が期待値と異なる(重複排除が機能していない可能性)"
);
assert_eq!(mesh.faces.len(), expected_faces, "subdivisions={n}: 面数が期待値と異なる");
for vtx in &mesh.vertices {
assert!(approx_eq(vtx.length(), 1.0), "subdivisions={n}: 単位球面上にない頂点がある");
}
for face in &mesh.faces {
for &idx in face {
assert!((idx as usize) < mesh.vertices.len(), "subdivisions={n}: 範囲外の頂点インデックス");
}
}
log_info!("subdivisions={n}: 頂点{expected_vertices} 面{expected_faces} OK");
}
log_info!("全チェックOK: geometry3d は期待通りに動作している");
}