1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::f32::consts::PI;
use cgmath::{InnerSpace, Vector3};
use super::generators::{IndexedPolygon, SharedVertex};
use super::{MapVertex, Quad, Vertex};
#[derive(Clone, Copy)]
pub struct Torus {
idx: usize,
radius: f32,
tubular_radius: f32,
radial_segments: usize,
tubular_segments: usize,
}
impl Torus {
pub fn new(
radius: f32,
tubular_radius: f32,
radial_segments: usize,
tubular_segments: usize,
) -> Self {
assert!(tubular_segments > 2 && radial_segments > 2);
Torus {
idx: 0,
radius,
tubular_radius,
radial_segments,
tubular_segments,
}
}
}
impl Iterator for Torus {
type Item = Quad<Vertex>;
fn next(&mut self) -> Option<Self::Item> {
if self.idx < self.indexed_polygon_count() {
let idx = self.idx;
self.idx += 1;
Some(
self.indexed_polygon(idx)
.map_vertex(|i| self.shared_vertex(i)),
)
} else {
None
}
}
}
impl SharedVertex<Vertex> for Torus {
fn shared_vertex(&self, idx: usize) -> Vertex {
let (h, u) = (
(idx / self.tubular_segments) as f32,
(idx % self.tubular_segments) as f32,
);
let alpha = u * 2. * PI / self.tubular_segments as f32;
let beta = h * 2. * PI / self.radial_segments as f32;
let gamma = self.radius + self.tubular_radius * alpha.cos();
Vertex {
pos: [
gamma * beta.cos(),
self.tubular_radius * alpha.sin(),
-gamma * beta.sin(),
].into(),
normal: Vector3::new(
alpha.cos() * beta.cos(),
alpha.sin(),
-alpha.cos() * beta.sin(),
).normalize()
.into(),
}
}
fn shared_vertex_count(&self) -> usize {
self.tubular_segments * self.radial_segments + 1
}
}
impl IndexedPolygon<Quad<usize>> for Torus {
fn indexed_polygon(&self, idx: usize) -> Quad<usize> {
let ncol = if self.indexed_polygon_count() - idx > self.tubular_segments {
self.tubular_segments as isize
} else {
-((self.indexed_polygon_count() - self.tubular_segments) as isize)
};
let nrow = if idx % self.tubular_segments != self.tubular_segments - 1 {
1isize
} else {
1isize - (self.tubular_segments as isize)
};
let idx = idx as isize;
Quad::new(idx, idx + ncol, idx + nrow + ncol, idx + nrow).map_vertex(|x| x as usize)
}
fn indexed_polygon_count(&self) -> usize {
self.tubular_segments * self.radial_segments
}
}