Introducing BabylonML πŸš€ - Declarative HTML Babylon

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>
9 Likes

Not meant to be off topic, but when I see ML, the first word comes out is β€œMachine Learning”

Totally fair - still down for a name change. Any ideas?

BabylonHTML? DeclarativeBabylon?

Instead of <bml-x> tag, maybe just <babylon-x>?

1 Like

BabylonHTML is probably better

2 Likes