#![allow(dead_code)]
use std::f32::consts::{PI, TAU};
pub struct SphereParams {
pub radius: f32,
pub subdivisions: u32,
}
pub fn new_sphere_params(radius: f32, subdivisions: u32) -> SphereParams {
SphereParams {
radius,
subdivisions,
}
}
pub fn uv_sphere_vertex(
radius: f32,
lat_idx: u32,
lon_idx: u32,
lat_segments: u32,
lon_segments: u32,
) -> [f32; 3] {
let lat = (lat_idx as f32 / lat_segments as f32) * PI - PI * 0.5;
let lon = (lon_idx as f32 / lon_segments as f32) * TAU;
let x = radius * lat.cos() * lon.cos();
let y = radius * lat.sin();
let z = radius * lat.cos() * lon.sin();
[x, y, z]
}
pub fn uv_sphere_vertex_count(lat_segs: u32, lon_segs: u32) -> usize {
((lat_segs + 1) * (lon_segs + 1)) as usize
}
pub fn uv_sphere_face_count(lat_segs: u32, lon_segs: u32) -> usize {
(lat_segs * lon_segs * 2) as usize
}
pub fn icosphere_vertex_count(subdivisions: u32) -> usize {
10 * 4_usize.pow(subdivisions) + 2
}
pub fn sphere_surface_area(r: f32) -> f32 {
4.0 * PI * r * r
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_sphere_params() {
let s = new_sphere_params(1.5, 3);
assert!((s.radius - 1.5).abs() < 1e-6);
assert_eq!(s.subdivisions, 3);
}
#[test]
fn test_uv_sphere_vertex_on_surface() {
let v = uv_sphere_vertex(2.0, 4, 4, 8, 8);
let r = (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]).sqrt();
assert!((r - 2.0).abs() < 1e-4);
}
#[test]
fn test_uv_sphere_vertex_count() {
let count = uv_sphere_vertex_count(8, 16);
assert_eq!(count, 9 * 17);
}
#[test]
fn test_uv_sphere_face_count() {
let count = uv_sphere_face_count(8, 16);
assert_eq!(count, 8 * 16 * 2);
}
#[test]
fn test_icosphere_vertex_count_0() {
assert_eq!(icosphere_vertex_count(0), 12);
}
#[test]
fn test_icosphere_vertex_count_1() {
assert_eq!(icosphere_vertex_count(1), 42);
}
#[test]
fn test_sphere_surface_area() {
let area = sphere_surface_area(1.0);
assert!((area - 4.0 * PI).abs() < 1e-4);
}
}