Visual Studio Code and following tutorial

Hi all,

I am new here and learning this Babylon.js so this is probably a beginners question. I am using Visual Studio Code with the live preview feature. This allows me to quickly preview changes I have made through a browser.

I have been following the Babylon.js tutorials to get an understanding of how it all works. Everything was going well until I hit this page: Getting Started - Chapter 2 - Face Materials | Babylon.js Documentation

At the bottom of that page it required me to wrap my house buildings into functions. However, as soon as I did that the scene refused to show in my live preview.

Everything is fine if I revert back before this step. Here is an example of my code (with my comments for my own self learning:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Babylon Template</title>

        <style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

            #renderCanvas {
                width: 100%;
                height: 100%;
                touch-action: none;
            }
        </style>

        <script src="https://cdn.babylonjs.com/babylon.js"></script>
        <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
        <script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
    </head>

   <body>

    <canvas id="renderCanvas" touch-action="none"></canvas> <!-- touch-action="none" for best results from PEP -->

    <script>
        const canvas = document.getElementById("renderCanvas"); // Get the canvas element
        const engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine

        // Add your code here matching the playground format
        //~~ CREATE SCENE ~~
        const createScene = () => {
    
            const scene = new BABYLON.Scene(engine);  

            
            //~~ SETUP CAMERA ~~
            const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 15, new BABYLON.Vector3(0, 0, 0));
            camera.attachControl(canvas, true);

            //~~ SETUP LIGHTING ~~
            const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));

            //~~ CREATE VARIABLES FOR FUNCTIONS ~~
            //Ground
            const ground = buildGround();
            //Small House
            const smallBox = buildSmallBox();
            const smallRoof = buildSmallRoof();
            //Large House
            const largeBox = buildLargeBox();
            const largeRoof = buildLargeRoof();

            return scene;

            //Engine render loop
            engine.runRenderLoop(function () {
                scene.render();
            });
        }



        //~~ BUILD FUNCTIONS ~~      
        //Ground:
        const buildGround = () =>{
            const groundMat = new BABYLON.StandardMaterial("groundMat");
            groundMat.diffuseColor = new BABYLON.Color3(0, 1, 0)
            
            const ground = BABYLON.MeshBuilder.CreateGround("ground", {width:10, height:10});
            //Adding the ground material to the ground. The variable is called ground. We are accessing the material property of the variable. We are then adding the newly
            //created ground material called groundMat
            ground.material = groundMat;
        
        }
              
        
        //Small Box:
        const buildSmallBox = () => {
                        
            //texture
            const boxMat = new BABYLON.StandardMaterial("boxMat"); //This is creating the variable to hold the standard material called boxMat.
            boxMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/cubehouse.png") //retrieving the diffuse texture from the file location
           
            //UV
            const faceUV = []; // makes faceUV equal an empty array
            faceUV[0] = new BABYLON.Vector4(0.5, 0.0, .75, 1.0); //rear of the house
            faceUV[1] = new BABYLON.Vector4(0.0, 0.0, .25, 1.0); // front of the house. The first number appears to be the bottom of the image on the x axis.
                                                                 // The second number appears to be the bottom of the image on the y axis.
                                                                 // The third number (0.25) appears to be how far into the image it moves across the x axis. Not sure if this is a percentage??
                                                                 // The last number demonstrates the top of the image. Once again, I believe it means 100% to the top.
            faceUV[2] = new BABYLON.Vector4(0.25, 0, 0.5, 1.0);   // This first number starts at the 0.25 and finishes at 0.5 on the x axis while y again is 0 to 1.
            faceUV[3] = new BABYLON.Vector4(0.75, 0, 1.0, 1.0);
            //testing to see what happens if I make the bottom UV all 0's
            faceUV[5] = new BABYLON.Vector4(0,0,0,0); //update: it doesn't put any image there, however, I wonder if this takes up performance to add this line or performance to allow it to render.
            //There appears to also be uv 4 and uv 5 in the array which is top of the box and bottom of the box. However, as both shouldn't be seen they are not considered.


            //Objects
            const box1 = BABYLON.MeshBuilder.CreateBox("box1", {faceUV: faceUV, wrap:true}); //I think the first faceUV mentioned in the parameters are asking for the faceUV details.
                                                                                            //As we created an array called faceUV and changed the sides, the creation of this function
                                                                                            //will then add the sides. Not sure yet what the wrap does. Will test it.
                                                                                            //***UPDATE*** looking at the picture, it placed my rear door at the top.
                                                                                            //Not sure what is happening here. My theory is it is rotating at each UV. Will do further research.
            //Small House and Roof
            box1.material = boxMat; //adding the boxMat material to the material properties of box1.
            box1.position.y = 0.5;

            return box1;


        }

    
        //Small Roof:
        const buildSmallRoof = () => {

            //Texture
            const roofMat = new BABYLON.StandardMaterial("roofMat"); //Creating the variable for the material as a standard material and giving it the name roofMat
            roofMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg"); //Using a diffuse texture, which is the most common type of texture which just paints over the surface of an object.


            //Objects
            const roof = BABYLON.MeshBuilder.CreateCylinder("roof",{ diameter: 1.3, height:1.2, tessellation:3});
            roof.material = roofMat;
            roof.scaling.x = 0.75;
            roof.rotation.z = Math.PI /2;
            roof.position.y = 1.22;

            return roof;
        }


        //Large Box:
        const buildLargeBox = () => {

            //Texture
            const boxMatLarge = new BABYLON.StandardMaterial("boxMatLarge"); //big house
            boxMatLarge.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/semihouse.png");


            //UV's
            const bigUV = [];
            bigUV[0] = new BABYLON.Vector4(0.6, 0.0, 1.0, 1.0); //rear face
            bigUV[1] = new BABYLON.Vector4(0.0, 0.0, 0.4, 1.0); //front house
            bigUV[2] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //right side
            bigUV[3] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //left side
            bigUV[5] = new BABYLON.Vector4(0,0,0,0); //Underneath so that it doesn't show the texture.


            //Objects
            const box2 = BABYLON.MeshBuilder.CreateBox("box2", {width: 2, faceUV: bigUV, wrap: true});
            box2.material = boxMatLarge;
            box2.position.y = 0.5;

            return box2;
        }
        
        
        //Large Roof:
        const buildLargeRoof = () =>{

            //Textures
            const roofMat = new BABYLON.StandardMaterial("roofMat"); //Creating the variable for the material as a standard material and giving it the name roofMat
            roofMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg"); //Using a diffuse texture, which is the most common type of texture which just paints over the surface of an object.


            //Objects
            const roof2 = BABYLON.MeshBuilder.CreateCylinder("roof2", {diameter: 1.3, height:1.2, tessellation: 3});
            roof2.material = roofMat;
            roof2.scaling.x = 0.75;
            roof2.scaling.y = 2;
            roof2.rotation.z = Math.PI / 2;
            roof2.position.y = 1.22;

            return roof2;


        }
        
        




        // Watch for browser/canvas resize events
        window.addEventListener("resize", function () {
                engine.resize();
        });
    </script>

   </body>

</html>

No errors appear in my inspector console on chrome. I have also tried to just use the example version that is provided.

Any help on this would be greatly appreciated!

1 Like

From looking at your code, it looks like nothing is calling the createScene function.

Try running it at the end of your script and see if it works then.

1 Like

Hi @TIF2 and welcome to the community. As @RaananW says a call to createScene is missing and the engine render loop can be moved as in

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Babylon Template</title>

        <style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

            #renderCanvas {
                width: 100%;
                height: 100%;
                touch-action: none;
            }
        </style>

        <script src="https://cdn.babylonjs.com/babylon.js"></script>
        <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
        <script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>
    </head>

   <body>

    <canvas id="renderCanvas" touch-action="none"></canvas> <!-- touch-action="none" for best results from PEP -->

    <script>
        const canvas = document.getElementById("renderCanvas"); // Get the canvas element
        const engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine

        // Add your code here matching the playground format
        //~~ CREATE SCENE ~~
        const createScene = () => {
    
            const scene = new BABYLON.Scene(engine);  

            
            //~~ SETUP CAMERA ~~
            const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 15, new BABYLON.Vector3(0, 0, 0));
            camera.attachControl(canvas, true);

            //~~ SETUP LIGHTING ~~
            const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));

            //~~ CREATE VARIABLES FOR FUNCTIONS ~~
            //Ground
            const ground = buildGround();
            //Small House
            const smallBox = buildSmallBox();
            const smallRoof = buildSmallRoof();
            //Large House
            const largeBox = buildLargeBox();
            const largeRoof = buildLargeRoof();

            return scene;

            
        }



        //~~ BUILD FUNCTIONS ~~      
        //Ground:
        const buildGround = () =>{
            const groundMat = new BABYLON.StandardMaterial("groundMat");
            groundMat.diffuseColor = new BABYLON.Color3(0, 1, 0)
            
            const ground = BABYLON.MeshBuilder.CreateGround("ground", {width:10, height:10});
            //Adding the ground material to the ground. The variable is called ground. We are accessing the material property of the variable. We are then adding the newly
            //created ground material called groundMat
            ground.material = groundMat;
        
        }
              
        
        //Small Box:
        const buildSmallBox = () => {
                        
            //texture
            const boxMat = new BABYLON.StandardMaterial("boxMat"); //This is creating the variable to hold the standard material called boxMat.
            boxMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/cubehouse.png") //retrieving the diffuse texture from the file location
           
            //UV
            const faceUV = []; // makes faceUV equal an empty array
            faceUV[0] = new BABYLON.Vector4(0.5, 0.0, .75, 1.0); //rear of the house
            faceUV[1] = new BABYLON.Vector4(0.0, 0.0, .25, 1.0); // front of the house. The first number appears to be the bottom of the image on the x axis.
                                                                 // The second number appears to be the bottom of the image on the y axis.
                                                                 // The third number (0.25) appears to be how far into the image it moves across the x axis. Not sure if this is a percentage??
                                                                 // The last number demonstrates the top of the image. Once again, I believe it means 100% to the top.
            faceUV[2] = new BABYLON.Vector4(0.25, 0, 0.5, 1.0);   // This first number starts at the 0.25 and finishes at 0.5 on the x axis while y again is 0 to 1.
            faceUV[3] = new BABYLON.Vector4(0.75, 0, 1.0, 1.0);
            //testing to see what happens if I make the bottom UV all 0's
            faceUV[5] = new BABYLON.Vector4(0,0,0,0); //update: it doesn't put any image there, however, I wonder if this takes up performance to add this line or performance to allow it to render.
            //There appears to also be uv 4 and uv 5 in the array which is top of the box and bottom of the box. However, as both shouldn't be seen they are not considered.


            //Objects
            const box1 = BABYLON.MeshBuilder.CreateBox("box1", {faceUV: faceUV, wrap:true}); //I think the first faceUV mentioned in the parameters are asking for the faceUV details.
                                                                                            //As we created an array called faceUV and changed the sides, the creation of this function
                                                                                            //will then add the sides. Not sure yet what the wrap does. Will test it.
                                                                                            //***UPDATE*** looking at the picture, it placed my rear door at the top.
                                                                                            //Not sure what is happening here. My theory is it is rotating at each UV. Will do further research.
            //Small House and Roof
            box1.material = boxMat; //adding the boxMat material to the material properties of box1.
            box1.position.y = 0.5;

            return box1;


        }

    
        //Small Roof:
        const buildSmallRoof = () => {

            //Texture
            const roofMat = new BABYLON.StandardMaterial("roofMat"); //Creating the variable for the material as a standard material and giving it the name roofMat
            roofMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg"); //Using a diffuse texture, which is the most common type of texture which just paints over the surface of an object.


            //Objects
            const roof = BABYLON.MeshBuilder.CreateCylinder("roof",{ diameter: 1.3, height:1.2, tessellation:3});
            roof.material = roofMat;
            roof.scaling.x = 0.75;
            roof.rotation.z = Math.PI /2;
            roof.position.y = 1.22;

            return roof;
        }


        //Large Box:
        const buildLargeBox = () => {

            //Texture
            const boxMatLarge = new BABYLON.StandardMaterial("boxMatLarge"); //big house
            boxMatLarge.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/semihouse.png");


            //UV's
            const bigUV = [];
            bigUV[0] = new BABYLON.Vector4(0.6, 0.0, 1.0, 1.0); //rear face
            bigUV[1] = new BABYLON.Vector4(0.0, 0.0, 0.4, 1.0); //front house
            bigUV[2] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //right side
            bigUV[3] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //left side
            bigUV[5] = new BABYLON.Vector4(0,0,0,0); //Underneath so that it doesn't show the texture.


            //Objects
            const box2 = BABYLON.MeshBuilder.CreateBox("box2", {width: 2, faceUV: bigUV, wrap: true});
            box2.material = boxMatLarge;
            box2.position.y = 0.5;

            return box2;
        }
        
        
        //Large Roof:
        const buildLargeRoof = () =>{

            //Textures
            const roofMat = new BABYLON.StandardMaterial("roofMat"); //Creating the variable for the material as a standard material and giving it the name roofMat
            roofMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg"); //Using a diffuse texture, which is the most common type of texture which just paints over the surface of an object.


            //Objects
            const roof2 = BABYLON.MeshBuilder.CreateCylinder("roof2", {diameter: 1.3, height:1.2, tessellation: 3});
            roof2.material = roofMat;
            roof2.scaling.x = 0.75;
            roof2.scaling.y = 2;
            roof2.rotation.z = Math.PI / 2;
            roof2.position.y = 1.22;

            return roof2;


        }
        
        const scene = createScene(); //Call the createScene function

		//Engine render loop
            engine.runRenderLoop(function () {
                scene.render();
            });


        // Watch for browser/canvas resize events
        window.addEventListener("resize", function () {
                engine.resize();
        });
    </script>

   </body>

Thanks for the welcome!

Ah I see! I must have deleted that at some stage when I was moving all of my code into the functions.

All working now. Thank you!

Seems like a great community. I am sure I will have many more questions to ask during this learning journey.

5 Likes