|
|
|
@ -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());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|