render head with random color triangles and no backface culling
This commit is contained in:
parent
10ac742f4f
commit
90420bdc72
2 changed files with 47 additions and 39 deletions
58
src/main.rs
58
src/main.rs
|
@ -36,11 +36,13 @@ const YELLOW: TGAColor = TGAColor {
|
|||
};
|
||||
|
||||
fn main() {
|
||||
let w = 128;
|
||||
let h = 128;
|
||||
let w = 800;
|
||||
let h = 800;
|
||||
let mut fb = TGAImage::new(w, h, TGAFormat::RGB);
|
||||
fill_triangles(&mut fb);
|
||||
fb.write_file("triangles.tga", true, true).unwrap();
|
||||
// fill_triangles(&mut fb);
|
||||
// fb.write_file("triangles.tga", true, true).unwrap();
|
||||
|
||||
_render_head(&mut fb);
|
||||
}
|
||||
|
||||
fn fill_triangles(fb: &mut TGAImage) {
|
||||
|
@ -63,11 +65,17 @@ fn fill_triangles(fb: &mut TGAImage) {
|
|||
t3.render_filled(GREEN, fb);
|
||||
}
|
||||
|
||||
fn _render_diablo(model: Model, fb: &mut TGAImage) {
|
||||
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;
|
||||
|
@ -121,30 +129,17 @@ fn line(mut a: Point2i, mut b: Point2i, color: TGAColor, mut 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;
|
||||
(a.x..b.x).into_par_iter().for_each(|x| {
|
||||
let ny = {
|
||||
if let Ok(y) = y.lock() {
|
||||
*y
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut y = a.y as f32;
|
||||
for x in a.x..b.x {
|
||||
let (px, py) = if is_steep {
|
||||
(ny.round_ties_even() as i32, x)
|
||||
(y.round_ties_even() as i32, x)
|
||||
} else {
|
||||
(x, ny.round_ties_even() as i32)
|
||||
(x, y.round_ties_even() as i32)
|
||||
};
|
||||
if let Ok(mut fb) = fb.lock() {
|
||||
fb.set(px as u32, py as u32, color);
|
||||
y += step;
|
||||
}
|
||||
if let Ok(mut y) = y.lock() {
|
||||
*y += step;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
@ -159,15 +154,6 @@ impl Triangle {
|
|||
Self { a, b, c }
|
||||
}
|
||||
|
||||
pub fn sort(&mut self) {
|
||||
let mut sorted = [self.a, self.b, self.c];
|
||||
sorted.sort_unstable_by(|a, b| a.y.cmp(&b.y));
|
||||
let [a, b, c] = sorted;
|
||||
self.a = a;
|
||||
self.b = b;
|
||||
self.c = c;
|
||||
}
|
||||
|
||||
pub fn signed_area(&self) -> f32 {
|
||||
0.5 * ((self.b.y - self.a.y) * (self.a.x + self.b.x)
|
||||
+ (self.c.y - self.b.y) * (self.c.x + self.b.x)
|
||||
|
@ -189,13 +175,13 @@ impl Triangle {
|
|||
pub fn render_filled(&self, color: TGAColor, fb: &mut TGAImage) {
|
||||
let fb = Arc::new(Mutex::new(fb));
|
||||
let bb = self.bb();
|
||||
let total_area = self.signed_area();
|
||||
let total_area_sign = self.signed_area().signum();
|
||||
(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 = Triangle::new(p, self.a, self.b).signed_area() / total_area;
|
||||
let b = Triangle::new(p, self.b, self.c).signed_area() / total_area;
|
||||
let c = Triangle::new(p, self.c, self.a).signed_area() / total_area;
|
||||
let a = Triangle::new(p, self.a, self.b).signed_area().signum() * total_area_sign;
|
||||
let b = Triangle::new(p, self.b, self.c).signed_area().signum() * total_area_sign;
|
||||
let c = Triangle::new(p, self.c, self.a).signed_area().signum() * total_area_sign;
|
||||
|
||||
if a.is_sign_positive()
|
||||
&& b.is_sign_positive()
|
||||
|
|
24
src/model.rs
24
src/model.rs
|
@ -1,7 +1,9 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
use crate::{
|
||||
RED, line,
|
||||
RED, Triangle, line,
|
||||
point::{Point2i, Point3f},
|
||||
tga::TGAImage,
|
||||
};
|
||||
|
@ -92,6 +94,26 @@ impl Model {
|
|||
line(c, a, RED, framebuffer);
|
||||
}
|
||||
}
|
||||
pub fn render_triangles(&self, framebuffer: &mut TGAImage) {
|
||||
let width = framebuffer.width;
|
||||
let height = framebuffer.height;
|
||||
|
||||
let mut rng = rand::rng();
|
||||
for face in self.faces.iter() {
|
||||
let a = world2view(self.verts[face[0]], width, height);
|
||||
let b = world2view(self.verts[face[1]], width, height);
|
||||
let c = world2view(self.verts[face[2]], width, height);
|
||||
let triangle = Triangle::new(a, b, c);
|
||||
let color = [
|
||||
rng.random_range(0..=255u8),
|
||||
rng.random_range(0..=255u8),
|
||||
rng.random_range(0..=255u8),
|
||||
255,
|
||||
]
|
||||
.into();
|
||||
triangle.render_filled(color, framebuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn world2view(point: Point3f, width: u32, height: u32) -> Point2i {
|
||||
|
|
Loading…
Reference in a new issue