Showing
4 changed files
with
55 additions
and
40 deletions
... | ... | @@ -156,6 +156,10 @@ where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> |
156 | 156 | fn edge(self, b :&Self) -> Vec<Self> { |
157 | 157 | self.edge_iter(b).collect() |
158 | 158 | } |
159 | + | |
160 | + fn face(edges :&[Self]) -> Vec<Self> { | |
161 | + edges.to_vec() | |
162 | + } | |
159 | 163 | } |
160 | 164 | |
161 | 165 | impl<T> Display for Coordinate<T> { | ... | ... |
... | ... | @@ -155,9 +155,10 @@ where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> { |
155 | 155 | |
156 | 156 | pub struct Camera<T> |
157 | 157 | where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> { |
158 | - width :T, | |
159 | - height :T, | |
160 | - project :TMatrix<T>, | |
158 | + width :T, | |
159 | + height :T, | |
160 | + distance :T, | |
161 | + project :TMatrix<T>, | |
161 | 162 | } |
162 | 163 | |
163 | 164 | pub struct DirectLight<T> |
... | ... | @@ -181,15 +182,20 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> |
181 | 182 | let wh = width / 2.into(); |
182 | 183 | let hh = height / 2.into(); |
183 | 184 | |
184 | - Camera { width: width | |
185 | - , height: height | |
186 | - , project: TMatrix::new( | |
185 | + Camera { width: width | |
186 | + , height: height | |
187 | + , distance: d | |
188 | + , project: TMatrix::new( | |
187 | 189 | ( fov, 0.into(), wh, 0.into()) |
188 | 190 | , (0.into(), fov, hh, 0.into()) |
189 | 191 | , (0.into(), 0.into(), d, 1.into()) |
190 | 192 | , (0.into(), 0.into(), 1.into(), 0.into()) ) } |
191 | 193 | } |
192 | 194 | |
195 | + pub fn get_distance(&self) -> T { | |
196 | + self.distance | |
197 | + } | |
198 | + | |
193 | 199 | pub fn get_projection(&self) -> TMatrix<T> { |
194 | 200 | self.project |
195 | 201 | } |
... | ... | @@ -253,11 +259,6 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> |
253 | 259 | let zc :T = T::sqrt(f3).unwrap() / f3 * a; |
254 | 260 | let ah :T = a / 2.into(); |
255 | 261 | |
256 | - // half the height in y | |
257 | - let _yh :T = a / f6 * T::sqrt(f6).unwrap(); | |
258 | - // half the deeps in z | |
259 | - let _zh :T = T::sqrt(f3).unwrap() / f4 * a; | |
260 | - | |
261 | 262 | let ps = vec!( Point::new( f0, yc, f0) |
262 | 263 | , Point::new(-ah, -yi, -zi) |
263 | 264 | , Point::new( ah, -yi, -zi) |
... | ... | @@ -285,8 +286,6 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> |
285 | 286 | |
286 | 287 | let fs = vec!(Face::new(vec!(0, 1, 2), &ps)); |
287 | 288 | |
288 | - println!("== {:?}", fs); | |
289 | - | |
290 | 289 | Polyeder{ points: ps, faces: fs } |
291 | 290 | } |
292 | 291 | |
... | ... | @@ -347,7 +346,6 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> |
347 | 346 | // matrix we do not need to do it here. |
348 | 347 | let to_coord = |p :&usize| { |
349 | 348 | let Point(v, _) = camera.project(self.points[*p]); |
350 | - // println!("== {:?} / {:?}", self.points[*p], (v.z() - 1.into()).recip()); | |
351 | 349 | Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into()) |
352 | 350 | }; |
353 | 351 | let to_poly = |f :&Face<T>| { |
... | ... | @@ -378,7 +376,7 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T> |
378 | 376 | }}; |
379 | 377 | |
380 | 378 | let mut ps :Vec<(Polygon<T>, u32)> = self.faces.iter() |
381 | - . filter_map(to_poly).collect(); | |
379 | + . filter_map(to_poly).collect(); | |
382 | 380 | // this sorts by the color value which is no longer neccessary as soon |
383 | 381 | // as the z-buffer is complete. |
384 | 382 | ps.sort_by(|a, b| a.1.cmp(&b.1)); | ... | ... |
... | ... | @@ -35,8 +35,7 @@ use fractional::fractional::{Fractional, from_vector}; |
35 | 35 | use fractional::trigonometry::Trig; |
36 | 36 | use fractional::vector::Vector; |
37 | 37 | use fractional::transform::{TMatrix, Transformable}; |
38 | - | |
39 | -use fractional::xcb::{XcbEasel, XcbCanvas}; | |
38 | +use fractional::xcb::XcbEasel; | |
40 | 39 | |
41 | 40 | use fractional::geometry::{Camera,DirectLight,Polyeder,Primitives}; |
42 | 41 | |
... | ... | @@ -322,8 +321,8 @@ fn _democanvas<T>( xcb :&XcbEasel |
322 | 321 | // was 50. |
323 | 322 | |
324 | 323 | canvas.set_title(title); |
325 | - <XcbCanvas as Canvas<T>>::init_events(&canvas); | |
326 | - <XcbCanvas as Canvas<T>>::start_events(&canvas, tx.clone()); | |
324 | + canvas.init_events(); | |
325 | + canvas.start_events(tx.clone()); | |
327 | 326 | |
328 | 327 | thread::spawn(move || { |
329 | 328 | let start = Instant::now(); |
... | ... | @@ -348,7 +347,7 @@ fn _democanvas<T>( xcb :&XcbEasel |
348 | 347 | //let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) ); |
349 | 348 | //let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) ); |
350 | 349 | |
351 | - <XcbCanvas as Canvas<T>>::clear(&mut canvas); | |
350 | + canvas.clear(); | |
352 | 351 | |
353 | 352 | for (o, color) in objects { |
354 | 353 | for (pg, c) in o.project(&camera, &light, color) { |
... | ... | @@ -367,11 +366,10 @@ fn _democanvas<T>( xcb :&XcbEasel |
367 | 366 | } |
368 | 367 | |
369 | 368 | last = last + step*(f + 1); |
370 | - <XcbCanvas as Canvas<T>>::put_text( &canvas | |
371 | - , Coordinate(10, 15, 0.into()) | |
372 | - , &format!( "sleep: {:?}" | |
373 | - , last - Instant::now() )); | |
374 | - <XcbCanvas as Canvas<T>>::show(&canvas); | |
369 | + canvas.put_text( Coordinate(10, 15, 0.into()) | |
370 | + , &format!( "sleep: {:?}" | |
371 | + , last - Instant::now() )); | |
372 | + canvas.show(); | |
375 | 373 | thread::sleep(last - Instant::now()); |
376 | 374 | } |
377 | 375 | }); | ... | ... |
... | ... | @@ -24,19 +24,21 @@ use std::sync::Arc; |
24 | 24 | use std::ptr; //::{null, null_mut}; |
25 | 25 | use std::thread; |
26 | 26 | use std::sync::mpsc; |
27 | +use std::ops::{Add, Sub, Div}; | |
27 | 28 | |
28 | 29 | use crate::easel::{Easel, Canvas, Drawable, Coordinate, Coordinates}; |
29 | 30 | |
30 | 31 | #[derive(Clone)] |
31 | 32 | pub struct XcbEasel (Arc<xcb::Connection>, i32); |
32 | 33 | |
33 | -pub struct XcbCanvas<'a> { conn :Arc<xcb::Connection> | |
34 | - , width :u16 | |
35 | - , height :u16 | |
36 | - , window :u32 | |
37 | - , pixmap :u32 | |
38 | - , gc :u32 | |
39 | - , shm :Box<&'a mut [u32]> } | |
34 | +pub struct XcbCanvas<'a, T> { conn :Arc<xcb::Connection> | |
35 | + , width :u16 | |
36 | + , height :u16 | |
37 | + , window :u32 | |
38 | + , pixmap :u32 | |
39 | + , gc :u32 | |
40 | + , zbuf :Vec<T> | |
41 | + , shm :Box<&'a mut [u32]> } | |
40 | 42 | |
41 | 43 | impl XcbEasel { |
42 | 44 | pub fn new() -> Result<XcbEasel, xcb::ConnError> { |
... | ... | @@ -55,7 +57,10 @@ impl XcbEasel { |
55 | 57 | self.setup().roots().nth(*num as usize) |
56 | 58 | } |
57 | 59 | |
58 | - pub fn canvas<'a>(&self, width :u16, height :u16) -> Option<XcbCanvas<'a>> { | |
60 | + pub fn canvas<'a, T>( &self | |
61 | + , width :u16 | |
62 | + , height :u16) -> Option<XcbCanvas<'a, T>> | |
63 | + where T: Clone + From<i32> { | |
59 | 64 | let Self(conn, _) = self; |
60 | 65 | let conn = conn.clone(); |
61 | 66 | let screen = match self.screen() { |
... | ... | @@ -80,6 +85,7 @@ impl XcbEasel { |
80 | 85 | , &[ (xcb::GC_FOREGROUND, screen.white_pixel()) |
81 | 86 | , (xcb::GC_GRAPHICS_EXPOSURES, 0) ] ); |
82 | 87 | |
88 | + let zbuf :Vec<T> = vec!(0.into(); (width * height) as usize); | |
83 | 89 | let (shmid, shm) = getshm((width * height) as usize); |
84 | 90 | xcb::shm::attach(&conn, shmseg, shmid as u32, false); |
85 | 91 | unsafe { libc::shmctl(shmid, libc::IPC_RMID, ptr::null_mut()); } |
... | ... | @@ -96,11 +102,12 @@ impl XcbEasel { |
96 | 102 | , window: window |
97 | 103 | , pixmap: pixmap |
98 | 104 | , gc: gc |
105 | + , zbuf: zbuf | |
99 | 106 | , shm: Box::new(shm) } ) |
100 | 107 | } |
101 | 108 | } |
102 | 109 | |
103 | -impl<'a> XcbCanvas<'a> { | |
110 | +impl<'a, T> XcbCanvas<'a, T> { | |
104 | 111 | pub fn set_title(&self, title :&str) { |
105 | 112 | let c = xcb::change_property_checked( &self.conn |
106 | 113 | , xcb::PROP_MODE_REPLACE as u8 |
... | ... | @@ -129,7 +136,9 @@ fn getshm<'a>(size :usize) -> (i32, &'a mut [u32]) { |
129 | 136 | |
130 | 137 | impl Easel for XcbEasel {} |
131 | 138 | |
132 | -impl<'a,T> Canvas<T> for XcbCanvas<'a> { | |
139 | +impl<'a, T> Canvas<T> for XcbCanvas<'a, T> | |
140 | +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T> | |
141 | + + Copy + From<i32> + PartialOrd { | |
133 | 142 | fn init_events(&self) { |
134 | 143 | let mask = [( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE |
135 | 144 | | xcb::EVENT_MASK_KEY_PRESS |
... | ... | @@ -216,6 +225,7 @@ impl<'a,T> Canvas<T> for XcbCanvas<'a> { |
216 | 225 | } |
217 | 226 | |
218 | 227 | fn clear(&mut self) { |
228 | + self.zbuf = vec!(0.into(); self.zbuf.len()); | |
219 | 229 | unsafe { |
220 | 230 | let ptr = self.shm.as_mut_ptr(); |
221 | 231 | ptr::write_bytes( ptr, 0 |
... | ... | @@ -227,9 +237,12 @@ impl<'a,T> Canvas<T> for XcbCanvas<'a> { |
227 | 237 | let Coordinates(c) = d.plot(); |
228 | 238 | let Coordinate(xofs, yofs, _) = ofs; |
229 | 239 | |
230 | - for Coordinate(x, y, _) in c { | |
240 | + for Coordinate(x, y, zr) in c { | |
231 | 241 | let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize; |
232 | - self.shm[idx] = color; | |
242 | + if self.zbuf[idx] < zr { | |
243 | + self.zbuf[idx] = zr; | |
244 | + self.shm[idx] = color; | |
245 | + } | |
233 | 246 | } |
234 | 247 | } |
235 | 248 | |
... | ... | @@ -241,11 +254,13 @@ impl<'a,T> Canvas<T> for XcbCanvas<'a> { |
241 | 254 | } |
242 | 255 | |
243 | 256 | fn set_pixel(&mut self, c :Coordinate<T>, color :u32) { |
244 | - let Coordinate(x, y, _) = c; | |
257 | + let Coordinate(x, y, zr) = c; | |
245 | 258 | let idx :usize = (y * (self.width as i32) + x) as usize; |
246 | 259 | |
247 | - //print!("({}, {})", idx, color); | |
248 | - self.shm[idx] = color; | |
260 | + if self.zbuf[idx] < zr { | |
261 | + self.zbuf[idx] = zr; | |
262 | + self.shm[idx] = color; | |
263 | + } | |
249 | 264 | } |
250 | 265 | |
251 | 266 | fn show(&self) { | ... | ... |
Please
register
or
login
to post a comment