fix triangle interpolation

This commit is contained in:
Joe Ardent 2025-09-08 14:41:03 -07:00
parent c11bfdcc00
commit 9f4a8f03df
3 changed files with 67 additions and 11 deletions

View file

@ -46,6 +46,10 @@ fn main() {
let b = Point2i::new(550, 390).with_color(GREEN);
let c = Point2i::new(230, 590).with_color(RED);
a.render(20, &mut fb);
b.render(20, &mut fb);
c.render(20, &mut fb);
let t = Triangle2i::new(a, b, c);
t.render_filled(BLACK, &mut fb);
fb.write_file("triangle.tga", true, true).unwrap();
@ -112,12 +116,12 @@ impl Triangle2i {
return;
}
let it = 1.0 / total_area;
(bb.xmin()..=bb.xmax()).into_par_iter().for_each(|x| {
(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 alpha = Triangle2i::new(p, self.a, self.b).signed_area() * it;
let beta = Triangle2i::new(p, self.b, self.c).signed_area() * it;
let gamma = Triangle2i::new(p, self.c, self.a).signed_area() * it;
let alpha = Triangle2i::new(p, self.b, self.c).signed_area() * it;
let beta = Triangle2i::new(p, self.c, self.a).signed_area() * it;
let gamma = Triangle2i::new(p, self.a, self.b).signed_area() * it;
if alpha.is_sign_positive()
&& beta.is_sign_positive()
@ -128,7 +132,7 @@ impl Triangle2i {
&& let Some(cb) = self.b.color
&& let Some(cc) = self.c.color
{
ca * alpha + cb * beta + cc * gamma + color
color + (ca * alpha) + (cb * beta) + (cc * gamma)
} else {
color
};

View file

@ -1,6 +1,14 @@
use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub};
use std::{
ops::{Add, Deref, DerefMut, Div, Mul, Sub},
sync::{Arc, Mutex},
};
use crate::tga::TGAColor;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::{
YELLOW,
tga::{TGAColor, TGAImage},
};
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Point2i {
@ -28,6 +36,25 @@ impl Point2i {
..self
}
}
pub fn render(&self, radius: i32, fb: &mut TGAImage) {
let xmin = self.x - radius;
let xmax = self.x + radius;
let ymin = self.y - radius;
let ymax = self.y + radius;
let r2 = radius.pow(2);
let fb = Arc::new(Mutex::new(fb));
(ymin..=ymax).into_par_iter().for_each(|y| {
(xmin..=xmax).into_par_iter().for_each(|x| {
let d2 = (x - self.x).pow(2) + (y - self.y).pow(2);
if d2 <= r2
&& let Ok(mut fb) = fb.lock()
{
fb.set(x as u32, y as u32, self.color.unwrap_or(YELLOW));
}
});
});
}
}
impl Add for Point2i {
@ -37,7 +64,12 @@ impl Add for Point2i {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
color: None,
color: if self.color.is_none() {
rhs.color
} else {
self.color
.map(|c| if let Some(oc) = rhs.color { c + oc } else { c })
},
}
}
}
@ -49,7 +81,12 @@ impl Sub for Point2i {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
color: None,
color: if self.color.is_none() {
rhs.color
} else {
self.color
.map(|c| if let Some(oc) = rhs.color { c - oc } else { c })
},
}
}
}

View file

@ -1,7 +1,7 @@
use std::{
fs::File,
io::{Read, Write},
ops::{Add, Deref, DerefMut, Mul},
ops::{Add, Deref, DerefMut, Mul, Sub},
};
const HEADER_SIZE: usize = 18;
@ -88,6 +88,21 @@ impl Add for TGAColor {
}
}
impl Sub for TGAColor {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
bgra: [
self[0].saturating_sub(rhs[0]),
self[1].saturating_sub(rhs[1]),
self[2].saturating_sub(rhs[2]),
self[3].saturating_sub(rhs[3]),
],
}
}
}
impl Mul<f32> for TGAColor {
type Output = Self;