Commit df1eb1c028b102449d53eaed293ec36e442690e5

Authored by Georg Hopp
1 parent 9911ab01

Pass 1/z into rasterizer and already interpolate on polygon edges

... ... @@ -22,13 +22,14 @@
22 22 //
23 23 use std::cmp;
24 24 use std::fmt::{Formatter, Display, Result};
  25 +use std::ops::{Add, Sub, Div};
25 26 use std::sync::mpsc;
26 27
27 28 pub trait Easel {
28 29 //fn canvas(&mut self, width :u16, height :u16) -> Option<&dyn Canvas>;
29 30 }
30 31
31   -pub trait Canvas {
  32 +pub trait Canvas<T> {
32 33 fn init_events(&self);
33 34 fn start_events(&self, tx :mpsc::Sender<i32>);
34 35
... ... @@ -36,65 +37,71 @@ pub trait Canvas {
36 37 fn height(&self) -> u16;
37 38
38 39 fn clear(&mut self);
39   - fn draw(&mut self, c :&dyn Drawable, ofs :Coordinate, color :u32);
40   - fn put_text(&self, ofs :Coordinate, s :&str);
  40 + fn draw(&mut self, c :&dyn Drawable<T>, ofs :Coordinate<T>, color :u32);
  41 + fn put_text(&self, ofs :Coordinate<T>, s :&str);
41 42 fn show(&self);
42 43 }
43 44
44   -pub trait Drawable {
45   - fn plot(&self) -> Coordinates;
  45 +pub trait Drawable<T> {
  46 + fn plot(&self) -> Coordinates<T>;
46 47 }
47 48
48 49 #[derive(Debug, Clone, Copy)]
49   -pub struct Coordinate(pub i32, pub i32);
  50 +pub struct Coordinate<T>(pub i32, pub i32, pub T);
50 51
51 52 #[derive(Debug, Clone)]
52   -pub struct Coordinates(pub Vec<Coordinate>);
  53 +pub struct Coordinates<T>(pub Vec<Coordinate<T>>);
53 54
54   -impl Coordinate {
  55 +impl<T> Coordinate<T>
  56 +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
  57 + + Clone + Copy + From<i32> {
55 58 // Tail recursive Bresenham line with integer incremental error.
56 59 fn line(self, b :&Self) -> Vec<Self> {
57   - fn inner( v :&mut [Coordinate]
  60 + fn inner<T>( v :&mut [Coordinate<T>]
58 61 , bx :i32, by :i32
59 62 , dx :i32, dy :i32
60 63 , sx :i32, sy :i32
61   - , err :i32) {
62   - let Coordinate(x, y) = v[0];
  64 + , dz :T, err :i32)
  65 + where T: Add<Output = T> + Copy {
  66 +
  67 + let Coordinate(x, y, z) = v[0];
63 68
64 69 if x != bx || y != by {
65   - let (x, y, err) = match (2*err >= dy, 2*err <= dx) {
66   - (true, false) => (x + sx, y, err + dy),
67   - (false, true) => ( x, y + sy, err + dx),
68   - _ => (x + sx, y + sy, err + dx + dy ),
  70 + let (x, y, z, err) = match (2*err >= dy, 2*err <= dx) {
  71 + (true, false) => (x + sx, y, z + dz, err + dy ),
  72 + (false, true) => ( x, y + sy, z + dz, err + dx ),
  73 + _ => (x + sx, y + sy, z + dz, err + dx + dy ),
69 74 };
70   - v[1] = Coordinate(x, y);
71   - inner(&mut v[1..], bx, by, dx, dy, sx, sy, err);
  75 + v[1] = Coordinate(x, y, z);
  76 + inner(&mut v[1..], bx, by, dx, dy, sx, sy, dz, err);
72 77 }
73 78 }
74 79
75   - let Coordinate(ax, ay) = self;
76   - let Coordinate(bx, by) = *b;
  80 + let Coordinate(ax, ay, az) = self;
  81 + let Coordinate(bx, by, bz) = *b;
77 82
78 83 let dx = (bx - ax).abs();
79 84 let sx :i32 = if ax < bx { 1 } else { -1 };
80 85 let dy = -(by - ay).abs();
81 86 let sy :i32 = if ay < by { 1 } else { -1 };
  87 + let size = cmp::max(dx, -dy);
  88 + let dz = (bz - az) / size.into();
82 89
83   - let mut v :Vec<Self> = vec!( Coordinate(0, 0)
84   - ; cmp::max(dx, -dy) as usize + 1);
85   - v[0] = Coordinate(ax, ay);
86   - inner(&mut v, bx, by, dx, dy, sx, sy, dx + dy);
  90 + let mut v :Vec<Self> = vec!( Coordinate(0, 0, 0.into())
  91 + ; (size as usize) + 1);
  92 + v[0] = Coordinate(ax, ay, az);
  93 + inner(&mut v, bx, by, dx, dy, sx, sy, dz, dx + dy);
87 94 v
88 95 }
89 96 }
90 97
91   -impl Display for Coordinate {
  98 +impl<T> Display for Coordinate<T> {
92 99 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
93 100 write!(f, "<{},{}>", self.0, self.1)
94 101 }
95 102 }
96 103
97   -impl Display for Coordinates {
  104 +impl<T> Display for Coordinates<T> where T: Copy {
98 105 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
99 106 let Coordinates(is) = self;
100 107
... ... @@ -116,16 +123,16 @@ impl Display for Coordinates {
116 123
117 124
118 125 #[derive(Debug, Clone, Copy)]
119   -pub struct Point(pub Coordinate);
  126 +pub struct Point<T>(pub Coordinate<T>);
120 127
121   -impl Drawable for Point{
122   - fn plot(&self) -> Coordinates {
  128 +impl<T> Drawable<T> for Point<T> where T: Copy {
  129 + fn plot(&self) -> Coordinates<T> {
123 130 let Point(c) = *self;
124 131 Coordinates(vec!(c))
125 132 }
126 133 }
127 134
128   -impl Display for Point {
  135 +impl<T> Display for Point<T> {
129 136 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
130 137 let Point(p) = self;
131 138 write!(f, "Point[{}]", p)
... ... @@ -133,30 +140,36 @@ impl Display for Point {
133 140 }
134 141
135 142 #[derive(Debug, Clone, Copy)]
136   -pub struct Line(pub Coordinate, pub Coordinate);
  143 +pub struct Line<T>(pub Coordinate<T>, pub Coordinate<T>);
137 144
138   -impl Drawable for Line {
139   - fn plot(&self) -> Coordinates {
  145 +impl<T> Drawable<T> for Line<T>
  146 +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
  147 + + Clone + Copy + From<i32> {
  148 + fn plot(&self) -> Coordinates<T> {
140 149 let Line(a, b) = *self;
141 150 Coordinates(a.line(&b))
142 151 }
143 152 }
144 153
145   -impl Display for Line {
  154 +impl<T> Display for Line<T> {
146 155 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
147 156 let Line(a, b) = self;
148 157 write!(f, "Line[{},{}]", a, b)
149 158 }
150 159 }
151 160
  161 +// In 3D a rectangle is not as trivial as in 2D, it might be somehow rotate
  162 +// and thus we need to specify a Z offset for the other two corners.
  163 +// As I do not need rectangle at all I just comment out this code for now.
  164 +/*
152 165 #[derive(Debug, Clone, Copy)]
153   -pub struct Rectangle(pub Coordinate, pub Coordinate);
  166 +pub struct Rectangle<T>(pub Coordinate<T>, pub Coordinate<T>);
154 167
155   -impl Drawable for Rectangle {
156   - fn plot(&self) -> Coordinates {
  168 +impl<T> Drawable<T> for Rectangle<T> {
  169 + fn plot(&self) -> Coordinates<T> {
157 170 let Rectangle(a, c) = *self;
158   - let Coordinate(ax, ay) = a;
159   - let Coordinate(cx, cy) = c;
  171 + let Coordinate(ax, ay, az) = a;
  172 + let Coordinate(cx, cy, cz) = c;
160 173 let b = Coordinate(cx, ay);
161 174 let d = Coordinate(ax, cy);
162 175
... ... @@ -177,16 +190,19 @@ impl Display for Rectangle {
177 190 write!(f, "Rec[{},{}]", a, b)
178 191 }
179 192 }
  193 +*/
180 194
181 195 #[derive(Debug, Clone)]
182   -pub struct Polyline(pub Coordinates);
  196 +pub struct Polyline<T>(pub Coordinates<T>);
183 197
184   -impl Drawable for Polyline {
185   - fn plot(&self) -> Coordinates {
  198 +impl<T> Drawable<T> for Polyline<T>
  199 +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
  200 + + Clone + Copy + From<i32> {
  201 + fn plot(&self) -> Coordinates<T> {
186 202 let Polyline(Coordinates(cs)) = self;
187 203
188 204 match cs[..] {
189   - [] => Coordinates(Vec::<Coordinate>::new()),
  205 + [] => Coordinates(Vec::<Coordinate<T>>::new()),
190 206 [a] => Coordinates(vec!(a)),
191 207 [a, b] => Coordinates(a.line(&b)),
192 208 _ => {
... ... @@ -203,7 +219,7 @@ impl Drawable for Polyline {
203 219 }
204 220 }
205 221
206   -impl Display for Polyline {
  222 +impl<T> Display for Polyline<T> where T: Copy {
207 223 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
208 224 let Polyline(a) = self;
209 225 write!(f, "PLine[{}]", a)
... ... @@ -211,14 +227,16 @@ impl Display for Polyline {
211 227 }
212 228
213 229 #[derive(Debug, Clone)]
214   -pub struct Polygon(pub Coordinates);
  230 +pub struct Polygon<T>(pub Coordinates<T>);
215 231
216   -impl Drawable for Polygon {
217   - fn plot(&self) -> Coordinates {
  232 +impl<T> Drawable<T> for Polygon<T>
  233 +where T: Add<Output = T> + Sub<Output = T> + Div<Output = T>
  234 + + Clone + Copy + From<i32> {
  235 + fn plot(&self) -> Coordinates<T> {
218 236 let Polygon(Coordinates(cs)) = self;
219 237
220 238 match cs[..] {
221   - [] => Coordinates(Vec::<Coordinate>::new()),
  239 + [] => Coordinates(Vec::<Coordinate<T>>::new()),
222 240 [a] => Coordinates(vec!(a)),
223 241 [a, b] => Coordinates(a.line(&b)),
224 242 _ => {
... ... @@ -240,7 +258,7 @@ impl Drawable for Polygon {
240 258 }
241 259 }
242 260
243   -impl Display for Polygon {
  261 +impl<T> Display for Polygon<T> where T: Copy {
244 262 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
245 263 let Polygon(a) = self;
246 264 write!(f, "Poly[{}]", a)
... ...
... ... @@ -150,7 +150,7 @@ where T: Add + Sub + Neg + Mul + Div + Debug + Copy + Trig + From<i32> {
150 150 fn project( &self
151 151 , camera :&Camera<T>
152 152 , light :&DirectLight<T>
153   - , col :u32 ) -> Vec<(Polygon, u32)>;
  153 + , col :u32 ) -> Vec<(Polygon<T>, u32)>;
154 154 }
155 155
156 156 pub struct Camera<T>
... ... @@ -173,7 +173,7 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
173 173 // equal to the size of the physical screen… e.g. window/canvas thus some
174 174 // effects can't be done. See book for examples with different viewport
175 175 // and screen sizes.
176   - pub fn new(c :&dyn Canvas, angle :i32) -> Self {
  176 + pub fn new(c :&dyn Canvas<T>, angle :i32) -> Self {
177 177 let width :T = (c.width() as i32).into();
178 178 let height :T = (c.height() as i32).into();
179 179 let d :T = 1.into();
... ... @@ -194,9 +194,8 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
194 194 self.project
195 195 }
196 196
197   - pub fn project(&self, p :Point<T>) -> Coordinate {
198   - let Point(v, _) = p.transform(&self.project);
199   - Coordinate(T::round(&v.x()), T::round(&v.y()))
  197 + pub fn project(&self, p :Point<T>) -> Point<T> {
  198 + p.transform(&self.project)
200 199 }
201 200 }
202 201
... ... @@ -318,6 +317,7 @@ impl<T> Primitives<T> for Polyeder<T>
318 317 where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
319 318 + Mul<Output = T> + Div<Output = T>
320 319 + Debug + Copy + Trig + From<i32> + PartialOrd {
  320 + // TODO Maybe this should also be an instance of Transformable…
321 321 fn transform(&self, m :&TMatrix<T>) -> Self {
322 322 let Polyeder{ points: ps, faces: fs } = self;
323 323
... ... @@ -332,23 +332,24 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
332 332 p
333 333 }
334 334
335   - // TODO for now we assume already prejected vertices (points)
336   - // in future we need to distinguish more clear between vertex and point
337   - // and projected_point.
338 335 fn project( &self
339 336 , camera :&Camera<T>
340 337 , light :&DirectLight<T>
341   - , color :u32 ) -> Vec<(Polygon, u32)> {
  338 + , color :u32 ) -> Vec<(Polygon<T>, u32)> {
342 339 // Helper to create a Polygon from Coordinates…
343 340 // TODO probably there needs to be a Polygon constructor for this.
344   - fn polygon<I>(c :I) -> Polygon
345   - where I: Iterator<Item = Coordinate> {
  341 + fn polygon<I, T>(c :I) -> Polygon<T>
  342 + where I: Iterator<Item = Coordinate<T>> {
346 343 Polygon(Coordinates(c.collect()))
347 344 }
348 345
349 346 // this one does the projection... as the projection was the last
350 347 // matrix we do not need to do it here.
351   - let to_coord = |p :&usize| camera.project(self.points[*p]);
  348 + let to_coord = |p :&usize| {
  349 + let Point(v, _) = camera.project(self.points[*p]);
  350 + println!("== {:?} / {:?}", self.points[*p], (v.z() - 1.into()).recip());
  351 + Coordinate(T::round(&v.x()), T::round(&v.y()), v.z() - 1.into())
  352 + };
352 353 let to_poly = |f :&Face<T>| {
353 354 let pg = polygon(f.corners.iter().map(to_coord));
354 355 let mut r :T = (((color >> 16) & 0xFF) as i32).into();
... ... @@ -374,7 +375,8 @@ where T: Add<Output = T> + Sub<Output = T> + Neg<Output = T>
374 375 None
375 376 }};
376 377
377   - let mut ps :Vec<(Polygon, u32)> = self.faces.iter().filter_map(to_poly).collect();
  378 + let mut ps :Vec<(Polygon<T>, u32)> = self.faces.iter()
  379 + . filter_map(to_poly).collect();
378 380 ps.sort_by(|a, b| a.1.cmp(&b.1));
379 381 ps
380 382 }
... ...
... ... @@ -30,13 +30,13 @@ use std::time::{Duration, Instant};
30 30
31 31 use fractional::continuous::Continuous;
32 32 use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline
33   - , Polygon, Rectangle};
  33 + , Polygon};
34 34 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 38
39   -use fractional::xcb::XcbEasel;
  39 +use fractional::xcb::{XcbEasel, XcbCanvas};
40 40 use fractional::easel::Canvas;
41 41
42 42 use fractional::geometry::{Camera,DirectLight,Polyeder,Primitives};
... ... @@ -243,10 +243,10 @@ fn _transform<T>(v :Vector<T>, v1 :Vector<T>, v2 :Vector<T>, v3 :Vector<T>)
243 243 }
244 244
245 245 fn _line() {
246   - let a = (Coordinate(0, 1), Coordinate(6, 4));
247   - let b = (Coordinate(0, 4), Coordinate(6, 1));
248   - let c = (Coordinate(1, 0), Coordinate(6, 8));
249   - let d = (Coordinate(1, 8), Coordinate(6, 0));
  246 + let a = (Coordinate(0, 1, 0.0), Coordinate(6, 4, 0.0));
  247 + let b = (Coordinate(0, 4, 0.0), Coordinate(6, 1, 0.0));
  248 + let c = (Coordinate(1, 0, 0.0), Coordinate(6, 8, 0.0));
  249 + let d = (Coordinate(1, 8, 0.0), Coordinate(6, 0, 0.0));
250 250
251 251 for i in [a, b, c, d].iter() {
252 252 println!("{:>14} : {}", Line(i.0, i.1), Line(i.0, i.1).plot());
... ... @@ -254,19 +254,15 @@ fn _line() {
254 254 }
255 255
256 256 println!();
257   - let r = Rectangle(Coordinate(1, 1), Coordinate(10, 5));
258   - println!("{:>14} : {}", r, r.plot());
259   -
260   - println!();
261 257 let pl = Polyline(
262 258 Coordinates(vec!(a.0, a.1, b.0, b.1, c.0, c.1, d.0, d.1)));
263 259 println!("{:>14} : {}", pl, pl.plot());
264 260
265 261 println!();
266 262 let pg = Polygon(
267   - Coordinates(vec!( Coordinate( 0, -10)
268   - , Coordinate( 10, 10)
269   - , Coordinate(-10, 10) )));
  263 + Coordinates(vec!( Coordinate( 0, -10, 0.0)
  264 + , Coordinate( 10, 10, 0.0)
  265 + , Coordinate(-10, 10, 0.0) )));
270 266 println!("{:>14} : {}", pg, pg.plot());
271 267
272 268 let i = Vector(Fractional( 0,1), Fractional(-30,1), Fractional(0,1));
... ... @@ -285,9 +281,9 @@ fn _line() {
285 281
286 282 println!();
287 283 let pg = Polygon(
288   - Coordinates(vec!( Coordinate(to_i32(ix) + 100, to_i32(iy) + 100)
289   - , Coordinate(to_i32(jx) + 100, to_i32(jy) + 100)
290   - , Coordinate(to_i32(kx) + 100, to_i32(ky) + 100) )));
  284 + Coordinates(vec!( Coordinate(to_i32(ix) + 100, to_i32(iy) + 100, 0.0)
  285 + , Coordinate(to_i32(jx) + 100, to_i32(jy) + 100, 0.0)
  286 + , Coordinate(to_i32(kx) + 100, to_i32(ky) + 100, 0.0) )));
291 287 println!("{:>14} : {}", pg, pg.plot());
292 288
293 289 let i = Vector( 0.0, -30.0, 0.0);
... ... @@ -305,9 +301,9 @@ fn _line() {
305 301
306 302 println!();
307 303 let pg = Polygon(
308   - Coordinates(vec!( Coordinate(to_i32_2(ix) + 100, to_i32_2(iy) + 100)
309   - , Coordinate(to_i32_2(jx) + 100, to_i32_2(jy) + 100)
310   - , Coordinate(to_i32_2(kx) + 100, to_i32_2(ky) + 100) )));
  304 + Coordinates(vec!( Coordinate(to_i32_2(ix) + 100, to_i32_2(iy) + 100, 0.0)
  305 + , Coordinate(to_i32_2(jx) + 100, to_i32_2(jy) + 100, 0.0)
  306 + , Coordinate(to_i32_2(kx) + 100, to_i32_2(ky) + 100, 0.0) )));
311 307 println!("{:>14} : {}", pg, pg.plot());
312 308 }
313 309
... ... @@ -327,8 +323,8 @@ fn _democanvas<T>( xcb :&XcbEasel
327 323 // was 50.
328 324
329 325 canvas.set_title(title);
330   - canvas.init_events();
331   - canvas.start_events(tx.clone());
  326 + <XcbCanvas as Canvas<T>>::init_events(&canvas);
  327 + <XcbCanvas as Canvas<T>>::start_events(&canvas, tx.clone());
332 328
333 329 thread::spawn(move || {
334 330 let start = Instant::now();
... ... @@ -351,11 +347,11 @@ fn _democanvas<T>( xcb :&XcbEasel
351 347 , ( cube.transform(&rot2), 0x0000FF) );
352 348 //let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) );
353 349
354   - canvas.clear();
  350 + <XcbCanvas as Canvas<T>>::clear(&mut canvas);
355 351
356 352 for (o, color) in objects {
357 353 for (pg, c) in o.project(&camera, &light, color) {
358   - canvas.draw(&pg, Coordinate(0,0), c);
  354 + canvas.draw(&pg, Coordinate(0, 0, 0.into()), c);
359 355 }
360 356 }
361 357
... ... @@ -367,10 +363,11 @@ fn _democanvas<T>( xcb :&XcbEasel
367 363 }
368 364
369 365 last = last + step*(f + 1);
370   - canvas.put_text( Coordinate(10, 15)
371   - , &format!( "sleep: {:?}"
372   - , last - Instant::now() ));
373   - canvas.show();
  366 + <XcbCanvas as Canvas<T>>::put_text( &canvas
  367 + , Coordinate(10, 15, 0.into())
  368 + , &format!( "sleep: {:?}"
  369 + , last - Instant::now() ));
  370 + <XcbCanvas as Canvas<T>>::show(&canvas);
374 371 thread::sleep(last - Instant::now());
375 372 }
376 373 });
... ...
... ... @@ -129,7 +129,7 @@ fn getshm<'a>(size :usize) -> (i32, &'a mut [u32]) {
129 129
130 130 impl Easel for XcbEasel {}
131 131
132   -impl<'a> Canvas for XcbCanvas<'a> {
  132 +impl<'a,T> Canvas<T> for XcbCanvas<'a> {
133 133 fn init_events(&self) {
134 134 let mask = [( xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE
135 135 | xcb::EVENT_MASK_KEY_PRESS
... ... @@ -223,18 +223,18 @@ impl<'a> Canvas for XcbCanvas<'a> {
223 223 }
224 224 }
225 225
226   - fn draw(&mut self, d :&dyn Drawable, ofs :Coordinate, color: u32) {
227   - let Coordinates(c) = d.plot();
228   - let Coordinate(xofs, yofs) = ofs;
  226 + fn draw(&mut self, d :&dyn Drawable<T>, ofs :Coordinate<T>, color: u32) {
  227 + let Coordinates(c) = d.plot();
  228 + let Coordinate(xofs, yofs, _) = ofs;
229 229
230   - for Coordinate(x, y) in c {
  230 + for Coordinate(x, y, _) in c {
231 231 let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize;
232 232 self.shm[idx] = color;
233 233 }
234 234 }
235 235
236   - fn put_text(&self, ofs :Coordinate, s :&str) {
237   - let Coordinate(xofs, yofs) = ofs;
  236 + fn put_text(&self, ofs :Coordinate<T>, s :&str) {
  237 + let Coordinate(xofs, yofs, _) = ofs;
238 238 xcb::xproto::image_text_8( &self.conn, self.pixmap, self.gc
239 239 , xofs as i16, yofs as i16, s );
240 240 self.conn.flush();
... ... @@ -242,8 +242,8 @@ impl<'a> Canvas for XcbCanvas<'a> {
242 242
243 243 fn show(&self) {
244 244 xcb::copy_area( &self.conn, self.pixmap, self.window, self.gc
245   - , 0, 0, 0, 0
246   - , self.width, self.height );
  245 + , 0, 0, 0, 0
  246 + , self.width, self.height );
247 247 self.conn.flush();
248 248 }
249 249 }
... ...
Please register or login to post a comment