use std::collections::VecDeque; use std::marker::PhantomData; /// A polygon with 4 points. Maps to `GL_QUADS` #[derive(Clone, Debug, PartialEq, Eq, Copy)] pub struct Quad { /// the first point of a quad pub x: T, /// the second point of a quad pub y: T, /// the third point of a quad pub z: T, /// the fourth point of a quad pub w: T, } impl Quad { /// create a new `Quad` with supplied vertices pub fn new(v0: T, v1: T, v2: T, v3: T) -> Self { Quad { x: v0, y: v1, z: v2, w: v3, } } } /// A polygon with 3 points. Maps to `GL_TRIANGLE` #[derive(Clone, Debug, PartialEq, Eq, Copy)] pub struct Triangle { /// the first point of a triangle pub x: T, /// the second point of a triangle pub y: T, /// the third point of a triangle pub z: T, } impl Triangle { /// create a new `Triangle` with supplied vertcies pub fn new(v0: T, v1: T, v2: T) -> Self { Triangle { x: v0, y: v1, z: v2, } } } /// This is All-the-types container. This exists since some generators /// produce both `Triangles` and `Quads`. #[derive(Debug, Clone, PartialEq, Copy)] pub enum Polygon { /// A wraped triangle PolyTri(Triangle), /// A wraped quad PolyQuad(Quad), } /// The core mechanism of `Vertices` trait. This is a mechanism for unwraping /// a polygon extracting all of the vertices that it bound together. pub trait EmitVertices { /// Consume a polygon, each /// vertex is emitted to the parent function by calling the supplied /// lambda function fn emit_vertices(self, F) where F: FnMut(T); } impl EmitVertices for Line { fn emit_vertices(self, mut emit: F) where F: FnMut(T), { let Line { x, y } = self; emit(x); emit(y); } } impl EmitVertices for Triangle { fn emit_vertices(self, mut emit: F) where F: FnMut(T), { let Triangle { x, y, z } = self; emit(x); emit(y); emit(z); } } impl EmitVertices for Quad { fn emit_vertices(self, mut emit: F) where F: FnMut(T), { let Quad { x, y, z, w } = self; emit(x); emit(y); emit(z); emit(w); } } impl EmitVertices for Polygon { fn emit_vertices(self, emit: F) where F: FnMut(T), { use self::Polygon::{PolyQuad, PolyTri}; match self { PolyTri(p) => p.emit_vertices(emit), PolyQuad(p) => p.emit_vertices(emit), } } } /// Supplies a way to convert an iterator of polygons to an iterator /// of vertices. Useful for when you need to write the vertices into /// a graphics pipeline. pub trait Vertices { /// Convert a polygon iterator to a vertices iterator. fn vertices(self) -> VerticesIterator; } impl, T: Iterator> Vertices for T { fn vertices(self) -> VerticesIterator { VerticesIterator { source: self, buffer: VecDeque::new(), } } } /// an iterator that breaks a polygon down into its individual /// verticies. pub struct VerticesIterator { source: SRC, buffer: VecDeque, } impl, SRC: Iterator> Iterator for VerticesIterator { type Item = V; fn next(&mut self) -> Option { loop { match self.buffer.pop_front() { Some(v) => return Some(v), None => (), } match self.source.next() { Some(p) => p.emit_vertices(|v| self.buffer.push_back(v)), None => return None, } } } } /// equivalent of `map` but per-vertex pub trait MapVertex { /// `Output` should be a a container of the same shape of the type /// It's internal values should reflect any transformation the map did. type Output; /// map a function to each vertex in polygon creating a new polygon fn map_vertex(self, F) -> Self::Output where F: FnMut(T) -> U; } impl MapVertex for Line { type Output = Line; fn map_vertex(self, mut map: F) -> Line where F: FnMut(T) -> U, { let Line { x, y } = self; Line { x: map(x), y: map(y), } } } impl MapVertex for Triangle { type Output = Triangle; fn map_vertex(self, mut map: F) -> Triangle where F: FnMut(T) -> U, { let Triangle { x, y, z } = self; Triangle { x: map(x), y: map(y), z: map(z), } } } impl MapVertex for Quad { type Output = Quad; fn map_vertex(self, mut map: F) -> Quad where F: FnMut(T) -> U, { let Quad { x, y, z, w } = self; Quad { x: map(x), y: map(y), z: map(z), w: map(w), } } } impl MapVertex for Polygon { type Output = Polygon; fn map_vertex(self, map: F) -> Polygon where F: FnMut(T) -> U, { use self::Polygon::{PolyQuad, PolyTri}; match self { PolyTri(p) => PolyTri(p.map_vertex(map)), PolyQuad(p) => PolyQuad(p.map_vertex(map)), } } } /// This acts very similar to a vertex shader. It gives a way to manipulate /// and modify the vertices in a polygon. This is useful if you need to scale /// the mesh using a matrix multiply, or just for modifying the type of each /// vertex. pub trait MapToVertices: Sized { /// `Output` should be a a container of the same shape of the type /// It's internal values should reflect any transformation the map did. type Output; /// from a iterator of polygons, produces a iterator of polygons. Each /// vertex in the process is modified with the suppled function. fn vertex(self, map: F) -> MapToVerticesIter where F: FnMut(T) -> U; } impl, T: Iterator> MapToVertices for T { type Output = P; fn vertex(self, map: F) -> MapToVerticesIter where F: FnMut(VIn) -> VOut, { MapToVerticesIter { src: self, f: map, phantom: PhantomData, } } } pub struct MapToVerticesIter U> { src: SRC, f: F, phantom: PhantomData<(T, U)>, } impl< 'a, P, POut: MapVertex, SRC: Iterator, T, U, F: FnMut(T) -> U, > Iterator for MapToVerticesIter { type Item = P; fn size_hint(&self) -> (usize, Option) { self.src.size_hint() } fn next(&mut self) -> Option

{ self.src.next().map(|x| x.map_vertex(|x| (self.f)(x))) } } /// Represents a line #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash)] pub struct Line { /// the first point pub x: T, /// The second point pub y: T, } impl Line { /// Create a new line using point x and y pub fn new(x: T, y: T) -> Self { Line { x: x, y: y } } } /// Convert a Polygon into it's fragments pub trait EmitLines { /// The Vertex defines the corners of a Polygon type Vertex; /// convert a polygon into lines, each line is emitted via /// calling of the callback of `emit` This allow for /// a variable amount of lines to be returned fn emit_lines(self, emit: E) where E: FnMut(Line); } impl EmitLines for Triangle { type Vertex = T; fn emit_lines(self, mut emit: E) where E: FnMut(Line), { emit(Line::new(self.x.clone(), self.y.clone())); emit(Line::new(self.y, self.z.clone())); emit(Line::new(self.z, self.x)); } } impl EmitLines for Quad { type Vertex = T; fn emit_lines(self, mut emit: E) where E: FnMut(Line), { emit(Line::new(self.x.clone(), self.y.clone())); emit(Line::new(self.y, self.z.clone())); emit(Line::new(self.z, self.w.clone())); emit(Line::new(self.w, self.x)); } } impl EmitLines for Polygon { type Vertex = T; fn emit_lines(self, emit: E) where E: FnMut(Line), { match self { Polygon::PolyTri(x) => x.emit_lines(emit), Polygon::PolyQuad(x) => x.emit_lines(emit), } } } /// Creates an LinesIterator from another Iterator pub trait Lines: Sized { /// The type of each point in the lines type Vertex; /// Convert the iterator into a LinesIterator fn lines(self) -> LinesIterator; } impl Lines for T where T: Iterator, P: EmitLines, { type Vertex = V; fn lines(self) -> LinesIterator { LinesIterator { source: self, buffer: VecDeque::new(), } } } /// An iterator that turns Polygons into an Iterator of Lines pub struct LinesIterator { source: I, buffer: VecDeque>, } impl Iterator for LinesIterator where I: Iterator, P: EmitLines, { type Item = Line; fn size_hint(&self) -> (usize, Option) { let (n, _) = self.source.size_hint(); (n, None) } fn next(&mut self) -> Option> { loop { match self.buffer.pop_front() { Some(v) => return Some(v), None => (), } match self.source.next() { Some(p) => p.emit_lines(|v| self.buffer.push_back(v)), None => return None, } } } }