babylon.rs
A WebAssembly wrapper for babylon.js in Rust.
This project is pre-alpha and the api is in active exploration. Current priorities:
- get a basic GLTF up
- get a camera
- get some sort of interaction
This project uses js_ffi
for javascript binding and lazy_static
for global static singletons fairly extensively.
Idioms
- Scenes hold 3D objects
- Materials determine how a 3D object looks
- When an 3D object drops it's removed from the scene
HelloWorld
use babylon::prelude::*;
#[macro_use]
extern crate lazy_static;
use std::sync::Mutex;
lazy_static! {
static ref GAME: Mutex<Game> = Mutex::new(Game::new());
}
struct Game {
scene: Scene,
shape: Vec<Sphere>,
}
impl Game {
fn new() -> Self {
Game {
scene: Scene::create_from_basic_engine("#renderCanvas"),
shape: vec![],
}
}
}
#[no_mangle]
pub fn main() {
babylon::js::log("Starting demo...");
let mut game = GAME.lock().unwrap();
for _ in 0..10 {
let mut sphere = Sphere::new(&game.scene, babylon::js::random());
sphere.set_position(Vector::new(
babylon::js::random() - 0.5,
babylon::js::random() - 0.5,
babylon::js::random() - 0.5,
));
game.shape.push(sphere);
}
}
See this demo here ( be sure to play with mouse and arrow keys :arrow_left: :arrow_up: :arrow_down: :arrow_right:!)
Materials
let mut game = GAME.lock().unwrap();
for _ in 0..10 {
let mut cube = Cube::new(
&game.scene,
babylon::js::random(),
babylon::js::random(),
babylon::js::random(),
);
let mut mat = StandardMaterial::new(&game.scene);
mat.set_diffuse_color(Color::new(babylon::js::random(),babylon::js::random(),babylon::js::random()));
mat.set_alpha(babylon::js::random());
cube.set_material(&mat);
cube.set_position(Vector::new(
babylon::js::random() - 0.5,
babylon::js::random() - 0.5,
babylon::js::random() - 0.5,
));
game.shape.push(cube);
}
See this demo here ( be sure to play with mouse and arrow keys :arrow_left: :arrow_up: :arrow_down: :arrow_right:!)
Pong in 100 Lines
use babylon::prelude::*;
struct Game {
scene: Scene,
_camera: Camera,
_light_1: HemisphericLight,
_light_2: PointLight,
ball: Sphere,
paddle_1: Cube,
paddle_2: Cube,
paddle_dir: f64,
ball_dir: Vector,
}
impl Default for Game {
fn default() -> Self {
let mut scene = Scene::new("#renderCanvas");
scene.set_clear_color(Color::new(0.0, 0.0, 0.0));
let _camera = Camera::new(&scene);
let _light_1 = HemisphericLight::new(&scene);
let _light_2 = PointLight::new(&scene);
let ball = Sphere::new(&scene, 0.05);
let mut paddle_mat = StandardMaterial::new(&scene);
paddle_mat.set_diffuse_color(Color::new(0.5, 0.5, 0.5));
paddle_mat.set_emmisive_color(Color::new(0.5, 0.5, 0.5));
let mut paddle_1 = Cube::new(&scene, 0.5, 0.05, 0.05);
paddle_1.set_position(Vector::new(0.0, 0.5, 0.0));
paddle_1.set_material(&paddle_mat);
let mut paddle_2 = Cube::new(&scene, 0.5, 0.05, 0.05);
paddle_2.set_position(Vector::new(0.0, -0.5, 0.0));
paddle_2.set_material(&paddle_mat);
Game {
scene,
_camera,
_light_1,
_light_2,
ball,
paddle_1,
paddle_2,
paddle_dir: 0.0,
ball_dir: Vector::new(babylon::js::random() - 0.5, -1.0, 0.0),
}
}
}
impl BasicGame for Game {
fn get_scene(&self) -> &Scene {
&self.scene
}
fn run(&mut self, delta_time: f64) {
let p2 = self.paddle_2.get_position();
let bp = self.ball.get_position();
let b_x = self.ball_dir.x * delta_time + bp.x;
let b_y = self.ball_dir.y * delta_time + bp.y;
if b_x > 0.5 || b_x < -0.5 {
self.ball_dir.x = -self.ball_dir.x;
}
if b_y > 0.75 || b_y < -0.75 {
self.ball.set_position(Vector::new(0.0, 0.0, 0.0));
self.ball_dir.x = babylon::js::random() - 0.5;
self.ball_dir.y = -self.ball_dir.y;
} else if b_y > 0.45 || (b_y < -0.45 && b_x <= p2.x + 0.25 && b_x >= p2.x - 0.25) {
self.ball_dir.y = -self.ball_dir.y;
self.ball.set_position(Vector::new(b_x, b_y, 0.0));
} else {
self.ball.set_position(Vector::new(b_x, b_y, 0.0));
}
self.paddle_1.set_position_x(b_x);
if self.paddle_dir != 0.0 {
let p2_x = p2.x + delta_time * self.paddle_dir;
self.paddle_2.set_position_x(p2_x)
}
}
fn key_up(&mut self, _key_code: f64) {
self.paddle_dir = 0.0;
}
fn key_down(&mut self, key_code: f64) {
if key_code == 37.0 {
self.paddle_dir = 1.0;
} else if key_code == 39.0 {
self.paddle_dir = -1.0;
}
}
}
#[no_mangle]
pub fn main() {
run_basic_game::<Game>();
}
Other Demos
License
This project is licensed under either of
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in babylon.rs
by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.