render colored triangle, but something is weird with coordinates

This commit is contained in:
Joe Ardent 2025-09-08 13:52:04 -07:00
parent 06596a0f76
commit c11bfdcc00
3 changed files with 69 additions and 58 deletions

View file

@ -15,6 +15,8 @@ use point::*;
mod model;
use model::*;
const BLACK: TGAColor = TGAColor { bgra: [0u8; 4] };
const WHITE: TGAColor = TGAColor {
bgra: [255, 255, 255, 255],
};
@ -36,44 +38,17 @@ const YELLOW: TGAColor = TGAColor {
};
fn main() {
let w = 800;
let h = 800;
let w = 640;
let h = 640;
let mut fb = TGAImage::new(w, h, TGAFormat::RGB);
render_head(&mut fb);
}
let a = Point2i::new(170, 40).with_color(BLUE);
let b = Point2i::new(550, 390).with_color(GREEN);
let c = Point2i::new(230, 590).with_color(RED);
fn _render_diablo(fb: &mut TGAImage) {
let model = Model::from_obj("diablo3_pose.obj");
model.render_wireframe(fb);
fb.write_file("diablo.tga", true, true).unwrap();
}
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();
}
fn _baseline(framebuffer: &mut TGAImage) {
let ax = 7;
let ay = 3;
let bx = 12;
let by = 37;
let cx = 62;
let cy = 53;
framebuffer.set(ax, ay, WHITE);
framebuffer.set(bx, by, WHITE);
framebuffer.set(cx, cy, WHITE);
let a = Point2i::newu(ax, ay);
let b = Point2i::newu(bx, by);
let c = Point2i::newu(cx, cy);
line(a, b, BLUE, framebuffer);
line(c, b, GREEN, framebuffer);
line(c, a, YELLOW, framebuffer);
line(a, c, RED, framebuffer);
let t = Triangle2i::new(a, b, c);
t.render_filled(BLACK, &mut fb);
fb.write_file("triangle.tga", true, true).unwrap();
}
fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, mut fb: &mut TGAImage) {
@ -140,15 +115,23 @@ impl Triangle2i {
(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 = 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;
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;
if a.is_sign_positive()
&& b.is_sign_positive()
&& c.is_sign_positive()
if alpha.is_sign_positive()
&& beta.is_sign_positive()
&& gamma.is_sign_positive()
&& let Ok(mut fb) = fb.lock()
{
let color = if let Some(ca) = self.a.color
&& let Some(cb) = self.b.color
&& let Some(cc) = self.c.color
{
ca * alpha + cb * beta + cc * gamma + color
} else {
color
};
fb.set(x as u32, y as u32, color);
}
});

View file

@ -6,25 +6,25 @@ use crate::tga::TGAColor;
pub struct Point2i {
pub x: i32,
pub y: i32,
pub c: Option<TGAColor>,
pub color: Option<TGAColor>,
}
impl Point2i {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y, c: None }
Self { x, y, color: None }
}
pub fn newu(x: u32, y: u32) -> Self {
Self {
x: x as i32,
y: y as i32,
c: None,
color: None,
}
}
pub fn with_color(self, color: TGAColor) -> Self {
Self {
c: Some(color),
color: Some(color),
..self
}
}
@ -37,7 +37,7 @@ impl Add for Point2i {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
c: None,
color: None,
}
}
}
@ -49,7 +49,7 @@ impl Sub for Point2i {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
c: None,
color: None,
}
}
}
@ -61,7 +61,7 @@ impl Mul for Point2i {
Self {
x: self.x * rhs.x,
y: self.y * rhs.y,
c: None,
color: None,
}
}
}
@ -143,7 +143,7 @@ impl From<Point3f> for Point2i {
Self {
x: p.x().round_ties_even() as i32,
y: p.y().round_ties_even() as i32,
c: None,
color: None,
}
}
}

View file

@ -1,7 +1,7 @@
use std::{
fs::File,
io::{Read, Write},
ops::{Deref, DerefMut},
ops::{Add, Deref, DerefMut, Mul},
};
const HEADER_SIZE: usize = 18;
@ -73,6 +73,34 @@ impl From<ColorBuf> for TGAColor {
}
}
impl Add for TGAColor {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
bgra: [
self[0].saturating_add(rhs[0]),
self[1].saturating_add(rhs[1]),
self[2].saturating_add(rhs[2]),
self[3].saturating_add(rhs[3]),
],
}
}
}
impl Mul<f32> for TGAColor {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
let b = (self.b() as f32 * rhs).round_ties_even() as u8;
let g = (self.g() as f32 * rhs).round_ties_even() as u8;
let r = (self.r() as f32 * rhs).round_ties_even() as u8;
let a = (self.a() as f32 * rhs).round_ties_even() as u8;
Self { bgra: [b, g, r, a] }
}
}
impl TGAColor {
pub fn new() -> Self {
Self {
@ -80,20 +108,20 @@ impl TGAColor {
}
}
pub fn b(&mut self) -> &mut u8 {
&mut self[0]
pub fn b(&self) -> u8 {
self[0]
}
pub fn g(&mut self) -> &mut u8 {
&mut self[1]
pub fn g(&self) -> u8 {
self[1]
}
pub fn r(&mut self) -> &mut u8 {
&mut self[2]
pub fn r(&self) -> u8 {
self[2]
}
pub fn a(&mut self) -> &mut u8 {
&mut self[3]
pub fn a(&self) -> u8 {
self[3]
}
}