Hey everyone, over the past two nights, I threw together something similar to A-Frame powered by Babylon β Babylon you can write using HTML β> Babylon+ML = BabylonML!
BabylonML is a declarative, component-based framework built on top of the powerful Babylon.js engine. It allows web developers to create complex 3D scenes using familiar HTML-like tags, abstracting away much of the boilerplate JavaScript typically required.
Docs: https://babylonml.netlify.app/
This is MIT licensed, git repo here: GitHub - SonnyC56/babylonml: An html abstraction of babylon js
I am going to keep building this out, would love suggestions or community contributions. There still may be some bugs, working thru them when I have time.
Basic Example - BabylonML - Local Test
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>BabylonML - Local Test</title>
<style>
/* Basic styling to make the scene visible */
html, body {
margin: 0;
padding: 0;
overflow: hidden; /* Prevent scrollbars */
height: 100%;
width: 100%;
}
bml-scene {
width: 100vw; /* Viewport width */
height: 100vh; /* Viewport height */
display: block; /* Make it a block element */
}
canvas {
display: block; /* Prevent potential small gap below canvas */
}
</style>
<!--
Load the FRAMEWORK SCRIPT.
IMPORTANT: We point to the *unminified* development build
('../dist/babylonml.js') for easier debugging locally.
The path '../dist/' means "go up one level from 'examples/'
and then into the 'dist/' folder".
-->
<script src="../dist/babylonml.min.js"></script>
</head>
<body>
<!-- The root element for the Babylon.js experience -->
<bml-scene>
<!--
This scene relies on the default camera and light.
- No <bml-entity camera="..."> is defined, so a default FreeCamera is created.
- No <bml-entity light="..."> is defined, so a default HemisphericLight is created.
You can navigate using mouse/touch controls provided by the default FreeCamera.
-->
<bml-entity
id="my-box"
geometry="type: box; size: 1"
material="color: #4682B4"
position="0 0.5 0"
rotation="0 45 0">
</bml-entity>
<!-- A ground plane -->
<bml-entity
geometry="type: ground; width: 10; height: 10"
material="color: #8FBC8F">
<!-- Position defaults to 0 0 0 -->
</bml-entity>
</bml-scene>
<script>
// Optional: You can add JavaScript here to interact with the scene
// after it's potentially ready.
const sceneEl = document.querySelector('bml-scene');
// Check if the scene is already ready when the script runs
if (sceneEl && sceneEl.isReady) {
console.log("DEBUG: Scene was already ready. Running setup directly.");
babylonScene = sceneEl.babylonScene; // Get scene reference directly
console.log("DEBUG: babylonScene reference obtained. ", babylonScene);
// lets change the color of the box to blue
const box = document.getElementById('my-box');
if (box) {
console.log('Attempting to change box color via attribute...');
box.setAttribute('material', 'color: #0000FF'); // Change color to blue
}
} else if (sceneEl) {
console.log("DEBUG: Scene not ready yet. Adding event listener.");
sceneEl.addEventListener('bml-scene-ready', (event) => {
console.log("DEBUG: bml-scene-ready event fired!"); // <-- Log event firing
babylonScene = event.detail.scene;
consoler.log("DEBUG: babylonScene reference obtained. ", babylonScene);
// Example: Simple interaction after a delay
setTimeout(() => {
const box = document.getElementById('my-box');
if (box) {
console.log('Attempting to change box color via attribute...');
box.setAttribute('material', 'color: #0000FF'); // Change color to blue
}
}, 5000); // After 5 seconds
});
}
// Example: Accessing BML global API (if implemented)
if (window.BML) {
console.log('BML Global API found:', BML);
// Example: How a user might register their own component
// BML.registerComponent('my-custom-spin', { ... });
}
</script>
</body>
</html>
Basic Model Loader - BabylonML - Mesh Example
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>BabylonML - Mesh Example</title>
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
bml-scene { width: 100%; height: 100%; display: block; }
</style>
<!-- Load BabylonML library (adjust path as needed) -->
<script src="https://firebasestorage.googleapis.com/v0/b/story-splat.firebasestorage.app/o/public%2Fbabylon%2Fcdn%2Fbabylonml.min-1.1.0.js?alt=media&token=b2fe3e00-4c27-467b-accb-89d7783348b5"></script> <!-- Point to local build -->
</head>
<body>
<bml-scene>
<!-- Basic lighting and camera -->
<bml-entity light="type: hemispheric; intensity: 0.7"></bml-entity>
<bml-entity light="type: directional; direction: 1 -1 1; intensity: 0.7"></bml-entity>
<bml-entity camera="type: arcRotate; target: 0 1 0; alpha: -1.57; beta: 1.2; radius: 5"></bml-entity>
<!-- Load the GLB mesh -->
<!-- Using the Avocado model from the official BabylonJS assets repository -->
<bml-entity
geometry="type: mesh; src: https://firebasestorage.googleapis.com/v0/b/story-splat.firebasestorage.app/o/users%2FmFNJrfet99Qv9mMX2OC6hewy1xC2%2Fsplats%2FGreek_Statue_London_textured_mesh_lowpoly_glb.glb?alt=media&token=d79e2c56-420b-4e1f-81d8-0a7f3cdcf43c"
position="0 0 0"
rotation="0 0 0"
scale="1 1 1">
</bml-entity>
</bml-scene>
</body>
</html>
360 Video Player - BabylonML - Video Dome Example
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>BabylonML - Video Dome Example</title>
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
bml-scene { width: 100%; height: 100%; display: block; }
</style>
<!-- Load BabylonML library (adjust path as needed) -->
<script src="https://firebasestorage.googleapis.com/v0/b/story-splat.firebasestorage.app/o/public%2Fbabylon%2Fcdn%2Fbabylonml.min-1.1.0.js?alt=media&token=b2fe3e00-4c27-467b-accb-89d7783348b5"></script> </head>
<body>
<bml-scene>
<!-- Camera -->
<bml-entity camera="type: arcRotate; target: 0 0 0; alpha: 1.57; beta: 1.57; radius: 0.1"></bml-entity>
<!-- Video Dome -->
<!-- Using a publicly available 360 video -->
<!-- Note: Autoplay might be blocked by browser policy if not muted or interacted with -->
<bml-entity
id="video-dome-entity"
geometry="type: videodome; src: https://assets.babylonjs.com/photoDomes/solarProbeMission.mp4; size: 1000; autoPlay: true; loop: true; muted: true; clickToPlay: true">
<!-- clickToPlay: true allows user interaction to start/pause -->
</bml-entity>
<!-- Optional: Add a small object inside the dome -->
<bml-entity geometry="type: sphere; diameter: 0.5" position="0 0 0" material="color: blue"></bml-entity>
</bml-scene>
</body>
</html>