rustraight 0.6.4

A simple 2D game library for Rust, inspired by DXLib
// 3D数学ユーティリティ(geometry3d)の動作確認用サンプル。ウィンドウ初期化不要、アセット不要。
//
// 確認対象:
//   Vec3(加減算・スカラー倍・単項マイナス・dot・cross・length・normalize)
//   icosphere(頂点/面の重複排除・単位球面上への配置)
//
// コンソール出力のみで完結するため `cargo run --example 13_geometry3d` でそのまま確認できる。

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 は期待通りに動作している");
}