add optional color to points

This commit is contained in:
Joe Ardent 2025-09-08 12:42:43 -07:00
parent 10882983fe
commit 06596a0f76
4 changed files with 30 additions and 60 deletions

View file

@ -40,27 +40,7 @@ fn main() {
let h = 800; let h = 800;
let mut fb = TGAImage::new(w, h, TGAFormat::RGB); let mut fb = TGAImage::new(w, h, TGAFormat::RGB);
_render_head(&mut fb); 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);
} }
fn _render_diablo(fb: &mut TGAImage) { fn _render_diablo(fb: &mut TGAImage) {
@ -69,7 +49,7 @@ fn _render_diablo(fb: &mut TGAImage) {
fb.write_file("diablo.tga", true, true).unwrap(); 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"); let model = Model::from_obj("head.obj");
model.render_triangles(fb); model.render_triangles(fb);
fb.write_file("head.tga", true, true).unwrap(); fb.write_file("head.tga", true, true).unwrap();
@ -96,27 +76,6 @@ fn _baseline(framebuffer: &mut TGAImage) {
line(a, c, RED, framebuffer); 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) { 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(); let is_steep = (a.x - b.x).abs() < (a.y - b.y).abs();
if is_steep { 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)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Triangle { struct Triangle2i {
a: Point2i, a: Point2i,
b: Point2i, b: Point2i,
c: Point2i, c: Point2i,
} }
impl Triangle { impl Triangle2i {
pub fn new(a: Point2i, b: Point2i, c: Point2i) -> Self { pub fn new(a: Point2i, b: Point2i, c: Point2i) -> Self {
Self { a, b, c } Self { a, b, c }
} }
@ -177,21 +136,17 @@ impl Triangle {
if total_area < 1.0 { if total_area < 1.0 {
return; return;
} }
let it = 1.0 / total_area;
(bb.ymin()..=bb.ymax()).into_par_iter().for_each(|y| { (bb.ymin()..=bb.ymax()).into_par_iter().for_each(|y| {
(bb.xmin()..bb.xmax()).into_par_iter().for_each(|x| { (bb.xmin()..bb.xmax()).into_par_iter().for_each(|x| {
let p = Point2i::new(x, y); let p = Point2i::new(x, y);
let a = Triangle::new(p, self.a, self.b) let a = Triangle2i::new(p, self.a, self.b).signed_area() * it;
.signed_area() let b = Triangle2i::new(p, self.b, self.c).signed_area() * it;
.is_sign_positive(); let c = Triangle2i::new(p, self.c, self.a).signed_area() * it;
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();
if a && b if a.is_sign_positive()
&& c && b.is_sign_positive()
&& c.is_sign_positive()
&& let Ok(mut fb) = fb.lock() && let Ok(mut fb) = fb.lock()
{ {
fb.set(x as u32, y as u32, color); fb.set(x as u32, y as u32, color);

View file

@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut};
use rand::Rng; use rand::Rng;
use crate::{ use crate::{
RED, Triangle, line, RED, Triangle2i, line,
point::{Point2i, Point3f}, point::{Point2i, Point3f},
tga::TGAImage, tga::TGAImage,
}; };
@ -103,7 +103,7 @@ impl Model {
let a = world2view(self.verts[face[0]], width, height); let a = world2view(self.verts[face[0]], width, height);
let b = world2view(self.verts[face[1]], width, height); let b = world2view(self.verts[face[1]], width, height);
let c = world2view(self.verts[face[2]], 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 = [ let color = [
rng.random_range(0..=255u8), rng.random_range(0..=255u8),
rng.random_range(0..=255u8), rng.random_range(0..=255u8),

View file

@ -1,20 +1,31 @@
use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub}; use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub};
use crate::tga::TGAColor;
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Point2i { pub struct Point2i {
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
pub c: Option<TGAColor>,
} }
impl Point2i { impl Point2i {
pub fn new(x: i32, y: i32) -> Self { pub fn new(x: i32, y: i32) -> Self {
Self { x, y } Self { x, y, c: None }
} }
pub fn newu(x: u32, y: u32) -> Self { pub fn newu(x: u32, y: u32) -> Self {
Self { Self {
x: x as i32, x: x as i32,
y: y 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 { Self {
x: self.x + rhs.x, x: self.x + rhs.x,
y: self.y + rhs.y, y: self.y + rhs.y,
c: None,
} }
} }
} }
@ -37,6 +49,7 @@ impl Sub for Point2i {
Self { Self {
x: self.x - rhs.x, x: self.x - rhs.x,
y: self.y - rhs.y, y: self.y - rhs.y,
c: None,
} }
} }
} }
@ -48,6 +61,7 @@ impl Mul for Point2i {
Self { Self {
x: self.x * rhs.x, x: self.x * rhs.x,
y: self.y * rhs.y, y: self.y * rhs.y,
c: None,
} }
} }
} }
@ -129,6 +143,7 @@ impl From<Point3f> for Point2i {
Self { Self {
x: p.x().round_ties_even() as i32, x: p.x().round_ties_even() as i32,
y: p.y().round_ties_even() as i32, y: p.y().round_ties_even() as i32,
c: None,
} }
} }
} }

View file

@ -47,7 +47,7 @@ impl TryFrom<u8> for TGAFormat {
} }
} }
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)] #[repr(transparent)]
pub struct TGAColor { pub struct TGAColor {
pub bgra: ColorBuf, pub bgra: ColorBuf,