From 2197f3d51a2cf2caed6e0e65c48f98a32e8fcbdc Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 25 Jul 2026 02:06:13 +0300 Subject: [PATCH] =?UTF-8?q?WIP:=20Koch=E2=80=99s=20Snowflake?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 16 +++++++++ Cargo.toml | 1 + src/mesh.rs | 76 +++++++++++++++++++++++++++++++++++-------- ui/src/main_window.ui | 4 +-- 4 files changed, 81 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96a81a8..c5f3464 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -381,6 +381,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "either" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + [[package]] name = "equivalent" version = "1.0.2" @@ -629,6 +635,7 @@ version = "0.1.0" dependencies = [ "bytemuck", "glam", + "itertools", "pollster", "wgpu", "winit", @@ -656,6 +663,15 @@ dependencies = [ "hashbrown 0.16.1", ] +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + [[package]] name = "jni" version = "0.21.1" diff --git a/Cargo.toml b/Cargo.toml index 2bc6a2a..ab81523 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ opt-level = 3 [dependencies] bytemuck = { version = "1.25.2", features = ["derive"] } glam = { version = "0.30.9", features = ["bytemuck"] } +itertools = "0.15.0" pollster = "0.4.0" wgpu = "27.0.1" winit = "0.30.12" diff --git a/src/mesh.rs b/src/mesh.rs index 9f62c6f..232804c 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,6 +1,7 @@ -use std::f32::consts::PI; +use std::f32::consts::{FRAC_PI_3, PI}; use glam::{Mat2, Vec3, Vec3Swizzles, vec2, vec3}; +use itertools::Itertools; pub type Face = [usize; 3]; @@ -93,16 +94,67 @@ pub fn shell(shape: &crate::ShapeArgs) -> Mesh { } pub fn solid(shape: &crate::ShapeArgs) -> Mesh { - let sides = shape.sides as usize; + let r = shape.base_diameter / 2.0; - let mut mesh = shell(shape); + let mut mesh = Mesh::default(); - let mut bottom = disc_faces(0, sides); - flip_faces(&mut bottom); - mesh.faces.extend(bottom); - - let top = disc_faces(mesh.vertices.len() - sides, sides); - mesh.faces.extend(top); + let mut pts = Vec::new(); + for a in 0..3 { + let angle = 2.0 * a as f32 * FRAC_PI_3; + let (y, x) = angle.sin_cos(); + pts.push(vec2(x, y)); + } + mesh.vertices + .extend(pts.iter().map(|pt| r * vec3(pt.x, pt.y, 0.0))); + mesh.faces.push([0, 2, 1]); + let n_layers = 4; + for layer in 1..n_layers { + let mut new_pts = Vec::new(); + let z0 = 1.0 - 3.0f32.powf(-(layer - 1) as f32); + let z = 1.0 - 3.0f32.powf(-layer as f32); + for [a, b] in pts.iter().copied().circular_array_windows() { + let along = b - a; + let across = -along.perp(); + let c = (2. * a + b) / 3.; + let d = (a + 2. * b) / 3.; + let mid = (a + b) / 2.; + let e = mid + across * (1.0f32 / 12.).sqrt(); + new_pts.push(a); + new_pts.push(c); + new_pts.push(e); + new_pts.push(d); + let base = mesh.vertices.len(); + mesh.vertices + .extend([a, mid, b].map(|pt| r * vec3(pt.x, pt.y, z0))); + mesh.vertices + .extend([a, c, e, d, b].map(|pt| r * vec3(pt.x, pt.y, z))); + mesh.faces.extend( + [ + [0, 4, 3], + [0, 1, 4], + [1, 5, 4], + [1, 6, 5], + [1, 2, 6], + [2, 7, 6], + ] + .map(|face| face.map(|index| base + index)), + ); + } + pts = new_pts; + } + { + let z0 = 1.0 - 3.0f32.powf(-(n_layers - 1) as f32); + let z = 1.0 - 3.0f32.powf(-n_layers as f32); + for [a, b] in pts.iter().copied().circular_array_windows() { + let base = mesh.vertices.len(); + mesh.vertices + .extend([a, b].map(|pt| r * vec3(pt.x, pt.y, z0))); + mesh.vertices + .extend([a, b].map(|pt| r * vec3(pt.x, pt.y, z))); + mesh.faces + .extend([[0, 3, 2], [0, 1, 3]].map(|face| face.map(|index| base + index))); + } + } mesh } @@ -143,9 +195,5 @@ pub fn cup(shape: &crate::ShapeArgs) -> Mesh { } pub fn make(shape: &crate::ShapeArgs) -> Mesh { - match shape.mode { - crate::Mode::Solid => solid(shape), - crate::Mode::Shell => cup(shape), - crate::Mode::Mesh => Default::default(), // TODO implement - } + solid(shape) } diff --git a/ui/src/main_window.ui b/ui/src/main_window.ui index a9b65b6..9a55045 100644 --- a/ui/src/main_window.ui +++ b/ui/src/main_window.ui @@ -221,13 +221,13 @@ 4.000000000000000 - 100.000000000000000 + 200.000000000000000 QAbstractSpinBox::StepType::AdaptiveDecimalStepType - 36.000000000000000 + 100.000000000000000