Jump to content

declarative React


Recommended Posts

I had an idea this morning based on some recent ECS (Entity Component System) questions in the forum and I've updated my react-babylonjs project - have not pushed out the code as I am tidying it up and there is a breaking change.  I only spent a couple of hours to build it all and it's really easy to add components.  Here is the default BabylonJS PG (yes, missing ground) - it's working no problems found yet:

import { Scene, FreeCamera, HemisphericLight, Sphere } from 'react-babylonjs'
import { Vector3 } from 'babylonjs';

import './Sample1.css'

const Sample1 = () => (
  <Scene id="sample-canvas">
    <FreeCamera name="main-camera" position={new Vector3(0, 5, -10)} target={Vector3.Zero()} />
    <HemisphericLight name="hemi-light" intensity={0.7} direction={Vector3.Up()} />
    <Sphere name="sphere" diameterX={3} diameterY={3} diameterZ={3} position={new Vector3(0, 1, 0)} />

export default Sample1

My main component class has a declaration like this, so easy to expand.  I have re-usable initialisers and behaviours already, so lots of code re-use and easy to add more properties.  Here is the pertinent portion of base class declaration to inherit from: (apologies in advance for people not familiar with TypeScript, as it will be gibberish):

export default abstract class SceneComponent<T extends U, U, V extends SceneComponentProps<T>> extends Component<V, {}> {

    constructor(props?: V, context?: any) {
        super(props, context);
        this.create = this.create.bind(this);

     * Called once for each Scene Component
     * @param scene babylonJS scene
    abstract create(scene: Scene) : T;
    abstract get propsInitialisers(): PropsInitialiser<U, V>[];

    render() {...}

Anyway, will publish it all in the next few days.  I think it addresses a different audience than the viewer, so thought it wouldn't hurt to update the NPM.  I'll have in the demo as well props being pushed up to components and viewable on gh-pages. cheers.

Link to comment
Share on other sites

Added more functionality.  Here is how behaviours are attached to components (ie: meshes).  This will spin the box 0.01 rads on each frame - it's just an example:

<Box name="box" size={1.7} position={new Vector3(0, 1, 0)}>
  <RotateMeshBehaviour radians={0.01} axis={Axis.Y} />

I will put up a github demo page next week showing props/state flowing to the controls.  That seems like the most powerful part.  That and people who know nothing about BabylonJS can integrate something like a Carousel or 3D model gallery in their React website with zero code.

Link to comment
Share on other sites

Added an example with props flowing from state to BabylonJS - following link "With React Props":
I'll probably just leave it like that unless somebody would like more components.  It was really just a thought experiment on how to build a BabylonJS scene without any code and also to control the scene with just props/state.  I also added to the gh-pages site the code snippets.

Link to comment
Share on other sites

Not sure what to document on the main site, as the declarative syntax using React components will only work with the NPM.  The existing https://doc.babylonjs.com/resources/babylonjs_and_reactjs page I made for React was very generic, to help people get a reference to the canvas for attaching the engine/camera and to teach how the component lifecycle makes it possible (ie: need to wait for canvas to be added to DOM before attaching). Also, how add and clean up resources/event handlers.  The essentials.

This new declarative model is more a thought experiment how to make it easy for React developers (and in future also Angular/Vue.js/etc.) how they could add 3D models/meshes/animations/lights/cameras with zero code and fitting into the mindset/paradigm of the tools. ie: React has a props/state flow that we can harness to control our meshes/lights/models/cameras.  Not *needing* to write code is a goal, but extensible hooks (observers/callbacks) are there to fill in the gaps.  I think I can do actions, GUI and animations declaratively as well, but this is only meant to go so far.  I would hope somebody could use declarative components to build a scene without even knowing what a canvas or WebGL are :)

Link to comment
Share on other sites

more progress :)  I have added basically everything I needed to get equivalence with the WebVR playground, since that's more or less the direction I am headed.  Here is the default playground, if you choose the WebVR example (https://playground.babylonjs.com/#TAFSN0#2) - it's an IcoSphere that changes colour from the colour picker.

To get more or less to that playground functionality, I needed to add a default environment, shadow generator, vr experience helper, IcoSphere and StandardMaterial.  I have opted not to include the GUI (and color picker), but instead a scene that involves more interaction with a 3D model.  Also, the VR experience helper needed to use the ground from the default environment for teleportation.  I ended up connecting all the pieces as components - admittedly the code is getting more brittle and I can feel the class explosion.  The main obstacle was getting the VR Experience Helper to use the ground from the Environment for teleportation (floorMeshes), so I have added a component registry.  When all the components have loaded, the components get another 'life cycle' call, so the Experience Helper can be configured to use the ground from the Environment, if available.  The only other interesting bit was that the shadow generator is given a list of mesh names "shadow casters" - the 3D model can load much later async, so added a listener on the scene for new meshes.  Seems to work OK.

I only have to work out why the shadows disappear in VR mode, but my computer was screaming, so may be a video card thing :)  Also a glitch with continually closing/opening the side bar, but I have a fix for fov_mode that I will probably add to the main component as a default.

Link to comment
Share on other sites

The next playground I was after was the 3D GUI:

The only minor obstacle is that the React components load as child controls first.  ie: The Holographic Button loads before the 3D panel, but the panel needs to be ready and the panel needs a GUI3DManager, so sort of a second pass was added for 3D GUI controls.

I wanted to have the CylinderPanel with holographic buttons like the PG above and a Skybox where I could set the texture.  I have clicking on the buttons changing the skybox texture - the texture files load slow over GH pages! The jsx/tsx Markup looks like this:

<Scene id="sample-canvas">
<HemisphericLight name="light1" intensity={0.7} direction={Vector3.Up()} />
<Skybox texture={activeSkybox.texture} />
<ArcRotateCamera target={ Vector3.Zero() } radius={10} alpha={-Math.PI / 4} beta={(Math.PI / 2)}/>
  <CylinderPanel margin={0.2}>
      Array.from(new Array(60), (_, index) => index).map(number => {
        return (


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...