use std::sync::Arc;
use crate::math::{Point2, Point3, Transform, Transformable, Vec3, Vec4};
use crate::prelude::Triangle;
#[derive(Clone)]
pub struct TriangleMesh {
pub indices: Vec<u32>,
pub vertices: Vec<Point3>,
pub normals: Vec<Vec3>,
pub tangents: Vec<Vec4>,
pub uvs: Vec<Point2>,
}
impl TriangleMesh {
pub fn new(
indices: Vec<u32>,
vertices: Vec<Point3>,
normals: Vec<Vec3>,
tangents: Vec<Vec4>,
uvs: Vec<Point2>,
) -> Self {
Self {
indices,
vertices,
normals,
tangents,
uvs,
}
}
pub fn triangle(leg_length: f64) -> TriangleMesh {
let indices = vec![0, 1, 2];
let vertices = vec![
Point3::new(leg_length, 0.0, -leg_length),
Point3::new(-leg_length, 0.0, leg_length),
Point3::new(leg_length, 0.0, leg_length),
];
let normals = vec![Vec3::Y; 3];
let tangents = vec![];
let uvs = vec![];
TriangleMesh::new(indices, vertices, normals, tangents, uvs)
}
pub fn plane(half_size: f64) -> TriangleMesh {
let indices = vec![0, 1, 2, 0, 3, 1];
let vertices = vec![
Point3::new(half_size, 0.0, -half_size),
Point3::new(-half_size, 0.0, half_size),
Point3::new(half_size, 0.0, half_size),
Point3::new(-half_size, 0.0, -half_size),
];
let normals = vec![Vec3::Y; 4];
let tangents = vec![];
let uvs = vec![];
TriangleMesh::new(indices, vertices, normals, tangents, uvs)
}
pub fn cube(half_size: f64) -> TriangleMesh {
let indices = vec![
0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16,
17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23,
];
let vertices = vec![
Point3::new(half_size, half_size, -half_size),
Point3::new(-half_size, half_size, half_size),
Point3::new(half_size, half_size, half_size),
Point3::new(-half_size, half_size, -half_size),
Point3::new(half_size, -half_size, -half_size),
Point3::new(-half_size, -half_size, half_size),
Point3::new(half_size, -half_size, half_size),
Point3::new(-half_size, -half_size, -half_size),
Point3::new(half_size, -half_size, half_size),
Point3::new(half_size, half_size, half_size),
Point3::new(half_size, half_size, -half_size),
Point3::new(half_size, -half_size, -half_size),
Point3::new(-half_size, -half_size, half_size),
Point3::new(-half_size, half_size, half_size),
Point3::new(-half_size, half_size, -half_size),
Point3::new(-half_size, -half_size, -half_size),
Point3::new(half_size, -half_size, half_size),
Point3::new(-half_size, -half_size, half_size),
Point3::new(-half_size, half_size, half_size),
Point3::new(half_size, half_size, half_size),
Point3::new(half_size, -half_size, -half_size),
Point3::new(-half_size, -half_size, -half_size),
Point3::new(-half_size, half_size, -half_size),
Point3::new(half_size, half_size, -half_size),
];
let normals = vec![
Vec3::Y,
Vec3::Y,
Vec3::Y,
Vec3::Y,
-Vec3::Y,
-Vec3::Y,
-Vec3::Y,
-Vec3::Y,
Vec3::X,
Vec3::X,
Vec3::X,
Vec3::X,
-Vec3::X,
-Vec3::X,
-Vec3::X,
-Vec3::X,
Vec3::Z,
Vec3::Z,
Vec3::Z,
Vec3::Z,
-Vec3::Z,
-Vec3::Z,
-Vec3::Z,
-Vec3::Z,
];
let tangents = vec![];
let uvs = vec![];
TriangleMesh::new(indices, vertices, normals, tangents, uvs)
}
pub fn vertex_mean(&self) -> Point3 {
self.vertices.iter().fold(Point3::ZERO, |acc, p| acc + *p) / self.vertices.len() as f64
}
pub fn triangles(self) -> impl Iterator<Item = Triangle> {
let triangle_count = self.indices.len() / 3;
let triangle_mesh = Arc::new(self);
(0..triangle_count).map(move |i| Triangle::new(Arc::clone(&triangle_mesh), i))
}
}
impl Transformable for TriangleMesh {
fn translate(mut self, translation: Vec3) -> Self {
for vertex in self.vertices.iter_mut() {
*vertex += translation;
}
self
}
fn rotate(mut self, origin: Point3, axis: Vec3, angle: f64) -> Self {
let transform = Transform::rotate(origin, axis, angle);
for vertex in self.vertices.iter_mut() {
*vertex = transform.mat4 * *vertex;
}
for normal in self.normals.iter_mut() {
*normal = transform.mat4 * *normal;
}
self
}
fn rotate_x(mut self, angle: f64) -> Self {
let vertex_mean = self.vertex_mean();
let transform = Transform::rotate_x(vertex_mean, angle);
for vertex in self.vertices.iter_mut() {
*vertex = transform.mat4 * *vertex;
}
for normal in self.normals.iter_mut() {
*normal = transform.mat4 * *normal;
}
self
}
fn rotate_y(mut self, angle: f64) -> Self {
let vertex_mean = self.vertex_mean();
let transform = Transform::rotate_y(vertex_mean, angle);
for vertex in self.vertices.iter_mut() {
*vertex = vertex_mean + transform.mat4 * (*vertex - vertex_mean);
}
for normal in self.normals.iter_mut() {
*normal = transform.mat4 * *normal;
}
self
}
fn rotate_z(mut self, angle: f64) -> Self {
let vertex_mean = self.vertex_mean();
let transform = Transform::rotate_z(vertex_mean, angle);
for vertex in self.vertices.iter_mut() {
*vertex = vertex_mean + transform.mat4 * (*vertex - vertex_mean);
}
for normal in self.normals.iter_mut() {
*normal = transform.mat4 * *normal;
}
self
}
fn scale_x(self, factor: f64) -> Self {
let vertex_mean = self.vertex_mean();
self.scale(vertex_mean, Vec3::new(factor, 1.0, 1.0))
}
fn scale_y(self, factor: f64) -> Self {
let vertex_mean = self.vertex_mean();
self.scale(vertex_mean, Vec3::new(1.0, factor, 1.0))
}
fn scale_z(self, factor: f64) -> Self {
let vertex_mean = self.vertex_mean();
self.scale(vertex_mean, Vec3::new(1.0, 1.0, factor))
}
fn scale_xyz(self, scale: Vec3) -> Self {
let vertex_mean = self.vertex_mean();
self.scale(vertex_mean, scale)
}
fn scale(mut self, origin: Point3, scale: Vec3) -> Self {
let transform = Transform::scale(origin, scale);
for vertex in self.vertices.iter_mut() {
*vertex = transform.mat4 * *vertex;
}
for normal in self.normals.iter_mut() {
*normal = transform.mat4 * *normal;
}
self
}
fn look_at(self, _target: Point3, _view_up: Vec3) -> Self {
todo!()
}
}