From 88a406f84d49dd064647c38e7bf2bda3e92a38cb Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Sun, 7 Sep 2025 13:52:14 -0700 Subject: [PATCH] move triangle methods onto Triangle struct --- src/main.rs | 118 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 44 deletions(-) diff --git a/src/main.rs b/src/main.rs index a712b97..c2f2eae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,26 +44,23 @@ fn main() { } fn fill_triangles(fb: &mut TGAImage) { - /* - triangle( 7, 45, 35, 100, 45, 60, framebuffer, red); - triangle(120, 35, 90, 5, 45, 110, framebuffer, white); - triangle(115, 83, 80, 90, 85, 120, framebuffer, green); - */ - let t1a = Point2i::new(7, 45); let t1b = Point2i::new(35, 100); let t1c = Point2i::new(45, 60); - triangle_filled(t1a, t1b, t1c, RED, fb); + let t1 = Triangle::new(t1a, t1b, t1c); + t1.render_filled(RED, fb); let t2a = Point2i::new(120, 35); let t2b = Point2i::new(90, 5); let t2c = Point2i::new(45, 110); - triangle_filled(t2a, t2b, t2c, WHITE, fb); + let t2 = Triangle::new(t2a, t2b, t2c); + t2.render_filled(WHITE, fb); let a = Point2i::new(115, 83); let b = Point2i::new(80, 90); let c = Point2i::new(85, 120); - triangle_filled(a, b, c, GREEN, fb); + let t3 = Triangle::new(a, b, c); + t3.render_filled(GREEN, fb); } fn _render_diablo(model: Model, fb: &mut TGAImage) { @@ -150,48 +147,81 @@ fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, mut fb: &mut TGAImage) }); } -fn triangle_lines(a: Point2i, b: Point2i, c: Point2i, color: TGAColor, fb: &mut TGAImage) { - line(a, b, color, fb); - line(b, c, color, fb); - line(c, a, color, fb); +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct Triangle { + a: Point2i, + b: Point2i, + c: Point2i, } -fn triangle_filled(a: Point2i, b: Point2i, c: Point2i, color: TGAColor, fb: &mut TGAImage) { - let mut sorted = [a, b, c]; - sorted.sort_unstable_by(|a, b| a.y.cmp(&b.y)); - let [a, b, c] = sorted; - - let total_height = c.y - a.y; - - let (lower_left, upper_right) = triangle_bb(a, b, c); - for y in lower_left.y..=upper_right.y { - let a = Point2i::new(lower_left.x, y); - let b = Point2i::new(upper_right.x, y); - line(a, b, color, fb); +impl Triangle { + pub fn new(a: Point2i, b: Point2i, c: Point2i) -> Self { + let mut sorted = [a, b, c]; + sorted.sort_unstable_by(|a, b| a.y.cmp(&b.y)); + let [a, b, c] = sorted; + Self { a, b, c } } - let segment_height = b.y - a.y; - for y in a.y..=b.y { - let dy = y - a.y; - let x1 = a.x + ((c.x - a.x) * dy) / total_height; - let x2 = a.x + ((b.x - a.x) * dy) / segment_height; - line(Point2i::new(x1, y), Point2i::new(x2, y), color, fb); + pub fn signed_area(&self) -> f32 { + 0.5 * ((self.b.y - self.a.y) * (self.a.x + self.b.x) + + (self.c.y - self.b.y) * (self.c.x + self.b.x) + + (self.a.y - self.c.y) * (self.a.x + self.c.x)) as f32 } - let segment_height = c.y - b.y; - for y in b.y..=c.y { - let x1 = a.x + ((c.x - a.x) * (y - a.y)) / total_height; - let x2 = b.x + ((c.x - b.x) * (y - b.y)) / segment_height; - line(Point2i::new(x1, y), Point2i::new(x2, y), color, fb); + pub fn bb(&self) -> AABB { + let xmax = self.a.x.max(self.b.x.max(self.c.x)); + let xmin = self.a.x.min(self.b.x.min(self.c.x)); + + let ymax = self.a.y.max(self.b.y.max(self.c.y)); + let ymin = self.a.y.min(self.b.y.min(self.c.y)); + AABB { + lower_left: Point2i::new(xmin, ymin), + upper_right: Point2i::new(xmax, ymax), + } + } + pub fn render_filled(&self, color: TGAColor, fb: &mut TGAImage) { + let bb = self.bb(); + for y in bb.ymin()..=bb.ymax() { + let a = Point2i::new(bb.xmin(), y); + let b = Point2i::new(bb.xmax(), y); + line(a, b, color, fb); + } + } + + pub fn render_lines(&self, color: TGAColor, fb: &mut TGAImage) { + line(self.a, self.b, color, fb); + line(self.b, self.c, color, fb); + line(self.c, self.a, color, fb); } } -fn triangle_bb(a: Point2i, b: Point2i, c: Point2i) -> (Point2i, Point2i) { - let xmax = a.x.max(b.x.max(c.x)); - let xmin = a.x.min(b.x.min(c.x)); - - let ymax = a.y.max(b.y.max(c.y)); - let ymin = a.y.min(b.y.min(c.y)); - - (Point2i::new(xmin, ymin), Point2i::new(xmax, ymax)) +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct AABB { + lower_left: Point2i, + upper_right: Point2i, +} + +impl AABB { + pub fn new(lower_left: Point2i, upper_right: Point2i) -> Self { + Self { + lower_left, + upper_right, + } + } + + pub fn xmin(&self) -> i32 { + self.lower_left.x + } + + pub fn xmax(&self) -> i32 { + self.upper_right.x + } + + pub fn ymin(&self) -> i32 { + self.lower_left.y + } + + pub fn ymax(&self) -> i32 { + self.upper_right.y + } }