use std::ops::Range;
use crate::primitive::topology::Polygonal;
pub struct Generate<'a, G, S, P>
where
G: 'a,
{
generator: &'a G,
state: S,
range: Range<usize>,
f: fn(&'a G, &S, usize) -> P,
}
impl<'a, G, S, P> Generate<'a, G, S, P>
where
G: 'a,
{
pub(in crate::primitive) fn new(
generator: &'a G,
state: S,
n: usize,
f: fn(&'a G, &S, usize) -> P,
) -> Self {
Generate {
generator,
state,
range: 0..n,
f,
}
}
}
impl<'a, G, S, P> Iterator for Generate<'a, G, S, P>
where
G: 'a,
{
type Item = P;
fn next(&mut self) -> Option<Self::Item> {
self.range
.next()
.map(|index| (self.f)(self.generator, &self.state, index))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
}
}
pub trait PolygonGenerator {
fn polygon_count(&self) -> usize;
}
pub trait NormalGenerator {
type State: Default;
}
pub trait NormalVertexGenerator: NormalGenerator {
type Output;
fn vertex_with_normal_from(&self, state: &Self::State, index: usize) -> Self::Output;
fn vertex_with_normal_count(&self) -> usize;
}
pub trait VerticesWithNormal: NormalVertexGenerator + Sized {
fn vertices_with_normal(
&self,
) -> Generate<Self, Self::State, <Self as NormalVertexGenerator>::Output> {
self.vertices_with_normal_from(Default::default())
}
fn vertices_with_normal_from(
&self,
state: Self::State,
) -> Generate<Self, Self::State, <Self as NormalVertexGenerator>::Output> {
Generate::new(
self,
state,
self.vertex_with_normal_count(),
Self::vertex_with_normal_from,
)
}
}
impl<G> VerticesWithNormal for G where G: NormalVertexGenerator + Sized {}
pub trait NormalIndexGenerator: PolygonGenerator + NormalVertexGenerator {
type Output: Polygonal<Vertex = usize>;
fn index_for_normal(&self, index: usize) -> <Self as NormalIndexGenerator>::Output;
}
pub trait IndicesForNormal: NormalIndexGenerator + Sized {
fn indices_for_normal(&self) -> Generate<Self, (), <Self as NormalIndexGenerator>::Output> {
Generate::new(self, (), self.polygon_count(), |generator, _, index| {
generator.index_for_normal(index)
})
}
}
impl<G> IndicesForNormal for G where G: NormalIndexGenerator + Sized {}
pub trait NormalPolygonGenerator: PolygonGenerator + NormalGenerator {
type Output: Polygonal;
fn polygon_with_normal_from(&self, state: &Self::State, index: usize) -> Self::Output;
}
pub trait PolygonsWithNormal: NormalPolygonGenerator + Sized {
fn polygons_with_normal(
&self,
) -> Generate<Self, Self::State, <Self as NormalPolygonGenerator>::Output> {
self.polygons_with_normal_from(Default::default())
}
fn polygons_with_normal_from(
&self,
state: Self::State,
) -> Generate<Self, Self::State, <Self as NormalPolygonGenerator>::Output> {
Generate::new(
self,
state,
self.polygon_count(),
Self::polygon_with_normal_from,
)
}
}
impl<G> PolygonsWithNormal for G where G: NormalPolygonGenerator {}
pub trait PositionGenerator {
type State: Default;
}
pub trait PositionVertexGenerator: PositionGenerator {
type Output;
fn vertex_with_position_from(&self, state: &Self::State, index: usize) -> Self::Output;
fn vertex_with_position_count(&self) -> usize;
}
pub trait VerticesWithPosition: PositionVertexGenerator + Sized {
fn vertices_with_position(
&self,
) -> Generate<Self, Self::State, <Self as PositionVertexGenerator>::Output> {
self.vertices_with_position_from(Default::default())
}
fn vertices_with_position_from(
&self,
state: Self::State,
) -> Generate<Self, Self::State, <Self as PositionVertexGenerator>::Output> {
Generate::new(
self,
state,
self.vertex_with_position_count(),
Self::vertex_with_position_from,
)
}
}
impl<G> VerticesWithPosition for G where G: PositionVertexGenerator + Sized {}
pub trait PositionIndexGenerator: PolygonGenerator + PositionVertexGenerator {
type Output: Polygonal<Vertex = usize>;
fn index_for_position(&self, index: usize) -> <Self as PositionIndexGenerator>::Output;
}
pub trait IndicesForPosition: PositionIndexGenerator + Sized {
fn indices_for_position(&self) -> Generate<Self, (), <Self as PositionIndexGenerator>::Output> {
Generate::new(self, (), self.polygon_count(), |generator, _, index| {
generator.index_for_position(index)
})
}
}
impl<G> IndicesForPosition for G where G: PositionIndexGenerator + Sized {}
pub trait PositionPolygonGenerator: PolygonGenerator + PositionGenerator {
type Output: Polygonal;
fn polygon_with_position_from(&self, state: &Self::State, index: usize) -> Self::Output;
}
pub trait PolygonsWithPosition: PositionPolygonGenerator + Sized {
fn polygons_with_position(
&self,
) -> Generate<Self, Self::State, <Self as PositionPolygonGenerator>::Output> {
self.polygons_with_position_from(Default::default())
}
fn polygons_with_position_from(
&self,
state: Self::State,
) -> Generate<Self, Self::State, <Self as PositionPolygonGenerator>::Output> {
Generate::new(
self,
state,
self.polygon_count(),
Self::polygon_with_position_from,
)
}
}
impl<G> PolygonsWithPosition for G where G: PositionPolygonGenerator {}
pub trait UvMapGenerator {
type State: Default;
}
pub trait UvMapPolygonGenerator: PolygonGenerator + UvMapGenerator {
type Output: Polygonal;
fn polygon_with_uv_map_from(
&self,
state: &Self::State,
index: usize,
) -> <Self as UvMapPolygonGenerator>::Output;
}
pub trait PolygonsWithUvMap: Sized + UvMapPolygonGenerator {
fn polygons_with_uv_map(
&self,
) -> Generate<Self, Self::State, <Self as UvMapPolygonGenerator>::Output> {
self.polygons_with_uv_map_from(Default::default())
}
fn polygons_with_uv_map_from(
&self,
state: Self::State,
) -> Generate<Self, Self::State, <Self as UvMapPolygonGenerator>::Output> {
Generate::new(
self,
state,
self.polygon_count(),
Self::polygon_with_uv_map_from,
)
}
}
impl<G> PolygonsWithUvMap for G where G: UvMapPolygonGenerator {}