use std;
use crate::{math, vertex};
use super::*;
pub fn lines3d_vertex_index_counts (
latitude_divisions : u16, longitude_divisions : u16
) -> (u32, u32) {
let latitude_divisions = (latitude_divisions - latitude_divisions % 2) as u32;
let longitude_divisions = longitude_divisions as u32;
( 2 + (latitude_divisions - 1) * longitude_divisions, 2 * longitude_divisions * (2 * latitude_divisions - 1) ) }
pub fn sphere (
index_offset : u32, latitude_divisions : u16, longitude_divisions : u16
) -> (Vec <vertex::Vert3dInstanced>, Vec <u32>) {
use std::f32::consts::PI;
assert!(2 <= latitude_divisions);
assert!(2 <= longitude_divisions);
let (num_vertices, num_indices) = lines3d_vertex_index_counts (
latitude_divisions, longitude_divisions);
let latitude_divisions = (latitude_divisions - latitude_divisions % 2) as u32;
let hemisphere_latitude_divisions = latitude_divisions / 2;
let longitude_divisions = longitude_divisions as u32;
let num_parallels = latitude_divisions - 1;
let num_meridians = longitude_divisions;
let latitude_angle = PI / latitude_divisions as f32;
let longitude_angle = 2.0 * (PI / longitude_divisions as f32);
let (mut vertices, mut indices) = {
let mut vertices
= Vec::<vertex::Vert3dInstanced>::with_capacity (num_vertices as usize);
let mut indices = Vec::<u32>::with_capacity (num_indices as usize);
let Lines3d {
vertices: mut hemisphere_vertices, indices: mut hemisphere_indices
} = Lines3d::hemisphere (
index_offset,
hemisphere_latitude_divisions as u16,
longitude_divisions as u16
);
vertices.append (&mut hemisphere_vertices);
indices.append (&mut hemisphere_indices);
(vertices, indices)
};
let south_pole_index = index_offset + vertices.len() as u32;
vertices.push (vertex::Vert3dInstanced {
inst_position: (-1.0 * math::Vector3::<f32>::unit_z()).into_array()
});
for i in 0..num_parallels / 2 {
let i = i as f32 + 1.0;
let v = *math::Rotation3::from_angle_x (math::Rad (-i * latitude_angle))
* (-1.0 * math::Vector3::<f32>::unit_z());
for j in 0..num_meridians {
let j = j as f32;
let w =
*math::Rotation3::from_angle_z (math::Rad (j * longitude_angle)) * v;
vertices.push (vertex::Vert3dInstanced { inst_position: w.into_array() });
}
}
debug_assert_eq!(vertices.len(), num_vertices as usize);
for i in 0..num_meridians {
indices.push (south_pole_index);
indices.push (south_pole_index + 1 + i);
}
for i in hemisphere_latitude_divisions..num_parallels {
let parallel_base_index = index_offset + 2 + i * num_meridians;
for j in 0..num_meridians {
indices.push (parallel_base_index + j);
indices.push (parallel_base_index + (j + 1) % num_meridians);
if i < num_parallels-1 {
indices.push (parallel_base_index + j);
indices.push (parallel_base_index + j + num_meridians);
} else {
indices.push (parallel_base_index + j);
indices.push (south_pole_index - num_meridians + j);
}
}
}
debug_assert_eq!(indices.len(), num_indices as usize);
(vertices, indices)
}