Animation in 3D space – one of the integral and exciting processes. Animation gives life to your static scene. I think you have already thought about the animation of objects when working with three.js. Yes, animate objects is possible with functions of three.js, we can change the position, size, rotation, and other properties of objects (and their children) in real-time. However, this becomes problematic if we want to change the properties of tens or even hundreds of related objects at once, especially when it comes to three-dimensional animation of the (rigged) characters. In this case, much easier to animate the 3d model in a special editor, and then export the model into a suitable format for loading into three.js. In this lesson we will look at a variety of three-dimensional editors, and we learn how to download our animated models in three.js scene.
During my research and experience, I found that only two file formats could contain the animation (to be used in three.js): Json and Dae.
Before we start our discussion, you may test our demos. In the first demo, we load Json model, last two demos – Dae models.
3D editors and experience
The following 3D programs are installed on my computer:
- 3ds Max Design 2014 (additionally, a special plugin to export models into Json was installed for the 3DS Max)
- Poser Pro 2014
- Unity
- Blender (additionally, a special plugin to export models into Json was installed for the Blender)
Well, first of all, I downloaded a bunch (more than 20) of various models in different formats. There were different models: static and animated. I was going to use these models to import in the installed 3D editors.
Poser Pro 2014
This program, seemed me like a very friendly program to work with 3D characters. There are many ready models in ‘Library’, and you can handle with the model easily, using your mouse. After, you can export your result to Collada (dae). First window offers to select ‘Export Range’. Then – Export Options. I tried various options, but unfortunately, all my attempts to load the exported dae file into three.js failed. It always gave me the following error: Uncaught TypeError: Cannot read property ‘add’ of undefined (three.min.71.js:365)
But, when I tried to import this file in Blender, the animation was here. I tried to re-export it into dae again (in Blender), but it didn’t work. I also tried to export that model into Json and load into scene – this worked, however the animation was corrupted. Thus I decided to put away this program. It didn’t want to work properly by some reason.
Unity
This is a bit difficult-to-use program. It allows you to import models (as assets), make some changes with the model, and export to dae (Collada Export). I tried with several models, however after I exported the models into dae, the models failed to load in three.js. It gave the following error: Uncaught TypeError: Cannot read property ‘elements’ of null (three.min.71.js:44). Thus I decided to put this program away, too.
3ds Max Design 2014
The program has a pretty friendly interface, but it could be complex, because of many functions and properties. 3ds Max supports many 3D formats, so you can export/import most of models. However, nearly always, when I tried to load the result models (in DAE format), I received the following error:
Uncaught TypeError: Cannot read property ‘initialized’ of undefined (three.min.71.js:696)
I also tried to use the installed plugin (ThreeJsExporter), but it also didn’t give me the desired result.
Blender
From the first view it looks like this program is the most low level editor. Like 3DS Max, it has a lot of functions, but this is much lighter and free (other programs that we used require a paid license). But, for a beginner, it could be difficult to learn this program. Especially after all the programs we tried before – all of them have friendly graphic interface, but there is no the toolbar with buttons in the Blender. Sometimes it is really difficult to find something here. However, this program finally does what we need. It also supports various 3d file formats, like dae/fbx (that support the animation).
If you export to Collada/dae, I recommend to use the following properties:
If you export to Json, use the following properties:
Of course, not any models could be easily exported without any problem, but most of them. The initial model should be properly rigged with bones.
Besides that, if you notice, that your model looks like that (after exporting):
So, the model is currupted. To solve this situation, I recommend the following steps:
1) Click right mouse button on a nearest bone (so you will select it), then press twice ‘A’ button (to select all bones), switch to Pose Mode.
2) Goto ‘Pose’ -> ‘Clear Transform’ -> ‘All’.
3) Then switch to ‘Object Mode’, select your model in any place, then press twice ‘A’ button again (to select the whole model), then: CTRL-A -> Location, CTRL-A -> Position, CTRL-A -> Scale
After, try to export to DAE (or Json) again. After these actions, the model usually works fine in three.js. If not – try another initial model (dae / fbx). This method worked for me with several animated models, but not with all downloaded models. Now, let’s start with coding. First of all, create a new html file and put the following code:
index.html
04 |
< meta charset = "utf-8" /> |
05 |
< meta name = "author" content = "Script Tutorials" /> |
06 |
< title >WebGL With Three.js - Lesson 11 - Animated Objects | Script Tutorials</ title > |
07 |
< meta name = "viewport" content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" > |
08 |
< link href = "css/main.css" rel = "stylesheet" type = "text/css" /> |
11 |
< script src = "js/three.min.71.js" ></ script > |
12 |
< script src = "js/THREEx.WindowResize.js" ></ script > |
13 |
< script src = "js/OrbitControls.js" ></ script > |
14 |
< script src = "js/stats.min.js" ></ script > |
15 |
< script src = "js/ColladaLoader.js" ></ script > |
16 |
< script src = "js/script.js" ></ script > |
This simple code loads all the necessary libraries.
Skeleton of the scene
Now, create ‘js’ directory, and empty ‘script.js’ in the directory. Put the following code into this file:
js/script.js
02 |
scene: null , camera: null , renderer: null , |
03 |
container: null , controls: null , |
04 |
clock: null , stats: null , |
07 |
this .scene = new THREE.Scene(); |
08 |
this .scene.fog = new THREE.FogExp2(0xc8e0ff, 0.0003); |
09 |
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight; |
11 |
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 1, FAR = 1000; |
12 |
this .camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR); |
13 |
this .scene.add( this .camera); |
14 |
this .camera.position.set(100, 0, 0); |
15 |
this .camera.lookAt( new THREE.Vector3(0,0,0)); |
17 |
this .renderer = new THREE.WebGLRenderer({ antialias: true }); |
18 |
this .renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); |
19 |
this .renderer.setClearColor( this .scene.fog.color); |
21 |
this .container = document.createElement( 'div' ); |
22 |
document.body.appendChild( this .container); |
23 |
this .container.appendChild( this .renderer.domElement); |
25 |
THREEx.WindowResize( this .renderer, this .camera); |
27 |
this .controls = new THREE.OrbitControls( this .camera); |
28 |
this .controls.target = new THREE.Vector3(0, 0, 0); |
29 |
this .controls.maxDistance = 150; |
31 |
this .clock = new THREE.Clock(); |
33 |
this .stats = new Stats(); |
34 |
this .stats.domElement.style.position = 'absolute' ; |
35 |
this .stats.domElement.style.left = '50px' ; |
36 |
this .stats.domElement.style.bottom = '50px' ; |
37 |
this .stats.domElement.style.zIndex = 1; |
38 |
this .container.appendChild( this .stats.domElement ); |
40 |
this .scene.add( new THREE.AmbientLight(0xFFFFFF)); |
46 |
loadJsonModel: function () { |
48 |
loadDaeModel: function () { |
53 |
requestAnimationFrame(animate); |
59 |
var delta = lesson11.clock.getDelta(); |
60 |
lesson11.controls.update(delta); |
61 |
lesson11.stats.update(); |
62 |
THREE.AnimationHandler.update(delta); |
66 |
if (lesson11.renderer) { |
67 |
lesson11.renderer.render(lesson11.scene, lesson11.camera); |
71 |
function initializeLesson() { |
75 |
if (window.addEventListener) |
76 |
window.addEventListener( 'load' , initializeLesson, false ); |
77 |
else if (window.attachEvent) |
78 |
window.attachEvent( 'onload' , initializeLesson); |
79 |
else window.onload = initializeLesson; |
This is basic code to run the scene.
loadJsonModel
The following code is used to load Json models:
01 |
loadJsonModel: function () { |
03 |
var jsonLoader = new THREE.JSONLoader(); |
04 |
jsonLoader.load( 'models/girl.json' , function (geometry, materials) { |
05 |
materials.forEach( function (mat) { |
09 |
var modelMesh = new THREE.SkinnedMesh( |
10 |
geometry, new THREE.MeshFaceMaterial(materials) |
14 |
modelMesh.position.set(0, -20, 0); |
15 |
modelMesh.scale.set(scale, scale, scale); |
17 |
var animation = new THREE.Animation( |
18 |
modelMesh, geometry.animations[0], |
19 |
THREE.AnimationHandler.CATMULLROM |
22 |
lesson11.scene.add(modelMesh); |
After the model file is loaded, we set ‘skinning’ to ‘true’ for all children materials. Then we create THREE.SkinnedMesh with THREE.MeshFaceMaterial (to support original materials), then we scale and set position the model, prepare the animation, and finally – add the model into our scene and play the animation.
The following code is used to load Dae models:
01 |
loadDaeModel: function () { |
03 |
var daeLoader = new THREE.ColladaLoader(); |
04 |
daeLoader.options.convertUpAxis = true ; |
05 |
daeLoader.load( 'models/robot.dae' , function (collada) { |
06 |
var modelMesh = collada.scene; |
08 |
modelMesh.traverse( function (child) { |
09 |
if (child instanceof THREE.SkinnedMesh) { |
10 |
var animation = new THREE.Animation(child, child.geometry.animation); |
16 |
modelMesh.position.set(0, -20, 0); |
17 |
modelMesh.scale.set(scale, scale, scale); |
19 |
lesson11.scene.add(modelMesh); |
As you see, the code is a bit different then ‘loadJsonModel’. After we load the model, we traverse all it’s children and start playing the animation. Then we set the position and scale, and add the model mesh to the scene.
The lesson is finished. See you in the next tutorial.
[sociallocker]
[/sociallocker]