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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use std::f32::consts::PI;
use super::{Quad, Polygon, Triangle};
use super::generators::{SharedVertex, IndexedPolygon};
#[derive(Clone, Copy)]
pub struct Cylinder {
u: usize,
h: isize,
sub_u: usize,
}
impl Cylinder {
pub fn new(u: usize) -> Self {
Cylinder {
u: 0,
h: -1,
sub_u: u,
}
}
fn vert(&self, u: usize, h: isize) -> (f32, f32, f32) {
let a = (u as f32 / self.sub_u as f32) * PI * 2.;
(a.cos(), a.sin(), h as f32)
}
}
impl Iterator for Cylinder {
type Item = Polygon<(f32, f32, f32)>;
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.sub_u * (2 - self.h) as usize - self.u;
(n, Some(n))
}
fn next(&mut self) -> Option<Self::Item> {
if self.u == self.sub_u {
if self.h == 1 {
return None;
}
self.u = 0;
self.h += 1;
}
let x = self.vert(self.u, self.h);
let y = self.vert(self.u, 1);
let z = self.vert(self.u+1, 1);
let w = self.vert(self.u+1, self.h);
self.u += 1;
Some(match self.h {
-1 => Polygon::PolyTri(Triangle::new(x, (0., 0., -1.), w)),
0 => Polygon::PolyQuad(Quad::new(x, w, z, y)),
1 => Polygon::PolyTri(Triangle::new(x, w, (0., 0., 1.))),
_ => unreachable!()
})
}
}
impl SharedVertex<(f32, f32, f32)> for Cylinder {
fn shared_vertex(&self, idx: usize) -> (f32, f32, f32) {
if idx == 0 {
(0., 0., -1.)
} else if idx == self.shared_vertex_count() - 1 {
(0., 0., 1.)
} else {
let idx = idx - 1;
let u = idx % self.sub_u;
let h = (idx / self.sub_u) as isize * 2 - 1;
self.vert(u, h)
}
}
fn shared_vertex_count(&self) -> usize {
2 * self.sub_u + 2
}
}
impl IndexedPolygon<Polygon<usize>> for Cylinder {
fn indexed_polygon(&self, idx: usize) -> Polygon<usize> {
let u = idx % self.sub_u;
let v = (u + 1) % self.sub_u;
match idx / self.sub_u {
0 => {
let base = 1;
let start = 0;
Polygon::PolyTri(Triangle::new(base + u, start, base + v))
},
1 => {
let base = 1;
Polygon::PolyQuad(Quad::new(base + u,
base + v,
base + v + self.sub_u,
base + u + self.sub_u))
},
2 => {
let base = 1 + self.sub_u;
let end = self.shared_vertex_count() - 1;
Polygon::PolyTri(Triangle::new(base + u, base + v, end))
},
_ => unreachable!()
}
}
fn indexed_polygon_count(&self) -> usize {
3 * self.sub_u
}
}