diff --git a/Cargo.toml b/Cargo.toml
index 7f1f76c..b63108a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,6 +16,7 @@ features = [
"Document",
"HtmlCanvasElement",
"CanvasRenderingContext2d",
+ "Performance",
"console",
]
diff --git a/index.html b/index.html
index 8701c32..fcac4de 100644
--- a/index.html
+++ b/index.html
@@ -1,14 +1,33 @@
-
-
- Rust WASM Game Window
-
-
-
-
-
+
+
+Rust WASM Game Window
+
+
+
+
+
diff --git a/src/lib.rs b/src/lib.rs
index aeb33d5..3d5072f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,7 +3,7 @@ use std::f64;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
-//use web_sys::console;
+use web_sys::console;
mod cga;
use cga::CGA;
@@ -58,9 +58,9 @@ const E2: usize = 2;
//const E12345: usize = 31;
struct Ship {
- _pos: CGA,
- _vel: CGA,
- _orientation: CGA,
+ pos: CGA,
+ //_vel: CGA,
+ //_orientation: CGA,
}
enum Geometry {
@@ -97,7 +97,8 @@ fn point_to_screen_space(x: f64, y: f64) -> (f64, f64) {
fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) {
//Naively assume we are given a valid point
- let (x,y) = point_to_screen_space(point[E1], point[E2]);
+ let (x,y) = get_point(point);
+ let (x,y) = point_to_screen_space(x, y);
context.begin_path();
context.set_fill_style_str(RED);
@@ -105,6 +106,18 @@ fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) {
context.fill();
}
+//TODO Integrate into get geometry
+fn get_point(point: &CGA) -> (f64, f64) {
+ let e_vec = CGA::e4();
+ let e_bar = CGA::e5();
+ let n_vec = &e_vec + &e_bar; //Null vector for the point at infinity.
+
+ let normalization = -(point | &n_vec)[SCALAR];
+ let x = point[E1] / normalization;
+ let y = point[E2] / normalization;
+ (x,y)
+}
+
fn get_geometry(circle: &CGA) -> Geometry {
//Naively assume we are given a valid line/circle
let n_bar = CGA::e4() - CGA::e5();
@@ -146,24 +159,116 @@ fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) {
let canvas_r = r*RADIUS;
context.arc(canvas_x, canvas_y, canvas_r, 0., TWO_PI).unwrap();
},
- Geometry::Line(x,y,theta) => {
- let (p1x, p1y) = (x - theta.cos(), y - theta.sin());
- let (p2x, p2y) = (x + theta.cos(), y + theta.sin());
- let (canvas_x1, canvas_y1) = point_to_screen_space(p1x, p1y);
- let (canvas_x2, canvas_y2) = point_to_screen_space(p2x, p2y);
- draw_point(&context, &point_to_cga(x,y));
- context.move_to(canvas_x1, canvas_y1);
- context.line_to(canvas_x2, canvas_y2);
- },
+ Geometry::Line(x,y,theta) => {
+ let (p1x, p1y) = (x - theta.cos(), y - theta.sin());
+ let (p2x, p2y) = (x + theta.cos(), y + theta.sin());
+ let (canvas_x1, canvas_y1) = point_to_screen_space(p1x, p1y);
+ let (canvas_x2, canvas_y2) = point_to_screen_space(p2x, p2y);
+ draw_point(&context, &point_to_cga(x,y));
+ context.move_to(canvas_x1, canvas_y1);
+ context.line_to(canvas_x2, canvas_y2);
+ },
}
context.stroke();
}
+fn get_hyperbolic_translation(vec: &CGA) -> CGA {
+ let vec_sqr = (vec * vec)[SCALAR];
+ if vec_sqr >= 1. {
+ panic!("Translation Vector Out of Bounds");
+ }
+ let message = format!("Get TX\nvec {} \nvecvec {}\nvec_sqr {}", vec, vec*vec, vec_sqr);
+ console::log_1(&message.into());
+ let t = 1.0 / ( 1. - vec_sqr).sqrt() * ( CGA::new(1., SCALAR) + CGA::e5()*vec);
+ t
+}
+
+fn get_hyperbolic_point(vec: &CGA) -> CGA {
+ let vec_sqr = (vec * vec)[SCALAR];
+ if vec_sqr >= 1. {
+ panic!("Vector out of bounds");
+ }
+
+ let p = 1. / (1. - vec_sqr)*(CGA::new(vec_sqr, SCALAR) + 2.*vec - (CGA::e4() - CGA::e5()));
+ p
+}
+
+struct Asteroid {
+}
+
+#[wasm_bindgen]
+pub struct Game {
+ context: CanvasRenderingContext2d,
+ ship: Ship,
+ //asteroids: Vec::,
+ point: (f64, f64),
+ //keys: HashSet,
+}
+
+#[wasm_bindgen]
+impl Game {
+#[wasm_bindgen(constructor)]
+ pub fn new(canvas_id: &str) -> Self {
+ let window = web_sys::window().unwrap();
+ let document = window.document().unwrap();
+ let canvas = document
+ .get_element_by_id(canvas_id)
+ .ok_or_else( || JsValue::from_str("Canvas not found")).unwrap()
+ .dyn_into::().unwrap();
+ canvas.set_width(WIDTH as u32);
+ canvas.set_height(HEIGHT as u32);
+ let context = canvas
+ .get_context("2d").unwrap()
+ .ok_or_else( || JsValue::from_str("Failed to get context")).unwrap()
+ .dyn_into::().unwrap();
+
+ let ship = Ship { pos: get_hyperbolic_point(&CGA::zero()) };
+ Game { context: context, point: (0.,0.), ship }
+ }
+
+ pub fn draw(&self) {
+ self.context.begin_path();
+ self.context.set_fill_style_str(BACKGROUND);
+ self.context.fill_rect(0.0, 0.0, WIDTH, HEIGHT);
+ self.context.fill();
+ self.context.set_stroke_style_str(BLACK);
+ self.context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
+ self.context.stroke();
+
+ let x = self.point.0;
+ let y = self.point.1;
+ draw_point(&self.context, &self.ship.pos);
+
+ //self.context.begin_path();
+ //self.context.set_fill_style_str(GREEN);
+ //self.context.arc(x, y, 20., 0., TWO_PI).unwrap();
+ //self.context.fill();
+
+ }
+
+ pub fn update(&mut self, dt: f64) { //dt in milliseconds
+ let theta:f64 = 0.1;
+ let vel:f64 = 1.*dt/1000.;
+ let dir = theta.cos()*CGA::e1() + theta.sin()*CGA::e2();
+ let vec = vel* &dir;
+
+ let tx = get_hyperbolic_translation(&vec);
+ let txr = tx.Reverse();
+ self.ship.pos = &tx * &self.ship.pos * &txr;
+
+ let norm = (&self.ship.pos | CGA::e4() )[SCALAR];
+ self.ship.pos = &self.ship.pos * (1.0 / norm);
+ }
+}
+
+
+
// Start entry point
#[wasm_bindgen(start)]
pub fn start() -> Result<(), JsValue> {
- let _ship = Ship { _pos: point_to_cga(0.,0.), _vel: CGA::zero(), _orientation: CGA::zero() };
+// let _ship = Ship { _pos: point_to_cga(0.,0.), _vel: CGA::zero(), _orientation: CGA::zero() };
+/*
// Grab document and canvas
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
@@ -178,7 +283,7 @@ pub fn start() -> Result<(), JsValue> {
let context = canvas
.get_context("2d")?
.unwrap()
- .dyn_into::()?;
+ .dyn_into::().unwrap();
//Set up play area.
context.begin_path();
@@ -188,51 +293,51 @@ pub fn start() -> Result<(), JsValue> {
context.set_stroke_style_str(BLACK);
context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
context.stroke();
+*/
+ /* //Testing example lines and circles.
+ let point = point_to_cga(0.,0.);
+ draw_point(&context, &point);
- //Testing example lines and circles.
- let point = point_to_cga(0.,0.);
- draw_point(&context, &point);
+ let p1 = point_to_cga(0.9, 0.0);
+ draw_point(&context, &p1);
+ let p2 = point_to_cga(0.0, 0.9);
+ draw_point(&context, &p2);
+ let p3 = point_to_cga(0.7, 0.6);
+ draw_point(&context, &p3);
+ let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); //wedge e3 to force into the plane
+ draw_line(&context, &circle);
- let p1 = point_to_cga(0.9, 0.0);
- draw_point(&context, &p1);
- let p2 = point_to_cga(0.0, 0.9);
- draw_point(&context, &p2);
- let p3 = point_to_cga(0.7, 0.6);
- draw_point(&context, &p3);
- let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); //wedge e3 to force into the plane
- draw_line(&context, &circle);
+ let p1 = point_to_cga(0.9, 0.2);
+ draw_point(&context, &p1);
+ let p2 = point_to_cga(-0.9, -0.);
+ draw_point(&context, &p2);
+ let p3 = point_to_cga(0., 0.1);
+ draw_point(&context, &p3);
+ let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
+ draw_line(&context, &circle);
- let p1 = point_to_cga(0.9, 0.2);
- draw_point(&context, &p1);
- let p2 = point_to_cga(-0.9, -0.);
- draw_point(&context, &p2);
- let p3 = point_to_cga(0., 0.1);
- draw_point(&context, &p3);
- let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
- draw_line(&context, &circle);
+ let p1 = point_to_cga(0.9, 0.1);
+ draw_point(&context, &p1);
+ let p2 = point_to_cga(-0.9, -0.1);
+ draw_point(&context, &p2);
+ let p3 = point_to_cga(0., 0.0);
+ draw_point(&context, &p3);
+ let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
+ draw_line(&context, &circle);
- let p1 = point_to_cga(0.9, 0.1);
- draw_point(&context, &p1);
- let p2 = point_to_cga(-0.9, -0.1);
- draw_point(&context, &p2);
- let p3 = point_to_cga(0., 0.0);
- draw_point(&context, &p3);
- let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
- draw_line(&context, &circle);
+ let p1 = point_to_cga(0.9, 0.);
+ draw_point(&context, &p1);
+ let p2 = point_to_cga(0.9, -0.1);
+ draw_point(&context, &p2);
+ let circle = &p1 ^ &p2 ^ &CGA::e4() ^ &CGA::e3(); //Wedge e4 to create a circle through p1 and p1 that is tangent to the unit circle.
+ draw_line(&context, &circle);
- let p1 = point_to_cga(0.9, 0.);
- draw_point(&context, &p1);
- let p2 = point_to_cga(0.9, -0.1);
- draw_point(&context, &p2);
- let circle = &p1 ^ &p2 ^ &CGA::e4() ^ &CGA::e3(); //Wedge e4 to create a circle through p1 and p1 that is tangent to the unit circle.
- draw_line(&context, &circle);
-
- let p1 = point_to_cga(0.9, 0.);
- draw_point(&context, &p1);
- let p2 = point_to_cga(0.9, -0.1);
- draw_point(&context, &p2);
- let circle = &p1 ^ &p2 ^ &CGA::e5() ^ &CGA::e3(); //Orthogonal to the line at infinity
- draw_line(&context, &circle);
+ let p1 = point_to_cga(0.9, 0.);
+ draw_point(&context, &p1);
+ let p2 = point_to_cga(0.9, -0.1);
+ draw_point(&context, &p2);
+ let circle = &p1 ^ &p2 ^ &CGA::e5() ^ &CGA::e3(); //Orthogonal to the line at infinity
+ draw_line(&context, &circle);*/
Ok(())
}