fix triangle interpolation
This commit is contained in:
parent
c11bfdcc00
commit
9f4a8f03df
3 changed files with 67 additions and 11 deletions
14
src/main.rs
14
src/main.rs
|
@ -46,6 +46,10 @@ fn main() {
|
||||||
let b = Point2i::new(550, 390).with_color(GREEN);
|
let b = Point2i::new(550, 390).with_color(GREEN);
|
||||||
let c = Point2i::new(230, 590).with_color(RED);
|
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);
|
let t = Triangle2i::new(a, b, c);
|
||||||
t.render_filled(BLACK, &mut fb);
|
t.render_filled(BLACK, &mut fb);
|
||||||
fb.write_file("triangle.tga", true, true).unwrap();
|
fb.write_file("triangle.tga", true, true).unwrap();
|
||||||
|
@ -112,12 +116,12 @@ impl Triangle2i {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let it = 1.0 / total_area;
|
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.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 p = Point2i::new(x, y);
|
||||||
let alpha = Triangle2i::new(p, self.a, self.b).signed_area() * it;
|
let alpha = Triangle2i::new(p, self.b, self.c).signed_area() * it;
|
||||||
let beta = 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.c, self.a).signed_area() * it;
|
let gamma = Triangle2i::new(p, self.a, self.b).signed_area() * it;
|
||||||
|
|
||||||
if alpha.is_sign_positive()
|
if alpha.is_sign_positive()
|
||||||
&& beta.is_sign_positive()
|
&& beta.is_sign_positive()
|
||||||
|
@ -128,7 +132,7 @@ impl Triangle2i {
|
||||||
&& let Some(cb) = self.b.color
|
&& let Some(cb) = self.b.color
|
||||||
&& let Some(cc) = self.c.color
|
&& let Some(cc) = self.c.color
|
||||||
{
|
{
|
||||||
ca * alpha + cb * beta + cc * gamma + color
|
color + (ca * alpha) + (cb * beta) + (cc * gamma)
|
||||||
} else {
|
} else {
|
||||||
color
|
color
|
||||||
};
|
};
|
||||||
|
|
45
src/point.rs
45
src/point.rs
|
@ -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)]
|
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Point2i {
|
pub struct Point2i {
|
||||||
|
@ -28,6 +36,25 @@ impl Point2i {
|
||||||
..self
|
..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 {
|
impl Add for Point2i {
|
||||||
|
@ -37,7 +64,12 @@ 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,
|
||||||
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 {
|
Self {
|
||||||
x: self.x - rhs.x,
|
x: self.x - rhs.x,
|
||||||
y: self.y - rhs.y,
|
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 })
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
src/tga.rs
17
src/tga.rs
|
@ -1,7 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
ops::{Add, Deref, DerefMut, Mul},
|
ops::{Add, Deref, DerefMut, Mul, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
const HEADER_SIZE: usize = 18;
|
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 {
|
impl Mul<f32> for TGAColor {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue