Commit d8cd5ed970d1c24f4ecdae57e68d11a2a171cf8d

Authored by Georg Hopp
1 parent 35ec5d36

more accurate timing

... ... @@ -30,8 +30,11 @@ pub trait Canvas {
30 30 fn init_events(&self);
31 31 fn start_events(&self, tx :mpsc::Sender<i32>);
32 32
  33 + fn width(&self) -> u16;
  34 + fn height(&self) -> u16;
  35 +
33 36 fn clear(&mut self);
34   - fn draw(&mut self, c :&dyn Drawable, ofs :Coordinate);
  37 + fn draw(&mut self, c :&dyn Drawable, ofs :Coordinate, color :u32);
35 38 fn show(&self);
36 39 }
37 40
... ... @@ -225,7 +228,9 @@ impl Drawable for Polygon {
225 228 }
226 229 let mut j = a.line(&i);
227 230 let l = j.len();
228   - r.append(&mut j[1..l-1].to_vec());
  231 + if l > 1 {
  232 + r.append(&mut j[1..l-1].to_vec());
  233 + }
229 234 Coordinates(r)
230 235 },
231 236 }
... ...
... ... @@ -24,8 +24,8 @@ use std::fmt::Display;
24 24 use std::num::TryFromIntError;
25 25 use std::ops::{Add,Sub,Neg,Mul,Div};
26 26 use std::sync::mpsc;
27   -use std::time;
28 27 use std::thread;
  28 +use std::time::{Duration, Instant};
29 29
30 30 use fractional::continuous::Continuous;
31 31 use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline
... ... @@ -340,37 +340,149 @@ fn main() {
340 340
341 341 let (tx, rx) = mpsc::channel();
342 342
343   - let i = Vector(Fractional( 0,1), Fractional(-35,1), Fractional(0,1));
344   - let j = Vector(Fractional( 30,1), Fractional( 17,1), Fractional(0,1));
345   - let k = Vector(Fractional(-30,1), Fractional( 17,1), Fractional(0,1));
346   -
347   - fn to_i32(x :Fractional) -> i32 {
348   - let Fractional(n, d) = x;
349   - (n / d + if (n % d).abs() < (n / 2).abs() { 0 } else { 1 }) as i32
  343 + // TODO I ran into overflow issues using fractionals so for now
  344 + // use floating point values.
  345 + // https://rechneronline.de/pi/tetrahedron.php
  346 + // yi = a / 12 * √6
  347 + // yc = a / 4 * √6
  348 + // zi = √3 / 6 * a
  349 + // zc = √3 / 3 * a
  350 + let yi = 60.0 / 12.0 * 6.0.sqrt().unwrap();
  351 + let yc = 60.0 / 4.0 * 6.0.sqrt().unwrap();
  352 + let zi = 3.0.sqrt().unwrap() / 6.0 * 60.0;
  353 + let zc = 3.0.sqrt().unwrap() / 3.0 * 60.0;
  354 +
  355 + let i = Vector( 0.0, yc, 0.0);
  356 + let j = Vector(-30.0, -yi, -zi);
  357 + let k = Vector( 30.0, -yi, -zi);
  358 + let l = Vector( 0.0, -yi, zc);
  359 +
  360 + let cf1 = Vector(-30.0, 30.0, -30.0);
  361 + let cf2 = Vector(-30.0, -30.0, -30.0);
  362 + let cf3 = Vector( 30.0, -30.0, -30.0);
  363 + let cf4 = Vector( 30.0, 30.0, -30.0);
  364 +
  365 + let cb1 = Vector(-30.0, 30.0, 30.0);
  366 + let cb2 = Vector(-30.0, -30.0, 30.0);
  367 + let cb3 = Vector( 30.0, -30.0, 30.0);
  368 + let cb4 = Vector( 30.0, 30.0, 30.0);
  369 +
  370 + fn to_screen(c: &dyn Canvas, v :Vector<f64>) -> Coordinate {
  371 + // TODO .. these are in fact constants that should be stored once
  372 + // somewhere… Rust doesn't let me make this static here.
  373 + // In a way they are part of the canvas and they should change as the
  374 + // canvas is changing…
  375 + let fovx :f64 = 1.0 / <f64 as Trig>::tan(50);
  376 + let fovy :f64 = c.width() as f64 / c.height() as f64 * fovx;
  377 +
  378 + let xs = ( v.x() / v.z() * fovx * c.width() as f64 ).round() as i32
  379 + + c.width() as i32 / 2;
  380 + let ys = ( -v.y() / v.z() * fovy * c.height() as f64 ).round() as i32
  381 + + c.height() as i32 / 2;
  382 +
  383 + Coordinate(xs, ys)
350 384 }
351 385
352 386 canvas.start_events(tx);
353 387
  388 + let start = Instant::now();
  389 + let step = Duration::from_millis(25);
  390 + let mut last = Instant::now();
354 391 thread::spawn(move || {
355   - let mut deg :i32 = 0;
356   - loop {
357   - let rot :TMatrix<Fractional> = rotate_z(deg) * rotate_x(-deg);
  392 + //const DWC :f64 = 10.0;
358 393
359   - let Vector(ix, iy, _) = rot.apply(&i);
360   - let Vector(jx, jy, _) = rot.apply(&j);
361   - let Vector(kx, ky, _) = rot.apply(&k);
  394 + loop {
  395 + let deg = ((start.elapsed() / 20).as_millis() % 360) as i32;
  396 + let rot1 :TMatrix<f64> = rotate_z(deg)
  397 + * rotate_x(-deg*2)
  398 + * translate(Vector(0.0, 0.0, 150.0));
  399 +
  400 + let rot2 :TMatrix<f64> = rotate_z(deg)
  401 + * rotate_y(-deg*2)
  402 + * translate(Vector(0.0, 0.0, 150.0));
  403 +
  404 + let ia = rot1.apply(&i);
  405 + let ja = rot1.apply(&j);
  406 + let ka = rot1.apply(&k);
  407 + let la = rot1.apply(&l);
  408 +
  409 + let cf1a = rot2.apply(&cf1);
  410 + let cf2a = rot2.apply(&cf2);
  411 + let cf3a = rot2.apply(&cf3);
  412 + let cf4a = rot2.apply(&cf4);
  413 +
  414 + let cb1a = rot2.apply(&cb1);
  415 + let cb2a = rot2.apply(&cb2);
  416 + let cb3a = rot2.apply(&cb3);
  417 + let cb4a = rot2.apply(&cb4);
  418 +
  419 + let pg1 = Polygon(Coordinates(vec!( to_screen(&canvas, ja)
  420 + , to_screen(&canvas, ka)
  421 + , to_screen(&canvas, la) )));
  422 + let pg2 = Polygon(Coordinates(vec!( to_screen(&canvas, ja)
  423 + , to_screen(&canvas, ia)
  424 + , to_screen(&canvas, ka) )));
  425 + let pg3 = Polygon(Coordinates(vec!( to_screen(&canvas, la)
  426 + , to_screen(&canvas, ia)
  427 + , to_screen(&canvas, ja) )));
  428 + let pg4 = Polygon(Coordinates(vec!( to_screen(&canvas, ka)
  429 + , to_screen(&canvas, ia)
  430 + , to_screen(&canvas, la) )));
  431 +
  432 + // front: cf1 cf2 cf3 cf4
  433 + let cf = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a)
  434 + , to_screen(&canvas, cf2a)
  435 + , to_screen(&canvas, cf3a)
  436 + , to_screen(&canvas, cf4a) )));
  437 + // back: cb4 cb3 cb2 cb1
  438 + let cb = Polygon(Coordinates(vec!( to_screen(&canvas, cb4a)
  439 + , to_screen(&canvas, cb3a)
  440 + , to_screen(&canvas, cb2a)
  441 + , to_screen(&canvas, cb1a) )));
  442 + // top: cf2 cb2 cb3 cf3
  443 + let ct = Polygon(Coordinates(vec!( to_screen(&canvas, cf2a)
  444 + , to_screen(&canvas, cb2a)
  445 + , to_screen(&canvas, cb3a)
  446 + , to_screen(&canvas, cf3a) )));
  447 + // bottom: cf1 cf4 cb4 cb1
  448 + let co = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a)
  449 + , to_screen(&canvas, cf4a)
  450 + , to_screen(&canvas, cb4a)
  451 + , to_screen(&canvas, cb1a) )));
  452 + // left: cf1 cb1 cb2 cf2
  453 + let cl = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a)
  454 + , to_screen(&canvas, cb1a)
  455 + , to_screen(&canvas, cb2a)
  456 + , to_screen(&canvas, cf2a) )));
  457 + // right: cf3 cb3 cb4 cf4
  458 + let cr = Polygon(Coordinates(vec!( to_screen(&canvas, cf3a)
  459 + , to_screen(&canvas, cb3a)
  460 + , to_screen(&canvas, cb4a)
  461 + , to_screen(&canvas, cf4a) )));
362 462
363   - let pg = Polygon(
364   - Coordinates(vec!( Coordinate(to_i32(ix), to_i32(iy))
365   - , Coordinate(to_i32(jx), to_i32(jy))
366   - , Coordinate(to_i32(kx), to_i32(ky)) )));
367 463 canvas.clear();
368   - canvas.draw(&pg, Coordinate(75,75));
  464 + canvas.draw(&pg1, Coordinate(0,0), 0xFFFF00);
  465 + canvas.draw(&pg2, Coordinate(0,0), 0xFFFF00);
  466 + canvas.draw(&pg3, Coordinate(0,0), 0xFFFF00);
  467 + canvas.draw(&pg4, Coordinate(0,0), 0xFFFF00);
  468 + canvas.draw( &cf, Coordinate(0,0), 0x0000FF);
  469 + canvas.draw( &cb, Coordinate(0,0), 0x0000FF);
  470 + canvas.draw( &ct, Coordinate(0,0), 0x0000FF);
  471 + canvas.draw( &co, Coordinate(0,0), 0x0000FF);
  472 + canvas.draw( &cl, Coordinate(0,0), 0x0000FF);
  473 + canvas.draw( &cr, Coordinate(0,0), 0x0000FF);
369 474 canvas.show();
370 475
371   - deg = (deg + 1) % 360;
  476 + let passed = Instant::now() - last;
  477 + let f = (passed.as_nanos() / step.as_nanos()) as u32;
  478 +
  479 + if f > 1 {
  480 + println!("!!! Detected frame drop");
  481 + }
372 482
373   - thread::sleep(time::Duration::from_millis(5));
  483 + last = last + step*(f + 1);
  484 + println!("Sleep for: {:?}", last - Instant::now());
  485 + thread::sleep(last - Instant::now());
374 486 }
375 487 });
376 488
... ...
... ... @@ -207,6 +207,14 @@ impl<'a> Canvas for XcbCanvas<'a> {
207 207 });
208 208 }
209 209
  210 + fn width(&self) -> u16 {
  211 + self.width
  212 + }
  213 +
  214 + fn height(&self) -> u16 {
  215 + self.height
  216 + }
  217 +
210 218 fn clear(&mut self) {
211 219 unsafe {
212 220 let ptr = self.shm.as_mut_ptr();
... ... @@ -215,13 +223,13 @@ impl<'a> Canvas for XcbCanvas<'a> {
215 223 }
216 224 }
217 225
218   - fn draw(&mut self, d :&dyn Drawable, ofs :Coordinate) {
  226 + fn draw(&mut self, d :&dyn Drawable, ofs :Coordinate, color: u32) {
219 227 let Coordinates(c) = d.plot();
220 228 let Coordinate(xofs, yofs) = ofs;
221 229
222 230 for Coordinate(x, y) in c {
223 231 let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize;
224   - self.shm[idx] = 0xFFFFFF;
  232 + self.shm[idx] = color;
225 233 }
226 234 }
227 235
... ...
Please register or login to post a comment