Browse Source

Fixing issues

David Catuhe 9 years ago
parent
commit
2d15e67b33
45 changed files with 3279 additions and 2600 deletions
  1. 17 17
      dist/preview release/babylon.core.js
  2. 2311 2298
      dist/preview release/babylon.d.ts
  3. 24 24
      dist/preview release/babylon.js
  4. 284 70
      dist/preview release/babylon.max.js
  5. 23 23
      dist/preview release/babylon.noworker.js
  6. 67 5
      src/Audio/babylon.sound.js
  7. 71 6
      src/Audio/babylon.sound.ts
  8. 1 0
      src/Bones/babylon.bone.ts
  9. 7 1
      src/Bones/babylon.skeleton.js
  10. 17 9
      src/Bones/babylon.skeleton.ts
  11. 1 1
      src/Cameras/babylon.arcRotateCamera.js
  12. 1 1
      src/Cameras/babylon.arcRotateCamera.ts
  13. 1 1
      src/Lights/Shadows/babylon.shadowGenerator.js
  14. 1 1
      src/Lights/Shadows/babylon.shadowGenerator.ts
  15. 0 1
      src/Lights/babylon.light.ts
  16. 10 1
      src/Loading/Plugins/babylon.babylonFileLoader.js
  17. 11 1
      src/Loading/Plugins/babylon.babylonFileLoader.ts
  18. 1 0
      src/Materials/Textures/babylon.renderTargetTexture.js
  19. 1 0
      src/Materials/Textures/babylon.renderTargetTexture.ts
  20. 5 5
      src/Materials/babylon.effect.js
  21. 16 16
      src/Materials/babylon.effect.ts
  22. 13 0
      src/Materials/babylon.material.js
  23. 12 0
      src/Materials/babylon.material.ts
  24. 23 21
      src/Materials/babylon.standardMaterial.js
  25. 23 21
      src/Materials/babylon.standardMaterial.ts
  26. 5 1
      src/Mesh/babylon.abstractMesh.js
  27. 7 2
      src/Mesh/babylon.abstractMesh.ts
  28. 1 0
      src/Mesh/babylon.geometry.ts
  29. 89 13
      src/Mesh/babylon.mesh.js
  30. 102 13
      src/Mesh/babylon.mesh.ts
  31. 21 6
      src/Mesh/babylon.subMesh.js
  32. 19 6
      src/Mesh/babylon.subMesh.ts
  33. 1 1
      src/Particles/babylon.solidParticleSystem.js
  34. 3 2
      src/Particles/babylon.solidParticleSystem.ts
  35. 14 7
      src/Physics/Plugins/babylon.cannonJSPlugin.js
  36. 16 10
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  37. 1 1
      src/Physics/Plugins/babylon.oimoJSPlugin.js
  38. 1 1
      src/Physics/Plugins/babylon.oimoJSPlugin.ts
  39. 0 1
      src/Shaders/default.fragment.fx
  40. 1 0
      src/Tools/babylon.tools.js
  41. 6 3
      src/Tools/babylon.tools.ts
  42. 11 1
      src/babylon.engine.js
  43. 14 1
      src/babylon.engine.ts
  44. 12 4
      src/babylon.scene.js
  45. 14 4
      src/babylon.scene.ts

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


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


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


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


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


+ 67 - 5
src/Audio/babylon.sound.js

@@ -6,7 +6,7 @@ var BABYLON;
         * @param name Name of your sound
         * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
-        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel
+        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
         */
         function Sound(name, urlOrArrayBuffer, scene, readyToPlayCallback, options) {
             var _this = this;
@@ -103,7 +103,9 @@ var BABYLON;
                     }
                     else {
                         if (urlOrArrayBuffer instanceof ArrayBuffer) {
-                            this._soundLoaded(urlOrArrayBuffer);
+                            if (urlOrArrayBuffer.byteLength > 0) {
+                                this._soundLoaded(urlOrArrayBuffer);
+                            }
                         }
                         else {
                             BABYLON.Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
@@ -420,6 +422,10 @@ var BABYLON;
         };
         Sound.prototype.attachToMesh = function (meshToConnectTo) {
             var _this = this;
+            if (this._connectedMesh) {
+                this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
+                this._registerFunc = null;
+            }
             this._connectedMesh = meshToConnectTo;
             if (!this.spatialSound) {
                 this.spatialSound = true;
@@ -439,7 +445,44 @@ var BABYLON;
                 this._updateDirection();
             }
         };
-        Sound.Parse = function (parsedSound, scene, rootUrl) {
+        Sound.prototype.clone = function () {
+            var _this = this;
+            if (!this._streaming) {
+                var setBufferAndRun = function () {
+                    if (_this._isReadyToPlay) {
+                        clonedSound._audioBuffer = _this.getAudioBuffer();
+                        clonedSound._isReadyToPlay = true;
+                        if (clonedSound.autoplay) {
+                            clonedSound.play();
+                        }
+                    }
+                    else {
+                        window.setTimeout(setBufferAndRun, 300);
+                    }
+                };
+                var currentOptions = {
+                    autoplay: this.autoplay, loop: this.loop,
+                    volume: this._volume, spatialSound: this.spatialSound, maxDistance: this.maxDistance,
+                    useCustomAttenuation: this.useCustomAttenuation, rolloffFactor: this.rolloffFactor,
+                    refDistance: this.refDistance, distanceModel: this.distanceModel
+                };
+                var clonedSound = new Sound(this.name + "_cloned", new ArrayBuffer(0), this._scene, null, currentOptions);
+                if (this.useCustomAttenuation) {
+                    clonedSound.setAttenuationFunction(this._customAttenuationFunction);
+                }
+                clonedSound.setPosition(this._position);
+                clonedSound.setPlaybackRate(this._playbackRate);
+                setBufferAndRun();
+                return clonedSound;
+            }
+            else {
+                return null;
+            }
+        };
+        Sound.prototype.getAudioBuffer = function () {
+            return this._audioBuffer;
+        };
+        Sound.Parse = function (parsedSound, scene, rootUrl, sourceSound) {
             var soundName = parsedSound.name;
             var soundUrl = rootUrl + soundName;
             var options = {
@@ -450,8 +493,27 @@ var BABYLON;
                 distanceModel: parsedSound.distanceModel,
                 playbackRate: parsedSound.playbackRate
             };
-            var newSound = new Sound(soundName, soundUrl, scene, function () { scene._removePendingData(newSound); }, options);
-            scene._addPendingData(newSound);
+            var newSound;
+            if (!sourceSound) {
+                newSound = new Sound(soundName, soundUrl, scene, function () { scene._removePendingData(newSound); }, options);
+                scene._addPendingData(newSound);
+            }
+            else {
+                var setBufferAndRun = function () {
+                    if (sourceSound._isReadyToPlay) {
+                        newSound._audioBuffer = sourceSound.getAudioBuffer();
+                        newSound._isReadyToPlay = true;
+                        if (newSound.autoplay) {
+                            newSound.play();
+                        }
+                    }
+                    else {
+                        window.setTimeout(setBufferAndRun, 300);
+                    }
+                };
+                newSound = new Sound(soundName, new ArrayBuffer(0), scene, null, options);
+                setBufferAndRun();
+            }
             if (parsedSound.position) {
                 var soundPosition = BABYLON.Vector3.FromArray(parsedSound.position);
                 newSound.setPosition(soundPosition);

+ 71 - 6
src/Audio/babylon.sound.ts

@@ -49,7 +49,7 @@
         * @param name Name of your sound 
         * @param urlOrArrayBuffer Url to the sound to load async or ArrayBuffer 
         * @param readyToPlayCallback Provide a callback function if you'd like to load your code once the sound is ready to be played
-        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel
+        * @param options Objects to provide with the current available options: autoplay, loop, volume, spatialSound, maxDistance, rolloffFactor, refDistance, distanceModel, panningModel, streaming
         */
         constructor(name: string, urlOrArrayBuffer: any, scene: Scene, readyToPlayCallback?: () => void, options?) {
             this.name = name;
@@ -118,7 +118,9 @@
                     }
                     else {
                         if (urlOrArrayBuffer instanceof ArrayBuffer) {
-                            this._soundLoaded(urlOrArrayBuffer);
+                            if ((<ArrayBuffer>urlOrArrayBuffer).byteLength > 0) {
+                                this._soundLoaded(urlOrArrayBuffer);
+                            }
                         }
                         else {
                             Tools.Error("Parameter must be a URL to the sound or an ArrayBuffer of the sound.");
@@ -457,6 +459,10 @@
         }
 
         public attachToMesh(meshToConnectTo: AbstractMesh) {
+            if (this._connectedMesh) {
+                this._connectedMesh.unregisterAfterWorldMatrixUpdate(this._registerFunc);
+                this._registerFunc = null;
+            }
             this._connectedMesh = meshToConnectTo;
             if (!this.spatialSound) {
                 this.spatialSound = true;
@@ -478,7 +484,47 @@
             }
         }
 
-        public static Parse(parsedSound: any, scene: Scene, rootUrl: string): Sound {
+        public clone(): Sound {
+            if (!this._streaming) {
+                var setBufferAndRun = () => {
+                    if (this._isReadyToPlay) {
+                        clonedSound._audioBuffer = this.getAudioBuffer();
+                        clonedSound._isReadyToPlay = true;
+                        if (clonedSound.autoplay) { clonedSound.play(); }
+                    }
+                    else {
+                        window.setTimeout(setBufferAndRun, 300);
+                    }
+                };
+
+                var currentOptions = {
+                    autoplay: this.autoplay, loop: this.loop,
+                    volume: this._volume, spatialSound: this.spatialSound, maxDistance: this.maxDistance,
+                    useCustomAttenuation: this.useCustomAttenuation, rolloffFactor: this.rolloffFactor,
+                    refDistance: this.refDistance, distanceModel: this.distanceModel
+                };
+
+                var clonedSound = new Sound(this.name + "_cloned", new ArrayBuffer(0), this._scene, null, currentOptions);
+                if (this.useCustomAttenuation) {
+                    clonedSound.setAttenuationFunction(this._customAttenuationFunction);
+                }
+                clonedSound.setPosition(this._position);
+                clonedSound.setPlaybackRate(this._playbackRate);
+                setBufferAndRun();
+
+                return clonedSound;
+            }
+            // Can't clone a streaming sound
+            else {
+                return null;
+            } 
+        }
+
+        public getAudioBuffer() {
+            return this._audioBuffer;
+        }
+
+        public static Parse(parsedSound: any, scene: Scene, rootUrl: string, sourceSound?: Sound): Sound {
             var soundName = parsedSound.name;
             var soundUrl = rootUrl + soundName;
 
@@ -491,8 +537,27 @@
                 playbackRate: parsedSound.playbackRate
             };
 
-            var newSound = new Sound(soundName, soundUrl, scene, () => { scene._removePendingData(newSound); }, options);
-            scene._addPendingData(newSound);
+            var newSound: Sound;
+
+            if (!sourceSound) {
+                newSound = new Sound(soundName, soundUrl, scene, () => { scene._removePendingData(newSound); }, options);
+                scene._addPendingData(newSound);
+            }
+            else {
+                var setBufferAndRun = () => {
+                    if (sourceSound._isReadyToPlay) {
+                        newSound._audioBuffer = sourceSound.getAudioBuffer();
+                        newSound._isReadyToPlay = true;
+                        if (newSound.autoplay) { newSound.play(); }
+                    }
+                    else {
+                        window.setTimeout(setBufferAndRun, 300);
+                    }
+                }
+
+                newSound = new Sound(soundName, new ArrayBuffer(0), scene, null, options);
+                setBufferAndRun();
+            }
 
             if (parsedSound.position) {
                 var soundPosition = Vector3.FromArray(parsedSound.position);
@@ -515,4 +580,4 @@
             return newSound;
         }
     }
-}
+}

+ 1 - 0
src/Bones/babylon.bone.ts

@@ -2,6 +2,7 @@
     export class Bone extends Node {
         public children = new Array<Bone>();
         public animations = new Array<Animation>();
+        public length: number; 
 
         private _skeleton: Skeleton;
         private _matrix: Matrix;

+ 7 - 1
src/Bones/babylon.skeleton.js

@@ -92,7 +92,7 @@ var BABYLON;
                     var parentIndex = this.bones.indexOf(source.getParent());
                     parentBone = result.bones[parentIndex];
                 }
-                var bone = new BABYLON.Bone(source.name, result, parentBone, source.getBaseMatrix());
+                var bone = new BABYLON.Bone(source.name, result, parentBone, source.getBaseMatrix().clone());
                 BABYLON.Tools.DeepCopy(source.animations, bone.animations);
             }
             return result;
@@ -116,6 +116,9 @@ var BABYLON;
                     matrix: bone.getLocalMatrix().toArray()
                 };
                 serializationObject.bones.push(serializedBone);
+                if (bone.length) {
+                    serializedBone.length = bone.length;
+                }
                 if (bone.animations && bone.animations.length > 0) {
                     serializedBone.animation = bone.animations[0].serialize();
                 }
@@ -131,6 +134,9 @@ var BABYLON;
                     parentBone = skeleton.bones[parsedBone.parentBoneIndex];
                 }
                 var bone = new BABYLON.Bone(parsedBone.name, skeleton, parentBone, BABYLON.Matrix.FromArray(parsedBone.matrix));
+                if (parsedBone.length) {
+                    bone.length = parsedBone.length;
+                }
                 if (parsedBone.animation) {
                     bone.animations.push(BABYLON.Animation.Parse(parsedBone.animation));
                 }

+ 17 - 9
src/Bones/babylon.skeleton.ts

@@ -88,7 +88,7 @@
                     bone.getWorldMatrix().copyFrom(bone.getLocalMatrix());
                 }
 
-                bone.getInvertedAbsoluteTransform().multiplyToArray(bone.getWorldMatrix(), this._transformMatrices, index * 16);                
+                bone.getInvertedAbsoluteTransform().multiplyToArray(bone.getWorldMatrix(), this._transformMatrices, index * 16);
             }
 
             this._identity.copyToArray(this._transformMatrices, this.bones.length * 16);
@@ -122,7 +122,7 @@
                     parentBone = result.bones[parentIndex];
                 }
 
-                var bone = new Bone(source.name, result, parentBone, source.getBaseMatrix());
+                var bone = new Bone(source.name, result, parentBone, source.getBaseMatrix().clone());
                 Tools.DeepCopy(source.animations, bone.animations);
             }
 
@@ -156,32 +156,40 @@
 
                 serializationObject.bones.push(serializedBone);
 
+                if (bone.length) {
+                    serializedBone.length = bone.length;
+                }
+
                 if (bone.animations && bone.animations.length > 0) {
                     serializedBone.animation = bone.animations[0].serialize();
                 }
             }
             return serializationObject;
         }
-        
-        public static Parse(parsedSkeleton: any, scene: Scene) : Skeleton {
+
+        public static Parse(parsedSkeleton: any, scene: Scene): Skeleton {
             var skeleton = new Skeleton(parsedSkeleton.name, parsedSkeleton.id, scene);
 
             for (var index = 0; index < parsedSkeleton.bones.length; index++) {
                 var parsedBone = parsedSkeleton.bones[index];
-    
+
                 var parentBone = null;
                 if (parsedBone.parentBoneIndex > -1) {
                     parentBone = skeleton.bones[parsedBone.parentBoneIndex];
                 }
-    
+
                 var bone = new Bone(parsedBone.name, skeleton, parentBone, Matrix.FromArray(parsedBone.matrix));
-    
+
+                if (parsedBone.length) {
+                    bone.length = parsedBone.length;
+                }
+
                 if (parsedBone.animation) {
                     bone.animations.push(Animation.Parse(parsedBone.animation));
                 }
             }
-    
+
             return skeleton;
         }
     }
-}
+}

+ 1 - 1
src/Cameras/babylon.arcRotateCamera.js

@@ -102,7 +102,7 @@ var BABYLON;
             configurable: true
         });
         ArcRotateCamera.prototype._getTargetPosition = function () {
-            return this.target.position || this.target;
+            return this.target.getAbsolutePosition ? this.target.getAbsolutePosition() : this.target;
         };
         // Cache
         ArcRotateCamera.prototype._initCache = function () {

+ 1 - 1
src/Cameras/babylon.arcRotateCamera.ts

@@ -89,7 +89,7 @@
         }
 
         public _getTargetPosition(): Vector3 {
-            return this.target.position || this.target;
+            return this.target.getAbsolutePosition ? this.target.getAbsolutePosition() : this.target; 
         }
 
         // Cache

+ 1 - 1
src/Lights/Shadows/babylon.shadowGenerator.js

@@ -61,7 +61,7 @@ var BABYLON;
                 if (batch.mustReturn) {
                     return;
                 }
-                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null);
+                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
                 if (_this.isReady(subMesh, hardwareInstancedRendering)) {
                     engine.enableEffect(_this._effect);
                     mesh._bind(subMesh, _this._effect, BABYLON.Material.TriangleFillMode);

+ 1 - 1
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -184,7 +184,7 @@
                     return;
                 }
 
-                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null);
+                var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);
 
                 if (this.isReady(subMesh, hardwareInstancedRendering)) {
                     engine.enableEffect(this._effect);

+ 0 - 1
src/Lights/babylon.light.ts

@@ -73,7 +73,6 @@
                 return false;
             }
 
-
             if (this.excludeWithLayerMask !== 0 && this.excludeWithLayerMask & mesh.layerMask) {
                 return false;
             }

+ 10 - 1
src/Loading/Plugins/babylon.babylonFileLoader.js

@@ -321,17 +321,26 @@ var BABYLON;
                     }
                 }
                 // Sounds
+                var loadedSounds = [];
+                var loadedSound;
                 if (BABYLON.AudioEngine && parsedData.sounds) {
                     for (index = 0, cache = parsedData.sounds.length; index < cache; index++) {
                         var parsedSound = parsedData.sounds[index];
                         if (BABYLON.Engine.audioEngine.canUseWebAudio) {
-                            BABYLON.Sound.Parse(parsedSound, scene, rootUrl);
+                            if (!loadedSounds[parsedSound.name]) {
+                                loadedSound = BABYLON.Sound.Parse(parsedSound, scene, rootUrl);
+                                loadedSounds[loadedSound.name] = loadedSound;
+                            }
+                            else {
+                                BABYLON.Sound.Parse(parsedSound, scene, rootUrl, loadedSounds[parsedSound.name]);
+                            }
                         }
                         else {
                             var emptySound = new BABYLON.Sound(parsedSound.name, null, scene);
                         }
                     }
                 }
+                loadedSounds = [];
                 // Connect parents & children and parse actions
                 for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                     var mesh = scene.meshes[index];

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

@@ -352,17 +352,27 @@
             }
 
             // Sounds
+            var loadedSounds: Sound[] = [];
+            var loadedSound: Sound;
             if (AudioEngine && parsedData.sounds) {
                 for (index = 0, cache = parsedData.sounds.length; index < cache; index++) {
                     var parsedSound = parsedData.sounds[index];
                     if (Engine.audioEngine.canUseWebAudio) {
-                        Sound.Parse(parsedSound, scene, rootUrl);
+                        if (!loadedSounds[parsedSound.name]) {
+                            loadedSound = Sound.Parse(parsedSound, scene, rootUrl);
+                            loadedSounds[loadedSound.name] = loadedSound;
+                        }
+                        else {
+                            Sound.Parse(parsedSound, scene, rootUrl, loadedSounds[parsedSound.name]);
+                        }
                     } else {
                         var emptySound = new Sound(parsedSound.name, null, scene);
                     }
                 }
             }
 
+            loadedSounds = [];
+
             // Connect parents & children and parse actions
             for (index = 0, cache = scene.meshes.length; index < cache; index++) {
                 var mesh = scene.meshes[index];

+ 1 - 0
src/Materials/Textures/babylon.renderTargetTexture.js

@@ -158,6 +158,7 @@ var BABYLON;
             if (this.isCube) {
                 for (var face = 0; face < 6; face++) {
                     this.renderToTarget(face, currentRenderList, useCameraPostProcess, dumpForDebug);
+                    scene.incrementRenderId();
                 }
             }
             else {

+ 1 - 0
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -175,6 +175,7 @@
             if (this.isCube) {
                 for (var face = 0; face < 6; face++) {
                     this.renderToTarget(face, currentRenderList, useCameraPostProcess, dumpForDebug);
+                    scene.incrementRenderId();
                 }
             } else {
                 this.renderToTarget(0, currentRenderList, useCameraPostProcess, dumpForDebug);

+ 5 - 5
src/Materials/babylon.effect.js

@@ -134,7 +134,7 @@ var BABYLON;
                 return;
             }
             var vertexShaderUrl;
-            if (vertex[0] === "." || vertex[0] === "/") {
+            if (vertex[0] === "." || vertex[0] === "/" || vertex.indexOf("http") > -1) {
                 vertexShaderUrl = vertex;
             }
             else {
@@ -160,7 +160,7 @@ var BABYLON;
                 return;
             }
             var fragmentShaderUrl;
-            if (fragment[0] === "." || fragment[0] === "/") {
+            if (fragment[0] === "." || fragment[0] === "/" || fragment.indexOf("http") > -1) {
                 fragmentShaderUrl = fragment;
             }
             else {
@@ -305,9 +305,9 @@ var BABYLON;
             return this;
         };
         Effect.prototype.setMatrix = function (uniformName, matrix) {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName].equals(matrix))
-                return this;
-            this._cacheMatrix(uniformName, matrix);
+            //if (this._valueCache[uniformName] && this._valueCache[uniformName].equals(matrix))
+            //    return this;
+            // this._cacheMatrix(uniformName, matrix);
             this._engine.setMatrix(this.getUniform(uniformName), matrix);
             return this;
         };

+ 16 - 16
src/Materials/babylon.effect.ts

@@ -5,8 +5,8 @@
         private _currentRank = 32;
         private _maxRank = -1;
 
-        private _mesh : AbstractMesh;
-        private _meshRank : number;
+        private _mesh: AbstractMesh;
+        private _meshRank: number;
 
         public addFallback(rank: number, define: string): void {
             if (!this._defines[rank]) {
@@ -24,14 +24,14 @@
             this._defines[rank].push(define);
         }
 
-            public addCPUSkinningFallback(rank: number, mesh : BABYLON.AbstractMesh){
-                this._meshRank = rank;
-                this._mesh = mesh;
-    
-                if (rank > this._maxRank) {
-                    this._maxRank = rank;
-                }
+        public addCPUSkinningFallback(rank: number, mesh: BABYLON.AbstractMesh) {
+            this._meshRank = rank;
+            this._mesh = mesh;
+
+            if (rank > this._maxRank) {
+                this._maxRank = rank;
             }
+        }
 
         public get isMoreFallbacks(): boolean {
             return this._currentRank <= this._maxRank;
@@ -45,7 +45,7 @@
                 currentDefines = currentDefines.replace("#define " + currentFallbacks[index], "");
             }
 
-            if (this._mesh && this._currentRank === this._meshRank){
+            if (this._mesh && this._currentRank === this._meshRank) {
                 this._mesh.computeBonesUsingShaders = false;
                 currentDefines = currentDefines.replace("#define NUM_BONE_INFLUENCERS " + this._mesh.numBoneInfluencers, "#define NUM_BONE_INFLUENCERS 0");
                 Tools.Log("Falling back to CPU skinning for " + this._mesh.name);
@@ -178,7 +178,7 @@
 
             var vertexShaderUrl;
 
-            if (vertex[0] === "." || vertex[0] === "/") {
+            if (vertex[0] === "." || vertex[0] === "/" || vertex.indexOf("http") > -1) {
                 vertexShaderUrl = vertex;
             } else {
                 vertexShaderUrl = Engine.ShadersRepository + vertex;
@@ -209,7 +209,7 @@
 
             var fragmentShaderUrl;
 
-            if (fragment[0] === "." || fragment[0] === "/") {
+            if (fragment[0] === "." || fragment[0] === "/" || fragment.indexOf("http") > -1) {
                 fragmentShaderUrl = fragment;
             } else {
                 fragmentShaderUrl = Engine.ShadersRepository + fragment;
@@ -380,10 +380,10 @@
         }
 
         public setMatrix(uniformName: string, matrix: Matrix): Effect {
-            if (this._valueCache[uniformName] && this._valueCache[uniformName].equals(matrix))
-                return this;
+            //if (this._valueCache[uniformName] && this._valueCache[uniformName].equals(matrix))
+            //    return this;
 
-            this._cacheMatrix(uniformName, matrix);
+           // this._cacheMatrix(uniformName, matrix);
             this._engine.setMatrix(this.getUniform(uniformName), matrix);
 
             return this;
@@ -508,4 +508,4 @@
         // Statics
         public static ShadersStore = {};
     }
-} 
+} 

+ 13 - 0
src/Materials/babylon.material.js

@@ -132,6 +132,19 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Material.prototype, "isFrozen", {
+            get: function () {
+                return this.checkReadyOnlyOnce;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Material.prototype.freeze = function () {
+            this.checkReadyOnlyOnce = true;
+        };
+        Material.prototype.unfreeze = function () {
+            this.checkReadyOnlyOnce = false;
+        };
         Material.prototype.isReady = function (mesh, useInstances) {
             return true;
         };

+ 12 - 0
src/Materials/babylon.material.ts

@@ -140,6 +140,18 @@
             }
         }
 
+        public get isFrozen(): boolean {
+            return this.checkReadyOnlyOnce;
+        }
+
+        public freeze(): void {
+            this.checkReadyOnlyOnce = true;
+        }
+
+        public unfreeze(): void {
+            this.checkReadyOnlyOnce = false;
+        }
+
         public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
             return true;
         }

+ 23 - 21
src/Materials/babylon.standardMaterial.js

@@ -141,7 +141,7 @@ var BABYLON;
             this.useEmissiveAsIllumination = false;
             this.linkEmissiveWithDiffuse = false;
             this.useReflectionFresnelFromSpecular = false;
-            this.useSpecularOverAlpha = true;
+            this.useSpecularOverAlpha = false;
             this.disableLighting = false;
             this.roughness = 0;
             this.useLightmapAsShadowmap = false;
@@ -322,7 +322,7 @@ var BABYLON;
             }
         };
         StandardMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
+            if (this.isFrozen) {
                 if (this._wasPreviouslyReady) {
                     return true;
                 }
@@ -680,12 +680,12 @@ var BABYLON;
             var scene = this.getScene();
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
             // Bones
             if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
                 this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
             }
             if (scene.getCachedMaterial() !== this) {
+                this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
                 if (StandardMaterial.FresnelEnabled) {
                     // Fresnel
                     if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
@@ -770,24 +770,26 @@ var BABYLON;
                 }
                 this._effect.setColor3("vEmissiveColor", this.emissiveColor);
             }
-            // Diffuse
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-            // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                StandardMaterial.BindLights(scene, mesh, this._effect, this._defines);
-            }
-            // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE || this.reflectionTexture) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
-            }
-            // Fog
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
-                this._effect.setColor3("vFogColor", scene.fogColor);
-            }
-            // Log. depth
-            if (this._defines.LOGARITHMICDEPTH) {
-                this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
+            if (scene.getCachedMaterial() !== this || !this.isFrozen) {
+                // Diffuse
+                this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+                // Lights
+                if (scene.lightsEnabled && !this.disableLighting) {
+                    StandardMaterial.BindLights(scene, mesh, this._effect, this._defines);
+                }
+                // View
+                if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE || this.reflectionTexture) {
+                    this._effect.setMatrix("view", scene.getViewMatrix());
+                }
+                // Fog
+                if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
+                    this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+                    this._effect.setColor3("vFogColor", scene.fogColor);
+                }
+                // Log. depth
+                if (this._defines.LOGARITHMICDEPTH) {
+                    this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
+                }
             }
             _super.prototype.bind.call(this, world, mesh);
         };

+ 23 - 21
src/Materials/babylon.standardMaterial.ts

@@ -147,7 +147,7 @@
         public useEmissiveAsIllumination = false;
         public linkEmissiveWithDiffuse = false;
         public useReflectionFresnelFromSpecular = false;
-        public useSpecularOverAlpha = true;
+        public useSpecularOverAlpha = false;
         public disableLighting = false;
 
         public roughness = 0;
@@ -376,7 +376,7 @@
         }
 
         public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
-            if (this.checkReadyOnlyOnce) {
+            if (this.isFrozen) {
                 if (this._wasPreviouslyReady) {
                     return true;
                 }
@@ -806,7 +806,6 @@
 
             // Matrices        
             this.bindOnlyWorldMatrix(world);
-            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
             // Bones
             if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
@@ -814,6 +813,7 @@
             }
 
             if (scene.getCachedMaterial() !== this) {
+                this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
 
                 if (StandardMaterial.FresnelEnabled) {
                     // Fresnel
@@ -923,28 +923,30 @@
                 this._effect.setColor3("vEmissiveColor", this.emissiveColor);
             }
             
-            // Diffuse
-            this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
+            if (scene.getCachedMaterial() !== this || !this.isFrozen) {
+                // Diffuse
+                this._effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
 
-            // Lights
-            if (scene.lightsEnabled && !this.disableLighting) {
-                StandardMaterial.BindLights(scene, mesh, this._effect, this._defines);
-            }
+                // Lights
+                if (scene.lightsEnabled && !this.disableLighting) {
+                    StandardMaterial.BindLights(scene, mesh, this._effect, this._defines);
+                }
 
-            // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE || this.reflectionTexture) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
-            }
+                // View
+                if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE || this.reflectionTexture) {
+                    this._effect.setMatrix("view", scene.getViewMatrix());
+                }
 
-            // Fog
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
-                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
-                this._effect.setColor3("vFogColor", scene.fogColor);
-            }
+                // Fog
+                if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                    this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+                    this._effect.setColor3("vFogColor", scene.fogColor);
+                }
 
-            // Log. depth
-            if (this._defines.LOGARITHMICDEPTH) {
-                this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
+                // Log. depth
+                if (this._defines.LOGARITHMICDEPTH) {
+                    this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
+                }
             }
 
             super.bind(world, mesh);

+ 5 - 1
src/Mesh/babylon.abstractMesh.js

@@ -77,6 +77,7 @@ var BABYLON;
             this._intersectionsInProgress = new Array();
             this._onAfterWorldMatrixUpdate = new Array();
             this._isWorldMatrixFrozen = false;
+            this._unIndexed = false;
             this._onCollisionPositionChange = function (collisionId, newPosition, collidedMesh) {
                 if (collidedMesh === void 0) { collidedMesh = null; }
                 //TODO move this to the collision coordinator!
@@ -403,7 +404,9 @@ var BABYLON;
             }
             for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
                 var subMesh = this.subMeshes[subIndex];
-                subMesh.updateBoundingInfo(matrix);
+                if (!subMesh.IsGlobal) {
+                    subMesh.updateBoundingInfo(matrix);
+                }
             }
         };
         AbstractMesh.prototype.computeWorldMatrix = function (force) {
@@ -411,6 +414,7 @@ var BABYLON;
                 return this._worldMatrix;
             }
             if (!force && (this._currentRenderId === this.getScene().getRenderId() || this.isSynchronized(true))) {
+                this._currentRenderId = this.getScene().getRenderId();
                 return this._worldMatrix;
             }
             this._cache.position.copyFrom(this.position);

+ 7 - 2
src/Mesh/babylon.abstractMesh.ts

@@ -74,7 +74,7 @@
         public _physicsMass: number;
         public _physicsFriction: number;
         public _physicRestitution: number;
-        public onPhysicsCollide: (collidedMesh: AbstractMesh) => void; 
+        public onPhysicsCollide: (collidedMesh: AbstractMesh, contact: any) => void; 
 
         // Collisions
         private _checkCollisions = false;
@@ -127,6 +127,8 @@
 
         private _isWorldMatrixFrozen = false;
 
+        public _unIndexed = false;
+
         // Loading properties
         public _waitingActions: any;
         public _waitingFreezeWorldMatrix: boolean;
@@ -439,7 +441,9 @@
             for (var subIndex = 0; subIndex < this.subMeshes.length; subIndex++) {
                 var subMesh = this.subMeshes[subIndex];
 
-                subMesh.updateBoundingInfo(matrix);
+                if (!subMesh.IsGlobal) {
+                    subMesh.updateBoundingInfo(matrix);
+                }
             }
         }
 
@@ -449,6 +453,7 @@
             }
 
             if (!force && (this._currentRenderId === this.getScene().getRenderId() || this.isSynchronized(true))) {
+                this._currentRenderId = this.getScene().getRenderId();
                 return this._worldMatrix;
             }
 

+ 1 - 0
src/Mesh/babylon.geometry.ts

@@ -19,6 +19,7 @@
         private _indexBuffer;
         public _boundingInfo: BoundingInfo;
         public _delayLoadingFunction: (any: any, geometry: Geometry) => void;
+        public _softwareSkinningRenderId: number;
 
         constructor(id: string, scene: Scene, vertexData?: VertexData, updatable?: boolean, mesh?: Mesh) {
             this.id = id;

+ 89 - 13
src/Mesh/babylon.mesh.js

@@ -460,17 +460,22 @@ var BABYLON;
             var engine = this.getScene().getEngine();
             // Wireframe
             var indexToBind;
-            switch (fillMode) {
-                case BABYLON.Material.PointFillMode:
-                    indexToBind = null;
-                    break;
-                case BABYLON.Material.WireFrameFillMode:
-                    indexToBind = subMesh.getLinesIndexBuffer(this.getIndices(), engine);
-                    break;
-                default:
-                case BABYLON.Material.TriangleFillMode:
-                    indexToBind = this._geometry.getIndexBuffer();
-                    break;
+            if (this._unIndexed) {
+                indexToBind = null;
+            }
+            else {
+                switch (fillMode) {
+                    case BABYLON.Material.PointFillMode:
+                        indexToBind = null;
+                        break;
+                    case BABYLON.Material.WireFrameFillMode:
+                        indexToBind = subMesh.getLinesIndexBuffer(this.getIndices(), engine);
+                        break;
+                    default:
+                    case BABYLON.Material.TriangleFillMode:
+                        indexToBind = this._unIndexed ? null : this._geometry.getIndexBuffer();
+                        break;
+                }
             }
             // VBOs
             engine.bindMultiBuffers(this._geometry.getVertexBuffers(), indexToBind, effect);
@@ -486,10 +491,20 @@ var BABYLON;
                     engine.drawPointClouds(subMesh.verticesStart, subMesh.verticesCount, instancesCount);
                     break;
                 case BABYLON.Material.WireFrameFillMode:
-                    engine.draw(false, 0, subMesh.linesIndexCount, instancesCount);
+                    if (this._unIndexed) {
+                        engine.drawUnIndexed(false, subMesh.verticesStart, subMesh.verticesCount, instancesCount);
+                    }
+                    else {
+                        engine.draw(false, 0, subMesh.linesIndexCount, instancesCount);
+                    }
                     break;
                 default:
-                    engine.draw(true, subMesh.indexStart, subMesh.indexCount, instancesCount);
+                    if (this._unIndexed) {
+                        engine.drawUnIndexed(true, subMesh.verticesStart, subMesh.verticesCount, instancesCount);
+                    }
+                    else {
+                        engine.draw(true, subMesh.indexStart, subMesh.indexCount, instancesCount);
+                    }
             }
         };
         Mesh.prototype.registerBeforeRender = function (func) {
@@ -972,6 +987,60 @@ var BABYLON;
             }
             this.synchronizeInstances();
         };
+        Mesh.prototype.convertToUnIndexedMesh = function () {
+            /// <summary>Remove indices by unfolding faces into buffers</summary>
+            /// <summary>Warning: This implies adding vertices to the mesh in order to get exactly 3 vertices per face</summary>
+            var kinds = this.getVerticesDataKinds();
+            var vbs = [];
+            var data = [];
+            var newdata = [];
+            var updatableNormals = false;
+            var kindIndex;
+            var kind;
+            for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
+                kind = kinds[kindIndex];
+                var vertexBuffer = this.getVertexBuffer(kind);
+                vbs[kind] = vertexBuffer;
+                data[kind] = vbs[kind].getData();
+                newdata[kind] = [];
+            }
+            // Save previous submeshes
+            var previousSubmeshes = this.subMeshes.slice(0);
+            var indices = this.getIndices();
+            var totalIndices = this.getTotalIndices();
+            // Generating unique vertices per face
+            var index;
+            for (index = 0; index < totalIndices; index++) {
+                var vertexIndex = indices[index];
+                for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
+                    kind = kinds[kindIndex];
+                    var stride = vbs[kind].getStrideSize();
+                    for (var offset = 0; offset < stride; offset++) {
+                        newdata[kind].push(data[kind][vertexIndex * stride + offset]);
+                    }
+                }
+            }
+            // Updating indices
+            for (index = 0; index < totalIndices; index += 3) {
+                indices[index] = index;
+                indices[index + 1] = index + 1;
+                indices[index + 2] = index + 2;
+            }
+            this.setIndices(indices);
+            // Updating vertex buffers
+            for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
+                kind = kinds[kindIndex];
+                this.setVerticesData(kind, newdata[kind], vbs[kind].isUpdatable());
+            }
+            // Updating submeshes
+            this.releaseSubMeshes();
+            for (var submeshIndex = 0; submeshIndex < previousSubmeshes.length; submeshIndex++) {
+                var previousOne = previousSubmeshes[submeshIndex];
+                var subMesh = new BABYLON.SubMesh(previousOne.materialIndex, previousOne.indexStart, previousOne.indexCount, previousOne.indexStart, previousOne.indexCount, this);
+            }
+            this._unIndexed = true;
+            this.synchronizeInstances();
+        };
         // will inverse faces orientations, and invert normals too if specified
         Mesh.prototype.flipFaces = function (flipNormals) {
             if (flipNormals === void 0) { flipNormals = false; }
@@ -1470,6 +1539,13 @@ var BABYLON;
          * @param {skeleton} skeleton to apply
          */
         Mesh.prototype.applySkeleton = function (skeleton) {
+            if (!this.geometry) {
+                return;
+            }
+            if (this.geometry._softwareSkinningRenderId == this.getScene().getRenderId()) {
+                return;
+            }
+            this.geometry._softwareSkinningRenderId = this.getScene().getRenderId();
             if (!this.isVerticesDataPresent(BABYLON.VertexBuffer.PositionKind)) {
                 return this;
             }

+ 102 - 13
src/Mesh/babylon.mesh.ts

@@ -505,17 +505,21 @@
             // Wireframe
             var indexToBind;
 
-            switch (fillMode) {
-                case Material.PointFillMode:
-                    indexToBind = null;
-                    break;
-                case Material.WireFrameFillMode:
-                    indexToBind = subMesh.getLinesIndexBuffer(this.getIndices(), engine);
-                    break;
-                default:
-                case Material.TriangleFillMode:
-                    indexToBind = this._geometry.getIndexBuffer();
-                    break;
+            if (this._unIndexed) {
+                indexToBind = null;
+            } else {
+                switch (fillMode) {
+                    case Material.PointFillMode:
+                        indexToBind = null;
+                        break;
+                    case Material.WireFrameFillMode:
+                        indexToBind = subMesh.getLinesIndexBuffer(this.getIndices(), engine);
+                        break;
+                    default:
+                    case Material.TriangleFillMode:
+                        indexToBind = this._unIndexed ? null : this._geometry.getIndexBuffer();
+                        break;
+                }
             }
 
             // VBOs
@@ -535,11 +539,19 @@
                     engine.drawPointClouds(subMesh.verticesStart, subMesh.verticesCount, instancesCount);
                     break;
                 case Material.WireFrameFillMode:
-                    engine.draw(false, 0, subMesh.linesIndexCount, instancesCount);
+                    if (this._unIndexed) {
+                        engine.drawUnIndexed(false, subMesh.verticesStart, subMesh.verticesCount, instancesCount);
+                    } else {
+                        engine.draw(false, 0, subMesh.linesIndexCount, instancesCount);
+                    }
                     break;
 
                 default:
-                    engine.draw(true, subMesh.indexStart, subMesh.indexCount, instancesCount);
+                    if (this._unIndexed) {
+                        engine.drawUnIndexed(true, subMesh.verticesStart, subMesh.verticesCount, instancesCount);
+                    } else {
+                        engine.draw(true, subMesh.indexStart, subMesh.indexCount, instancesCount);
+                    }
             }
         }
 
@@ -1148,6 +1160,73 @@
             this.synchronizeInstances();
         }
 
+        public convertToUnIndexedMesh(): void {
+            /// <summary>Remove indices by unfolding faces into buffers</summary>
+            /// <summary>Warning: This implies adding vertices to the mesh in order to get exactly 3 vertices per face</summary>
+
+            var kinds = this.getVerticesDataKinds();
+            var vbs = [];
+            var data = [];
+            var newdata = [];
+            var updatableNormals = false;
+            var kindIndex: number;
+            var kind: string;
+            for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
+                kind = kinds[kindIndex];
+                var vertexBuffer = this.getVertexBuffer(kind);
+                vbs[kind] = vertexBuffer;
+                data[kind] = vbs[kind].getData();
+                newdata[kind] = [];
+            }
+
+            // Save previous submeshes
+            var previousSubmeshes = this.subMeshes.slice(0);
+
+            var indices = this.getIndices();
+            var totalIndices = this.getTotalIndices();
+
+            // Generating unique vertices per face
+            var index: number;
+            for (index = 0; index < totalIndices; index++) {
+                var vertexIndex = indices[index];
+
+                for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
+                    kind = kinds[kindIndex];
+                    var stride = vbs[kind].getStrideSize();
+
+                    for (var offset = 0; offset < stride; offset++) {
+                        newdata[kind].push(data[kind][vertexIndex * stride + offset]);
+                    }
+                }
+            }
+
+            // Updating indices
+            for (index = 0; index < totalIndices; index += 3) {
+                indices[index] = index;
+                indices[index + 1] = index + 1;
+                indices[index + 2] = index + 2;
+            }
+
+            this.setIndices(indices);
+
+            // Updating vertex buffers
+            for (kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
+                kind = kinds[kindIndex];
+                this.setVerticesData(kind, newdata[kind], vbs[kind].isUpdatable());
+            }
+
+            // Updating submeshes
+            this.releaseSubMeshes();
+            for (var submeshIndex = 0; submeshIndex < previousSubmeshes.length; submeshIndex++) {
+                var previousOne = previousSubmeshes[submeshIndex];
+                var subMesh = new SubMesh(previousOne.materialIndex, previousOne.indexStart, previousOne.indexCount, previousOne.indexStart, previousOne.indexCount, this);
+            }
+
+            this._unIndexed = true;
+
+            this.synchronizeInstances();
+        }
+
         // will inverse faces orientations, and invert normals too if specified
         public flipFaces(flipNormals: boolean = false): void {
             var vertex_data = VertexData.ExtractFromMesh(this);
@@ -1737,6 +1816,16 @@
          * @param {skeleton} skeleton to apply
          */
         public applySkeleton(skeleton: Skeleton): Mesh {
+            if (!this.geometry) {
+                return;
+            }
+
+            if (this.geometry._softwareSkinningRenderId == this.getScene().getRenderId()) {
+                return;
+            }
+
+            this.geometry._softwareSkinningRenderId = this.getScene().getRenderId();
+
             if (!this.isVerticesDataPresent(VertexBuffer.PositionKind)) {
                 return this;
             }

+ 21 - 6
src/Mesh/babylon.subMesh.js

@@ -19,7 +19,17 @@ var BABYLON;
                 mesh.computeWorldMatrix(true);
             }
         }
+        Object.defineProperty(SubMesh.prototype, "IsGlobal", {
+            get: function () {
+                return (this.verticesStart === 0 && this.verticesCount == this._mesh.getTotalVertices());
+            },
+            enumerable: true,
+            configurable: true
+        });
         SubMesh.prototype.getBoundingInfo = function () {
+            if (this.IsGlobal) {
+                return this._mesh.getBoundingInfo();
+            }
             return this._boundingInfo;
         };
         SubMesh.prototype.getMesh = function () {
@@ -41,6 +51,9 @@ var BABYLON;
         };
         // Methods
         SubMesh.prototype.refreshBoundingInfo = function () {
+            if (this.IsGlobal) {
+                return;
+            }
             var data = this._renderingMesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
             if (!data) {
                 this._boundingInfo = this._mesh._boundingInfo;
@@ -59,16 +72,16 @@ var BABYLON;
             this._boundingInfo = new BABYLON.BoundingInfo(extend.minimum, extend.maximum);
         };
         SubMesh.prototype._checkCollision = function (collider) {
-            return this._boundingInfo._checkCollision(collider);
+            return this.getBoundingInfo()._checkCollision(collider);
         };
         SubMesh.prototype.updateBoundingInfo = function (world) {
-            if (!this._boundingInfo) {
+            if (!this.getBoundingInfo()) {
                 this.refreshBoundingInfo();
             }
-            this._boundingInfo._update(world);
+            this.getBoundingInfo()._update(world);
         };
         SubMesh.prototype.isInFrustum = function (frustumPlanes) {
-            return this._boundingInfo.isInFrustum(frustumPlanes);
+            return this.getBoundingInfo().isInFrustum(frustumPlanes);
         };
         SubMesh.prototype.render = function (enableAlphaMode) {
             this._renderingMesh.render(this, enableAlphaMode);
@@ -85,7 +98,7 @@ var BABYLON;
             return this._linesIndexBuffer;
         };
         SubMesh.prototype.canIntersects = function (ray) {
-            return ray.intersectsBox(this._boundingInfo.boundingBox);
+            return ray.intersectsBox(this.getBoundingInfo().boundingBox);
         };
         SubMesh.prototype.intersects = function (ray, positions, indices, fastCheck) {
             var intersectInfo = null;
@@ -113,7 +126,9 @@ var BABYLON;
         // Clone    
         SubMesh.prototype.clone = function (newMesh, newRenderingMesh) {
             var result = new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh, false);
-            result._boundingInfo = new BABYLON.BoundingInfo(this._boundingInfo.minimum, this._boundingInfo.maximum);
+            if (!this.IsGlobal) {
+                result._boundingInfo = new BABYLON.BoundingInfo(this.getBoundingInfo().minimum, this.getBoundingInfo().maximum);
+            }
             return result;
         };
         // Dispose

+ 19 - 6
src/Mesh/babylon.subMesh.ts

@@ -30,7 +30,15 @@
             }
         }
 
+        public get IsGlobal(): boolean {
+            return (this.verticesStart === 0 && this.verticesCount == this._mesh.getTotalVertices());
+        }
+
         public getBoundingInfo(): BoundingInfo {
+            if (this.IsGlobal) {
+                return this._mesh.getBoundingInfo();
+            }
+
             return this._boundingInfo;
         }
 
@@ -59,6 +67,9 @@
 
         // Methods
         public refreshBoundingInfo(): void {
+            if (this.IsGlobal) {
+                return;
+            }
             var data = this._renderingMesh.getVerticesData(VertexBuffer.PositionKind);
 
             if (!data) {
@@ -80,18 +91,18 @@
         }
 
         public _checkCollision(collider: Collider): boolean {
-            return this._boundingInfo._checkCollision(collider);
+            return this.getBoundingInfo()._checkCollision(collider);
         }
 
         public updateBoundingInfo(world: Matrix): void {
-            if (!this._boundingInfo) {
+            if (!this.getBoundingInfo()) {
                 this.refreshBoundingInfo();
             }
-            this._boundingInfo._update(world);
+            this.getBoundingInfo()._update(world);
         }
 
         public isInFrustum(frustumPlanes: Plane[]): boolean {
-            return this._boundingInfo.isInFrustum(frustumPlanes);
+            return this.getBoundingInfo().isInFrustum(frustumPlanes);
         }
 
         public render(enableAlphaMode: boolean): void {
@@ -115,7 +126,7 @@
         }
 
         public canIntersects(ray: Ray): boolean {
-            return ray.intersectsBox(this._boundingInfo.boundingBox);
+            return ray.intersectsBox(this.getBoundingInfo().boundingBox);
         }
 
         public intersects(ray: Ray, positions: Vector3[], indices: number[] | Int32Array, fastCheck?: boolean): IntersectionInfo {
@@ -152,7 +163,9 @@
         public clone(newMesh: AbstractMesh, newRenderingMesh?: Mesh): SubMesh {
             var result = new SubMesh(this.materialIndex, this.verticesStart, this.verticesCount, this.indexStart, this.indexCount, newMesh, newRenderingMesh, false);
 
-            result._boundingInfo = new BoundingInfo(this._boundingInfo.minimum, this._boundingInfo.maximum);
+            if (!this.IsGlobal) {
+                result._boundingInfo = new BoundingInfo(this.getBoundingInfo().minimum, this.getBoundingInfo().maximum);
+            }
 
             return result;
         }

+ 1 - 1
src/Particles/babylon.solidParticleSystem.js

@@ -88,7 +88,7 @@ var BABYLON;
             if (this._colors32) {
                 vertexData.set(this._colors32, BABYLON.VertexBuffer.ColorKind);
             }
-            var mesh = new BABYLON.Mesh(name, this._scene);
+            var mesh = new BABYLON.Mesh(this.name, this._scene);
             vertexData.applyToMesh(mesh, this._updatable);
             this.mesh = mesh;
             this.mesh.isPickable = this._pickable;

+ 3 - 2
src/Particles/babylon.solidParticleSystem.ts

@@ -66,7 +66,7 @@ module BABYLON {
         private _w: number = 0.0;
 
 
-        constructor(name: string, scene: Scene, options?: { updatable?: boolean, isPickable?: boolean }) {
+        constructor(name: string, scene: Scene, options?: { updatable?: boolean; isPickable?: boolean }) {
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
@@ -104,7 +104,7 @@ module BABYLON {
             if (this._colors32) {
                 vertexData.set(this._colors32, VertexBuffer.ColorKind);
             }
-            var mesh = new Mesh(name, this._scene);
+            var mesh = new Mesh(this.name, this._scene);
             vertexData.applyToMesh(mesh, this._updatable);
             this.mesh = mesh;
             this.mesh.isPickable = this._pickable;
@@ -634,3 +634,4 @@ module BABYLON {
         }
     }
 }
+

+ 14 - 7
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -10,14 +10,13 @@ var BABYLON;
                     var registeredMesh = this._registeredMeshes[index];
                     if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
                         var body = registeredMesh.body;
-                        var center = mesh.getBoundingInfo().boundingBox.center;
-                        body.position.set(center.x, center.y, center.z);
+                        var center = mesh.getBoundingInfo().boundingBox.center.clone();
                         body.quaternion.copy(mesh.rotationQuaternion);
                         if (registeredMesh.deltaRotation) {
                             var tmpQ = new CANNON.Quaternion(-0.7071067811865475, 0, 0, 0.7071067811865475);
                             body.quaternion = body.quaternion.mult(tmpQ);
                         }
-                        if (registeredMesh.heightmap) {
+                        if (registeredMesh.type === CANNON.Shape.types.HEIGHTFIELD) {
                             //calculate the correct body position:
                             var rotationQuaternion = mesh.rotationQuaternion;
                             mesh.rotationQuaternion = new BABYLON.Quaternion();
@@ -33,13 +32,17 @@ var BABYLON;
                             mesh.computeWorldMatrix(true);
                             //calculate the translation
                             var translation = mesh.getBoundingInfo().boundingBox.center.subtract(center).subtract(mesh.position).negate();
-                            body.position = new CANNON.Vec3(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSize.y, translation.z);
+                            center.copyFromFloats(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSize.y, translation.z);
                             //add it inverted to the delta 
                             registeredMesh.delta = mesh.getBoundingInfo().boundingBox.center.subtract(center);
                             registeredMesh.delta.y += mesh.getBoundingInfo().boundingBox.extendSize.y;
                             mesh.setPivotMatrix(oldPivot);
                             mesh.computeWorldMatrix(true);
                         }
+                        else if (registeredMesh.type === CANNON.Shape.types.TRIMESH) {
+                            center.copyFromFloats(mesh.position.x, mesh.position.y, mesh.position.z);
+                        }
+                        body.position.set(center.x, center.y, center.z);
                         return;
                     }
                 }
@@ -74,7 +77,7 @@ var BABYLON;
                             //find the mesh that collided with the registered mesh
                             for (var idx = 0; idx < _this._registeredMeshes.length; idx++) {
                                 if (_this._registeredMeshes[idx].body == e.body) {
-                                    registeredMesh.mesh.onPhysicsCollide(_this._registeredMeshes[idx].mesh);
+                                    registeredMesh.mesh.onPhysicsCollide(_this._registeredMeshes[idx].mesh, e.contact);
                                 }
                             }
                         };
@@ -136,7 +139,8 @@ var BABYLON;
                 case BABYLON.PhysicsEngine.MeshImpostor:
                     var rawVerts = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
                     var rawFaces = mesh.getIndices();
-                    returnValue = this._createConvexPolyhedron(rawVerts, rawFaces, mesh);
+                    BABYLON.Tools.Warn("MeshImpostor only collides against spheres.");
+                    returnValue = new CANNON.Trimesh(rawVerts, rawFaces); //this._createConvexPolyhedron(rawVerts, rawFaces, mesh);
                     break;
                 case BABYLON.PhysicsEngine.HeightmapImpostor:
                     returnValue = this._createHeightmap(mesh);
@@ -274,10 +278,13 @@ var BABYLON;
                 mesh.setPivotMatrix(oldPivot);
                 mesh.computeWorldMatrix(true);
             }
+            else if (shape.type === CANNON.Shape.types.TRIMESH) {
+                deltaPosition = BABYLON.Vector3.Zero();
+            }
             //add the shape
             body.addShape(shape);
             this._world.add(body);
-            this._registeredMeshes.push({ mesh: mesh, body: body, material: material, delta: deltaPosition, deltaRotation: deltaRotation, heightmap: shape.type === CANNON.Shape.types.HEIGHTFIELD });
+            this._registeredMeshes.push({ mesh: mesh, body: body, material: material, delta: deltaPosition, deltaRotation: deltaRotation, type: shape.type });
             return body;
         };
         CannonJSPlugin.prototype.registerMeshesAsCompound = function (parts, options) {

+ 16 - 10
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -7,7 +7,7 @@
         material: any;
         delta: Vector3;
         deltaRotation: Quaternion;
-        heightmap: boolean;
+        type: any;
         collisionFunction?: (event: any) => void;
 
     }
@@ -57,7 +57,7 @@
                             //find the mesh that collided with the registered mesh
                             for (var idx = 0; idx < this._registeredMeshes.length; idx++) {
                                 if (this._registeredMeshes[idx].body == e.body) {
-                                    registeredMesh.mesh.onPhysicsCollide(this._registeredMeshes[idx].mesh);
+                                    registeredMesh.mesh.onPhysicsCollide(this._registeredMeshes[idx].mesh, e.contact);
                                 }
                             }
                         }
@@ -131,8 +131,8 @@
                 case PhysicsEngine.MeshImpostor:
                     var rawVerts = mesh.getVerticesData(VertexBuffer.PositionKind);
                     var rawFaces = mesh.getIndices();
-
-                    returnValue = this._createConvexPolyhedron(rawVerts, rawFaces, mesh);
+                    Tools.Warn("MeshImpostor only collides against spheres.");
+                    returnValue = new CANNON.Trimesh(rawVerts, rawFaces); //this._createConvexPolyhedron(rawVerts, rawFaces, mesh);
                     break;
                 case PhysicsEngine.HeightmapImpostor:
                     returnValue = this._createHeightmap(mesh);
@@ -312,6 +312,8 @@
 
                 mesh.setPivotMatrix(oldPivot);
                 mesh.computeWorldMatrix(true);
+            } else if (shape.type === CANNON.Shape.types.TRIMESH) {
+                deltaPosition = Vector3.Zero();
             }
             
             //add the shape
@@ -319,7 +321,7 @@
 
             this._world.add(body);
 
-            this._registeredMeshes.push({ mesh: mesh, body: body, material: material, delta: deltaPosition, deltaRotation: deltaRotation, heightmap: shape.type === CANNON.Shape.types.HEIGHTFIELD });
+            this._registeredMeshes.push({ mesh: mesh, body: body, material: material, delta: deltaPosition, deltaRotation: deltaRotation, type: shape.type });
 
             return body;
         }
@@ -396,8 +398,7 @@
                 if (registeredMesh.mesh === mesh || registeredMesh.mesh === mesh.parent) {
                     var body = registeredMesh.body;
 
-                    var center = mesh.getBoundingInfo().boundingBox.center;
-                    body.position.set(center.x, center.y, center.z);
+                    var center = mesh.getBoundingInfo().boundingBox.center.clone();
 
                     body.quaternion.copy(mesh.rotationQuaternion);
 
@@ -406,7 +407,7 @@
                         body.quaternion = body.quaternion.mult(tmpQ);
                     }
 
-                    if (registeredMesh.heightmap) {
+                    if (registeredMesh.type === CANNON.Shape.types.HEIGHTFIELD) {
                         //calculate the correct body position:
                         var rotationQuaternion = mesh.rotationQuaternion;
                         mesh.rotationQuaternion = new BABYLON.Quaternion();
@@ -428,14 +429,19 @@
                         //calculate the translation
                         var translation = mesh.getBoundingInfo().boundingBox.center.subtract(center).subtract(mesh.position).negate();
 
-                        body.position = new CANNON.Vec3(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSize.y, translation.z);
+                        center.copyFromFloats(translation.x, translation.y - mesh.getBoundingInfo().boundingBox.extendSize.y, translation.z);
                         //add it inverted to the delta 
                         registeredMesh.delta = mesh.getBoundingInfo().boundingBox.center.subtract(center);
                         registeredMesh.delta.y += mesh.getBoundingInfo().boundingBox.extendSize.y;
 
                         mesh.setPivotMatrix(oldPivot);
                         mesh.computeWorldMatrix(true);
+                    } else if (registeredMesh.type === CANNON.Shape.types.TRIMESH) {
+                        center.copyFromFloats(mesh.position.x, mesh.position.y, mesh.position.z);
                     }
+
+                    body.position.set(center.x, center.y, center.z);
+
                     return;
                 }
             }
@@ -487,4 +493,4 @@
             return null;
         }
     }
-}
+}

+ 1 - 1
src/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -318,7 +318,7 @@ var BABYLON;
                             //get the mesh and execute the callback
                             var otherMesh = mesh.getScene().getMeshByUniqueID(otherUniqueId);
                             if (otherMesh)
-                                mesh.onPhysicsCollide(otherMesh);
+                                mesh.onPhysicsCollide(otherMesh, contact);
                         }
                         contact = contact.next;
                     }

+ 1 - 1
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -402,7 +402,7 @@ module BABYLON {
                             //get the mesh and execute the callback
                             var otherMesh = mesh.getScene().getMeshByUniqueID(otherUniqueId);
                             if (otherMesh)
-                                mesh.onPhysicsCollide(otherMesh);
+                                mesh.onPhysicsCollide(otherMesh, contact); 
                         }
                         contact = contact.next;
                     }

+ 0 - 1
src/Shaders/default.fragment.fx

@@ -898,7 +898,6 @@ void main(void) {
 #endif
 #endif
 
-
 #ifdef OPACITY
 	vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);
 

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

@@ -556,6 +556,7 @@ var BABYLON;
             if (previousCamera) {
                 scene.activeCamera = previousCamera;
             }
+            camera.getProjectionMatrix(true); // Force cache refresh;
         };
         // XHR response validator for local file scenario
         Tools.ValidateXHRData = function (xhr, dataType) {

+ 6 - 3
src/Tools/babylon.tools.ts

@@ -147,7 +147,7 @@
                     enc4 = 64;
                 }
                 output += keyStr.charAt(enc1) + keyStr.charAt(enc2) +
-                keyStr.charAt(enc3) + keyStr.charAt(enc4);
+                    keyStr.charAt(enc3) + keyStr.charAt(enc4);
             }
 
             return "data:image/png;base64," + output;
@@ -540,7 +540,7 @@
             }
         }
 
-        public static DumpFramebuffer(width: number, height: number, engine: Engine, successCallback?: (data: String) => void): void {
+        public static DumpFramebuffer(width: number, height: number, engine: Engine, successCallback?: (data: string) => void): void {
             // Read the contents of the framebuffer
             var numberOfChannelsByLine = width * 4;
             var halfHeight = height / 2;
@@ -606,7 +606,7 @@
             }
         }
 
-        public static CreateScreenshot(engine: Engine, camera: Camera, size: any, successCallback?: (data: String) => void): void {
+        public static CreateScreenshot(engine: Engine, camera: Camera, size: any, successCallback?: (data: string) => void): void {
             var width: number;
             var height: number;
 
@@ -665,6 +665,8 @@
             if (previousCamera) {
                 scene.activeCamera = previousCamera;
             }
+
+            camera.getProjectionMatrix(true); // Force cache refresh;
         }
 
         // XHR response validator for local file scenario
@@ -1004,3 +1006,4 @@
     }
 } 
 
+

+ 11 - 1
src/babylon.engine.js

@@ -622,7 +622,7 @@ var BABYLON;
         });
         Object.defineProperty(Engine, "Version", {
             get: function () {
-                return "2.3.0-alpha";
+                return "2.3.0-beta";
             },
             enumerable: true,
             configurable: true
@@ -1066,6 +1066,16 @@ var BABYLON;
             }
             this._gl.drawArrays(this._gl.POINTS, verticesStart, verticesCount);
         };
+        Engine.prototype.drawUnIndexed = function (useTriangles, verticesStart, verticesCount, instancesCount) {
+            // Apply states
+            this.applyStates();
+            this._drawCalls++;
+            if (instancesCount) {
+                this._caps.instancedArrays.drawArraysInstancedANGLE(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount, instancesCount);
+                return;
+            }
+            this._gl.drawArrays(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount);
+        };
         // Shaders
         Engine.prototype._releaseEffect = function (effect) {
             if (this._compiledEffects[effect._key]) {

+ 14 - 1
src/babylon.engine.ts

@@ -484,7 +484,7 @@
         }
 
         public static get Version(): string {
-            return "2.3.0-alpha";
+            return "2.3.0-beta";
         }
 
         // Updatable statics so stick with vars here
@@ -1239,6 +1239,19 @@
             this._gl.drawArrays(this._gl.POINTS, verticesStart, verticesCount);
         }
 
+        public drawUnIndexed(useTriangles: boolean, verticesStart: number, verticesCount: number, instancesCount?: number): void {
+            // Apply states
+            this.applyStates();
+            this._drawCalls++;
+
+            if (instancesCount) {
+                this._caps.instancedArrays.drawArraysInstancedANGLE(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount, instancesCount);
+                return;
+            }
+
+            this._gl.drawArrays(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount);
+        }
+
         // Shaders
         public _releaseEffect(effect: Effect): void {
             if (this._compiledEffects[effect._key]) {

+ 12 - 4
src/babylon.scene.js

@@ -1265,7 +1265,7 @@ var BABYLON;
             }
             // Render targets
             var beforeRenderTargetDate = BABYLON.Tools.Now;
-            if (this.renderTargetsEnabled) {
+            if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
                 BABYLON.Tools.StartPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
                     var renderTarget = this._renderTargets.data[renderIndex];
@@ -1277,9 +1277,7 @@ var BABYLON;
                 }
                 BABYLON.Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 this._renderId++;
-            }
-            if (this._renderTargets.length > 0) {
-                engine.restoreDefaultFramebuffer();
+                engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
             this._renderTargetsDuration += BABYLON.Tools.Now - beforeRenderTargetDate;
             // Prepare Frame
@@ -1651,6 +1649,16 @@ var BABYLON;
             this._depthRenderer.dispose();
             this._depthRenderer = null;
         };
+        Scene.prototype.freezeMaterials = function () {
+            for (var i = 0; i < this.materials.length; i++) {
+                this.materials[i].freeze();
+            }
+        };
+        Scene.prototype.unfreezeMaterials = function () {
+            for (var i = 0; i < this.materials.length; i++) {
+                this.materials[i].unfreeze();
+            }
+        };
         Scene.prototype.dispose = function () {
             this.beforeRender = null;
             this.afterRender = null;

+ 14 - 4
src/babylon.scene.ts

@@ -1615,7 +1615,7 @@
 
             // Render targets
             var beforeRenderTargetDate = Tools.Now;
-            if (this.renderTargetsEnabled) {
+            if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
                 Tools.StartPerformanceCounter("Render targets", this._renderTargets.length > 0);
                 for (var renderIndex = 0; renderIndex < this._renderTargets.length; renderIndex++) {
                     var renderTarget = this._renderTargets.data[renderIndex];
@@ -1628,9 +1628,7 @@
                 Tools.EndPerformanceCounter("Render targets", this._renderTargets.length > 0);
 
                 this._renderId++;
-            }
-            if (this._renderTargets.length > 0) { // Restore back buffer
-                engine.restoreDefaultFramebuffer();
+                engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
             this._renderTargetsDuration += Tools.Now - beforeRenderTargetDate;
 
@@ -2066,6 +2064,18 @@
             this._depthRenderer = null;
         }
 
+        public freezeMaterials(): void {
+            for (var i = 0; i < this.materials.length; i++) {
+                this.materials[i].freeze();
+            }
+        }
+
+        public unfreezeMaterials(): void {
+            for (var i = 0; i < this.materials.length; i++) {
+                this.materials[i].unfreeze();
+            }
+        }
+
         public dispose(): void {
             this.beforeRender = null;
             this.afterRender = null;