From 31fd34d083ca477e4cfa726204dece300cb45871 Mon Sep 17 00:00:00 2001 From: stickynotememo Date: Fri, 16 Jan 2026 16:30:36 +1100 Subject: [PATCH] Setup ear clipping interface --- src/main.rs | 2 +- src/points.rs | 54 ++++++++++++++++++++++++++++++++++++++++----------- src/render.rs | 10 +++++----- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/main.rs b/src/main.rs index dc5181e..8674bb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,7 @@ fn main() { (0, 1), (1, 2), (2, 0) ], vec![ - (0, 1, 2) + vec![0, 1, 2] ])]; let mut dt = Duration::ZERO; diff --git a/src/points.rs b/src/points.rs index 02de27f..c5009f4 100644 --- a/src/points.rs +++ b/src/points.rs @@ -21,41 +21,73 @@ pub struct Object { pub edges: Vec<(Point3D, Point3D)>, pub edge_indices: Vec<(usize, usize)>, - pub faces: Vec<(Point3D, Point3D, Point3D)>, - pub face_indices: Vec<(usize, usize, usize)>, + pub triangles: Vec<(Point3D, Point3D, Point3D)>, + pub triangle_indices: Vec<(usize, usize, usize)>, + + pub faces: Vec>, + pub face_indices: Vec>, } impl Object { /// Takes a vector of vertices and a vector of indices for each of the `edge_indices` and - /// `face_indices` parameters. These indices index the `vertices` array and represent the + /// `triangle_indices` parameters. These indices index the `vertices` array and represent the /// endpoints of the line segment (in the case of an edge) or the vertices of the triangle - /// (in the case of a face) + /// (in the case of a triangle) + + // TODO: use [Yoke](https://crates.io/crates/yoke) pub fn new(vertices: Vec, edge_indices: Vec<(usize, usize)>, - face_indices: Vec<(usize, usize, usize)>) -> Self { + face_indices: Vec>) -> Self { + + let mut ret = Self { + vertices, + + edges: vec![], + edge_indices, + + triangles: vec![], + triangle_indices: vec![], + + faces: vec![vec![]], + face_indices + }; - let mut ret = Self {vertices, edges: vec![], edge_indices, faces: vec![], face_indices}; for (i_start, i_end) in ret.edge_indices.iter() { ret.edges.push((ret.vertices[*i_start].clone(), ret.vertices[*i_end].clone())); } - for (i_one, i_two, i_three /* The three vertices of the triangle */) in ret.face_indices.iter() { - ret.faces.push((ret.vertices[*i_one].clone(), ret.vertices[*i_two].clone(), ret.vertices[*i_three].clone())); + for (i_one, i_two, i_three /* The three vertices of the triangle */) in ret.triangle_indices.iter() { + ret.triangles.push((ret.vertices[*i_one].clone(), ret.vertices[*i_two].clone(), ret.vertices[*i_three].clone())); } ret } - // Updates the `edges` and `faces` to correspond to updated vertices. + fn ear_clip(polygon: &Vec) -> Vec<(Point3D, Point3D, Point3D)> { + + todo!() + } + + /// Updates the `edges` and `faces` to correspond to updated vertices. + /// Triangulates based on the faces array. pub fn update(&mut self) { + // OPTIMISATION: Do we need to re-initalise self.{edges, faces, triangles} every execution? self.edges = vec![]; for (i_start, i_end) in self.edge_indices.iter() { self.edges.push((self.vertices[*i_start].clone(), self.vertices[*i_end].clone())); } self.faces = vec![]; - for (i_one, i_two, i_three /* The three vertices of the triangle */) in self.face_indices.iter() { - self.faces.push((self.vertices[*i_one].clone(), self.vertices[*i_two].clone(), self.vertices[*i_three].clone())); + for polygon_indices in self.face_indices.iter() { + self.faces.push(polygon_indices.iter().map(|indice| self.vertices[*indice]).collect()); + } + + self.triangles = vec![]; + for face in self.faces.iter() { + self.triangles.append(&mut Self::ear_clip(&face)); + } + for (i_one, i_two, i_three /* The three vertices of the triangle */) in self.triangle_indices.iter() { + self.triangles.push((self.vertices[*i_one].clone(), self.vertices[*i_two].clone(), self.vertices[*i_three].clone())); } } } diff --git a/src/render.rs b/src/render.rs index a1e1733..afa39fe 100644 --- a/src/render.rs +++ b/src/render.rs @@ -63,7 +63,7 @@ pub fn render(scene: &Scene, buf: &mut [u32]) { } - for (p0, p1, p2) in &obj.faces { + for (p0, p1, p2) in &obj.triangles { let (p0, p1, p2) = (p0.to_screen_coordinates(), p1.to_screen_coordinates(), p2.to_screen_coordinates()); // Finds the leftmost and rightmost points on the triangle and only iterates over them. @@ -74,12 +74,12 @@ pub fn render(scene: &Scene, buf: &mut [u32]) { for y in vertical_range.clone() { let p = Point2D{x: x as f64, y: y as f64}; - let area = 0.5 *(-p1.y*p2.x + p0.y*(-p1.x + p2.x) + p0.x*(p1.y - p2.y) + p1.x*p2.y); - let s = 1.0/(2.0*area)*(p0.y*p2.x - p0.x*p2.y + (p2.y - p0.y)*p.x + (p0.x - p2.x)*p.y); - let t = 1.0/(2.0*area)*(p0.x*p1.y - p0.y*p1.x + (p0.y - p1.y)*p.x + (p1.x - p0.x)*p.y); + // adapted from https://stackoverflow.com/a/14382692 + let area = 0.5 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y); + let s = 1.0/(2.0 * area) * (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y); + let t = 1.0/(2.0 * area) * (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y); if s > 0.0 && t > 0.0 && 1.0 - s - t > 0.0 { - // dbg!(p); *index_buffer(buf, p) = to_rgb((255, 255, 255)); }; }