From 06596a0f768a977b504852d04acc09dd9950bb94 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Mon, 8 Sep 2025 12:42:43 -0700 Subject: [PATCH] add optional color to points --- src/main.rs | 67 +++++++++------------------------------------------- src/model.rs | 4 ++-- src/point.rs | 17 ++++++++++++- src/tga.rs | 2 +- 4 files changed, 30 insertions(+), 60 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3208373..242e1f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,27 +40,7 @@ fn main() { let h = 800; let mut fb = TGAImage::new(w, h, TGAFormat::RGB); - _render_head(&mut fb); -} - -fn _fill_triangles(fb: &mut TGAImage) { - let t1a = Point2i::new(7, 45); - let t1b = Point2i::new(35, 100); - let t1c = Point2i::new(45, 60); - 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); - 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); - let t3 = Triangle::new(a, b, c); - t3.render_filled(GREEN, fb); + render_head(&mut fb); } fn _render_diablo(fb: &mut TGAImage) { @@ -69,7 +49,7 @@ fn _render_diablo(fb: &mut TGAImage) { fb.write_file("diablo.tga", true, true).unwrap(); } -fn _render_head(fb: &mut TGAImage) { +fn render_head(fb: &mut TGAImage) { let model = Model::from_obj("head.obj"); model.render_triangles(fb); fb.write_file("head.tga", true, true).unwrap(); @@ -96,27 +76,6 @@ fn _baseline(framebuffer: &mut TGAImage) { line(a, c, RED, framebuffer); } -fn _bench(fb: &mut TGAImage) { - let mut rng = rand::rng(); - - for _ in 0..1 << 24 { - let ax = rng.random_range(0..fb.width); - let ay = rng.random_range(0..fb.height); - let a = Point2i::newu(ax, ay); - - let bx = rng.random_range(0..fb.width); - let by = rng.random_range(0..fb.height); - let b = Point2i::newu(bx, by); - - line( - a, - b, - [rng.random(), rng.random(), rng.random(), rng.random()].into(), - fb, - ); - } -} - fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, mut fb: &mut TGAImage) { let is_steep = (a.x - b.x).abs() < (a.y - b.y).abs(); if is_steep { @@ -141,13 +100,13 @@ fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, mut fb: &mut TGAImage) } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -struct Triangle { +struct Triangle2i { a: Point2i, b: Point2i, c: Point2i, } -impl Triangle { +impl Triangle2i { pub fn new(a: Point2i, b: Point2i, c: Point2i) -> Self { Self { a, b, c } } @@ -177,21 +136,17 @@ impl Triangle { if total_area < 1.0 { return; } + let it = 1.0 / total_area; (bb.ymin()..=bb.ymax()).into_par_iter().for_each(|y| { (bb.xmin()..bb.xmax()).into_par_iter().for_each(|x| { let p = Point2i::new(x, y); - let a = Triangle::new(p, self.a, self.b) - .signed_area() - .is_sign_positive(); - let b = Triangle::new(p, self.b, self.c) - .signed_area() - .is_sign_positive(); - let c = Triangle::new(p, self.c, self.a) - .signed_area() - .is_sign_positive(); + let a = Triangle2i::new(p, self.a, self.b).signed_area() * it; + let b = Triangle2i::new(p, self.b, self.c).signed_area() * it; + let c = Triangle2i::new(p, self.c, self.a).signed_area() * it; - if a && b - && c + if a.is_sign_positive() + && b.is_sign_positive() + && c.is_sign_positive() && let Ok(mut fb) = fb.lock() { fb.set(x as u32, y as u32, color); diff --git a/src/model.rs b/src/model.rs index 2ba6070..cb9023f 100644 --- a/src/model.rs +++ b/src/model.rs @@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut}; use rand::Rng; use crate::{ - RED, Triangle, line, + RED, Triangle2i, line, point::{Point2i, Point3f}, tga::TGAImage, }; @@ -103,7 +103,7 @@ impl Model { let a = world2view(self.verts[face[0]], width, height); let b = world2view(self.verts[face[1]], width, height); let c = world2view(self.verts[face[2]], width, height); - let triangle = Triangle::new(a, b, c); + let triangle = Triangle2i::new(a, b, c); let color = [ rng.random_range(0..=255u8), rng.random_range(0..=255u8), diff --git a/src/point.rs b/src/point.rs index 76fe6ac..41e1574 100644 --- a/src/point.rs +++ b/src/point.rs @@ -1,20 +1,31 @@ use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub}; +use crate::tga::TGAColor; + #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Point2i { pub x: i32, pub y: i32, + pub c: Option, } impl Point2i { pub fn new(x: i32, y: i32) -> Self { - Self { x, y } + Self { x, y, c: None } } pub fn newu(x: u32, y: u32) -> Self { Self { x: x as i32, y: y as i32, + c: None, + } + } + + pub fn with_color(self, color: TGAColor) -> Self { + Self { + c: Some(color), + ..self } } } @@ -26,6 +37,7 @@ impl Add for Point2i { Self { x: self.x + rhs.x, y: self.y + rhs.y, + c: None, } } } @@ -37,6 +49,7 @@ impl Sub for Point2i { Self { x: self.x - rhs.x, y: self.y - rhs.y, + c: None, } } } @@ -48,6 +61,7 @@ impl Mul for Point2i { Self { x: self.x * rhs.x, y: self.y * rhs.y, + c: None, } } } @@ -129,6 +143,7 @@ impl From for Point2i { Self { x: p.x().round_ties_even() as i32, y: p.y().round_ties_even() as i32, + c: None, } } } diff --git a/src/tga.rs b/src/tga.rs index cd09164..1135246 100644 --- a/src/tga.rs +++ b/src/tga.rs @@ -47,7 +47,7 @@ impl TryFrom for TGAFormat { } } -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct TGAColor { pub bgra: ColorBuf,