mraphics_core/geometry/
sphere.rs1use std::f32::consts::PI;
2
3use crate::{CustomIndices, GadgetData, Geometry, GeometryIndices};
4
5pub struct Sphere {
6 pub radius: f32,
7
8 pub phi_start: f32,
9 pub phi_end: f32,
10 pub phi_segments: u16,
11
12 pub theta_start: f32,
13 pub theta_end: f32,
14 pub theta_segments: u16,
15}
16
17impl Sphere {
18 pub fn new() -> Self {
19 Self::default()
20 }
21}
22
23impl Default for Sphere {
24 fn default() -> Self {
25 Self {
26 radius: 1.0,
27 phi_start: 0.0,
28 phi_end: PI * 2.0,
29 phi_segments: 32,
30 theta_start: 0.0,
31 theta_end: PI,
32 theta_segments: 16,
33 }
34 }
35}
36
37impl Geometry for Sphere {
38 fn update_view(&self, view: &mut super::GeometryView) {
39 let mut vertices: Vec<f32> = Vec::new();
40 let mut indices: Vec<u16> = Vec::new();
41
42 let r = self.radius;
43 let phi_unit = (self.phi_end - self.phi_start) / self.phi_segments as f32;
44 let theta_unit = (self.theta_end - self.theta_start) / self.theta_segments as f32;
45
46 for i in 0..=self.theta_segments {
47 let i = i as f32;
48 for j in 0..self.phi_segments {
49 let j = j as f32;
50
51 let phi = self.phi_start + j * phi_unit;
52 let theta = self.theta_start + i * theta_unit;
53
54 vertices.push(r * phi.cos() * theta.sin());
55 vertices.push(r * theta.cos());
56 vertices.push(r * phi.sin() * theta.sin());
57 vertices.push(1.0);
58 }
59 }
60
61 let mut add_plane = |a: u16, b: u16, c: u16, d: u16| {
62 indices.push(a);
63 indices.push(b);
64 indices.push(d);
65
66 indices.push(b);
67 indices.push(c);
68 indices.push(d);
69 };
70
71 for i in 0..self.theta_segments {
72 for j in 0..self.phi_segments {
73 let next = if j + 1 == self.phi_segments { 0 } else { j + 1 };
74
75 if (self.phi_start > 0.0 || self.phi_end < PI * 2.0) && next == 0 {
76 continue;
77 }
78
79 let offset = i * self.phi_segments;
80 let a = offset + j;
81 let b = offset + self.phi_segments + j;
82 let c = offset + self.phi_segments + next;
83 let d = offset + next;
84
85 add_plane(a, b, c, d);
86 }
87 }
88
89 view.reset_vertices();
90
91 view.attributes.push(GadgetData {
92 label: String::from(crate::constants::POSITION_ATTR_LABEL),
93 index: crate::constants::POSITION_ATTR_INDEX,
94 data: Vec::from(bytemuck::cast_slice::<f32, u8>(&vertices)),
95 needs_update_value: true,
96 needs_update_buffer: true,
97 });
98 view.indices = GeometryIndices::CustomU16(CustomIndices::new(indices));
99 }
100}