Showing
3 changed files
with
150 additions
and
25 deletions
@@ -30,8 +30,11 @@ pub trait Canvas { | @@ -30,8 +30,11 @@ pub trait Canvas { | ||
30 | fn init_events(&self); | 30 | fn init_events(&self); |
31 | fn start_events(&self, tx :mpsc::Sender<i32>); | 31 | fn start_events(&self, tx :mpsc::Sender<i32>); |
32 | 32 | ||
33 | + fn width(&self) -> u16; | ||
34 | + fn height(&self) -> u16; | ||
35 | + | ||
33 | fn clear(&mut self); | 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 | fn show(&self); | 38 | fn show(&self); |
36 | } | 39 | } |
37 | 40 | ||
@@ -225,7 +228,9 @@ impl Drawable for Polygon { | @@ -225,7 +228,9 @@ impl Drawable for Polygon { | ||
225 | } | 228 | } |
226 | let mut j = a.line(&i); | 229 | let mut j = a.line(&i); |
227 | let l = j.len(); | 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 | Coordinates(r) | 234 | Coordinates(r) |
230 | }, | 235 | }, |
231 | } | 236 | } |
@@ -24,8 +24,8 @@ use std::fmt::Display; | @@ -24,8 +24,8 @@ use std::fmt::Display; | ||
24 | use std::num::TryFromIntError; | 24 | use std::num::TryFromIntError; |
25 | use std::ops::{Add,Sub,Neg,Mul,Div}; | 25 | use std::ops::{Add,Sub,Neg,Mul,Div}; |
26 | use std::sync::mpsc; | 26 | use std::sync::mpsc; |
27 | -use std::time; | ||
28 | use std::thread; | 27 | use std::thread; |
28 | +use std::time::{Duration, Instant}; | ||
29 | 29 | ||
30 | use fractional::continuous::Continuous; | 30 | use fractional::continuous::Continuous; |
31 | use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline | 31 | use fractional::easel::{ Coordinate, Coordinates, Drawable, Line, Polyline |
@@ -340,37 +340,149 @@ fn main() { | @@ -340,37 +340,149 @@ fn main() { | ||
340 | 340 | ||
341 | let (tx, rx) = mpsc::channel(); | 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 | canvas.start_events(tx); | 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 | thread::spawn(move || { | 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 | canvas.clear(); | 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 | canvas.show(); | 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,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 | fn clear(&mut self) { | 218 | fn clear(&mut self) { |
211 | unsafe { | 219 | unsafe { |
212 | let ptr = self.shm.as_mut_ptr(); | 220 | let ptr = self.shm.as_mut_ptr(); |
@@ -215,13 +223,13 @@ impl<'a> Canvas for XcbCanvas<'a> { | @@ -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 | let Coordinates(c) = d.plot(); | 227 | let Coordinates(c) = d.plot(); |
220 | let Coordinate(xofs, yofs) = ofs; | 228 | let Coordinate(xofs, yofs) = ofs; |
221 | 229 | ||
222 | for Coordinate(x, y) in c { | 230 | for Coordinate(x, y) in c { |
223 | let idx :usize = ((y+yofs)*(self.width as i32)+x+xofs) as usize; | 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