Learn how to create 3D objects and interactions for a Mixed Reality experience using Babylon.js. In this section, you’ll start with something simple, like painting the faces of a cube when you select the object.
This tutorial covers the following topics:
[!div class=”checklist”]
- How to add interactions
- Enable WebXR immersive mode
- Run the app on Windows Mixed Reality Simulator
- Run and debug the app on Android Chrome
In previous tutorial step a basic web page with a scene was created. Have the hosting web page open for editing.
<html>
<head>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<style>
body,#renderCanvas { width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = function() {
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3.Black;
const alpha = Math.PI/4;
const beta = Math.PI/3;
const radius = 8;
const target = new BABYLON.Vector3(0, 0, 0);
const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
const box = BABYLON.MeshBuilder.CreateBox("box", {});
box.position.x = 0.5;
box.position.y = 1;
return scene;
};
const sceneToRender = createScene();
engine.runRenderLoop(function(){
sceneToRender.render();
});
</script>
</body>
</html>
First, let’s update our code that creates the cube, so that the cube is painted with a random color. To do that, we will add material to our cube. Material allows us to specify color and textures and can be used to cover other objects. How a material appears depends on the light or lights used in the scene and how it is set to react. For example, the diffuseColor spreads the color all over the mesh to which it is attached. Add the following code:
const boxMaterial = new BABYLON.StandardMaterial("material", scene);
boxMaterial.diffuseColor = BABYLON.Color3.Random();
box.material = boxMaterial;
Now that the cube is painted with a random color, let’s add an interaction to:
To add interactions we should be using actions. An action is launched in response to the event trigger. For example, when the user clicks on the cube. All we need to do is instantiate BABYLON.ActionManager and register an action for certain trigger. The BABYLON.ExecuteCodeAction will run our JavaScript function when someone clicks on the cube:
box.actionManager = new BABYLON.ActionManager(scene);
box.actionManager.registerAction(new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnPickTrigger,
function (evt) {
const sourceBox = evt.meshUnderPointer;
//move the box upright
sourceBox.position.x += 0.1;
sourceBox.position.y += 0.1;
//update the color
boxMaterial.diffuseColor = BABYLON.Color3.Random();
}));
The final code of the web page will look as follows:
<html>
<head>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<style>
body,#renderCanvas { width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = function() {
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3.Black;
const alpha = Math.PI/4;
const beta = Math.PI/3;
const radius = 8;
const target = new BABYLON.Vector3(0, 0, 0);
const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
const box = BABYLON.MeshBuilder.CreateBox("box", {});
box.position.x = 0.5;
box.position.y = 1;
const boxMaterial = new BABYLON.StandardMaterial("material", scene);
boxMaterial.diffuseColor = BABYLON.Color3.Random();
box.material = boxMaterial;
box.actionManager = new BABYLON.ActionManager(scene);
box.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger,
function (evt) {
const sourceBox = evt.meshUnderPointer;
sourceBox.position.x += 0.1;
sourceBox.position.y += 0.1;
boxMaterial.diffuseColor = BABYLON.Color3.Random();
}));
return scene;
};
const sceneToRender = createScene();
engine.runRenderLoop(function(){
sceneToRender.render();
});
</script>
</body>
</html>
Now that our cube is changing colors, we’re ready to try the immersive experience.
In this step we’re going to introduce a ground. The cube will be hanging in the air and we will see a floor at the bottom. Add the ground as follows:
const ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 4});
This creates a simple 4x4-meter floor.
In order to add WebXR support, we need to call createDefaultXRExperienceAsync, which has a Promise result. Add this code at the end of createScene function instead of return scene;:
const xrPromise = scene.createDefaultXRExperienceAsync({
floorMeshes: [ground]
});
return xrPromise.then((xrExperience) => {
console.log("Done, WebXR is enabled.");
return scene;
});
Since the createScene function is now returning a promise instead of a scene, we need to modify how createScene and engine.runRenderLoop are called. Replace the current calls of these functions, which are located right before the </script> tag, with the code below:
createScene().then(sceneToRender => {
engine.runRenderLoop(() => sceneToRender.render());
});
The final code of the web page will look as follows:
<html>
<head>
<script src="https://cdn.babylonjs.com/babylon.js"></script>
<style>
body,#renderCanvas { width: 100%; height: 100%;}
</style>
</head>
<body>
<canvas id="renderCanvas"></canvas>
<script>
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = function() {
const scene = new BABYLON.Scene(engine);
scene.clearColor = new BABYLON.Color3.Black;
const alpha = Math.PI/4;
const beta = Math.PI/3;
const radius = 8;
const target = new BABYLON.Vector3(0, 0, 0);
const camera = new BABYLON.ArcRotateCamera("Camera", alpha, beta, radius, target, scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
const box = BABYLON.MeshBuilder.CreateBox("box", {});
box.position.x = 0.5;
box.position.y = 1;
const boxMaterial = new BABYLON.StandardMaterial("material", scene);
boxMaterial.diffuseColor = BABYLON.Color3.Random();
box.material = boxMaterial;
box.actionManager = new BABYLON.ActionManager(scene);
box.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger,
function (evt) {
const sourceBox = evt.meshUnderPointer;
sourceBox.position.x += 0.1;
sourceBox.position.y += 0.1;
boxMaterial.diffuseColor = BABYLON.Color3.Random();
}));
const ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 4});
const xrPromise = scene.createDefaultXRExperienceAsync({
floorMeshes: [ground]
});
return xrPromise.then((xrExperience) => {
console.log("Done, WebXR is enabled.");
return scene;
});
};
createScene().then(sceneToRender => {
engine.runRenderLoop(() => sceneToRender.render());
});
</script>
</body>
</html>
The above code generates the following output in the browser window:
Enable the Windows Mixed Reality Simulator if you have not done so in the past.
Select the Immersive-VR button on the bottom right corner:
This action will launch the Windows Mixed Reality Simulator window as shown below:
Use the W,A,S, and D keys on your keyboard to walk forward, back left and right accordingly. Use simulated hand to target the cube and press the Enter key on your keyboard to perform the click action. The cube will change its color and move to a new position.
[!NOTE] When targeting the cube, make sure that the end of hand ray (white circle) intersects with the cube as shown on the picture above. Learn more about Point and commit with hands.
Perform the following steps to enable debugging on your Android device:
To verify that the device is correctly configured to run WebXR, browse to a sample WebXR page on the device. You should see the message, such as:
Your browser supports WebXR and can run Virtual Reality and Augmented Reality experiences if you have the appropriate hardware.
Ensure that the web server on the development machine is running. For example, navigate to the root folder containing your web hosting page (index.html) and execute the following code (assuming you use serve npm package):
serve
chrome://inspect#devices
The following are the most important takeaways from this tutorial:
Congratulations! You’ve completed our series of Babylon.js tutorials and learned how to:
[!div class=”checklist”]
- Set up a development environment
- Create a new web page to display results
- The Babylon.js API to create and interact with basic 3D elements
- Run and test the application in a Windows Mixed Reality Simulator
For more information on Mixed Reality JavaScript development see JavaScript development overview.
If you’re looking for another Babylon.js tutorial, checkout the Piano-building Tutorial Series to learn how to build a piano in the VR space using Babylon.js.