Selaa lähdekoodia

Merge remote-tracking branch 'remotes/BabylonJS/master' into BabylonJS-master

Gwenaël Hagenmuller 11 vuotta sitten
vanhempi
commit
030c843317

+ 48 - 5
Babylon/Cameras/babylon.arcRotateCamera.js

@@ -21,6 +21,8 @@ var BABYLON = BABYLON || {};
 
         this._viewMatrix = new BABYLON.Matrix();
 
+        BABYLON.ArcRotateCamera.prototype._initCache.call(this);
+        
         this.getViewMatrix();
     };
     
@@ -29,6 +31,7 @@ var BABYLON = BABYLON || {};
     // Members
     BABYLON.ArcRotateCamera.prototype.inertialAlphaOffset = 0;
     BABYLON.ArcRotateCamera.prototype.inertialBetaOffset = 0;
+    BABYLON.ArcRotateCamera.prototype.inertialRadiusOffset = 0;
     BABYLON.ArcRotateCamera.prototype.lowerAlphaLimit = null;
     BABYLON.ArcRotateCamera.prototype.upperAlphaLimit = null;
     BABYLON.ArcRotateCamera.prototype.lowerBetaLimit = null;
@@ -37,6 +40,39 @@ var BABYLON = BABYLON || {};
     BABYLON.ArcRotateCamera.prototype.upperRadiusLimit = null;
     BABYLON.ArcRotateCamera.prototype.angularSensibility = 1000.0;
 
+    BABYLON.ArcRotateCamera.prototype._getTargetPosition = function () {
+        return this.target.position || this.target;
+    };
+    
+    // Cache
+    BABYLON.ArcRotateCamera.prototype._initCache = function () {
+        this._cache.target = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+        this._cache.alpha = undefined;
+        this._cache.beta = undefined;
+        this._cache.radius = undefined;
+    };
+
+    BABYLON.ArcRotateCamera.prototype._updateCache = function (ignoreParentClass) {
+        if(!ignoreParentClass)
+            BABYLON.Camera.prototype._updateCache.call(this);
+        
+        this._cache.target.copyFrom(this._getTargetPosition());
+        this._cache.alpha = this.alpha;
+        this._cache.beta = this.beta;
+        this._cache.radius = this.radius;
+    };
+
+    // Synchronized
+    BABYLON.ArcRotateCamera.prototype._isSynchronizedViewMatrix = function () {
+        if (!BABYLON.Camera.prototype._isSynchronizedViewMatrix.call(this))
+            return false;
+        
+        return this._cache.target.equals(this._getTargetPosition())
+            && this._cache.alpha === this.alpha
+            && this._cache.beta === this.beta
+            && this._cache.radius === this.radius;
+    };
+    
     // Methods
     BABYLON.ArcRotateCamera.prototype.attachControl = function(canvas, noPreventDefault) {
         var previousPosition;
@@ -127,7 +163,7 @@ var BABYLON = BABYLON || {};
                 }
 
                 if (delta)
-                    that.radius -= delta;
+                    that.inertialRadiusOffset += delta;
 
                 if (event.preventDefault) {
                     if (!noPreventDefault) {
@@ -267,19 +303,24 @@ var BABYLON = BABYLON || {};
         }
         
         // Inertia
-        if (this.inertialAlphaOffset != 0 || this.inertialBetaOffset != 0) {
+        if (this.inertialAlphaOffset != 0 || this.inertialBetaOffset != 0 || this.inertialRadiusOffset != 0) {
 
             this.alpha += this.inertialAlphaOffset;
             this.beta += this.inertialBetaOffset;
+            this.radius -= this.inertialRadiusOffset;
 
             this.inertialAlphaOffset *= this.inertia;
             this.inertialBetaOffset *= this.inertia;
+            this.inertialRadiusOffset *= this.inertia;
 
             if (Math.abs(this.inertialAlphaOffset) < BABYLON.Engine.epsilon)
                 this.inertialAlphaOffset = 0;
 
             if (Math.abs(this.inertialBetaOffset) < BABYLON.Engine.epsilon)
                 this.inertialBetaOffset = 0;
+
+            if (Math.abs(this.inertialRadiusOffset) < BABYLON.Engine.epsilon)
+                this.inertialRadiusOffset = 0;
         }
         
         // Limits
@@ -304,7 +345,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.ArcRotateCamera.prototype.setPosition = function(position) {
-        var radiusv3 = position.subtract(this.target.position ? this.target.position : this.target);
+        var radiusv3 = position.subtract(this._getTargetPosition());
         this.radius = radiusv3.length();
 
         this.alpha = Math.atan(radiusv3.z / radiusv3.x);
@@ -324,8 +365,10 @@ var BABYLON = BABYLON || {};
         var cosb = Math.cos(this.beta);
         var sinb = Math.sin(this.beta);
 
-        this.target.addToRef(new BABYLON.Vector3(this.radius * cosa * sinb, this.radius * cosb, this.radius * sina * sinb), this.position);
-        BABYLON.Matrix.LookAtLHToRef(this.position, this.target, this.upVector, this._viewMatrix);
+        var target = this._getTargetPosition();
+        
+        target.addToRef(new BABYLON.Vector3(this.radius * cosa * sinb, this.radius * cosb, this.radius * sina * sinb), this.position);
+        BABYLON.Matrix.LookAtLHToRef(this.position, target, this.upVector, this._viewMatrix);
 
         return this._viewMatrix;
     };

+ 109 - 13
Babylon/Cameras/babylon.camera.js

@@ -4,6 +4,8 @@ var BABYLON = BABYLON || {};
 
 (function () {
     BABYLON.Camera = function (name, position, scene) {
+        BABYLON.Node.call(this);
+        
         this.name = name;
         this.id = name;
         this.position = position;
@@ -19,6 +21,7 @@ var BABYLON = BABYLON || {};
         }
 
         this._computedViewMatrix = BABYLON.Matrix.Identity();
+        this._projectionMatrix = new BABYLON.Matrix();
 
         // Animations
         this.animations = [];
@@ -28,6 +31,9 @@ var BABYLON = BABYLON || {};
         
         // Viewport
         this.viewport = new BABYLON.Viewport(0, 0, 1.0, 1.0);
+        
+        //Cache
+        BABYLON.Camera.prototype._initCache.call(this);
     };
 
     BABYLON.Camera.prototype = Object.create(BABYLON.Node.prototype);
@@ -51,6 +57,84 @@ var BABYLON = BABYLON || {};
     BABYLON.Camera.prototype.getScene = function () {
         return this._scene;
     };
+    
+    //Cache
+    BABYLON.Camera.prototype._initCache = function () {
+        this._cache.position = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+        this._cache.upVector = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+
+        this._cache.mode = undefined;
+        this._cache.minZ = undefined;
+        this._cache.maxZ = undefined;
+
+        this._cache.fov = undefined;
+        this._cache.aspectRatio = undefined;
+
+        this._cache.orthoLeft = undefined;
+        this._cache.orthoRight = undefined;
+        this._cache.orthoBottom = undefined;
+        this._cache.orthoTop = undefined;
+        this._cache.renderWidth = undefined;
+        this._cache.renderHeight = undefined;
+    };
+
+    BABYLON.Camera.prototype._updateCache = function (ignoreParentClass) {
+        if(!ignoreParentClass)
+            BABYLON.Node.prototype._updateCache.call(this);
+        
+        this._cache.position.copyFrom(this.position);
+        this._cache.upVector.copyFrom(this.upVector);
+
+        this._cache.mode = this.mode;
+        this._cache.minZ = this.minZ;
+        this._cache.maxZ = this.maxZ;
+
+        this._cache.fov = this.fov;
+        this._cache.aspectRatio = engine.getAspectRatio();
+
+        this._cache.orthoLeft = this.orthoLeft;
+        this._cache.orthoRight = this.orthoRight;
+        this._cache.orthoBottom = this.orthoBottom;
+        this._cache.orthoTop = this.orthoTop;
+        this._cache.renderWidth = engine.getRenderWidth()
+        this._cache.renderHeight = engine.getRenderHeight();
+    };
+
+    // Synchronized
+    BABYLON.Camera.prototype._isSynchronized = function () {
+        return this._isSynchronizedViewMatrix() && this._isSynchronizedProjectionMatrix();
+    };
+
+    BABYLON.Camera.prototype._isSynchronizedViewMatrix = function () {
+        if (!BABYLON.Node.prototype._isSynchronized.call(this))
+            return false;
+        
+        return this._cache.position.equals(this.position) 
+            && this._cache.upVector.equals(this.upVector);
+    };
+
+    BABYLON.Camera.prototype._isSynchronizedProjectionMatrix = function () {
+        var r = this._cache.mode === this.mode
+             && this._cache.minZ === this.minZ
+             && this._cache.maxZ === this.maxZ;
+             
+        if (!r)
+            return false;
+
+        if (this.mode === BABYLON.Camera.PERSPECTIVE_CAMERA) {
+            r = this._cache.fov === this.fov
+                 && this._cache.aspectRatio === engine.getAspectRatio();
+        }
+        else {
+            r = this._cache.orthoLeft === this.orthoLeft
+                 && this._cache.orthoRight === this.orthoRight
+                 && this._cache.orthoBottom === this.orthoBottom
+                 && this._cache.orthoTop === this.orthoTop
+                 && this._cache.renderWidth === engine.getRenderWidth()
+                 && this._cache.renderHeight === engine.getRenderHeight();
+        }
+        return r;
+    };
 
     // Methods
     BABYLON.Camera.prototype.attachControl = function (canvas) {
@@ -61,6 +145,11 @@ var BABYLON = BABYLON || {};
 
     BABYLON.Camera.prototype._update = function () {
     };
+    
+    BABYLON.Camera.prototype._updateFromScene = function () {
+        this.updateCache();
+        this._update();
+    };
 
     BABYLON.Camera.prototype.getWorldMatrix = function () {
         var viewMatrix = this.getViewMatrix();
@@ -79,28 +168,35 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Camera.prototype.getViewMatrix = function () {
-        this._computedViewMatrix = this._getViewMatrix();
+        this._computedViewMatrix = this._computeViewMatrix();
 
-        if (this.parent && this.parent.getWorldMatrix) {
-            if (!this._worldMatrix) {
-                this._worldMatrix = BABYLON.Matrix.Identity();
-            }
-
-            this._computedViewMatrix.invertToRef(this._worldMatrix);
+        if(!this.parent 
+            ||  !this.parent.getWorldMatrix
+            || (!this.hasNewParent() && this.parent.isSynchronized())) {
+            return this._computedViewMatrix;
+        }
+        
+        this._computedViewMatrix.invertToRef(this._worldMatrix);
 
-            this._worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._computedViewMatrix);
+        this._worldMatrix.multiplyToRef(this.parent.getWorldMatrix(), this._computedViewMatrix);
 
-            this._computedViewMatrix.invert();
+        this._computedViewMatrix.invert();
 
+        return this._computedViewMatrix;
+    };
+    
+    BABYLON.Camera.prototype._computeViewMatrix = function (force) {
+        if (!force && this._isSynchronizedViewMatrix()) {
             return this._computedViewMatrix;
         }
-
+        
+        this._computedViewMatrix = this._getViewMatrix();
         return this._computedViewMatrix;
     };
 
-    BABYLON.Camera.prototype.getProjectionMatrix = function () {
-        if (!this._projectionMatrix) {
-            this._projectionMatrix = new BABYLON.Matrix();
+    BABYLON.Camera.prototype.getProjectionMatrix = function (force) {
+        if(!force && this._isSynchronizedProjectionMatrix()) {
+            return this._projectionMatrix;
         }
 
         var engine = this._scene.getEngine();

+ 60 - 5
Babylon/Cameras/babylon.freeCamera.js

@@ -34,6 +34,8 @@ var BABYLON = BABYLON || {};
         this._newPosition = BABYLON.Vector3.Zero();
         this._lookAtTemp = BABYLON.Matrix.Zero();
         this._tempMatrix = BABYLON.Matrix.Zero();
+        
+        BABYLON.FreeCamera.prototype._initCache.call(this);
     };
 
     BABYLON.FreeCamera.prototype = Object.create(BABYLON.Camera.prototype);
@@ -47,6 +49,48 @@ var BABYLON = BABYLON || {};
     BABYLON.FreeCamera.prototype.lockedTarget = null;
     BABYLON.FreeCamera.prototype.onCollide = null;
 
+    BABYLON.FreeCamera.prototype._getLockedTargetPosition = function () {       
+        if(!this.lockedTarget)
+            return null;
+        
+        return this.lockedTarget.position || this.lockedTarget;
+    };
+
+    // Cache
+    BABYLON.FreeCamera.prototype._initCache = function () {
+        this._cache.lockedTarget = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+        this._cache.rotation = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+    };
+
+    BABYLON.FreeCamera.prototype._updateCache = function (ignoreParentClass) {
+        if(!ignoreParentClass)
+            BABYLON.Camera.prototype._updateCache.call(this);
+        
+        var lockedTargetPosition = this._getLockedTargetPosition();
+        if (!lockedTargetPosition) {
+            this._cache.lockedTarget = null;
+        }
+        else {
+            if (!this._cache.lockedTarget) 
+                this._cache.lockedTarget = lockedTargetPosition.clone();
+            else
+                this._cache.lockedTarget.copyFrom(lockedTargetPosition);
+        }
+        
+        this._cache.rotation.copyFrom(this.rotation);
+    };
+
+    // Synchronized
+    BABYLON.FreeCamera.prototype._isSynchronizedViewMatrix = function () {
+        if (!BABYLON.Camera.prototype._isSynchronizedViewMatrix.call(this))
+            return false;
+
+        var lockedTargetPosition = this._getLockedTargetPosition();
+ 
+        return (this._cache.lockedTarget ? this._cache.lockedTarget.equals(lockedTargetPosition) : !lockedTargetPosition)
+            && this._cache.rotation.equals(this.rotation);
+    };    
+    
     // Methods
     BABYLON.FreeCamera.prototype._computeLocalCameraSpeed = function () {
         return this.speed * ((BABYLON.Tools.GetDeltaTime() / (BABYLON.Tools.GetFps() * 10.0)));
@@ -299,9 +343,24 @@ var BABYLON = BABYLON || {};
 
         // Inertia
         if (needToMove) {
+            if (Math.abs(this.cameraDirection.x) < BABYLON.Engine.epsilon)
+                this.cameraDirection.x = 0;
+
+            if (Math.abs(this.cameraDirection.y) < BABYLON.Engine.epsilon)
+                this.cameraDirection.y = 0;
+
+            if (Math.abs(this.cameraDirection.z) < BABYLON.Engine.epsilon)
+                this.cameraDirection.z = 0;
+        
             this.cameraDirection.scaleInPlace(this.inertia);
         }
         if (needToRotate) {
+            if (Math.abs(this.cameraRotation.x) < BABYLON.Engine.epsilon)
+                this.cameraRotation.x = 0;
+
+            if (Math.abs(this.cameraRotation.y) < BABYLON.Engine.epsilon)
+                this.cameraRotation.y = 0;
+        
             this.cameraRotation.scaleInPlace(this.inertia);
         }
     };
@@ -327,11 +386,7 @@ var BABYLON = BABYLON || {};
             // Computing target and final matrix
             this.position.addToRef(this._transformedReferencePoint, this._currentTarget);
         } else {
-            if (this.lockedTarget.position) {
-                this._currentTarget.copyFrom(this.lockedTarget.position);
-            } else {
-                this._currentTarget.copyFrom(this.lockedTarget);
-            }
+            this._currentTarget.copyFrom(this._getLockedTargetPosition());
         }
         
         BABYLON.Matrix.LookAtLHToRef(this.position, this._currentTarget, this.upVector, this._viewMatrix);

+ 16 - 14
Babylon/Mesh/babylon.mesh.js

@@ -4,6 +4,8 @@ var BABYLON = BABYLON || {};
 
 (function () {
     BABYLON.Mesh = function (name, scene) {
+        BABYLON.Node.call(this);
+        
         this.name = name;
         this.id = name;
         this._scene = scene;
@@ -30,15 +32,10 @@ var BABYLON = BABYLON || {};
         // Animations
         this.animations = [];
 
-        // Cache
         this._positions = null;
-        this._cache = {
-            localMatrixUpdated: false,
-            position: BABYLON.Vector3.Zero(),
-            scaling: BABYLON.Vector3.Zero(),
-            rotation: BABYLON.Vector3.Zero(),
-            rotationQuaternion: new BABYLON.Quaternion(0, 0, 0, 0)
-        };
+        
+        // Cache
+        BABYLON.Mesh.prototype._initCache.call(this);
 
         this._childrenFlag = false;
         this._localScaling = BABYLON.Matrix.Zero();
@@ -143,7 +140,7 @@ var BABYLON = BABYLON || {};
         return this._pivotMatrix;
     };
 
-    BABYLON.Mesh.prototype.isSynchronized = function () {
+    BABYLON.Mesh.prototype._isSynchronized = function () {
         if (this.billboardMode !== BABYLON.Mesh.BILLBOARDMODE_NONE)
             return false;
 
@@ -169,9 +166,6 @@ var BABYLON = BABYLON || {};
         if (!this._cache.scaling.equals(this.scaling))
             return false;
 
-        if (this.parent)
-            return !this.parent._needToSynchonizeChildren();
-
         return true;
     };
 
@@ -231,7 +225,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Mesh.prototype.computeWorldMatrix = function (force) {
-        if (!force && (this._currentRenderId == this._scene.getRenderId() || this.isSynchronized())) {
+        if (!force && (this._currentRenderId == this._scene.getRenderId() || this.isSynchronized(true))) {
             this._childrenFlag = false;
             return this._worldMatrix;
         }
@@ -1354,6 +1348,14 @@ var BABYLON = BABYLON || {};
 
         return ground;
     };
+    
+    BABYLON.Mesh.prototype._initCache = function (
+        this._cache.localMatrixUpdated = false;
+        this._cache.position = BABYLON.Vector3.Zero();
+        this._cache.scaling = BABYLON.Vector3.Zero();
+        this._cache.rotation = BABYLON.Vector3.Zero();
+        this._cache.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 0);
+    };
 
     // Tools
     BABYLON.Mesh.ComputeNormal = function (positions, normals, indices) {
@@ -1400,5 +1402,5 @@ var BABYLON = BABYLON || {};
             normals[index * 3 + 1] = normal.y;
             normals[index * 3 + 2] = normal.z;
         }
-    };   
+    };
 })();

+ 5 - 5
Babylon/Tools/babylon.math.js

@@ -191,7 +191,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Color3.prototype.equals = function (otherColor) {
-        return this.r === otherColor.r && this.g === otherColor.g && this.b === otherColor.b;
+        return otherColor && this.r === otherColor.r && this.g === otherColor.g && this.b === otherColor.b;
     };
 
     BABYLON.Color3.prototype.scale = function (scale) {
@@ -334,7 +334,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Vector2.prototype.equals = function (otherVector) {
-        return this.x === otherVector.x && this.y === otherVector.y;
+        return otherVector && this.x === otherVector.x && this.y === otherVector.y;
     };
 
     // Properties
@@ -540,7 +540,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Vector3.prototype.equals = function (otherVector) {
-        return this.x === otherVector.x && this.y === otherVector.y && this.z === otherVector.z;
+        return otherVector && this.x === otherVector.x && this.y === otherVector.y && this.z === otherVector.z;
     };
 
     BABYLON.Vector3.prototype.equalsToFloats = function (x, y, z) {
@@ -858,7 +858,7 @@ var BABYLON = BABYLON || {};
     };
     
     BABYLON.Quaternion.prototype.equals = function (otherQuaternion) {
-        return this.x === otherQuaternion.x && this.y === otherQuaternion.y && this.z === otherQuaternion.z && this.w === otherQuaternion.w;
+        return otherQuaternion && this.x === otherQuaternion.x && this.y === otherQuaternion.y && this.z === otherQuaternion.z && this.w === otherQuaternion.w;
     };
 
     BABYLON.Quaternion.prototype.clone = function () {
@@ -1176,7 +1176,7 @@ var BABYLON = BABYLON || {};
     };
 
     BABYLON.Matrix.prototype.equals = function (value) {
-        return (this.m[0] === value.m[0] && this.m[1] === value.m[1] && this.m[2] === value.m[2] && this.m[3] === value.m[3] &&
+        return value && (this.m[0] === value.m[0] && this.m[1] === value.m[1] && this.m[2] === value.m[2] && this.m[3] === value.m[3] &&
                 this.m[4] === value.m[4] && this.m[5] === value.m[5] && this.m[6] === value.m[6] && this.m[7] === value.m[7] &&
                 this.m[8] === value.m[8] && this.m[9] === value.m[9] && this.m[10] === value.m[10] && this.m[11] === value.m[11] &&
                 this.m[12] === value.m[12] && this.m[13] === value.m[13] && this.m[14] === value.m[14] && this.m[15] === value.m[15]);

+ 54 - 1
Babylon/babylon.node.js

@@ -4,6 +4,7 @@ var BABYLON = BABYLON || {};
 
 (function () {
     BABYLON.Node = function () {
+        BABYLON.Node.prototype._initCache.call(this);
     };
     
     // Properties
@@ -12,8 +13,60 @@ var BABYLON = BABYLON || {};
     BABYLON.Node.prototype._isReady = true;
     BABYLON.Node.prototype._isEnabled = true;
 
+    // Cache
+    BABYLON.Node.prototype._cache = null;
     
-    BABYLON.Node.prototype.isSynchronized = function () {
+    // override it in derived class if you add new variables to the cache
+    // and call it in the constructor of your class like this
+    // BABYLON.YourClass.prototype._initCache.call(this)
+    // DO NOT call parent class method
+    BABYLON.Node.prototype._initCache = function () {
+        this._cache = {};
+        this._cache.parent = undefined;
+    };
+
+    BABYLON.Node.prototype.updateCache = function (force) {
+        if (!force && this.isSynchronized())
+            return;
+        
+        this._cache.parent = this.parent;
+        
+        this._updateCache();
+    };
+
+    // override it in derived class if you add new variables to the cache
+    // and call the parent class method if !ignoreParentClass
+    // BABYLON.ParentClass.prototype._updateCache.call(this, ignoreParentClass)
+    BABYLON.Node.prototype._updateCache = function (ignoreParentClass) {
+    };
+
+    // override it in derived class if you add new variables to the cache
+    // and call the parent class method
+    // BABYLON.ParentClass.prototype._isSynchronized.call(this)
+    BABYLON.Node.prototype._isSynchronized = function () {
+        return true;
+    };
+
+    BABYLON.Node.prototype.isSynchronized = function (updateCache) {
+        var r = this.hasNewParent();
+
+        r = r ? true : (this.parent && this.parent._needToSynchonizeChildren());
+        
+        r = r ? true : !this._isSynchronized();
+        
+        if(updateCache)
+            this.updateCache(true);
+        
+        return !r;
+    };
+
+    BABYLON.Node.prototype.hasNewParent = function (update) {
+        if (this._cache.parent === this.parent)
+            return false;
+        
+        if(update)
+            this._cache.parent = this.parent;
+        
         return true;
     };
     

+ 1 - 1
Babylon/babylon.scene.js

@@ -660,7 +660,7 @@ var BABYLON = BABYLON || {};
         this.postProcessManager._finalizeFrame();
 
         // Update camera
-        this.activeCamera._update();
+        this.activeCamera._updateFromScene();
         
         // Reset some special arrays
         this._renderTargets.reset();

+ 1 - 1
readme.md

@@ -18,7 +18,7 @@ Online [sandbox](http://www.babylonjs.com/sandbox) where you can test your .baby
 ## Features
 - Complete scene graph with lights, cameras, materials and meshes
 - Collisions engine
-- Physics engine (thanks to cannon.js)
+- Physics engine (thanks to [cannon.js](http://github.com/schteppe/cannon.js))
 - Scene picking
 - Antialiasing
 - Animations engine