0

How to Add Audio to a Babylon.JS Scene – Tutorial

Posted by Dr. Burton on January 18, 2019 in Babylon.js, Game Development, Java Tutorials, Tutorials, VR, WebVR |

This is the 3rd tutorial in our Bablylon.JS series.

In the first two, we created a scene, added the WebVR capability, added a skybox, and finally the ground.
But what is an environment without music and sound effects?
To begin, here is our javascript from the first two tutorials:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>Tutorial 3 - Audio in Babylon js</title>

        <!-- Babylon.js -->
        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
        <script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
     
        <style>
            html, body {overflow: hidden; width: 100%;
                height: 100%; margin: 0; padding: 0; }

            #renderCanvas { width: 100%; height: 100%;
                touch-action: none; }
        </style>
    </head>
<body>
  <canvas id="renderCanvas"></canvas>
  <script>
    var canvas = document.getElementById("renderCanvas");

    var createScene = function() {
        // Create scene

      	var scene = new BABYLON.Scene(engine);
        // Default Environment
        var environment =  scene.createDefaultEnvironment({ 
            createSkybox: false,
            createGround: true,
            groundSize: 1000,
            groundColor: BABYLON.Color3.Green(),
            enableGroundShadow: true, 
            groundYBias: 1 
        });

        var skyMaterial = new BABYLON.StandardMaterial("skybox", scene);
            skyMaterial.backFaceCulling = false;
            skyMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox", scene);
            skyMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
            skyMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
            skyMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
        var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:1000.0}, scene);
        skybox.material = skyMaterial;

       // Enable VR
       var vrHelper = scene.createDefaultVRExperience({createDeviceOrientationCamera:false});
       vrHelper.enableTeleportation({floorMeshes: [environment.ground]});

       var building = BABYLON.SceneLoader.Append("./", "vrchapel.glb", scene, function (meshes) {    
       scene.createDefaultCameraOrLight(true, true, true);
       });         
    return scene;
    };
               
    var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
    var scene = createScene();

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

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

According to the documentation, the expected file type is mp3, but I found that wav file types also work without a problem.
Make sure that the audio file is located in the same or a sub-folder of the html file that will be loading it to play.

Now to load the audio file. I placed the instructions before the WebVR is loaded, immediately after the SkyBox is loaded:

     // A little mood music
     var music = new BABYLON.Sound("music", "mnkchant.mp3", scene, soundReady, {loop: true });

     function soundReady() {
         music.play();
     }

Let’s break the instruction down. We begin by creating a variable to associate with the sound file. It is loaded into memory using the new BABYLON.Sound command. The parameters for the command are:

  • The name of the sound (I used the same name as the variable for convenience)
  • The URL/location of the sound file
  • The scene to load the sound into (i.e. scene)
  • Function to call when the sound is loaded and ready to play
  • Options such as looping, volume, isPaused, etc

Once the sound is loaded and ready to play, the function soundReady is called which will play the music.

I found that this is great to get the music playing by default. When it is loaded in your server (local or a webserver), you will see an icon displayed in the top left corner:

This is because modern browser automatically silence any audio that begins playing in the browser (and let’s be honest, this is a good thing).

Clicking on the audio will allow you to hear the audio that you loaded.

In a later tutorial we will add the controls for the audio portion of the environment.

0

How to Change the Skybox and Ground settings in Babylon.JS – Tutorial

Posted by Dr. Burton on January 5, 2019 in Babylon.js, Java Tutorials, VR, WebVR |

In our last tutorial on Babylon.JS, we loaded a 3D model into a basic environment. But we had a problem with the skybox and ground settings (you can see the results here). Here was the final code from last time:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>Sample 1 using Babylon js</title>

        <!-- Babylon.js -->
        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
        <script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>

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

            #renderCanvas {width: 100%; height: 100%;
                touch-action: none; }
        </style>
    </head>
<body>
    <canvas id="renderCanvas"></canvas>
    <script>
        var canvas = document.getElementById("renderCanvas");

        var createScene = function() {
            // Create scene
        	var scene = new BABYLON.Scene(engine);
                        
            // Default Environment
            var environment = scene.createDefaultEnvironment({ enableGroundShadow: true, groundYBias: 1 });

            // Enable VR
            var vrHelper = scene.createDefaultVRExperience({createDeviceOrientationCamera:false});
            vrHelper.enableTeleportation({floorMeshes: [environment.ground]});

            var building = BABYLON.SceneLoader.Append("./", "vrchapel.glb", scene, function (meshes) {    
                scene.createDefaultCameraOrLight(true, true, true);
            });         
        	return scene;
        };
               
        var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
        var scene = createScene();

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

        // Resize
        window.addEventListener("resize", function () {
            engine.resize();
        });
    </script>
</body>
</html>
Which resulted in this

Let’s get those environment options adjusted so that they are not so distracting.
All of the environmental options can be adjusted at the time of creating the scene.createDefaultEnvironment. The only section that we need to adjust is the
var environment = scene.createDefaultEnvironment({
section in the code above.
First, by default, the skybox is on. To adjust the skybox, we can add a couple of environment options:

            var environment =  scene.createDefaultEnvironment({ 
                    createSkybox: true,
                    skyboxSize: 150,
                    skyboxColor: BABYLON.Color3.Teal(),
                    enableGroundShadow: true, 
                    groundYBias: 1 
            });

In this code snippet, I have added the

                createSkybox: true,
                skyboxSize: 150,
                skyboxColor: BABYLON.Color3.Teal(),

code. The createSkybox: true, is redundant, but is nice to have if you want to be obvious in your code. To remove the skybox, change the true to false.
The skybox is by default a size of 20. With the second option, I have increased it’s size to 150.
The last line allows us to change the skybox color to teal.

Note that capitalization does matter!

Let’s do a similar process for the ground:

                    createGround: true,
                    groundSize: 200,
                    groundColor: BABYLON.Color3.Green(),

By default, the ground is also on with a default size of 15.
To remove the ground, you can change the true to false.

There is a lot more we can do with the skybox and ground, but this will get us started for the next phase of our development.

You can see the the current look of our environment here: http://vrchapel.me/Tutorial2-skyboxandground.html

Now that we have a basic skybox and ground, let’s improve the skybox to make it a bit more realistic. Basic skyboxes are composed of 6 images, one for each face of a cube. Babylon uses a naming convention of the name of the image then _ab, the a representing positive or negative (p or n), and the b representing the x, y, or z coordinate. Thus, you get file names like skybox_nx.jpg to for the negative X image. You can download these and other skybox images from the babylonjs github repository. They are located in /playground/textures folder. https://github.com/BabylonJS/Babylon.js. I placed the textures in a new folder named “textures” in the same folder as my index.html file.

Time to load our new skybox. First, change the createSkybox in environment to false and comment out the associated options for the skybox:

            var environment =  scene.createDefaultEnvironment({ 
                    createSkybox: false,
//                  skyboxSize: 150,
//                  skyboxColor: BABYLON.Color3.Teal(),

Next, we will create a variable to hold the skybox images. This is done by creating a new babylon standard material of the type “skybox” for our scene. We will set back face culling to false and then load the textures. The rest of the associated code is setting the coordinates (so that the images are laid out correctly), and setting the diffuse and specular colors to black:

    var skyMaterial = new BABYLON.StandardMaterial("skybox", scene);
        skyMaterial.backFaceCulling = false;
        skyMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox", scene);
        skyMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        skyMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
        skyMaterial.specularColor = new BABYLON.Color3(0, 0, 0);

Finally, we create the skybox with a create box command and set the material of the box to the skyMaterial variable that we just created.

    var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:1000.0}, scene);
        skybox.material = skyMaterial;

And now you have a skybox! The only problem is that the camera starts on the outside of the skybox instead of inside, looking at our building. We will correct that in the next tutorial. For now, you can use your middle mouse button to zoom inside of the cube.
Here is the final version of this tutorial and it’s associated code: http://vrchapel.me/Tutorial2b-skyboxandground.html


<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>Sample using Babylon js</title>

        <!-- Babylon.js -->
        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
        <script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
     
        <style>
         html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; }

         #renderCanvas { width: 100%; height: 100%; touch-action: none; }
        </style>
    </head>
<body>
    <canvas id="renderCanvas"></canvas>
    <script>
        var canvas = document.getElementById("renderCanvas");

        var createScene = function() {
            // Create scene
        	var scene = new BABYLON.Scene(engine);
            // Default Environment
            var environment =  scene.createDefaultEnvironment({ 
                    createSkybox: false,
//                    skyboxSize: 150,
//                    skyboxColor: BABYLON.Color3.Teal(),
                    createGround: true,
                    groundSize: 1000,
                    groundColor: BABYLON.Color3.Green(),
                    enableGroundShadow: true, 
                    groundYBias: 1 
            });

            var skyMaterial = new BABYLON.StandardMaterial("skybox", scene);
                skyMaterial.backFaceCulling = false;
                skyMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox", scene);
                skyMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
                skyMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
                skyMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
            var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:1000.0}, scene);
               skybox.material = skyMaterial;

            // Enable VR
            var vrHelper = scene.createDefaultVRExperience({createDeviceOrientationCamera:false});
            vrHelper.enableTeleportation({floorMeshes: [environment.ground]});

            var building = BABYLON.SceneLoader.Append("./", "vrchapel.glb", scene, function (meshes) {    
                scene.createDefaultCameraOrLight(true, true, true);

            });         
        	return scene;
        };
               
        var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
        var scene = createScene();

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

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

Tags: , , , , , , ,

0

How to Load a 3D Model for VR with Babylon.JS – Tutorial

Posted by Dr. Burton on January 3, 2019 in Babylon.js, Game Development, Tutorials, WebVR |

I recently began a major project using Babylon.js The reason I selected Babylon.js was the support for browser based game environment (at 60fps), and web-based VR (WebVR).
The first thing I wanted to do was load a 3D model that had been created in Blender. Here is how.

In this tutorial I’m going to quickly cover setting up your development environment and then demonstrate how to load a 3D model that was created in Blender (v.2.8). Make sure you export the final model as a glTF. I prefer the glb format over glTF as it incorporates the entire model, animation, and materials in one file rather than multiple files.

Once you have your model, you will need to decide where you will be testing your script from: a local server or a web server.
For faster iteration, I suggest setting up your development system with a local server. This is now much easier than in the past thanks to Python’s server tools.

To setup a local server, follow the directions on the Mozilla.org site: https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server
(Note: I found one error in the Windows directions: use ‘python -m http.server’ to launch your server instead of ‘python3’).

Of course, once you have a model loading, you will want to be able to share it with the rest of the world. I used AWS lightsail and launched a node.js instance to host my files.

Using Filezilla, I was able to quickly upload the html and glb files to the server and share them with the world. The files are stored in the /opt/bitnami/apache2/htdocs folder

Babylon.js can be completely encapsulated within the html document. For this tutorial, we are going to keep it as simple as possible and keep the html and script in the index.html file, only loading the glb file.

The html code is straight forward, loading the babylon framework and the gltf loaders. After the scripts are loaded, we can set the style for the document and the render canvas:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>Sample using Babylon js</title>
        <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
        <script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
        <style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

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

Now that we have the header taken care of, we can jump into the body. First we need to create a canvas and then create a function that will store the scene. Once the function is declared, we can setup the scene:

<body>
   <canvas id="renderCanvas"></canvas>
   <script>
      var canvas = document.getElementById("renderCanvas");

      var createScene = function() {
         // Create scene
         var scene = new BABYLON.Scene(engine);

Next we will setup the default environment, enabling shadows on the ground. We will also turn on the VR option, so that anyone who has VR googles can see the object in VR.

         // Default Environment
         var environment = scene.createDefaultEnvironment({ enableGroundShadow: true, groundYBias: 1 });
    
        // Enable VR
        var vrHelper = scene.createDefaultVRExperience({createDeviceOrientationCamera:false});
        vrHelper.enableTeleportation({floorMeshes: [environment.ground]});

Now let’s get to the fun part; loading the model!
We are going to use the BABYLON.SceneLoader.Append command to make this happen. This allows us to load add the model to an existing scene. We will also set the camera and lights so that we can see everything.

        var building = BABYLON.SceneLoader.Append("./", "VRChapel.glb", scene, function (meshes) {    
            scene.createDefaultCameraOrLight(true, true, true); 
            }); 

There is a lot happening with the Append command, so let’s break it down:

The 1st parameter – “./” – provides the location or folder of the file to be loaded. In this case the glb file is in the same folder.
The 2nd parameter “VRChapel.glb” the model to be loaded. If you saved your file as a glTF, only the model will be loaded, no textures, materials, or animations.
The 3rd parameter tells the engine where to load the model too, in this case the scene.
The 4th parameter is a function to create the camera and lights for the scene.

Finally, we return the scene and launch the engine. Notice the at the scene is describe before the engine is launched.

        return scene;
      };
               
      var engine = new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true });
      var scene = createScene();

Finally, we add a rendering loop, handle window resizing, and close the html page:

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

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

And there you have the minimum code to load a 3D model in Babylon.JS.
Of course, there is SO much more that we can (and will) do with this environment. This is just the starting point.

Special thanks to Adrianna Mott for the model! You can see the results of this tutorial online at: http://vrchapel.me/Tutorial1-loadModel.html

The only problem at this point is the skybox which is a little small and located inside the building. We will address that in the next tutorial.

Tags: , , , , , , , ,

0

How to Fill a Picker Wheel from a SQLite Database in Corona SDK – Tutorial

Posted by Dr. Burton on December 16, 2018 in Android, Corona, iPad, iPhone, Kindle Fire, Lua, Mobile, Tutorials |

Last semester I had a group of students using Corona SDK who were using a database to list local establishments.  They needed a way to easily display the list of locations in the SQLite database to the application.
While I had discussed the possibility of reading from a database and loading a picker-wheel in the textbooks Learning Mobile Application & Game Development and Beginning Mobile App Development with Corona, these students were relatively new to app development and needed a little more guidance on the process.

So, without further background, here is how to load a picker-wheel from a local SQLite database in Corona SDK.

To get started we will need to load the required plugins for sqlite and the picker-wheel widget tool in Corona.  We will also make sure that the database is in the documents folder of the mobile device and not the resource folder.

*Note: I have created a database that lists all cities in the USA by zip code.  I will be using it for this demonstration.

require("sqlite3")
local widget = require "widget"

-- Does the database exist in the documents directory (allows updating and persistence)
local path = system.pathForFile("zip.sqlite", system.DocumentsDirectory )
file = io.open( path, "r" )
   if( file == nil )then           
   -- Doesn't Already Exist, So Copy it In From Resource Directory                          
   	pathSource = system.pathForFile( "zip.sqlite", system.ResourceDirectory )  
   	fileSource = io.open( pathSource, "rb" ) 
   	contentsSource = fileSource:read( "*a" )                                  
		--Write Destination File in Documents Directory                                  
		pathDest = system.pathForFile( "zip.sqlite", system.DocumentsDirectory )                 
		fileDest = io.open( pathDest, "wb" )                 
		fileDest:write( contentsSource )                 
		 -- Done                      
		io.close( fileSource )        
		io.close( fileDest )         
   end   
-- One Way or Another The Database File Exists Now -- So Open Database Connection         
db = sqlite3.open( path )

-- handle the applicationExit event to close the db
local function onSystemEvent( event )
	if( event.type == "applicationExit") then
		db:close()
	end
end

A quick note on the copy method.  When you are working on a Windows system for development, you MUST use the “rb” (read binary) and “wb” (write binary) methods for reading and writing a database.  This forces Corona to copy the file in the binary format.  On a Mac, you can do a regular “r” and “w”.  For greatest compatibility, we recommend always using rb and wb to avoid premature greying and extensive head-smashing-into-desk.

Time to load the data from the database.   To begin, create a table to store the data loaded from the database (click here to see my tutorial on tables). 
Next, create the SQL statement to load records from the database.  I have limited the SQL statement to the first 20 records for simplicity (there are 1000’s of records). 
After reading each row of data and creating a variable to store the city & state captured from the database, we add the text to the data table that will be used by our picker-wheel.

local data = {}
local sql = "SELECT * FROM zipcode LIMIT 20"
for row in db:nrows(sql) do
local text = row.city..", "..row.state
table.insert(data, text)
end

Time to create the picker-wheel.  We are going to keep it simple; just one column of data that contains the city and state information.
The picker-wheel will be 258 pixels from the top of the screen (for no real reason, just looked good on my test app), with a font size of 18 and a default color of black.  The currently selected city & state will be red.

--Create storage for picker wheel
local columnData = { {align = "left", startIndex = 3, labels=data } }

-- create the picker widget with columnData
local picker = widget.newPickerWheel({
    top=258,
    fontSize = 18,
    fontColor={0,0,0},
    fontColorSelected = { 1, 0, 0 },
    columnColor = { 0.8, 0.8, 0.8 },
    columns = columnData,
})

Just three more things to do: add a button to return the selected data to the console, setup the function to print the selected value, and finally, add a event listener to close the database if the user abruptly closes the app.


local function showValues( event )
		-- Retrieve the current values from the picker
		local values = picker:getValues()
		
		-- print the selected values
		print( "Column Information: " .. values[1].value )		
end	

local getValuesButton = widget.newButton
	{
	    left = 10,
	    top = 150,
		width = 298,
		height = 56,
		id = "getValues",
	    label = "Values",
	    onRelease = showValues,
	}	

-- system listener for applicationExit
Runtime:addEventListener ("system", onSystemEvent)
SQLite data loaded into Picker-wheel

And that is how you load a picker-wheel from a local SQLite database. This tutorial has been added to the Corona textbooks available on our website.
FYI, the students did a great job on their project!

If you would like the video tutorial of working with a Picker wheel and SQLite, checkout the link below!

Tags: , , , , , , , ,

0

Reflections on Personalized Education

Posted by Dr. Burton on May 30, 2018 in Deep Learning, Education, Technology |

Traditional education assumes a transmissive format of instruction.  With #VR we can leave behind the traditional “sage-on-the-stage” and enable new #epistemology approaches, enabling learners to experience #education instead of trying to recall it from a lecture. When we begin to include #AI agents, #bigdata; when we are creating true #personalizededucation that adapts to the needs of the student, then we are accomplishing what generations of educators have sought to accomplish.

 

 

More to come, this is just the beginning!!

Tags: , , , , ,

Copyright © 2010-2019 Burtons Media Group All rights reserved.
This site is using the Desk Mess Mirrored theme, v2.5, from BuyNowShop.com.