mraphics_core/geometry/
sphere.rs1use crate::{
2 CustomIndices, Geometry, GeometryIndices, Material, Mesh, Representable, Transformable,
3 Vertices,
4};
5use std::f32::consts::PI;
6
7#[derive(Clone)]
8pub struct Sphere {
9 pub radius: f32,
10
11 pub phi_start: f32,
12 pub phi_end: f32,
13 pub phi_segments: u16,
14
15 pub theta_start: f32,
16 pub theta_end: f32,
17 pub theta_segments: u16,
18
19 pub vertices: Vertices,
20 pub indices: Vec<u16>,
21}
22
23impl Sphere {
24 pub fn new() -> Self {
25 Self::default()
26 }
27}
28
29impl Default for Sphere {
30 fn default() -> Self {
31 Self {
32 radius: 1.0,
33 phi_start: 0.0,
34 phi_end: PI * 2.0,
35 phi_segments: 32,
36 theta_start: 0.0,
37 theta_end: PI,
38 theta_segments: 16,
39 vertices: Vertices::new(),
40 indices: Vec::new(),
41 }
42 }
43}
44
45impl Geometry for Sphere {
46 fn init_view(&self, view: &mut super::GeometryView) {
47 view.add_attribute(
48 crate::constants::POSITION_ATTR_LABEL,
49 crate::constants::POSITION_ATTR_INDEX,
50 Vec::<u8>::new(),
51 );
52 }
53
54 fn update_view(&self, view: &mut super::GeometryView) {
55 self.vertices.update_geometry_view(view);
56
57 view.get_attribute_mut(crate::constants::POSITION_ATTR_LABEL)
58 .unwrap()
59 .needs_update_buffer = true;
60 view.indices = GeometryIndices::CustomU16(CustomIndices::new((&self.indices).to_owned()));
61 }
62
63 fn update(&mut self) {
64 self.vertices = Vertices::new();
65 self.indices = Vec::new();
66
67 let r = self.radius;
68 let phi_unit = (self.phi_end - self.phi_start) / self.phi_segments as f32;
69 let theta_unit = (self.theta_end - self.theta_start) / self.theta_segments as f32;
70
71 for i in 0..=self.theta_segments {
72 let i = i as f32;
73 for j in 0..self.phi_segments {
74 let j = j as f32;
75
76 let phi = self.phi_start + j * phi_unit;
77 let theta = self.theta_start + i * theta_unit;
78
79 self.vertices.data.push([
80 r * phi.cos() * theta.sin(),
81 r * theta.cos(),
82 r * phi.sin() * theta.sin(),
83 1.0,
84 ]);
85 }
86 }
87
88 let mut add_plane = |a: u16, b: u16, c: u16, d: u16| {
89 self.indices.push(a);
90 self.indices.push(b);
91 self.indices.push(d);
92
93 self.indices.push(b);
94 self.indices.push(c);
95 self.indices.push(d);
96 };
97
98 for i in 0..self.theta_segments {
99 for j in 0..self.phi_segments {
100 let next = if j + 1 == self.phi_segments { 0 } else { j + 1 };
101
102 if (self.phi_start > 0.0 || self.phi_end < PI * 2.0) && next == 0 {
103 continue;
104 }
105
106 let offset = i * self.phi_segments;
107 let a = offset + j;
108 let b = offset + self.phi_segments + j;
109 let c = offset + self.phi_segments + next;
110 let d = offset + next;
111
112 add_plane(a, b, c, d);
113 }
114 }
115 }
116}
117
118impl<M: Material> Representable for Mesh<Sphere, M> {
119 type Intermediate = Vertices;
120
121 fn as_intermediate(&self) -> Self::Intermediate {
122 self.geometry.vertices.clone()
123 }
124
125 fn update_from_intermediate(&mut self, repr: &Self::Intermediate) {
126 self.geometry.vertices = repr.clone();
127 }
128}
129
130impl<M: Material> Transformable for Mesh<Sphere, M> {
131 fn apply_transform<Trans: Fn(&[f32; 3]) -> [f32; 3]>(
132 &self,
133 transform: Trans,
134 ) -> Self::Intermediate {
135 self.geometry.vertices.apply_transform(|vertex| {
136 let transformed = transform(&[vertex[0], vertex[1], vertex[2]]);
137 [transformed[0], transformed[1], transformed[2], 1.0]
138 })
139 }
140}