main.rs 4.33 KB
//
// Test our fractional crate / module...
//
// Georg Hopp <georg@steffers.org>
//
// Copyright © 2019 Georg Hopp
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

use std::fmt::Debug;
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::sync::mpsc;
use std::thread;
use std::time::{Duration, Instant};

use easel3d::easel::canvas::{Vertex, Canvas};
use easel3d::easel::fillable::Fillable;
use easel3d::math::trigonometry::Trig;
use easel3d::math::vector::Vector;
use easel3d::math::transform::TMatrix;
use easel3d::space::camera::Camera;
use easel3d::space::light::DirectLight;
use easel3d::space::polyeder::Polyeder;
use easel3d::space::primitives::Primitives;

mod easel3d_xcb;

use easel3d_xcb::XcbEasel;

fn democanvas<T>( xcb         :&XcbEasel
                , title       :&'static str
                , tx          :mpsc::Sender<i32>
                , _triangle   :Polyeder<T>
                , tetrahedron :Polyeder<T>
                , cube        :Polyeder<T>
                , light       :DirectLight<T> )
    where T: 'static + Add<Output = T> + Sub<Output = T> + Neg<Output = T>
           + Mul<Output = T> + Div<Output = T>
           + Debug + Copy + Trig + Send + From<i32> + From<f64> + PartialOrd {

    let mut canvas = xcb.canvas(301, 301).unwrap();
    let camera     = Camera::<T>::new(&canvas, 45); // the orig. view angle
                                                    // was 50.

    canvas.set_title(title);
    canvas.init_events();
    canvas.start_events(tx.clone());

    thread::spawn(move || {
        let     start = Instant::now();
        let     step  = Duration::from_millis(20);
        let mut last  = Instant::now();

        let t = TMatrix::translate(Vector(0.into() , 0.into() , 150.into()));

        loop {
            let deg = ((start.elapsed() / 20).as_millis() % (4*360)) as i32;

            let rz = TMatrix::rotate_z(deg);
            let rx = TMatrix::rotate_x(-deg*2);
            let ry = TMatrix::rotate_y(-deg*2);

            let rot1 = TMatrix::combine(vec!(rz, rx, t));
            let rot2 = TMatrix::combine(vec!(rz, ry, t));

            let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00)
                              , (       cube.transform(&rot2), 0x0000FF) );
            //let objects = vec!( (       cube.transform(&rot2), 0x0000FF) );
            //let objects = vec!( (tetrahedron.transform(&rot1), 0xFFFF00) );
            //let objects = vec!( (triangle.transform(&rot1), 0xFFFF00) );

            let rlx = TMatrix::rotate_x(-deg/4);
            let rly = TMatrix::rotate_y(-deg/1);
            let tlight = light.transform(&TMatrix::combine(vec!(rlx, rly)));

            canvas.clear();

            for (o, color) in objects {
                for (pg, c) in o.project(&camera, &tlight, color) {
                    (&pg).fill(&mut canvas, c);
                }
            }

            let passed = Instant::now() - last;
            let f      = (passed.as_nanos() / step.as_nanos()) as u32;

            if f > 1 {
                println!("{} !!! Detected frame drop", title);
            }

            last = last + step*(f + 1);
            canvas.put_text( Vertex::new(10, 15, 0.into())
                           , &format!( "sleep: {:?}"
                           , last - Instant::now() ));
            canvas.show();
            thread::sleep(last - Instant::now());
        }
    });
}

fn main() {
    let      xcb = XcbEasel::new().unwrap();
    let (tx, rx) = mpsc::channel();

    democanvas( &xcb, "Something...(f64)", tx.clone()
              , Polyeder::triangle(60.0)
              , Polyeder::tetrahedron(100.0)
              , Polyeder::cube(56.25)
              , DirectLight::new(Vector(0.0, 0.0, 1.0)) );

    for x in rx {
        match x {
            1 => break,
            _ => {},
        }
    }
}