Dodecahedron

Add the dodecahedron module
src/lib.rs additions:
#![allow(unused)] fn main() { use truck_meshalgo::prelude::*; // ...keep earlier functions through octahedron... pub mod dodecahedron; // add this pub use dodecahedron::dodecahedron; // add this }
Construct Main Function
src/dodecahedron.rs:
#![allow(unused)] fn main() { use std::iter::FromIterator; use truck_meshalgo::prelude::*; /// Dodecahedron built from a cube plus roof vertices. pub fn dodecahedron() -> PolygonMesh { //PLACE STEP 1-4 HERE } }
Step 1: Define helper scalars and vertex positions
#![allow(unused)] fn main() { let a = f64::sqrt(3.0) / 3.0; // half cube edge let l = 2.0 * a / (1.0 + f64::sqrt(5.0)); // half dodeca edge let d = f64::sqrt(1.0 - l * l); // other coordinate by Pythagoras let positions = vec![ Point3::new(-a, -a, -a), // [0] Point3::new(a, -a, -a), // [1] Point3::new(a, a, -a), // [2] Point3::new(-a, a, -a),// [3] Point3::new(-a, -a, a), // [4] Point3::new(a, -a, a), // [5] Point3::new(a, a, a), // [6] Point3::new(-a, a, a), // [7] Point3::new(d, -l, 0.0), // [8] Point3::new(d, l, 0.0), // [9] Point3::new(-d, l, 0.0), // [10] Point3::new(-d, -l, 0.0), // [11] Point3::new(0.0, d, -l), // [12] Point3::new(0.0, d, l), // [13] Point3::new(0.0, -d, l), // [14] Point3::new(0.0, -d, -l), // [15] Point3::new(-l, 0.0, d), // [16] Point3::new(l, 0.0, d), // [17] Point3::new(l, 0.0, -d), // [18] Point3::new(-l, 0.0, -d), // [19] ]; }
Explanation
The hexahedron’s edges act as diagonals of regular pentagons, so each dodecahedron edge equals the cube edge divided by the golden ratio. The “roof” vertices have one coordinate at zero; solving the remaining coordinate with the Pythagorean theorum gives the helper scalars a, l, and d used for all 20 vertex positions.
Step 2: Build attribute set
#![allow(unused)] fn main() { let attrs = StandardAttributes { positions, ..Default::default() }; }
Step 3: Define mesh faces
#![allow(unused)] fn main() { let faces = Faces::from_iter([ [4, 14, 5, 17, 16], [6, 13, 7, 16, 17], [6, 17, 5, 8, 9], [4, 16, 7, 10, 11], [4, 11, 0, 15, 14], [1, 8, 5, 14, 15], [6, 9, 2, 12, 13], [3, 10, 7, 13, 12], [1, 15, 0, 19, 18], [1, 18, 2, 9, 8], [3, 12, 2, 18, 19], [3, 19, 0, 11, 10], ]); }
Explanation
Each line is one pentagonal face, listing which vertices to connect by their index in the positions list (e.g., [4, 14, 5, 17, 16] means positions 4→14→5→17→16).
Step 4: Construct the mesh
#![allow(unused)] fn main() { PolygonMesh::new(attrs, faces) }
Export the dodecahedron
Add examples/dodecahedron.rs:
fn main() { let mesh = truck_meshes::dodecahedron(); truck_meshes::write_polygon_mesh(&mesh, "output/dodecahedron.obj"); }
Run it:
cargo run --example dodecahedron
View it
Open output/dodecahedron.obj in your preferred OBJ file viewer. You should see a single dodecahedron.
gif below from Preview (mac).

File tree after this step
truck_meshes/
├─ Cargo.toml
├─ src/
│ ├─ lib.rs
│ ├─ triangle.rs
│ ├─ square.rs
│ ├─ tetrahedron.rs
│ ├─ hexahedron.rs
│ ├─ octahedron.rs
│ └─ dodecahedron.rs
├─ examples/
│ ├─ triangle.rs
│ ├─ square.rs
│ ├─ tetrahedron.rs
│ ├─ hexahedron.rs
│ ├─ octahedron.rs
│ └─ dodecahedron.rs
└─ output/ # exported OBJ files (e.g., output/dodecahedron.obj)
Full code:
src/lib.rs:
#![allow(unused)] fn main() { use truck_meshalgo::prelude::*; pub fn write_polygon_mesh(mesh: &PolygonMesh, path: &str) { let mut obj = std::fs::File::create(path).unwrap(); obj::write(mesh, &mut obj).unwrap(); } pub mod triangle; pub use triangle::triangle; pub mod square; pub use square::square; pub mod tetrahedron; pub use tetrahedron::tetrahedron; pub mod hexahedron; pub use hexahedron::hexahedron; pub mod octahedron; pub use octahedron::octahedron; pub mod dodecahedron; pub use dodecahedron::dodecahedron; }
src/dodecahedron.rs:
#![allow(unused)] fn main() { use std::iter::FromIterator; use truck_meshalgo::prelude::*; pub fn dodecahedron() -> PolygonMesh { let a = f64::sqrt(3.0) / 3.0; let l = 2.0 * a / (1.0 + f64::sqrt(5.0)); let d = f64::sqrt(1.0 - l * l); let positions = vec![ Point3::new(-a, -a, -a), Point3::new(a, -a, -a), Point3::new(a, a, -a), Point3::new(-a, a, -a), Point3::new(-a, -a, a), Point3::new(a, -a, a), Point3::new(a, a, a), Point3::new(-a, a, a), Point3::new(d, -l, 0.0), Point3::new(d, l, 0.0), Point3::new(-d, l, 0.0), Point3::new(-d, -l, 0.0), Point3::new(0.0, d, -l), Point3::new(0.0, d, l), Point3::new(0.0, -d, l), Point3::new(0.0, -d, -l), Point3::new(-l, 0.0, d), Point3::new(l, 0.0, d), Point3::new(l, 0.0, -d), Point3::new(-l, 0.0, -d), ]; let attrs = StandardAttributes { positions, ..Default::default() }; let faces = Faces::from_iter([ [4, 14, 5, 17, 16], [6, 13, 7, 16, 17], [6, 17, 5, 8, 9], [4, 16, 7, 10, 11], [4, 11, 0, 15, 14], [1, 8, 5, 14, 15], [6, 9, 2, 12, 13], [3, 10, 7, 13, 12], [1, 15, 0, 19, 18], [1, 18, 2, 9, 8], [3, 12, 2, 18, 19], [3, 19, 0, 11, 10], ]); PolygonMesh::new(attrs, faces) } }
examples/dodecahedron.rs:
fn main() { let mesh = truck_meshes::dodecahedron(); truck_meshes::write_polygon_mesh(&mesh, "output/dodecahedron.obj"); }