Browse Source

First working z-buffer.

master
Georg Hopp 6 years ago
parent
commit
7900e2ff6a
Signed by: ghopp GPG Key ID: 4C5D226768784538
  1. 4
      fractional/src/easel.rs
  2. 14
      fractional/src/geometry.rs
  3. 14
      fractional/src/main.rs
  4. 29
      fractional/src/xcb.rs

4
fractional/src/easel.rs

@ -156,6 +156,10 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
fn edge(self, b :&Self) -> Vec<Self> { fn edge(self, b :&Self) -> Vec<Self> {
self.edge_iter(b).collect() self.edge_iter(b).collect()
} }
fn face(edges :&[Self]) -> Vec<Self> {
edges.to_vec()
}
} }
impl<T> Display for Coordinate<T> { impl<T> Display for Coordinate<T> {

14
fractional/src/geometry.rs

@ -157,6 +157,7 @@ pub struct Camera<T>
where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> { where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
width :T, width :T,
height :T, height :T,
distance :T,
project :TMatrix<T>, project :TMatrix<T>,
} }
@ -183,6 +184,7 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
Camera { width: width Camera { width: width
, height: height , height: height
, distance: d
, project: TMatrix::new( , project: TMatrix::new(
( fov, 0.into(), wh, 0.into()) ( fov, 0.into(), wh, 0.into())
, (0.into(), fov, hh, 0.into()) , (0.into(), fov, hh, 0.into())
@ -190,6 +192,10 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
, (0.into(), 0.into(), 1.into(), 0.into()) ) } , (0.into(), 0.into(), 1.into(), 0.into()) ) }
} }
pub fn get_distance(&self) -> T {
self.distance
}
pub fn get_projection(&self) -> TMatrix<T> { pub fn get_projection(&self) -> TMatrix<T> {
self.project self.project
} }
@ -253,11 +259,6 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
let zc :T = T::sqrt(f3).unwrap() / f3 * a; let zc :T = T::sqrt(f3).unwrap() / f3 * a;
let ah :T = a / 2.into(); 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) let ps = vec!( Point::new( f0, yc, f0)
, Point::new(-ah, -yi, -zi) , Point::new(-ah, -yi, -zi)
, Point::new( ah, -yi, -zi) , Point::new( ah, -yi, -zi)
@ -285,8 +286,6 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
let fs = vec!(Face::new(vec!(0, 1, 2), &ps)); let fs = vec!(Face::new(vec!(0, 1, 2), &ps));
println!("== {:?}", fs);
Polyeder{ points: ps, faces: fs } Polyeder{ points: ps, faces: fs }
} }
@ -347,7 +346,6 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
// matrix we do not need to do it here. // matrix we do not need to do it here.
let to_coord = |p :&usize| { let to_coord = |p :&usize| {
let Point(v, _) = camera.project(self.points[*p]); 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()) Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into())
}; };
let to_poly = |f :&Face<T>| { let to_poly = |f :&Face<T>| {

14
fractional/src/main.rs

@ -35,8 +35,7 @@ use fractional::fractional::{Fractional, from_vector};
use fractional::trigonometry::Trig; use fractional::trigonometry::Trig;
use fractional::vector::Vector; use fractional::vector::Vector;
use fractional::transform::{TMatrix, Transformable}; use fractional::transform::{TMatrix, Transformable};
use fractional::xcb::{XcbEasel, XcbCanvas};
use fractional::xcb::XcbEasel;
use fractional::geometry::{Camera,DirectLight,Polyeder,Primitives}; use fractional::geometry::{Camera,DirectLight,Polyeder,Primitives};
@ -322,8 +321,8 @@ fn _democanvas<T>( xcb :&XcbEasel
// was 50. // was 50.
canvas.set_title(title); canvas.set_title(title);
<XcbCanvas as Canvas<T>>::init_events(&canvas);
<XcbCanvas as Canvas<T>>::start_events(&canvas, tx.clone());
canvas.init_events();
canvas.start_events(tx.clone());
thread::spawn(move || { thread::spawn(move || {
let start = Instant::now(); let start = Instant::now();
@ -348,7 +347,7 @@ fn _democanvas<T>( xcb :&XcbEasel
//let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) ); //let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) );
//let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) ); //let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) );
<XcbCanvas as Canvas<T>>::clear(&mut canvas);
canvas.clear();
for (o, color) in objects { for (o, color) in objects {
for (pg, c) in o.project(&camera, &light, color) { for (pg, c) in o.project(&camera, &light, color) {
@ -367,11 +366,10 @@ fn _democanvas<T>( xcb :&XcbEasel
} }
last = last + step*(f + 1); last = last + step*(f + 1);
<XcbCanvas as Canvas<T>>::put_text( &canvas
, Coordinate(10, 15, 0.into())
canvas.put_text( Coordinate(10, 15, 0.into())
, &format!( "sleep: {:?}" , &format!( "sleep: {:?}"
, last - Instant::now() )); , last - Instant::now() ));
<XcbCanvas as Canvas<T>>::show(&canvas);
canvas.show();
thread::sleep(last - Instant::now()); thread::sleep(last - Instant::now());
} }
}); });

29
fractional/src/xcb.rs

@ -24,18 +24,20 @@ use std::sync::Arc;
use std::ptr; //::{null, null_mut}; use std::ptr; //::{null, null_mut};
use std::thread; use std::thread;
use std::sync::mpsc; use std::sync::mpsc;
use std::ops::{Add, Sub, Div};
use crate::easel::{Easel, Canvas, Drawable, Coordinate, Coordinates}; use crate::easel::{Easel, Canvas, Drawable, Coordinate, Coordinates};
#[derive(Clone)] #[derive(Clone)]
pub struct XcbEasel (Arc<xcb::Connection>, i32); pub struct XcbEasel (Arc<xcb::Connection>, i32);
pub struct XcbCanvas<'a> { conn :Arc<xcb::Connection>
pub struct XcbCanvas<'a, T> { conn :Arc<xcb::Connection>
, width :u16 , width :u16
, height :u16 , height :u16
, window :u32 , window :u32
, pixmap :u32 , pixmap :u32
, gc :u32 , gc :u32
, zbuf :Vec<T>
, shm :Box<&'a mut [u32]> } , shm :Box<&'a mut [u32]> }
impl XcbEasel { impl XcbEasel {
@ -55,7 +57,10 @@ impl XcbEasel {
self.setup().roots().nth(*num as usize) self.setup().roots().nth(*num as usize)
} }
pub fn canvas<'a>(&self, width :u16, height :u16) -> Option<XcbCanvas<'a>> {
pub fn canvas<'a, T>( &self
, width :u16
, height :u16) -> Option<XcbCanvas<'a, T>>
where T: Clone + From<i32> {
let Self(conn, _) = self; let Self(conn, _) = self;
let conn = conn.clone(); let conn = conn.clone();
let screen = match self.screen() { let screen = match self.screen() {
@ -80,6 +85,7 @@ impl XcbEasel {
, &[ (xcb::GC_FOREGROUND, screen.white_pixel()) , &[ (xcb::GC_FOREGROUND, screen.white_pixel())
, (xcb::GC_GRAPHICS_EXPOSURES, 0) ] ); , (xcb::GC_GRAPHICS_EXPOSURES, 0) ] );
let zbuf :Vec<T> = vec!(0.into(); (width * height) as usize);
let (shmid, shm) = getshm((width * height) as usize); let (shmid, shm) = getshm((width * height) as usize);
xcb::shm::attach(&conn, shmseg, shmid as u32, false); xcb::shm::attach(&conn, shmseg, shmid as u32, false);
unsafe { libc::shmctl(shmid, libc::IPC_RMID, ptr::null_mut()); } unsafe { libc::shmctl(shmid, libc::IPC_RMID, ptr::null_mut()); }
@ -96,11 +102,12 @@ impl XcbEasel {
, window: window , window: window
, pixmap: pixmap , pixmap: pixmap
, gc: gc , gc: gc
, zbuf: zbuf
, shm: Box::new(shm) } ) , shm: Box::new(shm) } )
} }
} }
impl<'a> XcbCanvas<'a> {
impl<'a, T> XcbCanvas<'a, T> {
pub fn set_title(&self, title :&str) { pub fn set_title(&self, title :&str) {
let c = xcb::change_property_checked( &self.conn let c = xcb::change_property_checked( &self.conn
, xcb::PROP_MODE_REPLACE as u8 , xcb::PROP_MODE_REPLACE as u8
@ -129,7 +136,9 @@ fn getshm<'a>(size :usize) -> (i32, &'a mut [u32]) {
impl Easel for XcbEasel {} impl Easel for XcbEasel {}
impl<'a,T> Canvas<T> for XcbCanvas<'a> {
impl<'a, T> Canvas<T> for XcbCanvas<'a, T>
where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
+ Copy + From<i32> + PartialOrd {
fn init_events(&self) { fn init_events(&self) {
let mask = [( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE let mask = [( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE
| xcb::EVENT_MASK_KEY_PRESS | xcb::EVENT_MASK_KEY_PRESS
@ -216,6 +225,7 @@ impl<'a,T> Canvas<T> for XcbCanvas<'a> {
} }
fn clear(&mut self) { fn clear(&mut self) {
self.zbuf = vec!(0.into(); self.zbuf.len());
unsafe { unsafe {
let ptr = self.shm.as_mut_ptr(); let ptr = self.shm.as_mut_ptr();
ptr::write_bytes( ptr, 0 ptr::write_bytes( ptr, 0
@ -227,11 +237,14 @@ impl<'a,T> Canvas<T> for XcbCanvas<'a> {
let Coordinates(c) = d.plot(); let Coordinates(c) = d.plot();
let Coordinate(xofs, yofs, _) = ofs; 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; let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize;
if self.zbuf[idx] < zr {
self.zbuf[idx] = zr;
self.shm[idx] = color; self.shm[idx] = color;
} }
} }
}
fn put_text(&self, ofs :Coordinate<T>, s :&str) { fn put_text(&self, ofs :Coordinate<T>, s :&str) {
let Coordinate(xofs, yofs, _) = ofs; let Coordinate(xofs, yofs, _) = ofs;
@ -241,12 +254,14 @@ impl<'a,T> Canvas<T> for XcbCanvas<'a> {
} }
fn set_pixel(&mut self, c :Coordinate<T>, color :u32) { fn set_pixel(&mut self, c :Coordinate<T>, color :u32) {
let Coordinate(x, y, _) = c;
let Coordinate(x, y, zr) = c;
let idx :usize = (y * (self.width as i32) + x) as usize; let idx :usize = (y * (self.width as i32) + x) as usize;
//print!("({}, {})", idx, color);
if self.zbuf[idx] < zr {
self.zbuf[idx] = zr;
self.shm[idx] = color; self.shm[idx] = color;
} }
}
fn show(&self) { fn show(&self) {
xcb::copy_area( &self.conn, self.pixmap, self.window, self.gc xcb::copy_area( &self.conn, self.pixmap, self.window, self.gc

Loading…
Cancel
Save