...
|
...
|
@@ -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
|
|
...
|
...
|
|