Showing
3 changed files
with
150 additions
and
25 deletions
... | ... | @@ -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