Hyperbolic Asteroids, first commit. Rendering Poincare disk, circles, and lines.
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/target
|
||||
154
Cargo.lock
generated
Normal file
154
Cargo.lock
generated
Normal file
@@ -0,0 +1,154 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
||||
|
||||
[[package]]
|
||||
name = "hyperbolic_asteroids"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "hyperbolic_asteroids"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
features = [
|
||||
"Window",
|
||||
"Document",
|
||||
"HtmlCanvasElement",
|
||||
"CanvasRenderingContext2d",
|
||||
"console",
|
||||
]
|
||||
|
||||
|
||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1755615617,
|
||||
"narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "20075955deac2583bb12f07151c2df830ef346b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
23
flake.nix
Normal file
23
flake.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
description = "Rust Wasm Shell";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
devShells.${system}.default = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.rustc
|
||||
pkgs.cargo
|
||||
pkgs.wasm-pack
|
||||
pkgs.lld
|
||||
pkgs.python3
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
14
index.html
Normal file
14
index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Rust WASM Game Window</title>
|
||||
</head>
|
||||
<body style="margin:0; background:#222; display:flex; justify-content:center; align-items:center; height:100vh;">
|
||||
<canvas id="game-canvas"></canvas>
|
||||
<script type="module">
|
||||
import init from "./pkg/hyperbolic_asteroids.js";
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1024
src/cga.rs
Normal file
1024
src/cga.rs
Normal file
File diff suppressed because it is too large
Load Diff
213
src/lib.rs
Normal file
213
src/lib.rs
Normal file
@@ -0,0 +1,213 @@
|
||||
use std::f64;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
|
||||
//use web_sys::console;
|
||||
|
||||
mod cga;
|
||||
use cga::CGA;
|
||||
|
||||
const PI: f64 = f64::consts::PI;
|
||||
const TWO_PI: f64 = 2.*PI;
|
||||
const ERROR: f64 = 0.0001;
|
||||
|
||||
const WIDTH: f64 = 600.;
|
||||
const HEIGHT: f64 = 600.;
|
||||
const CENTER_X: f64 = 300.;
|
||||
const CENTER_Y: f64 = 300.;
|
||||
const RADIUS: f64 = 250.;
|
||||
|
||||
const BACKGROUND: &str = "#ffffff";
|
||||
const BLACK: &str = "#000000";
|
||||
const RED: &str = "#ff0000";
|
||||
const GREEN: &str = "#00ff00";
|
||||
const _BLUE: &str = "#0000ff";
|
||||
|
||||
const SCALAR: usize = 0;
|
||||
const E1: usize = 1;
|
||||
const E2: usize = 2;
|
||||
//const E3: usize = 3;
|
||||
//const E4: usize = 4;
|
||||
//const E5: usize = 5;
|
||||
//const E12: usize = 6;
|
||||
//const E13: usize = 7;
|
||||
//const E14: usize = 8;
|
||||
//const E15: usize = 9;
|
||||
//const E23: usize = 10;
|
||||
//const E24: usize = 11;
|
||||
//const E25: usize = 12;
|
||||
//const E34: usize = 13;
|
||||
//const E35: usize = 14;
|
||||
//const E45: usize = 15;
|
||||
//const E123: usize = 16;
|
||||
//const E124: usize = 17;
|
||||
//const E125: usize = 18;
|
||||
//const E134: usize = 19;
|
||||
//const E135: usize = 20;
|
||||
//const E145: usize = 21;
|
||||
//const E234: usize = 22;
|
||||
//const E235: usize = 23;
|
||||
//const E245: usize = 24;
|
||||
//const E345: usize = 25;
|
||||
//const E1234: usize = 26;
|
||||
//const E1235: usize = 27;
|
||||
//const E1245: usize = 28;
|
||||
//const E1345: usize = 29;
|
||||
//const E2345: usize = 30;
|
||||
//const E12345: usize = 31;
|
||||
|
||||
struct Ship {
|
||||
_pos: CGA,
|
||||
_vel: CGA,
|
||||
_orientation: CGA,
|
||||
}
|
||||
|
||||
fn point_to_cga(x: f64, y: f64) -> CGA {
|
||||
let x_vec = CGA::e1();
|
||||
let y_vec = CGA::e2();
|
||||
let _z_vec =CGA::e3();
|
||||
let e_vec = CGA::e4();
|
||||
let e_bar = CGA::e5();
|
||||
let n_vec = &e_vec + &e_bar;
|
||||
let n_bar = &e_vec - &e_bar;
|
||||
|
||||
let mut ux = x;
|
||||
let mut uy = y;
|
||||
let mut mag_sqr = ux*ux + uy*uy;
|
||||
if mag_sqr > 1. {
|
||||
ux /= mag_sqr.sqrt();
|
||||
uy /= mag_sqr.sqrt();
|
||||
mag_sqr = 1.;
|
||||
}
|
||||
|
||||
0.5*mag_sqr*n_vec + ux*x_vec + uy*y_vec - 0.5*n_bar
|
||||
}
|
||||
|
||||
fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) {
|
||||
//Naively assume we are given a valid point
|
||||
let x = point[1]*RADIUS + CENTER_X;
|
||||
let y = point[2]*RADIUS + CENTER_Y;
|
||||
|
||||
context.begin_path();
|
||||
context.set_fill_style_str(RED);
|
||||
context.arc(x, y, 2., 0., TWO_PI).unwrap();
|
||||
context.fill();
|
||||
}
|
||||
|
||||
fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) {
|
||||
context.begin_path();
|
||||
context.set_stroke_style_str(GREEN);
|
||||
|
||||
//Naively assume we are given a valid line/circle
|
||||
let n_bar = CGA::e4() - CGA::e5();
|
||||
let n_vec = CGA::e4() + CGA::e5();
|
||||
let dual = line.Dual();
|
||||
|
||||
let lambda = -(&dual | &n_vec)[SCALAR];
|
||||
let mu = (&dual | &n_bar)[SCALAR];
|
||||
let x = dual[E1];
|
||||
let y = dual[E2];
|
||||
|
||||
|
||||
if lambda.abs() < ERROR {
|
||||
//Line
|
||||
let norm_sqr = x*x+y*y;
|
||||
if norm_sqr < ERROR {
|
||||
return;
|
||||
} else {
|
||||
let norm = norm_sqr.sqrt();
|
||||
let px = mu * 0.5 * x / norm_sqr;
|
||||
let py = mu * 0.5 * y / norm_sqr;
|
||||
let tx = -y / norm;
|
||||
let ty = x / norm;
|
||||
let p1x = px + tx * 1000.;
|
||||
let p1y = py + ty * 1000.;
|
||||
let p2x = px - tx * 1000.;
|
||||
let p2y = py - ty * 1000.;
|
||||
context.move_to(p1x*RADIUS + CENTER_X, p1y*RADIUS + CENTER_Y);
|
||||
context.line_to(p2x*RADIUS + CENTER_X, p2y*RADIUS + CENTER_Y);
|
||||
|
||||
}
|
||||
} else {
|
||||
//Extract Center and Radius
|
||||
let c_x = x/lambda;
|
||||
let c_y = y/lambda;
|
||||
let r_sqr = c_x*c_x + c_y*c_y - mu/lambda;
|
||||
let r = r_sqr.sqrt();
|
||||
|
||||
//draw_point(context, &point_to_cga(c_x, c_y));
|
||||
|
||||
//Convert into Canvas Space
|
||||
let canvas_cx = c_x*RADIUS + CENTER_X;
|
||||
let canvas_cy = c_y*RADIUS + CENTER_Y;
|
||||
let canvas_r = r*RADIUS;
|
||||
|
||||
//Draw
|
||||
context.arc(canvas_cx, canvas_cy, canvas_r, 0., TWO_PI).unwrap();
|
||||
}
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
// 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() };
|
||||
|
||||
// Grab document and canvas
|
||||
let window = web_sys::window().unwrap();
|
||||
let document = window.document().unwrap();
|
||||
let canvas = document
|
||||
.get_element_by_id("game-canvas")
|
||||
.unwrap()
|
||||
.dyn_into::<HtmlCanvasElement>()?;
|
||||
|
||||
canvas.set_width(WIDTH as u32);
|
||||
canvas.set_height(HEIGHT as u32);
|
||||
|
||||
let context = canvas
|
||||
.get_context("2d")?
|
||||
.unwrap()
|
||||
.dyn_into::<CanvasRenderingContext2d>()?;
|
||||
|
||||
//Set up play area.
|
||||
context.begin_path();
|
||||
context.set_fill_style_str(BACKGROUND);
|
||||
context.fill_rect(0.0, 0.0, WIDTH, HEIGHT);
|
||||
context.fill();
|
||||
context.set_stroke_style_str(BLACK);
|
||||
context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
|
||||
context.stroke();
|
||||
|
||||
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();
|
||||
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);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user