use crate::{Aabb, Consume, Cube, Point, Triangle, Quad};
use std::sync::mpsc::Sender;
pub trait Consumer<T> {
fn consumer(&self) -> Consume<Self, T>;
fn consume_all(&mut self, data: impl Iterator<Item = T>) {
let f = self.consumer();
for d in data {f(self, d)}
}
}
impl<T> Consumer<T> for Vec<T> {
fn consumer(&self) -> Consume<Self, T> {Vec::push}
}
impl<T> Consumer<T> for Sender<T> {
fn consumer(&self) -> Consume<Self, T> {
|s, d| s.send(d).expect("Sending data on channel failed")
}
}
impl<T, Material> Consumer<(Quad, Material)> for T
where T: Consumer<(Triangle, Material)>, Material: Copy
{
fn consumer(&self) -> Consume<Self, (Quad, Material)> {
|scene, (quad, mat)| {
let f = scene.consumer();
let (a, b) = crate::quad::quad_to_triangles(quad);
f(scene, (a, mat));
f(scene, (b, mat));
}
}
}
impl<T, Material> Consumer<(Cube, Material)> for T
where T: Consumer<(Quad, Material)>, Material: Copy
{
fn consumer(&self) -> Consume<Self, (Cube, Material)> {
use crate::cube::*;
|scene, (cube, mat)| {
let f = scene.consumer();
let quads = [
cube_far(&cube),
cube_near(&cube),
cube_top(&cube),
cube_bottom(&cube),
cube_left(&cube),
cube_right(&cube),
];
for q in quads {f(scene, (q, mat))}
}
}
}
impl<T, Material> Consumer<(Aabb, Material)> for T
where T: Consumer<(Cube, Material)>
{
fn consumer(&self) -> Consume<Self, (Aabb, Material)> {
|scene, (aabb, mat)| {
let f = scene.consumer();
let c = crate::cube::aabb_to_cube(aabb);
f(scene, (c, mat));
}
}
}
impl<T, Material> Consumer<(Point, Material)> for T
where T: Consumer<(Aabb, Material)>, Material: Copy
{
fn consumer(&self) -> Consume<Self, (Point, Material)> {
use vecmath::vec3_add;
|scene, (pt, mat)| {
let f = scene.consumer();
f(scene, ((pt, vec3_add(pt, [1.0; 3])), mat));
}
}
}
macro_rules! integer {
($($t:ty),*) => {$(
impl<T, Material> Consumer<(Point<$t>, Material)> for T
where T: Consumer<(Point, Material)>, Material: Copy
{
fn consumer(&self) -> Consume<Self, (Point<$t>, Material)> {
|scene, (pt, mat)| {
let f = scene.consumer();
f(scene, ([pt[0] as f32, pt[1] as f32, pt[2] as f32], mat));
}
}
}
)*}
}
integer!{u8, u16, u32, u64, i8, i16, i32, i64}