From 7900e2ff6a80d636cdb07ef049f902fd643a1311 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Wed, 8 Jan 2020 20:03:40 +0100 Subject: [PATCH] First working z-buffer. --- fractional/src/easel.rs | 4 ++++ fractional/src/geometry.rs | 28 +++++++++++------------- fractional/src/main.rs | 18 +++++++-------- fractional/src/xcb.rs | 45 +++++++++++++++++++++++++------------- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/fractional/src/easel.rs b/fractional/src/easel.rs index 9e6d5a6..c9a3f7e 100644 --- a/fractional/src/easel.rs +++ b/fractional/src/easel.rs @@ -156,6 +156,10 @@ where T: Add + Sub + Div fn edge(self, b :&Self) -> Vec { self.edge_iter(b).collect() } + + fn face(edges :&[Self]) -> Vec { + edges.to_vec() + } } impl Display for Coordinate { diff --git a/fractional/src/geometry.rs b/fractional/src/geometry.rs index 0f9b882..00dad89 100644 --- a/fractional/src/geometry.rs +++ b/fractional/src/geometry.rs @@ -155,9 +155,10 @@ where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From { pub struct Camera where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From { - width :T, - height :T, - project :TMatrix, + width :T, + height :T, + distance :T, + project :TMatrix, } pub struct DirectLight @@ -181,15 +182,20 @@ where T: Add + Sub + Neg let wh = width / 2.into(); let hh = height / 2.into(); - Camera { width: width - , height: height - , project: TMatrix::new( + Camera { width: width + , height: height + , distance: d + , project: TMatrix::new( ( fov, 0.into(), wh, 0.into()) , (0.into(), fov, hh, 0.into()) , (0.into(), 0.into(), d, 1.into()) , (0.into(), 0.into(), 1.into(), 0.into()) ) } } + pub fn get_distance(&self) -> T { + self.distance + } + pub fn get_projection(&self) -> TMatrix { self.project } @@ -253,11 +259,6 @@ where T: Add + Sub + Neg let zc :T = T::sqrt(f3).unwrap() / f3 * a; let ah :T = a / 2.into(); - // half the height in y - let _yh :T = a / f6 * T::sqrt(f6).unwrap(); - // half the deeps in z - let _zh :T = T::sqrt(f3).unwrap() / f4 * a; - let ps = vec!( Point::new( f0, yc, f0) , Point::new(-ah, -yi, -zi) , Point::new( ah, -yi, -zi) @@ -285,8 +286,6 @@ where T: Add + Sub + Neg let fs = vec!(Face::new(vec!(0, 1, 2), &ps)); - println!("== {:?}", fs); - Polyeder{ points: ps, faces: fs } } @@ -347,7 +346,6 @@ where T: Add + Sub + Neg // matrix we do not need to do it here. let to_coord = |p :&usize| { let Point(v, _) = camera.project(self.points[*p]); - // println!("== {:?} / {:?}", self.points[*p], (v.z() - 1.into()).recip()); Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into()) }; let to_poly = |f :&Face| { @@ -378,7 +376,7 @@ where T: Add + Sub + Neg }}; let mut ps :Vec<(Polygon, u32)> = self.faces.iter() - . filter_map(to_poly).collect(); + . filter_map(to_poly).collect(); // this sorts by the color value which is no longer neccessary as soon // as the z-buffer is complete. ps.sort_by(|a, b| a.1.cmp(&b.1)); diff --git a/fractional/src/main.rs b/fractional/src/main.rs index f0408e2..33a50f8 100644 --- a/fractional/src/main.rs +++ b/fractional/src/main.rs @@ -35,8 +35,7 @@ use fractional::fractional::{Fractional, from_vector}; use fractional::trigonometry::Trig; use fractional::vector::Vector; use fractional::transform::{TMatrix, Transformable}; - -use fractional::xcb::{XcbEasel, XcbCanvas}; +use fractional::xcb::XcbEasel; use fractional::geometry::{Camera,DirectLight,Polyeder,Primitives}; @@ -322,8 +321,8 @@ fn _democanvas( xcb :&XcbEasel // was 50. canvas.set_title(title); - >::init_events(&canvas); - >::start_events(&canvas, tx.clone()); + canvas.init_events(); + canvas.start_events(tx.clone()); thread::spawn(move || { let start = Instant::now(); @@ -348,7 +347,7 @@ fn _democanvas( xcb :&XcbEasel //let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) ); //let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) ); - >::clear(&mut canvas); + canvas.clear(); for (o, color) in objects { for (pg, c) in o.project(&camera, &light, color) { @@ -367,11 +366,10 @@ fn _democanvas( xcb :&XcbEasel } last = last + step*(f + 1); - >::put_text( &canvas - , Coordinate(10, 15, 0.into()) - , &format!( "sleep: {:?}" - , last - Instant::now() )); - >::show(&canvas); + canvas.put_text( Coordinate(10, 15, 0.into()) + , &format!( "sleep: {:?}" + , last - Instant::now() )); + canvas.show(); thread::sleep(last - Instant::now()); } }); diff --git a/fractional/src/xcb.rs b/fractional/src/xcb.rs index 9c09458..597be4e 100644 --- a/fractional/src/xcb.rs +++ b/fractional/src/xcb.rs @@ -24,19 +24,21 @@ use std::sync::Arc; use std::ptr; //::{null, null_mut}; use std::thread; use std::sync::mpsc; +use std::ops::{Add, Sub, Div}; use crate::easel::{Easel, Canvas, Drawable, Coordinate, Coordinates}; #[derive(Clone)] pub struct XcbEasel (Arc, i32); -pub struct XcbCanvas<'a> { conn :Arc - , width :u16 - , height :u16 - , window :u32 - , pixmap :u32 - , gc :u32 - , shm :Box<&'a mut [u32]> } +pub struct XcbCanvas<'a, T> { conn :Arc + , width :u16 + , height :u16 + , window :u32 + , pixmap :u32 + , gc :u32 + , zbuf :Vec + , shm :Box<&'a mut [u32]> } impl XcbEasel { pub fn new() -> Result { @@ -55,7 +57,10 @@ impl XcbEasel { self.setup().roots().nth(*num as usize) } - pub fn canvas<'a>(&self, width :u16, height :u16) -> Option> { + pub fn canvas<'a, T>( &self + , width :u16 + , height :u16) -> Option> + where T: Clone + From { let Self(conn, _) = self; let conn = conn.clone(); let screen = match self.screen() { @@ -80,6 +85,7 @@ impl XcbEasel { , &[ (xcb::GC_FOREGROUND, screen.white_pixel()) , (xcb::GC_GRAPHICS_EXPOSURES, 0) ] ); + let zbuf :Vec = vec!(0.into(); (width * height) as usize); let (shmid, shm) = getshm((width * height) as usize); xcb::shm::attach(&conn, shmseg, shmid as u32, false); unsafe { libc::shmctl(shmid, libc::IPC_RMID, ptr::null_mut()); } @@ -96,11 +102,12 @@ impl XcbEasel { , window: window , pixmap: pixmap , gc: gc + , zbuf: zbuf , shm: Box::new(shm) } ) } } -impl<'a> XcbCanvas<'a> { +impl<'a, T> XcbCanvas<'a, T> { pub fn set_title(&self, title :&str) { let c = xcb::change_property_checked( &self.conn , xcb::PROP_MODE_REPLACE as u8 @@ -129,7 +136,9 @@ fn getshm<'a>(size :usize) -> (i32, &'a mut [u32]) { impl Easel for XcbEasel {} -impl<'a,T> Canvas for XcbCanvas<'a> { +impl<'a, T> Canvas for XcbCanvas<'a, T> +where T: Add + Sub + Div + + Copy + From + PartialOrd { fn init_events(&self) { let mask = [( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_KEY_PRESS @@ -216,6 +225,7 @@ impl<'a,T> Canvas for XcbCanvas<'a> { } fn clear(&mut self) { + self.zbuf = vec!(0.into(); self.zbuf.len()); unsafe { let ptr = self.shm.as_mut_ptr(); ptr::write_bytes( ptr, 0 @@ -227,9 +237,12 @@ impl<'a,T> Canvas for XcbCanvas<'a> { let Coordinates(c) = d.plot(); let Coordinate(xofs, yofs, _) = ofs; - for Coordinate(x, y, _) in c { + for Coordinate(x, y, zr) in c { let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize; - self.shm[idx] = color; + if self.zbuf[idx] < zr { + self.zbuf[idx] = zr; + self.shm[idx] = color; + } } } @@ -241,11 +254,13 @@ impl<'a,T> Canvas for XcbCanvas<'a> { } fn set_pixel(&mut self, c :Coordinate, color :u32) { - let Coordinate(x, y, _) = c; + let Coordinate(x, y, zr) = c; let idx :usize = (y * (self.width as i32) + x) as usize; - //print!("({}, {})", idx, color); - self.shm[idx] = color; + if self.zbuf[idx] < zr { + self.zbuf[idx] = zr; + self.shm[idx] = color; + } } fn show(&self) {