From 59d264a38f42f4b44da829296f8df9a6ae8c8e23 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Sun, 7 Sep 2025 13:08:44 -0700 Subject: [PATCH] parallel lines, aabb for triangles --- Cargo.lock | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 56 +++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 97 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89132c3..b3b322b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,37 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "getrandom" version = "0.3.3" @@ -99,6 +130,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "syn" version = "1.0.109" @@ -147,6 +198,7 @@ version = "0.1.0" dependencies = [ "justerror", "rand", + "rayon", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index e86659c..43ccbe3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ edition = "2024" [dependencies] justerror = "1.1.0" rand = "0.9.2" +rayon = "1.11.0" thiserror = "2.0.16" diff --git a/src/main.rs b/src/main.rs index fdf631e..a712b97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,12 @@ #[macro_use] extern crate justerror; -mod tga; -use std::collections::BTreeMap; +use std::sync::{Arc, Mutex}; use rand::Rng; +use rayon::prelude::*; + +mod tga; use tga::*; mod point; @@ -112,7 +114,7 @@ fn _bench(fb: &mut TGAImage) { } } -fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, fb: &mut TGAImage) { +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 { std::mem::swap(&mut a.x, &mut a.y); @@ -122,17 +124,30 @@ fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, fb: &mut TGAImage) { std::mem::swap(&mut a, &mut b); } + let fb = Arc::new(Mutex::new(fb)); + let y = Arc::new(Mutex::new(a.y as f32)); + let step = (b.y - a.y) as f32 / (b.x - a.x) as f32; - let mut y = a.y as f32; - for x in (a.x)..b.x { - let (px, py) = if is_steep { - (y.round_ties_even() as i32, x) - } else { - (x, y.round_ties_even() as i32) + (a.x..b.x).into_par_iter().for_each(|x| { + let ny = { + if let Ok(y) = y.lock() { + *y + } else { + return; + } }; - fb.set(px as u32, py as u32, color); - y += step; - } + let (px, py) = if is_steep { + (ny.round_ties_even() as i32, x) + } else { + (x, ny.round_ties_even() as i32) + }; + if let Ok(mut fb) = fb.lock() { + fb.set(px as u32, py as u32, color); + } + if let Ok(mut y) = y.lock() { + *y += step; + } + }); } fn triangle_lines(a: Point2i, b: Point2i, c: Point2i, color: TGAColor, fb: &mut TGAImage) { @@ -148,6 +163,13 @@ fn triangle_filled(a: Point2i, b: Point2i, c: Point2i, color: TGAColor, fb: &mut 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); + } + let segment_height = b.y - a.y; for y in a.y..=b.y { let dy = y - a.y; @@ -163,3 +185,13 @@ fn triangle_filled(a: Point2i, b: Point2i, c: Point2i, color: TGAColor, fb: &mut line(Point2i::new(x1, y), Point2i::new(x2, y), 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)) +}