SceneJS – creating a JavaScript controlled, animated 3D character (part 2)

Introduction

This is the second part of the article about creating a JavaScript controlled and animated 3D character. In the first part of the article we have showed you where you can look for materials regarding 3D models creation. You have also learned how to export 3D models to the OBJ format and how to create a basic setup of SceneJS. In this part we will cover steps 4 and 5 – that is creating of a skybox and importing and animating 3D OBJ models in SceneJS using JavaScript.

Step 4 - Creating a Skybox

Now is the time to build an environment for our scene. A fast way to do that is to create a skybox node. But what is a skybox anyway? A skybox is a cube with a texture inside, which imitates an environment in a 3D scene. You actually put all the models inside a skybox, along with the camera and lights, then you texture it from inside to get the feel of a surrounding world. Seems simple, but to get that real feel of an environment we need to do a little trick. If we would just draw on the interior sides of the cube some graphic art representing the sky, the horizon and the earth beneath the camera, then we would end up with some kind of a cubic world. That is far from being close to reality and looks strange.

 

In order to get the things look right we should put our environment texture on to a sphere. That would solve our visual problem. But another one will occur. A sphere has much more vertices than a cube, so by putting a sphere object with a texture as a “skybox”, we would use up much of processing power of the device we are running our application on. The perfect solution to solve this problem is to create a cubic skybox with a spherical texture projection. Seems quite confusing but you can imagine it as if you have painted a room in a way that while sitting inside of it you would feel that you are actually inside a sphere. To make a long story short, to achieve our desired effect we can either use Blender or any other 3D software to make UV maps of a cube with a spherical projection of the texture like in this tutorial or use a program named CubeTheSphere . In our article we will use CubeTheSphere. It is a really quick and simple tool to use. What you need is a graphic which resembles our example graphical asset on Figure 1. 

 

Figure 1 – The graphical asset example needed to create a skybox using CubeTheSphere.

 

When you download and run CubeTheSphere, you must choose Open… from the File menu and choose your “horizon” image file. After the program will load up your graphical asset in the Options menu please choose which image texture size, each of the generated cube sides should have. After that go again to the File menu and select Extract All. After few seconds you should have ready all the sides of the cube with a spherical projection of your image on them. The last thing to do in order to prepare the CubeTheSphere files particularly for SceneJS is to go into your Tizen project folder, where you store the SceneJS library plugins folder. Inside the plugins folder we need to open the node folder and then find the skybox folder. Inside of it you will find JavaScript files representing skyboxes and a textures folder. Make a copy and open in a graphic program like Photoshop or Gimp one of the predefined images in the textures folder. Then use the generated cube sides from CubeTheSphere and place them in a way that you will see that they fit the pattern and that they don’t have any seems between them, just like on Figure 2.

 

Figure 2 – A finished skybox texture for a skybox node in SceneJS.

 

The last step to do in order to prepare your own custom skybox is to copy and rename one of the JavaScript skybox files in the skybox folder. Then go inside the file and change the file name in the texture path name to the name of the texture you have prepared earlier (fig. 2). Having done that, you are ready to insert your custom skybox node in your project. Just put the following code as a child node of your lights and then put under the comment // ATTACH HERE THE 3D MODEL WITH MATERIALS the standard 3D teapot like it was described earlier. You should get a teapot with a skybox around it. If you have problems, please look into the code of the sample application attached to this article. That should help you understand implementing the skybox node in SceneJS.

 

nodes: [

            // ******** CREATE THE SKYBOX ********    

            {
                type: "skybox/lumberWorld",
                size: 5000
            }, 
            {
                type: "material",
                color: {
                            r: 0.4,
                            g: 0.4,
                            b: 0.9
                        },
                        nodes: [{
                                
                                    // ATTACH HERE THE 3D MODEL WITH MATERIALS
                                
                                }]
                                
                            }
                            
                            
        ]

 

Step 5 - Importing and animating 3D models (OBJ) in SceneJS.

The last thing to do is to actually import the OBJ 3D models into our SceneJS project. Here we are going to show how to import only one element of the Lumber Jack to SceneJS. In the attached sample application you can find how to make a whole characters’ hierarchy of objects, which then can be moved with JavaScript. So, in order to import a model to SceneJS, you need to have an OBJ model file, a MTL file and a texture file (in our case a JPG) put into the models folder. Then just simply replace the material and 3D object code from the teapot example with the code below and you can load the textured head of our Lumber Jack in SceneJS.

 

[…]

nodes: [{
                type: "texture",  
                src: "models/head_texture.jpg",

                      nodes: [

                                // Import Wavefront .OBJ mesh
                                {
                                       type: "import/obj",
                                       src: "models/head.obj"
                                }
                             ]
}]

[…]

 

But as we mentioned earlier, we want to be able to move the loaded OBJ models. In order to do that we have to do the following:

  • Set a parent translate node to the material and OBJ nodes, co we can change its position.
  • We need to be able to fetch the translate node to change its properties using JavaScript.
  • We also need to get access to the animation function of the scene so we can change the properties of the translate node over time.
  • The last thing, which we can treat as an extra point is to connect the TweenMax.js library to the translate node in order to perform advanced animations.

So, how to set a translate node? It’s pretty easy. You just have to make a parent node to your model similar to the one beneath. You can additionally check the official translate node example here.

 

[…]

nodes: [{
                                                                          
type: "translate",
id: "newTranslate",
x: 0,
y: -1.5,
z: 0,

     nodes: [{

    	         // ATTACH HERE YOUR 3D MODEL NODE

            }]

}]

[…]

 

As you can see, the node above will change the position of its child 3D object to -1.5 units in the Y axis, relative to the center of the SceneJS 3D world. But this is just a static and instantaneous change. If we would like to animate our object, we need to fetch it for usage in JavaScript. To fetch a specific node, we need to use the scene.getNode() function. But first, the node we want to fetch needs an id. In our case the translate node was named newTranslate. The scene.getNode() function uses a callback in order to return the fetched node, so we will put inside this function another function, responsible for checking the tick event of SceneJS, which will help us in animating our 3D object inside that translate node. The following code describes how to fetch the node with the newTranslate id and move it in the Y axis. To do that we are using the set method on the property of the object we receive in the callback from fetching. 

 

[…]

scene.getNode("newTranslate",
        function(newTranslate) {

var newY = 0;

            scene.on("tick",
                function() {

    		  newY –= 0.1;

                    newTranslate.set({
                        y: newY;
                    });

                });

        });
[…]

 

The code above will move all objects inside the newTranslate node -0.1 in the Y axis, relative to the center of the SceneJS world, on every tick event of the SceneJS engine. As you see, it is not a complicated process.

Also using the TweenMax.js library can be easy together with SceneJS. The easiest way is to create a global object with a specific variable attached to it. Then when you want to trigger the animation just use TweenMax and change the parameters value. In the same time listen for the tick event in SceneJS and apply the changes using the set function just like in the example above. Combining SceneJS with TweenMax animation can give you incredible animation results. Especially when it comes for animating objects using the Bezier curves. Below you can find a simple and shortened example how to achieve the TweenMax animation with SceneJS. Please have an in depth view on TweenMax animation in SceneJS in the sample application attached to this article.

 

[…]

// INITIATE THE GLOBAL VARIABLE

var globalCoords = {};
    globalCoords.newY = 0;

[…]

// INTERPOLATE THE VALUE OF THE newX PROPERTY TO -20 IN 10 SECONDS

TweenMax.to(globalCoords, 10, {newY: -20, ease: Sine.easeInOut});

[…]

// FETCH THE NODE AND SET ITS Y PROPERTY TO THE INTERPOLATED VALUE OF newX

scene.getNode("newTranslate",
        function(newTranslate) {

            scene.on("tick",
                function() {

                    newTranslate.set({
                        y: globalCoords.newY;
                    });

                });

        });

[…]

 

As you see, just by adding few additional lines of code you can easily use the animating engine in your SceneJS projects.

Summary

Summing up both articles, we have showed you the basic steps of the process from creating your own 3D models to importing them and animating in the SceneJS engine. You have learned where to look for information about constructing your own 3D models. You also read about proper exporting of the OBJ 3D model files. Finally you have learned the basics of SceneJS, importing your custom 3D models into the engine and how to animate those models. Please have in mind that you will find many similarities in this work pipeline, while working with other 3D engines. So, the knowledge gained in this article is in a way a universal approach. We hope that this article will help you in creating great 3D content for the Tizen platform in the future.

For more information and an in depth view of SceneJS, please refer to the official SceneJS example website.

File attachments: 
List
SDK Version Since: 
2.3.0