Browse Source

more accurate timing

master
Georg Hopp 6 years ago
parent
commit
d8cd5ed970
Signed by: ghopp GPG Key ID: 4C5D226768784538
  1. 7
      fractional/src/easel.rs
  2. 154
      fractional/src/main.rs
  3. 12
      fractional/src/xcb.rs

7
fractional/src/easel.rs

@ -30,8 +30,11 @@ pub trait Canvas {
fn init_events(&self);
fn start_events(&self, tx :mpsc::Sender<i32>);
fn width(&self) -> u16;
fn height(&self) -> u16;
fn clear(&mut self);
fn draw(&mut self, c :&dyn Drawable, ofs :Coordinate);
fn draw(&mut self, c :&dyn Drawable, ofs :Coordinate, color :u32);
fn show(&self);
}
@ -225,7 +228,9 @@ impl Drawable for Polygon {
}
let mut j = a.line(&i);
let l = j.len();
if l > 1 {
r.append(&mut j[1..l-1].to_vec());
}
Coordinates(r)
},
}

154
fractional/src/main.rs

@ -24,8 +24,8 @@ use std::fmt::Display;
use std::num::TryFromIntError;
use std::ops::{Add,Sub,Neg,Mul,Div};
use std::sync::mpsc;
use std::time;
use std::thread;
use std::time::{Duration, Instant};
use fractional::continuous::Continuous;
use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline
@ -340,37 +340,149 @@ fn main() {
let (tx, rx) = mpsc::channel();
let i = Vector(Fractional( 0,1), Fractional(-35,1), Fractional(0,1));
let j = Vector(Fractional( 30,1), Fractional( 17,1), Fractional(0,1));
let k = Vector(Fractional(-30,1), Fractional( 17,1), Fractional(0,1));
fn to_i32(x :Fractional) -> i32 {
let Fractional(n, d) = x;
(n / d + if (n % d).abs() < (n / 2).abs() { 0 } else { 1 }) as i32
// TODO I ran into overflow issues using fractionals so for now
// use floating point values.
// https://rechneronline.de/pi/tetrahedron.php
// yi = a / 12 * √6
// yc = a / 4 * √6
// zi = √3 / 6 * a
// zc = √3 / 3 * a
let yi = 60.0 / 12.0 * 6.0.sqrt().unwrap();
let yc = 60.0 / 4.0 * 6.0.sqrt().unwrap();
let zi = 3.0.sqrt().unwrap() / 6.0 * 60.0;
let zc = 3.0.sqrt().unwrap() / 3.0 * 60.0;
let i = Vector( 0.0, yc, 0.0);
let j = Vector(-30.0, -yi, -zi);
let k = Vector( 30.0, -yi, -zi);
let l = Vector( 0.0, -yi, zc);
let cf1 = Vector(-30.0, 30.0, -30.0);
let cf2 = Vector(-30.0, -30.0, -30.0);
let cf3 = Vector( 30.0, -30.0, -30.0);
let cf4 = Vector( 30.0, 30.0, -30.0);
let cb1 = Vector(-30.0, 30.0, 30.0);
let cb2 = Vector(-30.0, -30.0, 30.0);
let cb3 = Vector( 30.0, -30.0, 30.0);
let cb4 = Vector( 30.0, 30.0, 30.0);
fn to_screen(c: &dyn Canvas, v :Vector<f64>) -> Coordinate {
// TODO .. these are in fact constants that should be stored once
// somewhere… Rust doesn't let me make this static here.
// In a way they are part of the canvas and they should change as the
// canvas is changing…
let fovx :f64 = 1.0 / <f64 as Trig>::tan(50);
let fovy :f64 = c.width() as f64 / c.height() as f64 * fovx;
let xs = ( v.x() / v.z() * fovx * c.width() as f64 ).round() as i32
+ c.width() as i32 / 2;
let ys = ( -v.y() / v.z() * fovy * c.height() as f64 ).round() as i32
+ c.height() as i32 / 2;
Coordinate(xs, ys)
}
canvas.start_events(tx);
let start = Instant::now();
let step = Duration::from_millis(25);
let mut last = Instant::now();
thread::spawn(move || {
let mut deg :i32 = 0;
loop {
let rot :TMatrix<Fractional> = rotate_z(deg) * rotate_x(-deg);
//const DWC :f64 = 10.0;
let Vector(ix, iy, _) = rot.apply(&i);
let Vector(jx, jy, _) = rot.apply(&j);
let Vector(kx, ky, _) = rot.apply(&k);
loop {
let deg = ((start.elapsed() / 20).as_millis() % 360) as i32;
let rot1 :TMatrix<f64> = rotate_z(deg)
* rotate_x(-deg*2)
* translate(Vector(0.0, 0.0, 150.0));
let rot2 :TMatrix<f64> = rotate_z(deg)
* rotate_y(-deg*2)
* translate(Vector(0.0, 0.0, 150.0));
let ia = rot1.apply(&i);
let ja = rot1.apply(&j);
let ka = rot1.apply(&k);
let la = rot1.apply(&l);
let cf1a = rot2.apply(&cf1);
let cf2a = rot2.apply(&cf2);
let cf3a = rot2.apply(&cf3);
let cf4a = rot2.apply(&cf4);
let cb1a = rot2.apply(&cb1);
let cb2a = rot2.apply(&cb2);
let cb3a = rot2.apply(&cb3);
let cb4a = rot2.apply(&cb4);
let pg1 = Polygon(Coordinates(vec!( to_screen(&canvas, ja)
, to_screen(&canvas, ka)
, to_screen(&canvas, la) )));
let pg2 = Polygon(Coordinates(vec!( to_screen(&canvas, ja)
, to_screen(&canvas, ia)
, to_screen(&canvas, ka) )));
let pg3 = Polygon(Coordinates(vec!( to_screen(&canvas, la)
, to_screen(&canvas, ia)
, to_screen(&canvas, ja) )));
let pg4 = Polygon(Coordinates(vec!( to_screen(&canvas, ka)
, to_screen(&canvas, ia)
, to_screen(&canvas, la) )));
// front: cf1 cf2 cf3 cf4
let cf = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a)
, to_screen(&canvas, cf2a)
, to_screen(&canvas, cf3a)
, to_screen(&canvas, cf4a) )));
// back: cb4 cb3 cb2 cb1
let cb = Polygon(Coordinates(vec!( to_screen(&canvas, cb4a)
, to_screen(&canvas, cb3a)
, to_screen(&canvas, cb2a)
, to_screen(&canvas, cb1a) )));
// top: cf2 cb2 cb3 cf3
let ct = Polygon(Coordinates(vec!( to_screen(&canvas, cf2a)
, to_screen(&canvas, cb2a)
, to_screen(&canvas, cb3a)
, to_screen(&canvas, cf3a) )));
// bottom: cf1 cf4 cb4 cb1
let co = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a)
, to_screen(&canvas, cf4a)
, to_screen(&canvas, cb4a)
, to_screen(&canvas, cb1a) )));
// left: cf1 cb1 cb2 cf2
let cl = Polygon(Coordinates(vec!( to_screen(&canvas, cf1a)
, to_screen(&canvas, cb1a)
, to_screen(&canvas, cb2a)
, to_screen(&canvas, cf2a) )));
// right: cf3 cb3 cb4 cf4
let cr = Polygon(Coordinates(vec!( to_screen(&canvas, cf3a)
, to_screen(&canvas, cb3a)
, to_screen(&canvas, cb4a)
, to_screen(&canvas, cf4a) )));
let pg = Polygon(
Coordinates(vec!( Coordinate(to_i32(ix), to_i32(iy))
, Coordinate(to_i32(jx), to_i32(jy))
, Coordinate(to_i32(kx), to_i32(ky)) )));
canvas.clear();
canvas.draw(&pg, Coordinate(75,75));
canvas.draw(&pg1, Coordinate(0,0), 0xFFFF00);
canvas.draw(&pg2, Coordinate(0,0), 0xFFFF00);
canvas.draw(&pg3, Coordinate(0,0), 0xFFFF00);
canvas.draw(&pg4, Coordinate(0,0), 0xFFFF00);
canvas.draw( &cf, Coordinate(0,0), 0x0000FF);
canvas.draw( &cb, Coordinate(0,0), 0x0000FF);
canvas.draw( &ct, Coordinate(0,0), 0x0000FF);
canvas.draw( &co, Coordinate(0,0), 0x0000FF);
canvas.draw( &cl, Coordinate(0,0), 0x0000FF);
canvas.draw( &cr, Coordinate(0,0), 0x0000FF);
canvas.show();
deg = (deg + 1) % 360;
let passed = Instant::now() - last;
let f = (passed.as_nanos() / step.as_nanos()) as u32;
if f > 1 {
println!("!!! Detected frame drop");
}
thread::sleep(time::Duration::from_millis(5));
last = last + step*(f + 1);
println!("Sleep for: {:?}", last - Instant::now());
thread::sleep(last - Instant::now());
}
});

12
fractional/src/xcb.rs

@ -207,6 +207,14 @@ impl<'a> Canvas for XcbCanvas<'a> {
});
}
fn width(&self) -> u16 {
self.width
}
fn height(&self) -> u16 {
self.height
}
fn clear(&mut self) {
unsafe {
let ptr = self.shm.as_mut_ptr();
@ -215,13 +223,13 @@ impl<'a> Canvas for XcbCanvas<'a> {
}
}
fn draw(&mut self, d :&dyn Drawable, ofs :Coordinate) {
fn draw(&mut self, d :&dyn Drawable, ofs :Coordinate, color: u32) {
let Coordinates(c) = d.plot();
let Coordinate(xofs, yofs) = ofs;
for Coordinate(x, y) in c {
let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize;
self.shm[idx] = 0xFFFFFF;
self.shm[idx] = color;
}
}

Loading…
Cancel
Save