diff --git a/src/main.rs b/src/main.rs index 303f7ea..0cf65a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,6 @@ use self::mushroom::Mushroom; use clap::Parser; use std::fs::OpenOptions; -#[macro_use] extern crate approx; // TODO: Investigate https://github.com/virtualritz/polyhedron-ops. @@ -80,7 +79,8 @@ fn main() { let mushroom = mushroom_from_args(&args); // Render the mushroom. - let mesh = render::cylinder(mushroom.stalk_h, mushroom.stalk_d, 128); + // let mesh = render::cylinder(mushroom.stalk_h, mushroom.stalk_d, 128); + let mesh = render::mushroom(&mushroom); // Save output to file. let mut file = OpenOptions::new() @@ -91,8 +91,7 @@ fn main() { .unwrap(); stl_io::write_stl(&mut file, mesh.iter()).unwrap(); - println!("From: {:?}", mushroom); - println!("Generated:\n{:?}", mesh); + println!("Generated from: {:?}", mushroom); } #[cfg(test)] diff --git a/src/render.rs b/src/render.rs index a5d43e6..4b4aed1 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,5 +1,7 @@ use stl_io::{self, Normal, Triangle, Vertex}; +use crate::mushroom::Mushroom; + fn new_triangle(p1: &Vertex, p2: &Vertex, p3: &Vertex) -> stl_io::Triangle { // Set Vector U to (Triangle.p2 minus Triangle.p1) // Set Vector V to (Triangle.p3 minus Triangle.p1) @@ -78,17 +80,40 @@ fn tube_top(center: &Vertex, edge: &Vec) -> Vec { return tube_base(¢er, &edge); } -pub fn cylinder(height: f32, radius: f32, steps: u32) -> Vec { - let base_center = Vertex::new([0.0, 0.0, 0.0]); - let base_edge = vertexes_on_circle(&base_center, radius, steps); - let top_center = Vertex::new([0.0, 0.0, height]); - let top_edge = vertexes_on_circle(&top_center, radius, steps); +pub fn mushroom(mushroom: &Mushroom) -> Vec { + // Max size of any flat surface in mm. + let resolution: f32 = 1.0; + + // We always use the same number of diameter steps to ensure the number of circular vertices doesn't change, + // which might create small breaks in our model. + let diameter_steps = std::cmp::max( + (mushroom.cap_d * std::f32::consts::TAU * resolution) as u32, + 64, + ); + + let stalk_base_center = Vertex::new([0.0, 0.0, 0.0]); + let stalk_base_edge = vertexes_on_circle(&stalk_base_center, mushroom.stalk_d, diameter_steps); + let stalk_top_center = Vertex::new([ + stalk_base_center[0], + stalk_base_center[1], + stalk_base_center[2] + mushroom.stalk_h, + ]); + let stalk_top_edge = vertexes_on_circle(&stalk_top_center, mushroom.stalk_d, diameter_steps); + let cap_base_edge = vertexes_on_circle(&stalk_top_center, mushroom.cap_d, diameter_steps); + let cap_top_center = Vertex::new([ + stalk_top_center[0], + stalk_top_center[1], + stalk_top_center[2] + mushroom.cap_h, + ]); + let cap_top_edge = vertexes_on_circle(&cap_top_center, mushroom.cap_d, diameter_steps); let mut result = Vec::new(); - result.append(&mut tube_base(&base_center, &base_edge)); - result.append(&mut tube_sides(&base_edge, &top_edge)); - result.append(&mut tube_top(&top_center, &top_edge)); + result.append(&mut tube_base(&stalk_base_center, &stalk_base_edge)); + result.append(&mut tube_sides(&stalk_base_edge, &stalk_top_edge)); + result.append(&mut tube_sides(&stalk_top_edge, &cap_base_edge)); + result.append(&mut tube_sides(&cap_base_edge, &cap_top_edge)); + result.append(&mut tube_top(&cap_top_center, &cap_top_edge)); return result; }