From 93e2d52d7cd3d9b7aa89ea7c0b44514b301b0cfe Mon Sep 17 00:00:00 2001 From: Tommy Builds Date: Sun, 9 Jun 2024 14:06:00 -0700 Subject: [PATCH 1/6] Refactor to support xform --- runtime/functor-runtime-common/Cargo.toml | 2 +- runtime/functor-runtime-common/src/lib.rs | 23 +---- runtime/functor-runtime-common/src/scene3d.rs | 86 +++++++++++++++++++ runtime/functor-runtime-desktop/src/main.rs | 10 +-- 4 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 runtime/functor-runtime-common/src/scene3d.rs diff --git a/runtime/functor-runtime-common/Cargo.toml b/runtime/functor-runtime-common/Cargo.toml index a5c6777..b590c3b 100644 --- a/runtime/functor-runtime-common/Cargo.toml +++ b/runtime/functor-runtime-common/Cargo.toml @@ -15,4 +15,4 @@ serde = { version = "1.0", features = ["derive"] } # Conditionally include dependencies for the WebAssembly target [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = "0.2" -serde-wasm-bindgen = "0.4" \ No newline at end of file +serde-wasm-bindgen = "0.4" diff --git a/runtime/functor-runtime-common/src/lib.rs b/runtime/functor-runtime-common/src/lib.rs index bca027a..9680fc3 100644 --- a/runtime/functor-runtime-common/src/lib.rs +++ b/runtime/functor-runtime-common/src/lib.rs @@ -20,27 +20,6 @@ where serde_wasm_bindgen::from_value(value).unwrap() } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum Scene3D { - Cube, - Sphere, - Cylinder, -} - -impl Scene3D { - pub fn cube() -> Self { - Self::Cube - } - - pub fn sphere() -> Self { - Self::Sphere - } - - pub fn cylinder() -> Self { - Self::Cylinder - } -} - pub fn add(left: usize, right: usize) -> usize { left + right } @@ -70,12 +49,14 @@ mod frame_time; pub mod geometry; pub mod material; mod render_context; +mod scene3d; mod shader; mod shader_program; pub mod texture; pub use frame_time::*; pub use render_context::*; +pub use scene3d::*; #[cfg(test)] mod tests { diff --git a/runtime/functor-runtime-common/src/scene3d.rs b/runtime/functor-runtime-common/src/scene3d.rs new file mode 100644 index 0000000..8ff189e --- /dev/null +++ b/runtime/functor-runtime-common/src/scene3d.rs @@ -0,0 +1,86 @@ +use cgmath::{Matrix4, SquareMatrix}; +use serde::{Deserialize, Serialize}; + +use crate::geometry::Geometry; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Shape { + Cube, + Sphere, + Cylinder, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SceneObject { + Geometry(Shape), +} + +fn serialize_matrix(matrix: &Matrix4, serializer: S) -> Result +where + S: serde::Serializer, +{ + let array: [[f32; 4]; 4] = [ + [matrix.x[0], matrix.x[1], matrix.x[2], matrix.x[3]], + [matrix.y[0], matrix.y[1], matrix.y[2], matrix.y[3]], + [matrix.z[0], matrix.z[1], matrix.z[2], matrix.z[3]], + [matrix.w[0], matrix.w[1], matrix.w[2], matrix.w[3]], + ]; + array.serialize(serializer) +} + +fn deserialize_matrix<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let array = <[[f32; 4]; 4]>::deserialize(deserializer)?; + Ok(Matrix4::new( + array[0][0], + array[0][1], + array[0][2], + array[0][3], + array[1][0], + array[1][1], + array[1][2], + array[1][3], + array[2][0], + array[2][1], + array[2][2], + array[2][3], + array[3][0], + array[3][1], + array[3][2], + array[3][3], + )) +} +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Scene3D { + pub obj: SceneObject, + #[serde( + serialize_with = "serialize_matrix", + deserialize_with = "deserialize_matrix" + )] + pub xform: Matrix4, +} + +impl Scene3D { + pub fn cube() -> Self { + Scene3D { + obj: SceneObject::Geometry(Shape::Cube), + xform: Matrix4::identity(), + } + } + + pub fn sphere() -> Self { + Scene3D { + obj: SceneObject::Geometry(Shape::Sphere), + xform: Matrix4::identity(), + } + } + + pub fn cylinder() -> Self { + Scene3D { + obj: SceneObject::Geometry(Shape::Sphere), + xform: Matrix4::identity(), + } + } +} diff --git a/runtime/functor-runtime-desktop/src/main.rs b/runtime/functor-runtime-desktop/src/main.rs index e98987d..e9ffa9f 100644 --- a/runtime/functor-runtime-desktop/src/main.rs +++ b/runtime/functor-runtime-desktop/src/main.rs @@ -7,7 +7,7 @@ use cgmath::Matrix4; use cgmath::{perspective, vec3, Deg, Point3}; use functor_runtime_common::geometry::Geometry; use functor_runtime_common::material::BasicMaterial; -use functor_runtime_common::{FrameTime, Scene3D}; +use functor_runtime_common::{FrameTime, Scene3D, SceneObject}; use glfw::{init, RenderContext}; use glow::*; use hot_reload_game::HotReloadGame; @@ -273,16 +273,16 @@ pub fn main() { let scene = game.render(time.clone()); // let scene = Scene3D::cube(); - match scene { - Scene3D::Cube => { + match scene.obj { + SceneObject::Geometry(functor_runtime_common::Shape::Cube) => { let mut cube = functor_runtime_common::geometry::Cube::create(); cube.draw(&gl); } - Scene3D::Cylinder => { + SceneObject::Geometry(functor_runtime_common::Shape::Cylinder) => { let mut cylinder = functor_runtime_common::geometry::Cylinder::create(); cylinder.draw(&gl); } - Scene3D::Sphere => { + SceneObject::Geometry(functor_runtime_common::Shape::Sphere) => { let mut sphere = functor_runtime_common::geometry::Sphere::create(); sphere.draw(&gl); } From 852b6f585508e7304b54e54a7c2520098788c7f4 Mon Sep 17 00:00:00 2001 From: Tommy Builds Date: Sun, 9 Jun 2024 14:19:50 -0700 Subject: [PATCH 2/6] Some tweaks --- examples/Pong/Pong.fs | 21 ++--- .../functor-runtime-common/src/frame_time.rs | 4 +- runtime/functor-runtime-common/src/scene3d.rs | 78 +++++++++++-------- runtime/functor-runtime-desktop/src/main.rs | 16 ++-- src/Functor.Game/FrameTime.fs | 4 +- src/Functor.Game/Math/Point2.fs | 4 +- src/Functor.Game/Math/Vector2.fs | 4 +- src/Functor.Game/Runtime.fs | 1 + src/Functor.Game/Scene3D.fs | 7 +- 9 files changed, 79 insertions(+), 60 deletions(-) diff --git a/examples/Pong/Pong.fs b/examples/Pong/Pong.fs index 635ce36..d0a1fe9 100644 --- a/examples/Pong/Pong.fs +++ b/examples/Pong/Pong.fs @@ -3,8 +3,8 @@ module Pong open Functor open Functor.Math -let GAME_HEIGHT = 600.0 -let GAME_WIDTH = 800.0 +let GAME_HEIGHT = 600.0f +let GAME_WIDTH = 800.0f type Paddle = { position: Point2 @@ -12,15 +12,15 @@ type Paddle = { } module Paddle = - let initial = { position = Point2.zero; size = Vector2.xy 0.1 0.3 } + let initial = { position = Point2.zero; size = Vector2.xy 0.1f 0.3f } type Ball = { position: Point2 velocity: Vector2 - radius: float } + radius: float32 } module Ball = - let initial = { position = Point2.zero; velocity = Vector2.zero; radius = 0.05 } + let initial = { position = Point2.zero; velocity = Vector2.zero; radius = 0.05f } type Model = { paddle1: Paddle @@ -51,7 +51,7 @@ let tick model (tick: Time.FrameTime) = { ball with position = newBallPosition } let handleCollisionWithTopAndBottomWalls ball = - if ball.position.y <= 0.0 || ball.position.y >= GAME_HEIGHT then + if ball.position.y <= 0.0f || ball.position.y >= GAME_HEIGHT then { ball with velocity = Vector2.xy ball.velocity.x -ball.velocity.y } else ball @@ -60,10 +60,10 @@ let tick model (tick: Time.FrameTime) = let ballBottom = ball.position.y + ball.radius let ballLeft = ball.position.x - ball.radius let ballRight = ball.position.x + ball.radius - let paddleTop = paddle.position.y - paddle.size.y / 2.0 - let paddleBottom = paddle.position.y + paddle.size.y / 2.0 - let paddleLeft = paddle.position.x - paddle.size.x / 2.0 - let paddleRight = paddle.position.x + paddle.size.x / 2.0 + let paddleTop = paddle.position.y - paddle.size.y / 2.0f + let paddleBottom = paddle.position.y + paddle.size.y / 2.0f + let paddleLeft = paddle.position.x - paddle.size.x / 2.0f + let paddleRight = paddle.position.x + paddle.size.x / 2.0f if ballTop >= paddleBottom && ballBottom <= paddleTop && ballLeft <= paddleRight && ballRight >= paddleLeft then { ball with velocity = Vector2.xy -ball.velocity.x ball.velocity.y } else ball @@ -83,6 +83,7 @@ let init (_args: array) = game |> GameBuilder.draw3d (fun model frameTime -> Graphics.Scene3D.cube() + |> Graphics.Scene3D.Transform.translateY (sin frameTime.dts) ) |> GameBuilder.tick tick |> Runtime.runGame \ No newline at end of file diff --git a/runtime/functor-runtime-common/src/frame_time.rs b/runtime/functor-runtime-common/src/frame_time.rs index 4e1a5b8..b4ee76e 100644 --- a/runtime/functor-runtime-common/src/frame_time.rs +++ b/runtime/functor-runtime-common/src/frame_time.rs @@ -3,8 +3,8 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Serialize, Deserialize)] pub struct FrameTime { // tts - total time in seconds - pub tts: f64, + pub tts: f32, // dts - delta time in seconds for this frame - pub dts: f64, + pub dts: f32, } diff --git a/runtime/functor-runtime-common/src/scene3d.rs b/runtime/functor-runtime-common/src/scene3d.rs index 8ff189e..9e6a88e 100644 --- a/runtime/functor-runtime-common/src/scene3d.rs +++ b/runtime/functor-runtime-common/src/scene3d.rs @@ -1,4 +1,4 @@ -use cgmath::{Matrix4, SquareMatrix}; +use cgmath::{vec3, Matrix4, SquareMatrix}; use serde::{Deserialize, Serialize}; use crate::geometry::Geometry; @@ -15,6 +15,50 @@ pub enum SceneObject { Geometry(Shape), } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Scene3D { + pub obj: SceneObject, + #[serde( + serialize_with = "serialize_matrix", + deserialize_with = "deserialize_matrix" + )] + pub xform: Matrix4, +} + +impl Scene3D { + pub fn cube() -> Self { + Scene3D { + obj: SceneObject::Geometry(Shape::Cube), + xform: Matrix4::identity(), + } + } + + pub fn sphere() -> Self { + Scene3D { + obj: SceneObject::Geometry(Shape::Sphere), + xform: Matrix4::identity(), + } + } + + pub fn cylinder() -> Self { + Scene3D { + obj: SceneObject::Geometry(Shape::Sphere), + xform: Matrix4::identity(), + } + } + + pub fn transform(self, xform: Matrix4) -> Self { + Scene3D { + xform: self.xform * xform, + ..self + } + } + + pub fn translate_y(self, y: f32) -> Self { + self.transform(Matrix4::from_translation(vec3(0.0, y, 0.0))) + } +} + fn serialize_matrix(matrix: &Matrix4, serializer: S) -> Result where S: serde::Serializer, @@ -52,35 +96,3 @@ where array[3][3], )) } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Scene3D { - pub obj: SceneObject, - #[serde( - serialize_with = "serialize_matrix", - deserialize_with = "deserialize_matrix" - )] - pub xform: Matrix4, -} - -impl Scene3D { - pub fn cube() -> Self { - Scene3D { - obj: SceneObject::Geometry(Shape::Cube), - xform: Matrix4::identity(), - } - } - - pub fn sphere() -> Self { - Scene3D { - obj: SceneObject::Geometry(Shape::Sphere), - xform: Matrix4::identity(), - } - } - - pub fn cylinder() -> Self { - Scene3D { - obj: SceneObject::Geometry(Shape::Sphere), - xform: Matrix4::identity(), - } - } -} diff --git a/runtime/functor-runtime-desktop/src/main.rs b/runtime/functor-runtime-desktop/src/main.rs index e9ffa9f..bc2f27d 100644 --- a/runtime/functor-runtime-desktop/src/main.rs +++ b/runtime/functor-runtime-desktop/src/main.rs @@ -262,19 +262,19 @@ pub fn main() { shader_version, }; - basic_material.draw_opaque( - &context, - &projection_matrix, - &view_matrix, - &world_matrix, - &skinning_data, - ); - let scene = game.render(time.clone()); // let scene = Scene3D::cube(); match scene.obj { SceneObject::Geometry(functor_runtime_common::Shape::Cube) => { + let xform = scene.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); let mut cube = functor_runtime_common::geometry::Cube::create(); cube.draw(&gl); } diff --git a/src/Functor.Game/FrameTime.fs b/src/Functor.Game/FrameTime.fs index f4673f5..532f0f7 100644 --- a/src/Functor.Game/FrameTime.fs +++ b/src/Functor.Game/FrameTime.fs @@ -5,6 +5,6 @@ open Fable.Core type FrameTime = [] - abstract dts: float + abstract dts: float32 [] - abstract tts: float \ No newline at end of file + abstract tts: float32 \ No newline at end of file diff --git a/src/Functor.Game/Math/Point2.fs b/src/Functor.Game/Math/Point2.fs index 5171420..d8f1635 100644 --- a/src/Functor.Game/Math/Point2.fs +++ b/src/Functor.Game/Math/Point2.fs @@ -1,10 +1,10 @@ namespace Functor.Math -type Point2 = { x: float; y: float } +type Point2 = { x: float32; y: float32 } module Point2 = - let zero = { x = 0.0; y = 0.0 } + let zero = { x = 0.0f; y = 0.0f } let xy x y = { x = x; y = y } diff --git a/src/Functor.Game/Math/Vector2.fs b/src/Functor.Game/Math/Vector2.fs index a147ba7..dd49687 100644 --- a/src/Functor.Game/Math/Vector2.fs +++ b/src/Functor.Game/Math/Vector2.fs @@ -1,10 +1,10 @@ namespace Functor.Math -type Vector2 = { x: float; y: float } +type Vector2 = { x: float32; y: float32 } module Vector2 = - let zero = { x = 0.0; y = 0.0 } + let zero = { x = 0.0f; y = 0.0f } let xy x y = { x = x; y = y } diff --git a/src/Functor.Game/Runtime.fs b/src/Functor.Game/Runtime.fs index af5dc6d..d4b47c9 100644 --- a/src/Functor.Game/Runtime.fs +++ b/src/Functor.Game/Runtime.fs @@ -28,6 +28,7 @@ module Runtime [] type JsValue = | Noop module UnsafeJsValue = + [] let to_js<'a>(obj): JsValue = nativeOnly // let from_js<'a>(jsValue: JsValue): 'a = nativeOnly diff --git a/src/Functor.Game/Scene3D.fs b/src/Functor.Game/Scene3D.fs index d88cbdd..13f912d 100644 --- a/src/Functor.Game/Scene3D.fs +++ b/src/Functor.Game/Scene3D.fs @@ -12,4 +12,9 @@ module Scene3D = let sphere(): Scene3D = nativeOnly [] - let cylinder(): Scene3D = nativeOnly \ No newline at end of file + let cylinder(): Scene3D = nativeOnly + + module Transform = + + [] + let translateY (y: float32) (scene: Scene3D): Scene3D = nativeOnly \ No newline at end of file From 9c7889390f0574e2136c34a8b65eafee8a815b38 Mon Sep 17 00:00:00 2001 From: Tommy Builds Date: Sun, 9 Jun 2024 14:28:31 -0700 Subject: [PATCH 3/6] Get working with native runtime --- examples/Pong/Pong.fs | 4 +- runtime/functor-runtime-common/src/scene3d.rs | 2 +- runtime/functor-runtime-desktop/src/main.rs | 147 ++++++++++-------- 3 files changed, 87 insertions(+), 66 deletions(-) diff --git a/examples/Pong/Pong.fs b/examples/Pong/Pong.fs index d0a1fe9..137385f 100644 --- a/examples/Pong/Pong.fs +++ b/examples/Pong/Pong.fs @@ -82,8 +82,8 @@ open Fable.Core.Rust let init (_args: array) = game |> GameBuilder.draw3d (fun model frameTime -> - Graphics.Scene3D.cube() - |> Graphics.Scene3D.Transform.translateY (sin frameTime.dts) + Graphics.Scene3D.sphere() + |> Graphics.Scene3D.Transform.translateY ((sin (frameTime.tts * 5.0f)) * 1.0f) ) |> GameBuilder.tick tick |> Runtime.runGame \ No newline at end of file diff --git a/runtime/functor-runtime-common/src/scene3d.rs b/runtime/functor-runtime-common/src/scene3d.rs index 9e6a88e..dcb633a 100644 --- a/runtime/functor-runtime-common/src/scene3d.rs +++ b/runtime/functor-runtime-common/src/scene3d.rs @@ -42,7 +42,7 @@ impl Scene3D { pub fn cylinder() -> Self { Scene3D { - obj: SceneObject::Geometry(Shape::Sphere), + obj: SceneObject::Geometry(Shape::Cylinder), xform: Matrix4::identity(), } } diff --git a/runtime/functor-runtime-desktop/src/main.rs b/runtime/functor-runtime-desktop/src/main.rs index bc2f27d..860ca40 100644 --- a/runtime/functor-runtime-desktop/src/main.rs +++ b/runtime/functor-runtime-desktop/src/main.rs @@ -2,6 +2,7 @@ use std::env; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::time::Instant; use cgmath::Matrix4; use cgmath::{perspective, vec3, Deg, Point3}; @@ -221,75 +222,95 @@ pub fn main() { let world_matrix = Matrix4::from_nonuniform_scale(1.0, 1.0, 1.0); let skinning_data = vec![]; - let time: FrameTime = FrameTime { - dts: 99.0, - tts: 100.0, - }; - - #[cfg(not(target_arch = "wasm32"))] - { - use glfw::Context; + let start_time = Instant::now(); + let mut last_time: f32 = 0.0; + + use glfw::Context; + + while !window.should_close() { + let elapsed_time = start_time.elapsed().as_secs_f32(); + let time: FrameTime = FrameTime { + dts: elapsed_time - last_time, + tts: elapsed_time, + }; + last_time = elapsed_time; + + // Check if file has changed + if file_changed.load(Ordering::SeqCst) { + println!("Reloading!"); + file_changed.store(false, Ordering::SeqCst); + game.reload(); + println!("Rendering: {:?}", game.render(time.clone())); + } - while !window.should_close() { - // Check if file has changed - if file_changed.load(Ordering::SeqCst) { - println!("Reloading!"); - file_changed.store(false, Ordering::SeqCst); - game.reload(); - println!("Rendering: {:?}", game.render(time.clone())); + glfw.poll_events(); + for (_, event) in glfw::flush_messages(&events) { + match event { + glfw::WindowEvent::Close => window.set_should_close(true), + _ => {} } + } - glfw.poll_events(); - for (_, event) in glfw::flush_messages(&events) { - match event { - glfw::WindowEvent::Close => window.set_should_close(true), - _ => {} - } - } + gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); + let radius = 5.0; + let camX = glfw.get_time().sin() as f32 * radius; + let camZ = glfw.get_time().cos() as f32 * radius; + let view_matrix: Matrix4 = Matrix4::look_at_rh( + Point3::new(camX, 0.0, camZ), + Point3::new(0.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + ); - gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); - let radius = 5.0; - let camX = glfw.get_time().sin() as f32 * radius; - let camZ = glfw.get_time().cos() as f32 * radius; - let view_matrix: Matrix4 = Matrix4::look_at_rh( - Point3::new(camX, 0.0, camZ), - Point3::new(0.0, 0.0, 0.0), - vec3(0.0, 1.0, 0.0), - ); - - let context = functor_runtime_common::RenderContext { - gl: &gl, - shader_version, - }; - - let scene = game.render(time.clone()); - // let scene = Scene3D::cube(); - - match scene.obj { - SceneObject::Geometry(functor_runtime_common::Shape::Cube) => { - let xform = scene.xform * world_matrix; - basic_material.draw_opaque( - &context, - &projection_matrix, - &view_matrix, - &xform, - &skinning_data, - ); - let mut cube = functor_runtime_common::geometry::Cube::create(); - cube.draw(&gl); - } - SceneObject::Geometry(functor_runtime_common::Shape::Cylinder) => { - let mut cylinder = functor_runtime_common::geometry::Cylinder::create(); - cylinder.draw(&gl); - } - SceneObject::Geometry(functor_runtime_common::Shape::Sphere) => { - let mut sphere = functor_runtime_common::geometry::Sphere::create(); - sphere.draw(&gl); - } + let context = functor_runtime_common::RenderContext { + gl: &gl, + shader_version, + }; + + let scene = game.render(time.clone()); + // let scene = Scene3D::cube(); + + match scene.obj { + SceneObject::Geometry(functor_runtime_common::Shape::Cube) => { + let xform = scene.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); + let mut cube = functor_runtime_common::geometry::Cube::create(); + cube.draw(&gl); + } + SceneObject::Geometry(functor_runtime_common::Shape::Cylinder) => { + let xform = scene.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); + + let mut cylinder = functor_runtime_common::geometry::Cylinder::create(); + cylinder.draw(&gl); + } + SceneObject::Geometry(functor_runtime_common::Shape::Sphere) => { + let xform = scene.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); + + let mut sphere = functor_runtime_common::geometry::Sphere::create(); + sphere.draw(&gl); } - - window.swap_buffers(); } + + window.swap_buffers(); } watcher_thread.join().unwrap(); From e7e0b3cf32a5a76c5515d2f5a913c8f02df61fcf Mon Sep 17 00:00:00 2001 From: Tommy Builds Date: Sun, 9 Jun 2024 14:40:17 -0700 Subject: [PATCH 4/6] Use functor-runtime-common for rendering --- runtime/functor-runtime-common/src/scene3d.rs | 60 +++++++++++++++++- runtime/functor-runtime-desktop/src/main.rs | 63 +++---------------- 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/runtime/functor-runtime-common/src/scene3d.rs b/runtime/functor-runtime-common/src/scene3d.rs index dcb633a..0d4293b 100644 --- a/runtime/functor-runtime-common/src/scene3d.rs +++ b/runtime/functor-runtime-common/src/scene3d.rs @@ -1,7 +1,11 @@ use cgmath::{vec3, Matrix4, SquareMatrix}; use serde::{Deserialize, Serialize}; -use crate::geometry::Geometry; +use crate::{ + geometry::{self, Geometry}, + material::BasicMaterial, + RenderContext, +}; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum Shape { @@ -57,6 +61,60 @@ impl Scene3D { pub fn translate_y(self, y: f32) -> Self { self.transform(Matrix4::from_translation(vec3(0.0, y, 0.0))) } + + pub fn render( + &self, + context: &RenderContext, + world_matrix: &Matrix4, + projection_matrix: &Matrix4, + view_matrix: &Matrix4, + ) { + // TODO: Factor out to pass in current_material + let mut basic_material = BasicMaterial::create(); + basic_material.initialize(&context); + + let skinning_data = vec![]; + match self.obj { + SceneObject::Geometry(Shape::Cube) => { + let xform = self.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); + let mut cube = geometry::Cube::create(); + cube.draw(&context.gl); + } + SceneObject::Geometry(Shape::Cylinder) => { + let xform = self.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); + + let mut cylinder = geometry::Cylinder::create(); + cylinder.draw(&context.gl); + } + SceneObject::Geometry(Shape::Sphere) => { + let xform = self.xform * world_matrix; + basic_material.draw_opaque( + &context, + &projection_matrix, + &view_matrix, + &xform, + &skinning_data, + ); + + let mut sphere = geometry::Sphere::create(); + sphere.draw(&context.gl); + } + } + } } fn serialize_matrix(matrix: &Matrix4, serializer: S) -> Result diff --git a/runtime/functor-runtime-desktop/src/main.rs b/runtime/functor-runtime-desktop/src/main.rs index 860ca40..3f1972e 100644 --- a/runtime/functor-runtime-desktop/src/main.rs +++ b/runtime/functor-runtime-desktop/src/main.rs @@ -199,28 +199,15 @@ pub fn main() { gl.enable(glow::DEPTH_TEST); - // let matrix: Matrix4 = Matrix4::from_nonuniform_scale(1.0, 2.5, 1.0); - - // let matrix_location = unsafe { - // gl.get_uniform_location(program, "world") - // .expect("Cannot get uniform") - // }; - // let data = (&array4x4(matrix) as *const [[f32; 4]; 4]) as *const f32; - // let raw = slice::from_raw_parts(data, 16); - // gl.uniform_matrix_4_f32_slice(Some(&matrix_location), false, raw); - let init_ctx = functor_runtime_common::RenderContext { gl: &gl, shader_version, }; - let mut basic_material = BasicMaterial::create(); - basic_material.initialize(&init_ctx); let projection_matrix: Matrix4 = perspective(Deg(45.0), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0); let world_matrix = Matrix4::from_nonuniform_scale(1.0, 1.0, 1.0); - let skinning_data = vec![]; let start_time = Instant::now(); let mut last_time: f32 = 0.0; @@ -267,48 +254,14 @@ pub fn main() { }; let scene = game.render(time.clone()); - // let scene = Scene3D::cube(); - - match scene.obj { - SceneObject::Geometry(functor_runtime_common::Shape::Cube) => { - let xform = scene.xform * world_matrix; - basic_material.draw_opaque( - &context, - &projection_matrix, - &view_matrix, - &xform, - &skinning_data, - ); - let mut cube = functor_runtime_common::geometry::Cube::create(); - cube.draw(&gl); - } - SceneObject::Geometry(functor_runtime_common::Shape::Cylinder) => { - let xform = scene.xform * world_matrix; - basic_material.draw_opaque( - &context, - &projection_matrix, - &view_matrix, - &xform, - &skinning_data, - ); - - let mut cylinder = functor_runtime_common::geometry::Cylinder::create(); - cylinder.draw(&gl); - } - SceneObject::Geometry(functor_runtime_common::Shape::Sphere) => { - let xform = scene.xform * world_matrix; - basic_material.draw_opaque( - &context, - &projection_matrix, - &view_matrix, - &xform, - &skinning_data, - ); - - let mut sphere = functor_runtime_common::geometry::Sphere::create(); - sphere.draw(&gl); - } - } + + functor_runtime_common::Scene3D::render( + &scene, + &context, + &world_matrix, + &projection_matrix, + &view_matrix, + ); window.swap_buffers(); } From 1ece5ae09f9be39ee47488b6e10f66996b234043 Mon Sep 17 00:00:00 2001 From: Tommy Builds Date: Sun, 9 Jun 2024 14:51:34 -0700 Subject: [PATCH 5/6] Get wasm building --- runtime/functor-runtime-desktop/src/main.rs | 5 --- runtime/functor-runtime-web/src/lib.rs | 47 ++++++++------------- src/Functor.Game/Runtime.fs | 2 +- 3 files changed, 18 insertions(+), 36 deletions(-) diff --git a/runtime/functor-runtime-desktop/src/main.rs b/runtime/functor-runtime-desktop/src/main.rs index 3f1972e..7dd089f 100644 --- a/runtime/functor-runtime-desktop/src/main.rs +++ b/runtime/functor-runtime-desktop/src/main.rs @@ -199,11 +199,6 @@ pub fn main() { gl.enable(glow::DEPTH_TEST); - let init_ctx = functor_runtime_common::RenderContext { - gl: &gl, - shader_version, - }; - let projection_matrix: Matrix4 = perspective(Deg(45.0), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0); diff --git a/runtime/functor-runtime-web/src/lib.rs b/runtime/functor-runtime-web/src/lib.rs index 636be4a..7c40aa1 100644 --- a/runtime/functor-runtime-web/src/lib.rs +++ b/runtime/functor-runtime-web/src/lib.rs @@ -142,6 +142,10 @@ async fn run_async() -> Result<(), JsValue> { .expect("performance should be available"); let mut i = 0; + + let initial_time = performance.now() as f32; + let mut last_time = initial_time; + *g.borrow_mut() = Some(Closure::new(move || { // let matrix: Matrix4 = Matrix4::from_nonuniform_scale(1.0, 2.5, 1.0); @@ -158,14 +162,10 @@ async fn run_async() -> Result<(), JsValue> { shader_version, }; - let mut basic_material = BasicMaterial::create(); - basic_material.initialize(&render_ctx); - let projection_matrix: Matrix4 = perspective(Deg(45.0), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0); let world_matrix = Matrix4::from_nonuniform_scale(1.0, 1.0, 1.0); - let skinning_data: Vec> = vec![]; gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); let radius = 5.0; @@ -178,40 +178,27 @@ async fn run_async() -> Result<(), JsValue> { vec3(0.0, 1.0, 0.0), ); - basic_material.draw_opaque( - &render_ctx, - &projection_matrix, - &view_matrix, - &world_matrix, - &skinning_data, - ); - // let scene = Scene3D::cube(); + let now = performance.now() as f32; let frameTime = FrameTime { - dts: 99.0, - tts: 100.0, + dts: (now - last_time) / 1000.0, + tts: (now - initial_time) / 1000.0, }; + last_time = now; let val = game_render(functor_runtime_common::to_js_value(&frameTime)); web_sys::console::log_2(&JsValue::from_str("calling render"), &val); - let scene = functor_runtime_common::from_js_value(val); - - match scene { - Scene3D::Cube => { - let mut cube = functor_runtime_common::geometry::Cube::create(); - cube.draw(&gl); - } - Scene3D::Cylinder => { - let mut cylinder = functor_runtime_common::geometry::Cylinder::create(); - cylinder.draw(&gl); - } - Scene3D::Sphere => { - let mut sphere = functor_runtime_common::geometry::Sphere::create(); - sphere.draw(&gl); - } - } + let scene: Scene3D = functor_runtime_common::from_js_value(val); + + functor_runtime_common::Scene3D::render( + &scene, + &render_ctx, + &world_matrix, + &projection_matrix, + &view_matrix, + ); // Schedule ourself for another requestAnimationFrame callback. request_animation_frame(f.borrow().as_ref().unwrap()); diff --git a/src/Functor.Game/Runtime.fs b/src/Functor.Game/Runtime.fs index d4b47c9..80256b1 100644 --- a/src/Functor.Game/Runtime.fs +++ b/src/Functor.Game/Runtime.fs @@ -28,7 +28,7 @@ module Runtime [] type JsValue = | Noop module UnsafeJsValue = - [] + [] let to_js<'a>(obj): JsValue = nativeOnly // let from_js<'a>(jsValue: JsValue): 'a = nativeOnly From baa6fdef9204fdfd7b9036b1d54044a73a73ccc2 Mon Sep 17 00:00:00 2001 From: Tommy Builds Date: Mon, 10 Jun 2024 07:01:56 -0700 Subject: [PATCH 6/6] Add x, z transform --- examples/Pong/Pong.fs | 2 +- runtime/functor-runtime-common/src/scene3d.rs | 9 +++++++++ runtime/functor-runtime-desktop/src/main.rs | 2 +- runtime/functor-runtime-web/src/lib.rs | 10 ---------- src/Functor.Game/Scene3D.fs | 7 +++++-- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/examples/Pong/Pong.fs b/examples/Pong/Pong.fs index 137385f..6e4ce9f 100644 --- a/examples/Pong/Pong.fs +++ b/examples/Pong/Pong.fs @@ -83,7 +83,7 @@ let init (_args: array) = game |> GameBuilder.draw3d (fun model frameTime -> Graphics.Scene3D.sphere() - |> Graphics.Scene3D.Transform.translateY ((sin (frameTime.tts * 5.0f)) * 1.0f) + |> Graphics.Scene3D.Transform.translateX ((sin (frameTime.tts * 5.0f)) * 1.0f) ) |> GameBuilder.tick tick |> Runtime.runGame \ No newline at end of file diff --git a/runtime/functor-runtime-common/src/scene3d.rs b/runtime/functor-runtime-common/src/scene3d.rs index 0d4293b..fb9ce24 100644 --- a/runtime/functor-runtime-common/src/scene3d.rs +++ b/runtime/functor-runtime-common/src/scene3d.rs @@ -58,10 +58,19 @@ impl Scene3D { } } + pub fn translate_x(self, x: f32) -> Self { + self.transform(Matrix4::from_translation(vec3(x, 0.0, 0.0))) + } + pub fn translate_y(self, y: f32) -> Self { self.transform(Matrix4::from_translation(vec3(0.0, y, 0.0))) } + pub fn translate_z(self, z: f32) -> Self { + self.transform(Matrix4::from_translation(vec3(0.0, 0.0, z))) + } + + pub fn render( &self, context: &RenderContext, diff --git a/runtime/functor-runtime-desktop/src/main.rs b/runtime/functor-runtime-desktop/src/main.rs index 7dd089f..726f83c 100644 --- a/runtime/functor-runtime-desktop/src/main.rs +++ b/runtime/functor-runtime-desktop/src/main.rs @@ -238,7 +238,7 @@ pub fn main() { let camX = glfw.get_time().sin() as f32 * radius; let camZ = glfw.get_time().cos() as f32 * radius; let view_matrix: Matrix4 = Matrix4::look_at_rh( - Point3::new(camX, 0.0, camZ), + Point3::new(0.0, 0.0, -1.0 * radius), Point3::new(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), ); diff --git a/runtime/functor-runtime-web/src/lib.rs b/runtime/functor-runtime-web/src/lib.rs index 7c40aa1..205be70 100644 --- a/runtime/functor-runtime-web/src/lib.rs +++ b/runtime/functor-runtime-web/src/lib.rs @@ -147,16 +147,6 @@ async fn run_async() -> Result<(), JsValue> { let mut last_time = initial_time; *g.borrow_mut() = Some(Closure::new(move || { - // let matrix: Matrix4 = Matrix4::from_nonuniform_scale(1.0, 2.5, 1.0); - - // let matrix_location = unsafe { - // gl.get_uniform_location(program, "world") - // .expect("Cannot get uniform") - // }; - // let data = (&array4x4(matrix) as *const [[f32; 4]; 4]) as *const f32; - // let raw = slice::from_raw_parts(data, 16); - // gl.uniform_matrix_4_f32_slice(Some(&matrix_location), false, raw); - let render_ctx = RenderContext { gl: &gl, shader_version, diff --git a/src/Functor.Game/Scene3D.fs b/src/Functor.Game/Scene3D.fs index 13f912d..593228a 100644 --- a/src/Functor.Game/Scene3D.fs +++ b/src/Functor.Game/Scene3D.fs @@ -15,6 +15,9 @@ module Scene3D = let cylinder(): Scene3D = nativeOnly module Transform = - + [] + let translateX (x: float32) (scene: Scene3D): Scene3D = nativeOnly [] - let translateY (y: float32) (scene: Scene3D): Scene3D = nativeOnly \ No newline at end of file + let translateY (y: float32) (scene: Scene3D): Scene3D = nativeOnly + [] + let translateZ (z: float32) (scene: Scene3D): Scene3D = nativeOnly