1use std;
2use crate::{math, vertex};
3use super::*;
4
5pub const fn lines3d_vertex_index_counts (
7 latitude_divisions : u16, longitude_divisions : u16
8) -> (u32, u32) {
9 let latitude_divisions = (latitude_divisions - latitude_divisions % 2) as u32;
10 let longitude_divisions = longitude_divisions as u32;
11 ( 2 + (latitude_divisions - 1) * longitude_divisions, 2 * longitude_divisions * (2 * latitude_divisions - 1) ) }
14
15impl Lines3d {
40 pub fn sphere (index_offset : u32, latitude_divisions : u16, longitude_divisions : u16)
41 -> Self
42 {
43 use std::f32::consts::PI;
44 assert!(2 <= latitude_divisions);
45 assert!(2 <= longitude_divisions);
46 let (num_vertices, num_indices) = lines3d_vertex_index_counts (
47 latitude_divisions, longitude_divisions);
48 let latitude_divisions = (latitude_divisions - latitude_divisions % 2) as u32;
49 let hemisphere_latitude_divisions = latitude_divisions / 2;
50 let longitude_divisions = longitude_divisions as u32;
51 let num_parallels = latitude_divisions - 1;
52 let num_meridians = longitude_divisions;
53 let latitude_angle = PI / latitude_divisions as f32;
54 let longitude_angle = 2.0 * (PI / longitude_divisions as f32);
55 let (mut vertices, mut indices) = {
56 let mut vertices =
57 Vec::<vertex::Vert3dInstanced>::with_capacity (num_vertices as usize);
58 let mut indices = Vec::<u32>::with_capacity (num_indices as usize);
59 let Lines3d {
60 vertices: mut hemisphere_vertices, indices: mut hemisphere_indices
61 } = Lines3d::hemisphere (
62 index_offset,
63 hemisphere_latitude_divisions as u16,
64 longitude_divisions as u16
65 );
66 vertices.append (&mut hemisphere_vertices);
67 indices.append (&mut hemisphere_indices);
68 (vertices, indices)
69 };
70 let south_pole_index = index_offset + vertices.len() as u32;
71 vertices.push (vertex::Vert3dInstanced {
73 inst_position: (-1.0 * math::Vector3::<f32>::unit_z()).into_array()
74 });
75 for i in 0..num_parallels / 2 {
77 let i = i as f32 + 1.0;
78 let v = *math::Rotation3::from_angle_x (math::Rad (-i * latitude_angle))
79 * (-1.0 * math::Vector3::<f32>::unit_z());
80 for j in 0..num_meridians {
81 let j = j as f32;
82 let w = *math::Rotation3::from_angle_z (math::Rad (j * longitude_angle)) * v;
83 vertices.push (vertex::Vert3dInstanced { inst_position: w.into_array() });
85 }
86 }
87 debug_assert_eq!(vertices.len(), num_vertices as usize);
88
89 for i in 0..num_meridians {
91 indices.push (south_pole_index);
92 indices.push (south_pole_index + 1 + i);
93 }
94 for i in hemisphere_latitude_divisions..num_parallels {
97 let parallel_base_index = index_offset + 2 + i * num_meridians;
98 for j in 0..num_meridians {
99 indices.push (parallel_base_index + j);
100 indices.push (parallel_base_index + (j + 1) % num_meridians);
101 indices.push (parallel_base_index + j);
102 if i < num_parallels-1 {
103 indices.push (parallel_base_index + j + num_meridians);
105 } else {
106 indices.push (south_pole_index - num_meridians + j);
108 }
109 }
110 }
111 debug_assert_eq!(indices.len(), num_indices as usize);
112
113 Lines3d { vertices, indices }
114 }
115}