Skip to content

Commit

Permalink
Add a page
Browse files Browse the repository at this point in the history
  • Loading branch information
mtshr committed Feb 14, 2024
1 parent 90ecd44 commit 7d2dc4d
Show file tree
Hide file tree
Showing 5 changed files with 340 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,23 @@ name = "github-pages"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
rand = "0.8.5"
wasm-bindgen = "0.2.91"
yew = { version = "0.21.0", features = ["csr"] }

[dependencies.web-sys]
version = "0.3.68"
features = [
"CanvasRenderingContext2d",
"HtmlCanvasElement"
]

[profile.release]
panic = 'abort'
codegen-units = 1
opt-level = 's'
lto = true
21 changes: 21 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title>Yew App</title>
<style>
a {
color: white
}

a:link {
color: white
}
</style>
<script src="./pkg/bundle.js" defer></script>
</head>

<body style="background-color: black"></body>

</html>
6 changes: 6 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import init, { run_app } from './pkg/github_pages.js';
async function main() {
await init('./pkg/github_pages_bg.wasm');
run_app();
}
main()
171 changes: 171 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
mod vec3;

use std::{array, f64::consts::TAU};

use vec3::Vec3;
use web_sys::{window, CanvasRenderingContext2d, HtmlCanvasElement};
use yew::prelude::*;

use wasm_bindgen::prelude::*;

enum Msg {
Tick,
}

struct AnimationCanvas {
canvas: NodeRef,
time: u32,
angle: [f64; 3],
angle_velocity: [f64; 3],
vertices: Vec<Vec3>,
callback: Closure<dyn FnMut()>,
}

fn cube() -> Vec<Vec3> {
let mut v = Vec::with_capacity(5 * 5 * 5);
for x in -2..=2 {
for y in -2..=2 {
for z in -2..=2 {
v.push(Vec3 {
x: x as f64,
y: y as f64,
z: z as f64,
})
}
}
}
v
}

impl Component for AnimationCanvas {
type Message = Msg;
type Properties = ();

fn create(ctx: &Context<Self>) -> Self {
let ctx = ctx.link().clone();

Self {
canvas: NodeRef::default(),
time: 0,
angle: array::from_fn(|_| rand::random::<f64>() * TAU),
angle_velocity: [0.01, 0.02, 0.03],
vertices: cube(),
callback: Closure::wrap(Box::new(move || ctx.send_message(Msg::Tick))),
}
}

fn rendered(&mut self, ctx: &Context<Self>, first_render: bool) {
if first_render {
ctx.link().send_message(Msg::Tick);
}
}

fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::Tick => {
self.tick();
self.render();
window()
.unwrap()
.request_animation_frame(self.callback.as_ref().unchecked_ref())
.unwrap();
false
}
}
}

fn view(&self, _ctx: &Context<Self>) -> Html {
html! {
<canvas id="canvas" width={640} height={640} ref={self.canvas.clone()}></canvas>
}
}
}

impl AnimationCanvas {
fn tick(&mut self) {
self.time = self.time.wrapping_add(1);

// update angle
for (a, v) in self.angle.iter_mut().zip(self.angle_velocity.iter_mut()) {
let delta = rand::random::<f64>() - 0.5;
*v = (*v + delta / 500.).clamp(0.01, 0.04);
*a = (*a + *v) % TAU;
}
}

fn render(&self) {
let canvas: HtmlCanvasElement = self.canvas.cast().unwrap();
let ctx: CanvasRenderingContext2d =
canvas.get_context("2d").unwrap().unwrap().unchecked_into();

let width = canvas.width() as f64;
let height = canvas.height() as f64;
let center = Vec3 {
x: width / 2.,
y: height / 2.,
z: 0f64,
};

ctx.set_fill_style(&"#000".into());
ctx.fill_rect(0f64, 0f64, width, height);

let mat = {
let (s1, c1) = self.angle[0].sin_cos();
let (s2, c2) = self.angle[1].sin_cos();
let (s3, c3) = self.angle[2].sin_cos();
[
[c2, -c3 * s2, s2 * s3],
[c1 * s2, c1 * c2 * c3 - s1 * s3, -c3 * s1 - c1 * c2 * s3],
[s1 * s2, c1 * s3 + c2 * c3 * s1, c1 * c3 - c2 * s1 * s3],
]
};

let mut vertices: Vec<_> = self
.vertices
.iter()
.map(|Vec3 { x, y, z }| Vec3 {
x: mat[0][0] * x + mat[0][1] * y + mat[0][2] * z,
y: mat[1][0] * x + mat[1][1] * y + mat[1][2] * z,
z: mat[2][0] * x + mat[2][1] * y + mat[2][2] * z,
})
.enumerate()
.collect();
vertices.sort_by(|(_, a), (_, b)| a.z.partial_cmp(&b.z).unwrap());

for (i, Vec3 { x, y, z }) in vertices.into_iter() {
let t = (self.time & 255) as f64 / 256. * TAU + (123454321 % (i * i + 1)) as f64;
let (dx, dy) = {
let a = (i * i % 5) as f64;
let b = (i % 3) as f64;
((a * t).cos(), (b * t).cos())
};

let gray_scale = (192. + (x / 2. - y + z) * 32.).clamp(0f64, 255.) as u8;
let co = z * 1.5 + 60.;
let x = center.x + (x + 0.03 * dx) * co;
let y = center.y + (y + 0.03 * dy) * co;
let r = 8.3 + 1.25 * t.cos() + z / 2.5;
ctx.set_fill_style(&format!("#{x:02X}{x:02X}{x:02X}", x = gray_scale).into());
ctx.begin_path();
ctx.arc(x, y, r, 0f64, TAU).unwrap();
ctx.fill();
}
}
}

#[function_component(App)]
fn app() -> Html {
html! {
<div style={"text-align: center"}>
<AnimationCanvas />
<div>
<a href={"https://github.com/mtshr"}>{"@mtshr"}</a>
</div>
</div>
}
}

#[wasm_bindgen]
pub fn run_app() {
yew::Renderer::<App>::new().render();
}
123 changes: 123 additions & 0 deletions src/vec3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use std::ops::{Add, Mul, Sub};

#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct Vec3 {
pub x: f64,
pub y: f64,
pub z: f64,
}

macro_rules! impl_binop {
($Trait:ident $fn:ident) => {
impl $Trait for Vec3 {
type Output = Vec3;

fn $fn(self, rhs: Vec3) -> Self::Output {
Vec3 {
x: self.x.$fn(rhs.x),
y: self.y.$fn(rhs.y),
z: self.z.$fn(rhs.z),
}
}
}

impl $Trait<Vec3> for &Vec3 {
type Output = Vec3;

fn $fn(self, rhs: Vec3) -> Self::Output {
Vec3 {
x: self.x.$fn(rhs.x),
y: self.y.$fn(rhs.y),
z: self.z.$fn(rhs.z),
}
}
}

impl $Trait<&Vec3> for Vec3 {
type Output = Vec3;

fn $fn(self, rhs: &Vec3) -> Self::Output {
Vec3 {
x: self.x.$fn(rhs.x),
y: self.y.$fn(rhs.y),
z: self.z.$fn(rhs.z),
}
}
}

impl $Trait<&Vec3> for &Vec3 {
type Output = Vec3;

fn $fn(self, rhs: &Vec3) -> Self::Output {
Vec3 {
x: self.x.$fn(rhs.x),
y: self.y.$fn(rhs.y),
z: self.z.$fn(rhs.z),
}
}
}
};
}

impl_binop!(Add add);
impl_binop!(Sub sub);

impl Mul<f64> for Vec3 {
type Output = Vec3;

fn mul(self, rhs: f64) -> Self::Output {
Vec3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}

impl Mul<f64> for &Vec3 {
type Output = Vec3;

fn mul(self, rhs: f64) -> Self::Output {
Vec3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}

impl Mul<&f64> for Vec3 {
type Output = Vec3;

fn mul(self, rhs: &f64) -> Self::Output {
Vec3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}

impl Mul<&f64> for &Vec3 {
type Output = Vec3;

fn mul(self, rhs: &f64) -> Self::Output {
Vec3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}

impl From<(f64, f64, f64)> for Vec3 {
fn from((x, y, z): (f64, f64, f64)) -> Self {
Vec3 { x, y, z }
}
}

impl From<[f64; 3]> for Vec3 {
fn from([x, y, z]: [f64; 3]) -> Self {
Vec3 { x, y, z }
}
}

0 comments on commit 7d2dc4d

Please sign in to comment.