Skip to content

Commit

Permalink
Roughly implemented subdivision and normal generation for the cylinder
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed May 29, 2017
1 parent 3bcbcc4 commit b845b6d
Showing 1 changed file with 69 additions and 36 deletions.
105 changes: 69 additions & 36 deletions src/cylinder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::cmp;
use std::f32::consts::PI;
use Vertex;
use super::{Quad, Polygon, Triangle};
Expand All @@ -24,8 +25,19 @@ pub struct Cylinder {
u: usize,
h: isize,
sub_u: usize,
sub_h: isize,
}

const TOP: Vertex = Vertex {
pos: [0., 0., 1.],
normal: [0., 0., 1.],
};

const BOT: Vertex = Vertex {
pos: [0., 0., -1.],
normal: [0., 0., -1.],
};

impl Cylinder {
/// Create a new cylinder.
/// `u` is the number of points across the radius.
Expand All @@ -35,26 +47,52 @@ impl Cylinder {
u: 0,
h: -1,
sub_u: u,
sub_h: 1,
}
}

pub fn subdivide(u: usize, h: usize) -> Self {
assert!(u > 1 && h > 0);
Cylinder {
u: 0,
h: -1,
sub_u: u,
sub_h: h as isize,
}
}

fn vert(&self, u: usize, h: isize) -> Vertex {
debug_assert!(u <= self.sub_u);
let a = (u as f32 / self.sub_u as f32) * PI * 2.;
[a.cos(), a.sin(), h as f32]
let n = [a.cos(), a.sin(), 0.];
let (hc, normal) = if h < 0 {
debug_assert_eq!(h, -1);
(0, [0., 0., -1.])
} else if h > self.sub_h {
debug_assert_eq!(h, self.sub_h + 1);
(self.sub_h, [0., 0., 1.])
} else {
(h, n)
};
let z = (hc as f32 / self.sub_h as f32) * 2. - 1.;
Vertex {
pos: [n[0], n[1], z],
normal: n,
}
}
}

impl Iterator for Cylinder {
type Item = Polygon<Vertex>;

fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.sub_u * (2 - self.h) as usize - self.u;
let n = self.sub_u * (1 + self.sub_h - 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 {
if self.h > self.sub_h {
return None;
}
self.u = 0;
Expand All @@ -67,67 +105,62 @@ impl Iterator for Cylinder {
// because sin(2pi) == sin(0), but rounding errors go in the way.
let u1 = self.u % self.sub_u;

let x = self.vert(u, -1);
let y = self.vert(u1, -1);
let z = self.vert(u1, 1);
let w = self.vert(u, 1);
let x = self.vert(u, self.h);
let y = self.vert(u1, self.h);

Some(match self.h {
-1 => Polygon::PolyTri(Triangle::new(x, [0., 0., -1.], y)),
0 => Polygon::PolyQuad(Quad::new(x, y, z, w)),
1 => Polygon::PolyTri(Triangle::new(w, z, [0., 0., 1.])),
_ => unreachable!()
Some(if self.h < 0 {
Polygon::PolyTri(Triangle::new(x, BOT, y))
} else if self.h > self.sub_h {
Polygon::PolyTri(Triangle::new(x, y, TOP))
} else {
let z = self.vert(u1, self.h + 1);
let w = self.vert(u, self.h + 1);
Polygon::PolyQuad(Quad::new(x, y, z, w))
})
}
}

impl SharedVertex<Vertex> for Cylinder {
fn shared_vertex(&self, idx: usize) -> Vertex {
if idx == 0 {
[0., 0., -1.]
BOT
} else if idx == self.shared_vertex_count() - 1 {
[0., 0., 1.]
TOP
} else {
// skip the bottom center
let idx = idx - 1;
let u = idx % self.sub_u;
let h = (idx / self.sub_u) as isize * 2 - 1;
let h = (idx / self.sub_u) as isize - 1;
self.vert(u, h)
}
}

fn shared_vertex_count(&self) -> usize {
2 * self.sub_u + 2
(3 + self.sub_h) as usize * 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 u1 = (idx + 1) % self.sub_u;
match idx / self.sub_u {
0 => {
let base = 1;
let start = 0;
Polygon::PolyTri(Triangle::new(base + u, start, base + u1))
},
1 => {
let base = 1;
Polygon::PolyQuad(Quad::new(base + u,
base + u1,
base + u1 + 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 + u1, end))
},
_ => unreachable!()
let h = (idx / self.sub_u) as isize - 1;
let base = 1 + idx - u;
if h < 0 {
let start = 0;
Polygon::PolyTri(Triangle::new(base + u, start, base + u1))
} else if h > self.sub_h {
let end = self.shared_vertex_count() - 1;
Polygon::PolyTri(Triangle::new(base + u, base + u1, end))
} else {
Polygon::PolyQuad(Quad::new(base + u,
base + u1,
base + u1 + self.sub_u,
base + u + self.sub_u))
}
}

fn indexed_polygon_count(&self) -> usize {
3 * self.sub_u
(2 + self.sub_h) as usize * self.sub_u
}
}

0 comments on commit b845b6d

Please sign in to comment.