use std::fmt::Debug;
use std::fmt::Display;
use num::Float;
use crate::structs::grid_point::GridPoint;
use crate::traits::mesh_builder::MeshBuilder;
use crate::structs::vertex_index::VertexIndex;
use crate::traits::voxel_data::Density;
#[derive(Debug)]
pub struct Mesh<F>
where
F: Float,
{
pub positions: Vec<F>,
pub normals: Vec<F>,
pub triangle_indices: Vec<usize>,
}
pub struct GenericMeshBuilder<F>
where
F: Float,
{
positions: Vec<F>,
normals: Vec<F>,
triangle_indices: Vec<usize>,
vertices: usize,
}
#[allow(clippy::new_without_default)]
impl<F> GenericMeshBuilder<F>
where
F: Float,
{
pub fn new() -> Self {
Self {
positions: vec![],
normals: vec![],
triangle_indices: vec![],
vertices: 0,
}
}
pub fn build(self) -> Mesh<F> {
Mesh {
positions: self.positions,
normals: self.normals,
triangle_indices: self.triangle_indices,
}
}
}
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],
],
},
],
});
}
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(())
}
}
impl MeshBuilder<f32, f32> for GenericMeshBuilder<f32> {
fn add_vertex_between(
&mut self,
point_a: GridPoint<f32, f32>,
point_b: GridPoint<f32, f32>,
interpolate_toward_b: f32,
) -> VertexIndex {
let position = point_a
.position
.interpolate_toward(&point_b.position, interpolate_toward_b);
let gradient_x =
point_a.gradient.0 + interpolate_toward_b * (point_b.gradient.0 - point_a.gradient.0);
let gradient_y =
point_a.gradient.1 + interpolate_toward_b * (point_b.gradient.1 - point_a.gradient.1);
let gradient_z =
point_a.gradient.2 + interpolate_toward_b * (point_b.gradient.2 - point_a.gradient.2);
let normal = f32::gradients_to_normal(gradient_x, gradient_y, gradient_z);
self.positions.push(position.x);
self.positions.push(position.y);
self.positions.push(position.z);
self.normals.push(normal[0]);
self.normals.push(normal[1]);
self.normals.push(normal[2]);
let index = self.vertices;
self.vertices += 1;
VertexIndex(index)
}
fn add_triangle(
&mut self,
vertex_1_index: VertexIndex,
vertex_2_index: VertexIndex,
vertex_3_index: VertexIndex,
) {
self.triangle_indices.push(vertex_1_index.0);
self.triangle_indices.push(vertex_2_index.0);
self.triangle_indices.push(vertex_3_index.0);
}
}