mraphics_core/geometry/
sphere.rs

1use 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}