use std::fmt::Debug;
use std::fmt::Display;
use std::ops::Add;
use std::ops::Mul;
use num::Float;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BlockDims<F>
where F: Float
{
pub base: [F; 3],
pub size: F,
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Block<F>
where F: Float,
{
pub dims: BlockDims<F>,
pub subdivisions: usize,
}
impl<F> Block<F>
where F: Float
{
pub fn from(base: [F; 3], size: F, subdivisions: usize) -> Self {
Block {
dims: BlockDims {
base: base,
size: size,
},
subdivisions: subdivisions,
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Mesh<F>
where
F: Float,
{
pub positions: Vec<F>,
pub normals: Vec<F>,
pub triangle_indices: Vec<usize>,
}
impl<F> Mesh<F>
where
F: Float,
{
pub fn num_tris(&self) -> usize {
self.triangle_indices.len() / 3
}
pub fn tris(&self) -> Vec<Triangle<F>> {
let mut tris: Vec<Triangle<F>> = vec![];
for i in 0..self.num_tris() {
let i1 = self.triangle_indices[3 * i];
let i2 = self.triangle_indices[3 * i + 1];
let i3 = self.triangle_indices[3 * i + 2];
tris.push(Triangle {
vertices: [
Vertex {
position: [
self.positions[3 * i1],
self.positions[3 * i1 + 1],
self.positions[3 * i1 + 2],
],
normal: [
self.normals[3 * i1],
self.normals[3 * i1 + 1],
self.normals[3 * i1 + 2],
],
},
Vertex {
position: [
self.positions[3 * i2],
self.positions[3 * i2 + 1],
self.positions[3 * i2 + 2],
],
normal: [
self.normals[3 * i2],
self.normals[3 * i2 + 1],
self.normals[3 * i2 + 2],
],
},
Vertex {
position: [
self.positions[3 * i3],
self.positions[3 * i3 + 1],
self.positions[3 * i3 + 2],
],
normal: [
self.normals[3 * i3],
self.normals[3 * i3 + 1],
self.normals[3 * i3 + 2],
],
},
],
});
}
return tris;
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct Triangle<F>
where
F: Float,
{
pub vertices: [Vertex<F>; 3],
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct Vertex<F>
where
F: Float,
{
pub position: [F; 3],
pub normal: [F; 3],
}
impl<F> Display for Triangle<F>
where
F: Float + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Triangle:")?;
let [v1, v2, v3] = self.vertices;
writeln!(f, " + Pos {:?} Norm {:?}", v1.position, v1.normal)?;
writeln!(f, " + Pos {:?} Norm {:?}", v2.position, v2.normal)?;
writeln!(f, " + Pos {:?} Norm {:?}", v3.position, v3.normal)?;
Ok(())
}
}
pub struct Position<F> {
pub x: F,
pub y: F,
pub z: F,
}
impl<F> Position<F>
where F: Float
{
pub fn interp_toward(&self, other: &Position<F>, factor: F) -> Position<F> {
Position {
x: self.x + factor * (other.x - self.x),
y: self.y + factor * (other.y - self.y),
z: self.z + factor * (other.z - self.z),
}
}
}
impl<F> Mul<F> for &Position<F>
where F: Float
{
type Output = Position<F>;
fn mul(self, rhs: F) -> Self::Output {
Position {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl<F> Add<&[F; 3]> for &Position<F>
where F: Float
{
type Output = Position<F>;
fn add(self, rhs: &[F; 3]) -> Self::Output {
Position {
x: self.x + rhs[0],
y: self.y + rhs[1],
z: self.z + rhs[2],
}
}
}