From 4464a9fae62226c0b9406af2c89ed9e35c198fc8 Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Sat, 20 Jun 2020 09:13:20 -0400 Subject: [PATCH] Add utility function to generate dodecahedron --- src/util/mod.rs | 1 + src/util/polyhedra.rs | 132 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 src/util/polyhedra.rs diff --git a/src/util/mod.rs b/src/util/mod.rs index 1914db3..5936783 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -7,3 +7,4 @@ pub mod morton; pub mod normalizer; mod tile_iterator; pub use tile_iterator::{Tile, TileIterator}; +pub mod polyhedra; diff --git a/src/util/polyhedra.rs b/src/util/polyhedra.rs new file mode 100644 index 0000000..bf88e59 --- /dev/null +++ b/src/util/polyhedra.rs @@ -0,0 +1,132 @@ +use itertools::izip; +use nalgebra::{convert, Point3, Vector3}; + +use crate::materials::Material; +use crate::raycasting::Triangle; +use crate::Real; + +use std::sync::Arc; + +pub fn triangulate_polygon( + vertices: &Vec>, + normal: &Vector3, + material: Arc>, +) -> Vec> { + assert!(vertices.len() >= 3); + let hinge = vertices[0]; + izip!(vertices.iter().skip(1), vertices.iter().skip(2)) + .map(|(a, b)| Triangle { + vertices: [hinge, *a, *b], + normals: [*normal, *normal, *normal], + material: Arc::clone(&material), + }) + .collect() +} + +pub fn generate_dodecahedron( + centre: Point3, + size: T, + material: Arc>, +) -> Vec> { + let phi = convert((1.0 + (5.0_f64).sqrt()) / 2.0); + let phi_inv = T::one() / phi; + let one = T::one(); + let zero = T::zero(); + + let faces = vec![ + vec![ + Vector3::new(phi_inv, zero, phi), + Vector3::new(-phi_inv, zero, phi), + Vector3::new(-one, -one, one), + Vector3::new(zero, -phi, phi_inv), + Vector3::new(one, -one, one), + ], + vec![ + Vector3::new(phi_inv, zero, phi), + Vector3::new(-phi_inv, zero, phi), + Vector3::new(-one, one, one), + Vector3::new(zero, phi, phi_inv), + Vector3::new(one, one, one), + ], + vec![ + Vector3::new(phi_inv, zero, phi), + Vector3::new(one, -one, one), + Vector3::new(phi, -phi_inv, zero), + Vector3::new(phi, phi_inv, zero), + Vector3::new(one, one, one), + ], + vec![ + Vector3::new(-phi_inv, zero, phi), + Vector3::new(-one, -one, one), + Vector3::new(-phi, -phi_inv, zero), + Vector3::new(-phi, phi_inv, zero), + Vector3::new(-one, one, one), + ], + vec![ + Vector3::new(-one, -one, one), + Vector3::new(-phi, -phi_inv, zero), + Vector3::new(-one, -one, -one), + Vector3::new(zero, -phi, -phi_inv), + Vector3::new(zero, -phi, phi_inv), + ], + vec![ + Vector3::new(zero, -phi, phi_inv), + Vector3::new(zero, -phi, -phi_inv), + Vector3::new(one, -one, -one), + Vector3::new(phi, -phi_inv, zero), + Vector3::new(one, -one, one), + ], + vec![ + Vector3::new(zero, phi, phi_inv), + Vector3::new(zero, phi, -phi_inv), + Vector3::new(-one, one, -one), + Vector3::new(-phi, phi_inv, zero), + Vector3::new(-one, one, one), + ], + vec![ + Vector3::new(one, one, one), + Vector3::new(phi, phi_inv, zero), + Vector3::new(one, one, -one), + Vector3::new(zero, phi, -phi_inv), + Vector3::new(zero, phi, phi_inv), + ], + vec![ + Vector3::new(one, -one, -one), + Vector3::new(zero, -phi, -phi_inv), + Vector3::new(-one, -one, -one), + Vector3::new(-phi_inv, zero, -phi), + Vector3::new(phi_inv, zero, -phi), + ], + vec![ + Vector3::new(one, one, -one), + Vector3::new(zero, phi, -phi_inv), + Vector3::new(-one, one, -one), + Vector3::new(-phi_inv, zero, -phi), + Vector3::new(phi_inv, zero, -phi), + ], + vec![ + Vector3::new(one, one, -one), + Vector3::new(phi, phi_inv, zero), + Vector3::new(phi, -phi_inv, zero), + Vector3::new(one, -one, -one), + Vector3::new(phi_inv, zero, -phi), + ], + vec![ + Vector3::new(-one, one, -one), + Vector3::new(-phi, phi_inv, zero), + Vector3::new(-phi, -phi_inv, zero), + Vector3::new(-one, -one, -one), + Vector3::new(-phi_inv, zero, -phi), + ], + ]; + + let scale = size * convert(3f64.sqrt() / 2.0); + faces + .iter() + .flat_map(|face| { + let normal = (face[1] - face[0]).cross(&(face[2] - face[1])); + let transformed_face = face.iter().map(|v| centre + v * scale).collect(); + triangulate_polygon(&transformed_face, &normal, Arc::clone(&material)) + }) + .collect() +}