Chapter 02Boxes (Cuboids)

Using the CreateBox method of the MeshBuilder class, we can make boxes and cuboids.

let box = BABYLON.MeshBuilder.CreateBox("name", {options}, scene);

The first argument of CreateBox() is a String that we can use to retrieve the entire box and data about the box later. The second argument is an object that specifies various properties of the box. The last argument is a reference to the scene in which the box will be inserted into.

<script>
    var canvas = document.getElementById("renderCanvas");
    var engine = new BABYLON.Engine(canvas, true);

    function createScene(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 4, Math.PI / 4, 3, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);
    
        let mat = new BABYLON.StandardMaterial("mat");
        mat.diffuseColor = new BABYLON.Color3(0, 1, 0);

        let box = BABYLON.MeshBuilder.CreateBox("box", {}, scene);
        box.material = mat;
        
        return scene;
    };

    var scene = createScene(canvas, engine);

    engine.runRenderLoop(function(){
        scene.render();
    });

    window.addEventListener("resize", function(){
        engine.resize();
    });
</script>

<canvas id="renderCanvas"></canvas>
Figure 1. Default Babylon.js box.

Properties

Size

The size parameter can be used to specify the height, width, and depth of the box. The default value is 1.

<script>
    var canvas7 = document.getElementById("renderCanvas7");
    var engine7 = new BABYLON.Engine(canvas7, true);

    function createScene7(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 4, Math.PI / 4, 4.5, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);
    
        let mat = new BABYLON.StandardMaterial("mat");
        mat.diffuseColor = new BABYLON.Color3(0, 1, 0);

        let box = BABYLON.MeshBuilder.CreateBox("box", {size: 2}, scene);
        box.material = mat;
        
        return scene;
    };

    var scene7 = createScene7(canvas7, engine7);

    engine7.runRenderLoop(function(){
        scene7.render();
    });

    window.addEventListener("resize", function(){
        engine7.resize();
    });
</script>

<canvas id="renderCanvas7"></canvas>
Figure 2. The size property is set to 2.

Height, Width, and Depth

To create a cuboid whose sides have different lengths, we can use the height, width, and depth parameters, which default to the value of the size parameter if not included.

<script>
    var canvas8 = document.getElementById("renderCanvas8");
    var engine8 = new BABYLON.Engine(canvas8, true);

    function createScene8(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 4, Math.PI / 4, 4, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);
    
        let mat = new BABYLON.StandardMaterial("mat");
        mat.diffuseColor = new BABYLON.Color3(0, 1, 0);

        let box = BABYLON.MeshBuilder.CreateBox("box", {height: 2, width: 1, depth: 2}, scene);
        box.material = mat;
        
        return scene;
    };

    var scene8 = createScene8(canvas8, engine8);

    engine8.runRenderLoop(function(){
        scene8.render();
    });

    window.addEventListener("resize", function(){
        engine8.resize();
    });
</script>

<canvas id="renderCanvas8"></canvas>
Figure 3. The height property is set to 2, the width property is set to 1, and the depth property is set to 2.

Face Colors

To add color to the box we can use the faceColors parameter. The faceColors parameter is an array of length 6 that holds color values for each face. The default value is Color4(1, 1, 1, 1), which is white.

The indices of the array we used for the faceColors parameter each correspond to a different side of the box.

<script>
    var canvas1 = document.getElementById("renderCanvas1");
    var engine1 = new BABYLON.Engine(canvas1, true);

    function createScene1(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 4, Math.PI / 4, 3, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);

        let colors = new Array(6);
        
        colors[0] = new BABYLON.Color3.Green;
        colors[1] = new BABYLON.Color3.Red;
        colors[2] = new BABYLON.Color3.Blue;
        colors[3] = new BABYLON.Color4(0, 0, 0, 0);
        colors[4] = new BABYLON.Color3.Yellow;
        colors[5] = new BABYLON.Color3.Yellow;

        let box = BABYLON.MeshBuilder.CreateBox("box", {faceColors: colors}, scene);
        return scene;
    };

    var scene1 = createScene1(canvas1, engine1);

    engine1.runRenderLoop(function(){
        scene1.render();
    });

    window.addEventListener("resize", function(){
        engine1.resize();
    });

</script>

<canvas id="renderCanvas1"></canvas>
Figure 4. The `faceColors property uses an array to set the sides of the box to colors green, red, blue, and black, in the order of their indices.

See our tutorial here for information on the color4 and color3 class.

Face UV

The faceUV property allows us to select a specific area to crop from an image, and then apply it to the box. The default value is Vector4(0, 0, 1, 1), which displays the entire image on each face.

Below is a list that specifies which sides correspond to which indices in the faceUV array.

FaceUV Index Direction of Face Normals
0 +z
1 -z
2 +x
3 -x
4 +y
5 -y
<script>
var canvas4 = document.getElementById("renderCanvas4");
var engine4 = new BABYLON.Engine(canvas4, true);

function createScene4(canvas, engine){
    let scene = new BABYLON.Scene(engine);
    scene.clearColor = new BABYLON.Color3(1, 1, 1);
    let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 4, Math.PI / 4, 3, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);

    let mat = new BABYLON.StandardMaterial("mat");
    mat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/numbers.jpg")
    mat.diffuseColor = new BABYLON.Color3.Green;

    let faceUV = [];
    faceUV[0] = new BABYLON.Vector4(0, 0, 0.166, 1); //rear face
    faceUV[1] = new BABYLON.Vector4(0.166, 0, .33, 1); //front face
    faceUV[2] = new BABYLON.Vector4(0.33, 0, 0.5, 1); //right side
    faceUV[3] = new BABYLON.Vector4(0.5, 0, 0.66, 1); //left side
    faceUV[4] = new BABYLON.Vector4(0.66, 0, .833, 1); //top face
    faceUV[5] = new BABYLON.Vector4(0.833, 0, 1, 1); // botttom face

    let box = BABYLON.MeshBuilder.CreateBox("box", {faceUV: faceUV}, scene);
    box.material = mat;

    return scene;
};

var scene4 = createScene4(canvas4, engine4);

engine4.runRenderLoop(function(){
    scene4.render();
});

window.addEventListener("resize", function(){
    engine4.resize();
});
</script>

<canvas id="renderCanvas4"></canvas>
Figure 5. We apply a texture to the box using faceUV so that the numbers appear on the side with the corresponding index.

In figure 3, we use Vector4() to apply the image to our box. We recommend looking at our Understanding Meshes chapter to review vectors in Babylon.js. The first set of parameters of Vector4() are the bottom left coordinates of the portion of the image we want to use on the mesh. We can call these u1 and v1. The second set of parameters for Vector4() are the upper right coordinates of the portion of the image we want to use on the mesh. We can call these u2 and v2.

To figure out what values we want to use for our arguments, we need to consider our image and the number values associated with the sides of the box.

Image used on the box in the sandbox

Both length and width of our image are considered to be value 1, so the values we enter for our coordinates will be float values between 0 and 1. We want to split our image into 6 separate sections for each box face.

Rear Face

faceUV[0] = new BABYLON.Vector4(0, 0, 0.166, 1);

The value for the rear face of the box is 0. In order for the number 0 in the image to appear on this face, we need to use vectors. In this case, the (x, y) coordinates, or the upper left coordinates, would be (0, 0), and the (z, w) coordinates, or the bottom right coordinates, would be (1/6, 1).

Front Face

faceUV[1] = new BABYLON.Vector4(0.166, 0, .33, 1);

The index value for the front face of the box is 1. In order for the number 1 in the image to appear on this face, we need to use vectors. In this case, the (x, y) coordinates, or the upper left coordinates, would be (1/6, 0), and the (z, w) coordinates, or the bottom right coordinates, would be (2/6, 1).

Right-side Face

faceUV[2] = new BABYLON.Vector4(0.33, 0, 0.5, 1);

The index value for the right-side face of the box is 2. We want the number 2 in the image to appear on this face. In this case, the (x, y) coordinates, or the upper left coordinates, would be (2/6, 0), and the (z, w) coordinates, or the bottom right coordinates, would be (3/6, 1).

Left-side Face

faceUV[3] = new BABYLON.Vector4(0.5, 0, 0.66, 1);

The index value for the left-side face of the box is 3. We want the number 3 in the image to appear on this face. In this case, the (x, y) coordinates, or the upper left coordinates, would be (3/6, 0), and the (z, w) coordinates, or the bottom right coordinates, would be (4/6, 1).

Top Face

faceUV[4] = new BABYLON.Vector4(0.66, 0, .833, 1);

The index value for the top face of the box is 4. We want the number 4 in the image to appear on this face. In this case, the (x, y) coordinates, or the upper left coordinates, would be (4/6, 0), and the (z, w) coordinates, or the bottom right coordinates, would be (5/6, 1).

Bottom Face

faceUV[5] = new BABYLON.Vector4(0.833, 0, 1, 1);

The index value for the bottom face of the box is 5. We want the number 5 in the image to appear on this face. In this case, the (x, y) coordinates, or the upper left coordinates, would be (5/6, 0), and the (z, w) coordinates, or the bottom right coordinates, would be (1, 1).

Finding the Values Algebraically

In order to precisely calculate what part of the image we want to apply to the mesh face, we can use the number of rows and columns to find the four values for Vector4() algebraically.

Wrap

The wrap parameter can be used to orientate images upright on the box sides if set to true. The default value is false.

<script>
    var canvas2 = document.getElementById("renderCanvas2");
    var engine2 = new BABYLON.Engine(canvas2, true);

    function createScene2(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 4, Math.PI / 4, 3, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);

        let mat = new BABYLON.StandardMaterial("mat");
        mat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/numbers.jpg");
        mat.diffuseColor = new BABYLON.Color3.Green;

        let faceUV = [];
        faceUV[0] = new BABYLON.Vector4(0, 0, 0.166, 1); //rear face
        faceUV[1] = new BABYLON.Vector4(0.166, 0, .33, 1); //front face
        faceUV[2] = new BABYLON.Vector4(0.33, 0, 0.5, 1); //right side
        faceUV[3] = new BABYLON.Vector4(0.5, 0, 0.66, 1); //left side
        faceUV[4] = new BABYLON.Vector4(0.66, 0, .833, 1); //top face
        faceUV[5] = new BABYLON.Vector4(0.833, 0, 1, 1); // botttom face

        let box = BABYLON.MeshBuilder.CreateBox("box", {faceUV: faceUV, wrap: true}, scene);
        box.material = mat;

        return scene;
    };

    var scene2 = createScene2(canvas2, engine2);

    engine2.runRenderLoop(function(){
        scene2.render();
    });

    window.addEventListener("resize", function(){
        engine2.resize();
    });
</script>

<canvas id="renderCanvas2"></canvas>
Figure 6. We use the wrap property to vertically orientate the texture on the sides of the box.

topBaseAt

We can change the orientation of our texture on the top of the box using the topBaseAt argument. The default value is 1, which means the base of the texture on the top face of the box will correspond to the side associated with index 1 of the faceUV array. This argument can take values 0, 1, 2, or 3, and the base will face the side with that index value.

The sides of the box are numbered 0 to 3 as illustrated below.

<script>
    var canvas5 = document.getElementById("renderCanvas5");
    var engine5 = new BABYLON.Engine(canvas5, true);

    function createScene5(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 4, Math.PI / 4, 3, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);

        let mat = new BABYLON.StandardMaterial("mat");
        mat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/numbers.jpg")
        mat.diffuseColor = new BABYLON.Color3.Green;

        let faceUV = [];
        faceUV[0] = new BABYLON.Vector4(0, 0, 0.166, 1); 
        faceUV[1] = new BABYLON.Vector4(0.166, 0, .33, 1); 
        faceUV[2] = new BABYLON.Vector4(0.33, 0, 0.5, 1); 
        faceUV[3] = new BABYLON.Vector4(0.5, 0, 0.66, 1); 
        faceUV[4] = new BABYLON.Vector4(0.66, 0, .833, 1); 
        faceUV[5] = new BABYLON.Vector4(0.833, 0, 1, 1); 

        let box = BABYLON.MeshBuilder.CreateBox("box", {faceUV: faceUV, wrap: true, topBaseAt: 3}, scene);
        box.material = mat;

        return scene;
    };

    var scene5 = createScene5(canvas5, engine5);

    engine5.runRenderLoop(function(){
        scene5.render();
    });

    window.addEventListener("resize", function(){
        engine5.resize();
    });

</script>

<canvas id="renderCanvas5"></canvas>
Figure 7. We orientate the texture on the top of the box using topBaseAt so that the base is facing index 3.

bottomBaseAt

We can change the orientation of our texture on the bottom face of the box using the bottomBaseAt argument. The default value is 1, which means the base of the texture on the bottom face of the box will correspond to the side associated with index 1 of the faceUV array. This argument can take values 0, 1, 2, or 3, and the base will face the side with that index value in the faceUV array.

The sides of the box are numbered 0 to 3 as illustrated below.

<script>
    var canvas3 = document.getElementById("renderCanvas3");
    var engine3 = new BABYLON.Engine(canvas3, true);

    function createScene3(canvas, engine){
        let scene = new BABYLON.Scene(engine);
        scene.clearColor = new BABYLON.Color3(1, 1, 1);
        let camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 4, 2.5 * Math.PI / 3, 3, BABYLON.Vector3.Zero(), scene);
        camera.attachControl(canvas, true);
        let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 0, 0), scene);

        let mat = new BABYLON.StandardMaterial("boxMat");
        mat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/numbers.jpg")
        mat.diffuseColor = new BABYLON.Color3.Green;
        
        let faceUV = [];
        faceUV[0] = new BABYLON.Vector4(0, 0, 0.166, 1); 
        faceUV[1] = new BABYLON.Vector4(0.166, 0, .33, 1); 
        faceUV[2] = new BABYLON.Vector4(0.33, 0, 0.5, 1); 
        faceUV[3] = new BABYLON.Vector4(0.5, 0, 0.66, 1); 
        faceUV[4] = new BABYLON.Vector4(0.66, 0, .833, 1); 
        faceUV[5] = new BABYLON.Vector4(0.833, 0, 1, 1); 

        let box = BABYLON.MeshBuilder.CreateBox("box", {faceUV: faceUV, wrap: true, bottomBaseAt: 3}, scene);
        box.material = mat;

        return scene;
    };

    var scene3 = createScene3(canvas3, engine3);

    engine3.runRenderLoop(function(){
        scene3.render();
    });

    window.addEventListener("resize", function(){
        engine3.resize();
    });

</script>

<canvas id="renderCanvas3"></canvas>
Figure 8. We orientate the texture on the bottom of the box using bottomBaseAt so that the base is facing index 3.

Updatable

If we want the box to be able to have its internal geometry changed after creation, we can set the parameter updatable equal to true. The default value is false.

Side Orientation

The sideOrientation property allows us to make our box double-sided. The default value is FRONTSIDE.

The different values for the sideOrientation property are:

FrontUVs and BackUVs

If the mesh is double-sided, we can choose what parts of a texture image to crop and stick on the front and back sides of the box with the frontUVs and backUVs parameters, respectively.

<script>
var canvas6 = document.getElementById("renderCanvas6");
var engine6 = new BABYLON.Engine(canvas6, true);

function createScene6(canvas, engine){
    let scene = new BABYLON.Scene(engine);
    scene.clearColor = new BABYLON.Color3(1, 1, 1);
    let camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 4, Math.PI / 4, 3, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas, true);
    let light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0), scene);

    let front = new BABYLON.Vector4(0, 0, 1/6, 1);
    let back = new BABYLON.Vector4(1/3, 0, 1/6, 1);

    let mat = new BABYLON.StandardMaterial("mat");
    mat.diffuseTexture = new BABYLON.Texture("https://www.babylonjs-playground.com/textures/fur.jpg")
    mat.diffuseColor = new BABYLON.Color3.Green;

    let box = BABYLON.MeshBuilder.CreateBox("box", {frontUVs: front, backUVs: back}, scene);
    box.material = mat;

    return scene;
};

var scene6 = createScene6(canvas6, engine6);

engine6.runRenderLoop(function(){
    scene6.render();
});

window.addEventListener("resize", function(){
    engine6.resize();
});
</script>

<canvas id="renderCanvas6"></canvas>
Figure 9. We apply a texture to the box using frontUVs so that the numbers appear on the side with the corresponding index.

References