Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Initial translate API #15

Merged
merged 6 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions examples/Pong/Pong.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ 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
size: Vector2
}

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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand All @@ -82,7 +82,8 @@ open Fable.Core.Rust
let init (_args: array<string>) =
game
|> GameBuilder.draw3d (fun model frameTime ->
Graphics.Scene3D.cube()
Graphics.Scene3D.sphere()
|> Graphics.Scene3D.Transform.translateX ((sin (frameTime.tts * 5.0f)) * 1.0f)
)
|> GameBuilder.tick tick
|> Runtime.runGame
2 changes: 1 addition & 1 deletion runtime/functor-runtime-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
serde-wasm-bindgen = "0.4"
4 changes: 2 additions & 2 deletions runtime/functor-runtime-common/src/frame_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
23 changes: 2 additions & 21 deletions runtime/functor-runtime-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
165 changes: 165 additions & 0 deletions runtime/functor-runtime-common/src/scene3d.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
use cgmath::{vec3, Matrix4, SquareMatrix};
use serde::{Deserialize, Serialize};

use crate::{
geometry::{self, Geometry},
material::BasicMaterial,
RenderContext,
};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Shape {
Cube,
Sphere,
Cylinder,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
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<f32>,
}

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::Cylinder),
xform: Matrix4::identity(),
}
}

pub fn transform(self, xform: Matrix4<f32>) -> Self {
Scene3D {
xform: self.xform * xform,
..self
}
}

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,
world_matrix: &Matrix4<f32>,
projection_matrix: &Matrix4<f32>,
view_matrix: &Matrix4<f32>,
) {
// 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<S>(matrix: &Matrix4<f32>, serializer: S) -> Result<S::Ok, S::Error>
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<Matrix4<f32>, 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],
))
}
Loading
Loading