Browse Source

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

Conflicts:
	dist/preview release/babylon.core.js
	dist/preview release/babylon.d.ts
	dist/preview release/babylon.js
	dist/preview release/babylon.max.js
	dist/preview release/babylon.noworker.js
David Catuhe 9 years ago
parent
commit
0479599a6d

+ 3 - 0
.gitignore

@@ -123,3 +123,6 @@ node_modules
 
 # for JetBrains IDE
 .idea
+
+# for VSCode
+.vscode

File diff suppressed because it is too large
+ 17 - 22
dist/preview release/babylon.core.js


File diff suppressed because it is too large
+ 522 - 518
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 25 - 32
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 2447 - 2412
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 24 - 31
dist/preview release/babylon.noworker.js


+ 1 - 0
dist/preview release/what's new.md

@@ -5,6 +5,7 @@
   - **Updates**
     - New OnPickTrigger support for spritesManager ([deltakosh](https://github.com/deltakosh))
     - New SPS method `digest()` ([jerome](https://github.com/jbousquie))    
+    - New SPS property `computeBoundingBox` ([jerome](https://github.com/jbousquie))  
     - Added a new OnPickOut trigger fired when you release the pointer button outside of a mesh or sprite. ([deltakosh](https://github.com/deltakosh))
     - Added support for OnPointerOver and OnPointerOut for sprites. ([deltakosh](https://github.com/deltakosh))
   - **Bug fixes**

+ 57 - 9
loaders/glTF/babylon.glTFFileLoader.js

@@ -335,6 +335,7 @@ var BABYLON;
     var loadAnimations = function (gltfRuntime) {
         for (var anim in gltfRuntime.animations) {
             var animation = gltfRuntime.animations[anim];
+            var lastAnimation = null;
             for (var i = 0; i < animation.channels.length; i++) {
                 // Get parameters and load buffers
                 var channel = animation.channels[i];
@@ -371,9 +372,17 @@ var BABYLON;
                     }
                 }
                 // Create animation and key frames
-                var babylonAnimation = new BABYLON.Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
+                var babylonAnimation = null;
                 var keys = [];
                 var arrayOffset = 0;
+                var modifyKey = false;
+                if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
+                    babylonAnimation = lastAnimation;
+                    modifyKey = true;
+                }
+                if (!modifyKey) {
+                    babylonAnimation = new BABYLON.Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
+                }
                 // For each frame
                 for (var j = 0; j < bufferInput.length; j++) {
                     var value = null;
@@ -392,26 +401,42 @@ var BABYLON;
                         var scaling = BABYLON.Vector3.Zero();
                         // Warning on decompose
                         var mat = bone.getBaseMatrix();
+                        if (modifyKey) {
+                            mat = lastAnimation.getKeys()[j].value;
+                        }
                         mat.decompose(scaling, rotationQuaternion, translation);
                         if (targetPath === "position") {
                             translation = value;
                         }
                         else if (targetPath === "rotationQuaternion") {
                             rotationQuaternion = value;
+                            // Y is Up
+                            if (GLTFFileLoader.MakeYUP) {
+                                rotationQuaternion = rotationQuaternion.multiply(new BABYLON.Quaternion(-0.707107, 0, 0, 0.707107));
+                            }
                         }
                         else {
                             scaling = value;
                         }
                         value = BABYLON.Matrix.Compose(scaling, rotationQuaternion, translation);
                     }
-                    keys.push({
-                        frame: bufferInput[j],
-                        value: value
-                    });
+                    if (!modifyKey) {
+                        keys.push({
+                            frame: bufferInput[j],
+                            value: value
+                        });
+                    }
+                    else {
+                        lastAnimation.getKeys()[j].value = value;
+                    }
                 }
                 // Finish
-                babylonAnimation.setKeys(keys);
-                targetNode.animations.push(babylonAnimation);
+                if (!modifyKey) {
+                    babylonAnimation.setKeys(keys);
+                    targetNode.animations.push(babylonAnimation);
+                }
+                lastAnimation = babylonAnimation;
+                gltfRuntime.scene.stopAnimation(targetNode);
                 gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
             }
         }
@@ -425,6 +450,10 @@ var BABYLON;
             var scale = BABYLON.Vector3.FromArray(node.scale);
             var rotation = BABYLON.Quaternion.FromArray(node.rotation);
             var position = BABYLON.Vector3.FromArray(node.translation);
+            // Y is Up
+            if (GLTFFileLoader.MakeYUP) {
+                rotation = rotation.multiply(new BABYLON.Quaternion(-0.707107, 0, 0, 0.707107));
+            }
             mat = BABYLON.Matrix.Compose(scale, rotation, position);
         }
         else {
@@ -550,6 +579,12 @@ var BABYLON;
             }
         }
     };
+    var printMat = function (m) {
+        console.log(m[0] + "\t" + m[1] + "\t" + m[2] + "\t" + m[3] + "\n" +
+            m[4] + "\t" + m[5] + "\t" + m[6] + "\t" + m[7] + "\n" +
+            m[8] + "\t" + m[9] + "\t" + m[10] + "\t" + m[11] + "\n" +
+            m[12] + "\t" + m[13] + "\t" + m[14] + "\t" + m[15] + "\n");
+    };
     /**
     * Imports a skeleton
     */
@@ -564,12 +599,14 @@ var BABYLON;
         var accessor = gltfRuntime.accessors[skins.inverseBindMatrices];
         var buffer = getBufferFromAccessor(gltfRuntime, accessor);
         var bindShapeMatrix = BABYLON.Matrix.FromArray(skins.bindShapeMatrix);
-        newSkeleton._identity = bindShapeMatrix;
         // Find the root bones
         var nodesToRoot = [];
         var nodesToRootToAdd = [];
         getNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot);
         newSkeleton.bones = [];
+        if (nodesToRoot.length === 0) {
+            newSkeleton.needInitialSkinMatrix = true;
+        }
         // Joints
         for (var i = 0; i < skins.jointNames.length; i++) {
             var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
@@ -579,6 +616,12 @@ var BABYLON;
                 continue;
             }
             var id = jointNode.id;
+            // Optimize, if the bone already exists...
+            var existingBone = gltfRuntime.scene.getBoneByID(id);
+            if (existingBone) {
+                newSkeleton.bones.push(existingBone);
+                continue;
+            }
             // Check if node already exists
             var foundBone = false;
             for (var j = 0; j < newSkeleton.bones.length; j++) {
@@ -613,7 +656,7 @@ var BABYLON;
             }
             // Create bone
             var mat = configureBoneTransformation(node);
-            if (!parentBone) {
+            if (!parentBone && nodesToRoot.length > 0) {
                 parentBone = getNodeToRoot(nodesToRoot, id);
                 if (parentBone) {
                     if (nodesToRootToAdd.indexOf(parentBone) === -1) {
@@ -621,6 +664,11 @@ var BABYLON;
                     }
                 }
             }
+            if (!parentBone && nodesToRoot.length === 0) {
+                var inverseBindMatrix = BABYLON.Matrix.FromArray(buffer, i * 16);
+                var invertMesh = BABYLON.Matrix.Invert(mesh.getWorldMatrix());
+                mat = mat.multiply(mesh.getWorldMatrix());
+            }
             var bone = new BABYLON.Bone(node.name, newSkeleton, parentBone, mat);
             bone.id = id;
         }

+ 69 - 9
loaders/glTF/babylon.glTFFileLoader.ts

@@ -355,6 +355,7 @@
     var loadAnimations = (gltfRuntime: IGLTFRuntime) => {
         for (var anim in gltfRuntime.animations) {
             var animation: IGLTFAnimation = gltfRuntime.animations[anim];
+            var lastAnimation: Animation = null;
 
             for (var i = 0; i < animation.channels.length; i++) {
                 // Get parameters and load buffers
@@ -403,9 +404,19 @@
                 }
 
                 // Create animation and key frames
-                var babylonAnimation = new Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, Animation.ANIMATIONLOOPMODE_CYCLE);
+                var babylonAnimation: Animation = null;
                 var keys = [];
                 var arrayOffset = 0;
+                var modifyKey = false;
+
+                if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
+                    babylonAnimation = lastAnimation;
+                    modifyKey = true;
+                }
+                
+                if (!modifyKey) {
+                    babylonAnimation = new Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, Animation.ANIMATIONLOOPMODE_CYCLE);
+                }
 
                 // For each frame
                 for (var j = 0; j < bufferInput.length; j++) {
@@ -428,6 +439,11 @@
 
                         // Warning on decompose
                         var mat = bone.getBaseMatrix();
+
+                        if (modifyKey) {
+                            mat = lastAnimation.getKeys()[j].value;
+                        }
+
                         mat.decompose(scaling, rotationQuaternion, translation);
 
                         if (targetPath === "position") {
@@ -435,6 +451,10 @@
                         }
                         else if (targetPath === "rotationQuaternion") {
                             rotationQuaternion = value;
+                            // Y is Up
+                            if (GLTFFileLoader.MakeYUP) {
+                                rotationQuaternion = rotationQuaternion.multiply(new Quaternion(-0.707107, 0, 0, 0.707107));
+                            }
                         }
                         else {
                             scaling = value;
@@ -443,16 +463,26 @@
                         value = Matrix.Compose(scaling, rotationQuaternion, translation);
                     }
 
-                    keys.push({
-                        frame: bufferInput[j],
-                        value: value
-                    });
+                    if (!modifyKey) {
+                        keys.push({
+                            frame: bufferInput[j],
+                            value: value
+                        });
+                    }
+                    else {
+                        lastAnimation.getKeys()[j].value = value;
+                    }
                 }
                 
                 // Finish
-                babylonAnimation.setKeys(keys);
-                targetNode.animations.push(babylonAnimation);
+                if (!modifyKey) {
+                    babylonAnimation.setKeys(keys);
+                    targetNode.animations.push(babylonAnimation);
+                }
+
+                lastAnimation = babylonAnimation;
 
+                gltfRuntime.scene.stopAnimation(targetNode);
                 gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
             }
         }
@@ -468,6 +498,11 @@
             var rotation = Quaternion.FromArray(node.rotation);
             var position = Vector3.FromArray(node.translation);
 
+            // Y is Up
+            if (GLTFFileLoader.MakeYUP) {
+                rotation = rotation.multiply(new Quaternion(-0.707107, 0, 0, 0.707107));
+            }
+
             mat = Matrix.Compose(scale, rotation, position);
         }
         else {
@@ -616,6 +651,15 @@
         }
     };
 
+    var printMat = (m: Float32Array) => {
+        console.log(
+            m[0] + "\t" + m[1] + "\t" + m[2] + "\t" + m[3] + "\n" +
+            m[4] + "\t" + m[5] + "\t" + m[6] + "\t" + m[7] + "\n" +
+            m[8] + "\t" + m[9] + "\t" + m[10] + "\t" + m[11] + "\n" +
+            m[12] + "\t" + m[13] + "\t" + m[14] + "\t" + m[15] + "\n"
+        );
+    }
+
     /**
     * Imports a skeleton
     */
@@ -634,7 +678,6 @@
         var buffer = getBufferFromAccessor(gltfRuntime, accessor);
 
         var bindShapeMatrix = Matrix.FromArray(skins.bindShapeMatrix);
-        (<any>newSkeleton)._identity = bindShapeMatrix;
 
         // Find the root bones
         var nodesToRoot: INodeToRoot[] = [];
@@ -643,6 +686,10 @@
         getNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot);
         newSkeleton.bones = [];
 
+        if (nodesToRoot.length === 0) {
+            newSkeleton.needInitialSkinMatrix = true;
+        }
+
         // Joints
         for (var i = 0; i < skins.jointNames.length; i++) {
             var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]);
@@ -655,6 +702,13 @@
             
             var id = jointNode.id;
 
+            // Optimize, if the bone already exists...
+            var existingBone = gltfRuntime.scene.getBoneByID(id);
+            if (existingBone) {
+                newSkeleton.bones.push(existingBone);
+                continue;
+            }
+
             // Check if node already exists
             var foundBone = false;
             for (var j = 0; j < newSkeleton.bones.length; j++) {
@@ -697,7 +751,7 @@
             // Create bone
             var mat = configureBoneTransformation(node);
 
-            if (!parentBone) {
+            if (!parentBone && nodesToRoot.length > 0) {
                 parentBone = getNodeToRoot(nodesToRoot, id);
 
                 if (parentBone) {
@@ -707,6 +761,12 @@
                 }
             }
 
+            if (!parentBone && nodesToRoot.length === 0) {
+                var inverseBindMatrix = Matrix.FromArray(buffer, i * 16);
+                var invertMesh = Matrix.Invert(mesh.getWorldMatrix());
+                mat = mat.multiply(mesh.getWorldMatrix());
+            }
+
             var bone = new Bone(node.name, newSkeleton, parentBone, mat);
             bone.id = id;
         }

+ 3 - 1
readme.md

@@ -5,6 +5,8 @@ Getting started? Play directly with the Babylon.js API via our [playground](http
 
 [![Build Status](https://travis-ci.org/BabylonJS/Babylon.js.svg)](https://travis-ci.org/BabylonJS/Babylon.js)
 
+Any questions? Here is our official [forum](http://www.html5gamedevs.com/forum/16-babylonjs/) on www.html5gamedevs.com.
+
 ## CDN
 - http://cdn.babylonjs.com/2-3/babylon.js 
 - http://cdn.babylonjs.com/2-3/babylon.max.js 
@@ -16,6 +18,7 @@ You can help by testing or contributing to the next version.
 - **2.4-alpha** can be found [here](https://github.com/BabylonJS/Babylon.js/tree/master/dist/preview%20release)
 - We are not complicated people, but we still have some [coding guidelines](http://doc.babylonjs.com/generals/Approved_Naming_Conventions)
 - Before submitting your PR, just check that everything goes well by [creating the minified version](http://doc.babylonjs.com/generals/Creating_the_Mini-fied_Version)
+- Need help to contribute? We have a [documentation for you](http://pixelcodr.com/tutos/contribute/contribute.html)
 
 ## Documentation
 - [Documentation](http://doc.babylonjs.com)
@@ -27,7 +30,6 @@ You can help by testing or contributing to the next version.
 ## Useful links
 
  - Official web site: [www.babylonjs.com](http://www.babylonjs.com/)
- - Official [forum](http://www.html5gamedevs.com/forum/16-babylonjs/) on www.html5gamedevs.com
  - Online [sandbox](http://www.babylonjs.com/sandbox) where you can test your .babylon scenes with a simple drag'n'drop
  - Online [shader creation tool](http://www.babylonjs.com/cyos/) where you can learn how to create GLSL shaders
  - 3DS Max [exporter](https://github.com/BabylonJS/Babylon.js/tree/master/Exporters/3ds%20Max) can be used to generate a .babylon file from 3DS Max

+ 7 - 0
src/Loading/Plugins/babylon.babylonFileLoader.js

@@ -207,6 +207,13 @@ var BABYLON;
                     var parsedLight = parsedData.lights[index];
                     BABYLON.Light.Parse(parsedLight, scene);
                 }
+                // Animations
+                if (parsedData.animations) {
+                    for (index = 0, cache = parsedData.animations.length; index < cache; index++) {
+                        var parsedAnimation = parsedData.animations[index];
+                        scene.animations.push(BABYLON.Animation.Parse(parsedAnimation));
+                    }
+                }
                 // Materials
                 if (parsedData.materials) {
                     for (index = 0, cache = parsedData.materials.length; index < cache; index++) {

+ 9 - 1
src/Loading/Plugins/babylon.babylonFileLoader.ts

@@ -222,6 +222,14 @@
                 Light.Parse(parsedLight, scene);
             }
 
+            // Animations
+            if (parsedData.animations) {
+                for (index = 0, cache = parsedData.animations.length; index < cache; index++) {
+                    var parsedAnimation = parsedData.animations[index];
+                    scene.animations.push(Animation.Parse(parsedAnimation));
+                }
+            }
+
             // Materials
             if (parsedData.materials) {
                 for (index = 0, cache = parsedData.materials.length; index < cache; index++) {
@@ -433,4 +441,4 @@
             return true;
         }
     });
-}
+}

+ 16 - 0
src/Particles/babylon.particleSystem.js

@@ -11,6 +11,8 @@ var BABYLON;
         function ParticleSystem(name, capacity, scene, customEffect) {
             var _this = this;
             this.name = name;
+            // Members
+            this.animations = [];
             this.renderingGroupId = 0;
             this.emitter = null;
             this.emitRate = 10;
@@ -332,6 +334,7 @@ var BABYLON;
         ParticleSystem.prototype.serialize = function () {
             var serializationObject = {};
             serializationObject.name = this.name;
+            // Emitter
             if (this.emitter.position) {
                 serializationObject.emitterId = this.emitter.id;
             }
@@ -343,6 +346,9 @@ var BABYLON;
             if (this.particleTexture) {
                 serializationObject.textureName = this.particleTexture.name;
             }
+            // Animations
+            BABYLON.Animation.AppendSerializedAnimations(this, serializationObject);
+            // Particle system
             serializationObject.minAngularSpeed = this.minAngularSpeed;
             serializationObject.maxAngularSpeed = this.maxAngularSpeed;
             serializationObject.minSize = this.minSize;
@@ -369,16 +375,26 @@ var BABYLON;
         ParticleSystem.Parse = function (parsedParticleSystem, scene, rootUrl) {
             var name = parsedParticleSystem.name;
             var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene);
+            // Texture
             if (parsedParticleSystem.textureName) {
                 particleSystem.particleTexture = new BABYLON.Texture(rootUrl + parsedParticleSystem.textureName, scene);
                 particleSystem.particleTexture.name = parsedParticleSystem.textureName;
             }
+            // Emitter
             if (parsedParticleSystem.emitterId) {
                 particleSystem.emitter = scene.getLastMeshByID(parsedParticleSystem.emitterId);
             }
             else {
                 particleSystem.emitter = BABYLON.Vector3.FromArray(parsedParticleSystem.emitter);
             }
+            // Animations
+            if (parsedParticleSystem.animations) {
+                for (var animationIndex = 0; animationIndex < parsedParticleSystem.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedParticleSystem.animations[animationIndex];
+                    particleSystem.animations.push(BABYLON.Animation.Parse(parsedAnimation));
+                }
+            }
+            // Particle system
             particleSystem.minAngularSpeed = parsedParticleSystem.minAngularSpeed;
             particleSystem.maxAngularSpeed = parsedParticleSystem.maxAngularSpeed;
             particleSystem.minSize = parsedParticleSystem.minSize;

+ 25 - 3
src/Particles/babylon.particleSystem.ts

@@ -9,12 +9,14 @@
         return ((random * (max - min)) + min);
     }
 
-    export class ParticleSystem implements IDisposable {
+    export class ParticleSystem implements IDisposable, IAnimatable {
         // Statics
         public static BLENDMODE_ONEONE = 0;
         public static BLENDMODE_STANDARD = 1;
 
         // Members
+        public animations: Animation[] = [];
+
         public id: string;
         public renderingGroupId = 0;
         public emitter = null;
@@ -449,17 +451,24 @@
             var serializationObject: any = {};
 
             serializationObject.name = this.name;
+
+            // Emitter
             if (this.emitter.position) {
                 serializationObject.emitterId = this.emitter.id;
             } else {
                 serializationObject.emitter = this.emitter.asArray();;
             }
+
             serializationObject.capacity = this.getCapacity();
 
             if (this.particleTexture) {
                 serializationObject.textureName = this.particleTexture.name;
             }
+            
+            // Animations
+            Animation.AppendSerializedAnimations(this, serializationObject);
 
+            // Particle system
             serializationObject.minAngularSpeed = this.minAngularSpeed;
             serializationObject.maxAngularSpeed = this.maxAngularSpeed;
             serializationObject.minSize = this.minSize;
@@ -488,15 +497,29 @@
         public static Parse(parsedParticleSystem: any, scene: Scene, rootUrl: string): ParticleSystem {
             var name = parsedParticleSystem.name;
             var particleSystem = new ParticleSystem(name, parsedParticleSystem.capacity, scene);
+
+            // Texture
             if (parsedParticleSystem.textureName) {
                 particleSystem.particleTexture = new Texture(rootUrl + parsedParticleSystem.textureName, scene);
                 particleSystem.particleTexture.name = parsedParticleSystem.textureName;
             }
+
+            // Emitter
             if (parsedParticleSystem.emitterId) {
                 particleSystem.emitter = scene.getLastMeshByID(parsedParticleSystem.emitterId);
             } else {
                 particleSystem.emitter = Vector3.FromArray(parsedParticleSystem.emitter);
             }
+
+            // Animations
+            if (parsedParticleSystem.animations) {
+                for (var animationIndex = 0; animationIndex < parsedParticleSystem.animations.length; animationIndex++) {
+                    var parsedAnimation = parsedParticleSystem.animations[animationIndex];
+                    particleSystem.animations.push(Animation.Parse(parsedAnimation));
+                }
+            }
+
+            // Particle system
             particleSystem.minAngularSpeed = parsedParticleSystem.minAngularSpeed;
             particleSystem.maxAngularSpeed = parsedParticleSystem.maxAngularSpeed;
             particleSystem.minSize = parsedParticleSystem.minSize;
@@ -523,5 +546,4 @@
             return particleSystem;
         }
     }
-}  
-
+}

+ 7 - 2
src/Particles/babylon.solidParticleSystem.js

@@ -80,7 +80,6 @@ var BABYLON;
             this._w = 0.0;
             this._minimum = BABYLON.Tmp.Vector3[0];
             this._maximum = BABYLON.Tmp.Vector3[1];
-            this._vertexWorld = BABYLON.Tmp.Vector3[2];
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
@@ -142,11 +141,13 @@ var BABYLON;
         * Thus the particles generated from digest() have their property "positiion" yet set.
         * @param mesh the mesh to be digested
         * @param facetNb the number of mesh facets per particle (optional, default 1), this parameter is overriden by the parameter "number" if any
+        * @param delta the random extra number of facets per partical (optional, default 0), each particle will have between facetNb and facetNb + delta facets
         * @param number the wanted number of particles : each particle is built with mesh_total_facets / number facets (optional)
         */
         SolidParticleSystem.prototype.digest = function (mesh, options) {
             var size = (options && options.facetNb) || 1;
             var number = (options && options.number);
+            var delta = (options && options.delta) || 0;
             var meshPos = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
             var meshInd = mesh.getIndices();
             var meshUV = mesh.getVerticesData(BABYLON.VertexBuffer.UVKind);
@@ -157,6 +158,7 @@ var BABYLON;
             if (number) {
                 number = (number > totalFacets) ? totalFacets : number;
                 size = Math.round(totalFacets / number);
+                delta = 0;
             }
             else {
                 size = (size > totalFacets) ? totalFacets : size;
@@ -166,7 +168,10 @@ var BABYLON;
             var facetUV = []; // submesh UV
             var facetCol = []; // submesh colors
             var barycenter = BABYLON.Tmp.Vector3[0];
+            var rand;
+            var sizeO = size;
             while (f < totalFacets) {
+                size = sizeO + Math.floor((1 + delta) * Math.random());
                 if (f > totalFacets - size) {
                     size = totalFacets - f;
                 }
@@ -580,7 +585,7 @@ var BABYLON;
             }
             if (this._computeBoundingBox) {
                 this.mesh._boundingInfo = new BABYLON.BoundingInfo(this._minimum, this._maximum);
-                this.mesh._boundingInfo.boundingBox.setWorldMatrix(this.mesh._worldMatrix);
+                this.mesh._boundingInfo.update(this.mesh._worldMatrix);
             }
             this.afterUpdateParticles(start, end, update);
         };

+ 8 - 4
src/Particles/babylon.solidParticleSystem.ts

@@ -102,8 +102,6 @@ module BABYLON {
         private _w: number = 0.0;
         private _minimum: Vector3 = Tmp.Vector3[0];
         private _maximum: Vector3 = Tmp.Vector3[1];
-        private _vertexWorld: Vector3 = Tmp.Vector3[2];
-
 
 
         /**
@@ -177,11 +175,13 @@ module BABYLON {
         * Thus the particles generated from digest() have their property "positiion" yet set.
         * @param mesh the mesh to be digested
         * @param facetNb the number of mesh facets per particle (optional, default 1), this parameter is overriden by the parameter "number" if any
+        * @param delta the random extra number of facets per partical (optional, default 0), each particle will have between facetNb and facetNb + delta facets
         * @param number the wanted number of particles : each particle is built with mesh_total_facets / number facets (optional)
         */
-        public digest(mesh: Mesh, options?: { facetNb?: number; number?: number }): void {
+        public digest(mesh: Mesh, options?: { facetNb?: number; number?: number; delta?: number }): void {
             var size: number = (options && options.facetNb) || 1;
             var number: number = (options && options.number);
+            var delta: number = (options && options.delta) || 0;
             var meshPos = mesh.getVerticesData(VertexBuffer.PositionKind);
             var meshInd = mesh.getIndices();
             var meshUV = mesh.getVerticesData(VertexBuffer.UVKind);
@@ -193,6 +193,7 @@ module BABYLON {
             if (number) {
                 number = (number > totalFacets) ? totalFacets : number;
                 size = Math.round(totalFacets / number);
+                delta = 0;
             } else {
                 size = (size > totalFacets) ? totalFacets : size;
             }
@@ -202,8 +203,11 @@ module BABYLON {
             var facetUV: number[] = [];       // submesh UV
             var facetCol: number[] = [];      // submesh colors
             var barycenter: Vector3 = Tmp.Vector3[0];
+            var rand: number;
+            var sizeO: number = size;
 
             while (f < totalFacets) {
+                size = sizeO + Math.floor((1 + delta) * Math.random());
                 if (f > totalFacets - size) {
                     size = totalFacets - f;
                 }
@@ -669,7 +673,7 @@ module BABYLON {
             }
             if (this._computeBoundingBox) {
                 this.mesh._boundingInfo = new BoundingInfo(this._minimum, this._maximum);
-                this.mesh._boundingInfo.boundingBox.setWorldMatrix(this.mesh._worldMatrix);
+                this.mesh._boundingInfo.update(this.mesh._worldMatrix);
             }
             this.afterUpdateParticles(start, end, update);
         }

+ 5 - 0
src/Tools/babylon.sceneSerializer.js

@@ -183,6 +183,9 @@ var BABYLON;
     var SceneSerializer = (function () {
         function SceneSerializer() {
         }
+        SceneSerializer.ClearCache = function () {
+            serializedGeometries = [];
+        };
         SceneSerializer.Serialize = function (scene) {
             var serializationObject = {};
             // Scene
@@ -224,6 +227,8 @@ var BABYLON;
             if (scene.activeCamera) {
                 serializationObject.activeCameraID = scene.activeCamera.id;
             }
+            // Animations
+            BABYLON.Animation.AppendSerializedAnimations(scene, serializationObject);
             // Materials
             serializationObject.materials = [];
             serializationObject.multiMaterials = [];

+ 8 - 0
src/Tools/babylon.sceneSerializer.ts

@@ -207,6 +207,10 @@
     }
 
     export class SceneSerializer {
+        public static ClearCache(): void {
+            serializedGeometries = [];
+        }
+
         public static Serialize(scene: Scene): any {
             var serializationObject: any = {};
 
@@ -255,6 +259,9 @@
                 serializationObject.activeCameraID = scene.activeCamera.id;
             }
 
+            // Animations
+            Animation.AppendSerializedAnimations(scene, serializationObject);
+
             // Materials
             serializationObject.materials = [];
             serializationObject.multiMaterials = [];
@@ -367,3 +374,4 @@
         }
     }
 }
+

+ 1 - 1
src/Tools/babylon.tools.js

@@ -496,7 +496,7 @@ var BABYLON;
                     var a = window.document.createElement("a");
                     a.href = base64Image;
                     var date = new Date();
-                    var stringDate = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
+                    var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
                     a.setAttribute("download", "screenshot_" + stringDate + ".png");
                     window.document.body.appendChild(a);
                     a.addEventListener("click", function () {

+ 2 - 1
src/Tools/babylon.tools.ts

@@ -592,7 +592,7 @@
                     var a = window.document.createElement("a");
                     a.href = base64Image;
                     var date = new Date();
-                    var stringDate = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
+                    var stringDate = (date.getFullYear() + "-" + (date.getMonth() + 1)).slice(-2) + "-" + date.getDate() + "_" + date.getHours() + "-" + ('0' + date.getMinutes()).slice(-2);
                     a.setAttribute("download", "screenshot_" + stringDate + ".png");
 
                     window.document.body.appendChild(a);
@@ -1013,3 +1013,4 @@
 } 
 
 
+

+ 8 - 8
src/babylon.engine.js

@@ -394,14 +394,14 @@ var BABYLON;
                 options.preserveDrawingBuffer = false;
             }
             // GL
-            try {
-                this._gl = (canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
-                if (this._gl) {
-                    this._webGLVersion = "2.0";
-                }
-            }
-            catch (e) {
-            }
+            //try {
+            //    this._gl = <WebGLRenderingContext>(canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
+            //    if (this._gl) {
+            //        this._webGLVersion = "2.0";
+            //    }
+            //} catch (e) {
+            //    // Do nothing
+            //}
             if (!this._gl) {
                 try {
                     this._gl = (canvas.getContext("webgl", options) || canvas.getContext("experimental-webgl", options));

+ 8 - 8
src/babylon.engine.ts

@@ -587,14 +587,14 @@
             }
 
             // GL
-            try {
-                this._gl = <WebGLRenderingContext>(canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
-                if (this._gl) {
-                    this._webGLVersion = "2.0";
-                }
-            } catch (e) {
-                // Do nothing
-            }
+            //try {
+            //    this._gl = <WebGLRenderingContext>(canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
+            //    if (this._gl) {
+            //        this._webGLVersion = "2.0";
+            //    }
+            //} catch (e) {
+            //    // Do nothing
+            //}
 
             if (!this._gl) {
                 try {

+ 2 - 0
src/babylon.scene.js

@@ -19,6 +19,8 @@ var BABYLON;
             this.forceShowBoundingBoxes = false;
             this.animationsEnabled = true;
             this.constantlyUpdateMeshUnderPointer = false;
+            // Animations
+            this.animations = [];
             this.cameraToUseForPointers = null; // Define this parameter if you are using multiple cameras and you want to specify which one should be used for pointer position
             this._startingPointerPosition = new BABYLON.Vector2(0, 0);
             this._startingPointerTime = 0;

+ 7 - 3
src/babylon.scene.ts

@@ -7,7 +7,7 @@
      * Represents a scene to be rendered by the engine.
      * @see http://doc.babylonjs.com/page.php?p=21911
      */
-    export class Scene {
+    export class Scene implements IAnimatable {
         // Statics
         private static _FOGMODE_NONE = 0;
         private static _FOGMODE_EXP = 1;
@@ -61,6 +61,9 @@
         public animationsEnabled = true;
         public constantlyUpdateMeshUnderPointer = false;
 
+        // Animations
+        public animations: Animation[] = [];
+
         // Pointers
         private _onPointerMove: (evt: PointerEvent) => void;
         private _onPointerDown: (evt: PointerEvent) => void;
@@ -278,7 +281,7 @@
         private _depthRenderer: DepthRenderer;
 
         private _uniqueIdCounter = 0;
-        
+
         private _pickedDownMesh: AbstractMesh;
         private _pickedDownSprite: Sprite;
 
@@ -628,7 +631,7 @@
                 if (this._pickedDownMesh && this._pickedDownMesh !== pickResult.pickedMesh) {
                     this._pickedDownMesh.actionManager.processTrigger(ActionManager.OnPickOutTrigger, ActionEvent.CreateNew(this._pickedDownMesh, evt));
                 }
-                
+
                 if (this.onPointerUp) {
                     this.onPointerUp(evt, pickResult);
                 }
@@ -2611,3 +2614,4 @@
         }
     }
 }
+