Bläddra i källkod

Merge remote-tracking branch 'upstream/master'

Temechon 9 år sedan
förälder
incheckning
eefa12c5ab
31 ändrade filer med 1404 tillägg och 1068 borttagningar
  1. 18 18
      dist/preview release/babylon.core.js
  2. 911 898
      dist/preview release/babylon.d.ts
  3. 25 25
      dist/preview release/babylon.js
  4. 145 30
      dist/preview release/babylon.max.js
  5. 25 25
      dist/preview release/babylon.noworker.js
  6. 1 0
      dist/preview release/what's new.md
  7. 3 0
      src/Debug/babylon.debugLayer.js
  8. 3 0
      src/Debug/babylon.debugLayer.ts
  9. 7 7
      src/Materials/Textures/Procedurals/babylon.standardProceduralTexture.js
  10. 7 7
      src/Materials/Textures/Procedurals/babylon.standardProceduralTexture.ts
  11. 3 0
      src/Mesh/babylon.abstractMesh.js
  12. 5 3
      src/Mesh/babylon.abstractMesh.ts
  13. 64 9
      src/Particles/babylon.solidParticleSystem.js
  14. 34 18
      src/Particles/babylon.solidParticleSystem.ts
  15. 23 6
      src/Physics/Plugins/babylon.cannonJSPlugin.js
  16. 35 8
      src/Physics/Plugins/babylon.cannonJSPlugin.ts
  17. 19 0
      src/Physics/Plugins/babylon.oimoJSPlugin.js
  18. 21 0
      src/Physics/Plugins/babylon.oimoJSPlugin.ts
  19. 8 1
      src/PostProcess/babylon.volumetricLightScatteringPostProcess.js
  20. 10 1
      src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts
  21. 0 0
      src/Shaders/bricktexture.fragment.fx
  22. 0 0
      src/Shaders/cloudtexture.fragment.fx
  23. 0 0
      src/Shaders/firetexture.fragment.fx
  24. 0 0
      src/Shaders/grasstexture.fragment.fx
  25. 0 0
      src/Shaders/marbletexture.fragment.fx
  26. 0 0
      src/Shaders/roadtexture.fragment.fx
  27. 0 0
      src/Shaders/woodtexture.fragment.fx
  28. 3 0
      src/Tools/babylon.sceneOptimizer.js
  29. 4 0
      src/Tools/babylon.sceneOptimizer.ts
  30. 14 6
      src/babylon.engine.js
  31. 16 6
      src/babylon.engine.ts

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 18 - 18
dist/preview release/babylon.core.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 911 - 898
dist/preview release/babylon.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 25 - 25
dist/preview release/babylon.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 145 - 30
dist/preview release/babylon.max.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 25 - 25
dist/preview release/babylon.noworker.js


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

@@ -36,6 +36,7 @@
     - It is now possible to get the physics engine's body and wolrd objects using the physics engine. [PR](https://github.com/BabylonJS/Babylon.js/pull/761) ([RaananW](https://github.com/RaananW))
     - new Heightmap Impostor for Cannon.js physics engine. [PR](https://github.com/BabylonJS/Babylon.js/pull/78), [Demo] (http://www.babylonjs-playground.com/#D3LQD#3) ([RaananW](https://github.com/RaananW))
     - A plane mesh can be created with a source plane (math). [PR](https://github.com/BabylonJS/Babylon.js/pull/779) ([RaananW](https://github.com/RaananW))
+    - AbstractMesh.onPhysicsCollide will be triggered when a physics-enabled mesh collides against another. [PR](https://github.com/BabylonJS/Babylon.js/pull/806) ([RaananW](https://github.com/RaananW))
   - **Bug fixes**
     - Fixed a bug with spherical mapping ([deltakosh](https://github.com/deltakosh)) 
     - Fixed a bug with clone and createInstance which was forcing the recomputation of bounding boxes ([deltakosh](https://github.com/deltakosh)) 

+ 3 - 0
src/Debug/babylon.debugLayer.js

@@ -354,6 +354,8 @@ var BABYLON;
             var button = document.createElement("button");
             button.innerHTML = title;
             button.style.height = "24px";
+            button.style.width = "150px";
+            button.style.marginBottom = "5px";
             button.style.color = "#444444";
             button.style.border = "1px solid white";
             button.className = "debugLayerButton";
@@ -552,6 +554,7 @@ var BABYLON;
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._generateTexBox(this._optionsSubsetDiv, "<b>Tools:</b>", this.accentColor);
                 this._generateButton(this._optionsSubsetDiv, "Dump rendertargets", function (element) { _this._scene.dumpNextRenderTargets = true; });
+                this._generateButton(this._optionsSubsetDiv, "Run SceneOptimizer", function (element) { BABYLON.SceneOptimizer.OptimizeAsync(_this._scene); });
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._globalDiv.appendChild(this._statsDiv);
                 this._globalDiv.appendChild(this._logDiv);

+ 3 - 0
src/Debug/babylon.debugLayer.ts

@@ -486,6 +486,8 @@
             var button = document.createElement("button");
             button.innerHTML = title;
             button.style.height = "24px";
+            button.style.width = "150px";
+            button.style.marginBottom = "5px";
             button.style.color = "#444444";
             button.style.border = "1px solid white"; 
             button.className = "debugLayerButton";
@@ -697,6 +699,7 @@
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
                 this._generateTexBox(this._optionsSubsetDiv, "<b>Tools:</b>", this.accentColor);
                 this._generateButton(this._optionsSubsetDiv, "Dump rendertargets", (element) => { this._scene.dumpNextRenderTargets = true; });
+                this._generateButton(this._optionsSubsetDiv, "Run SceneOptimizer", (element) => { SceneOptimizer.OptimizeAsync(this._scene); });
                 this._optionsSubsetDiv.appendChild(document.createElement("br"));
   
                 this._globalDiv.appendChild(this._statsDiv);

+ 7 - 7
src/Materials/Textures/Procedurals/babylon.standardProceduralTexture.js

@@ -8,7 +8,7 @@ var BABYLON;
     var WoodProceduralTexture = (function (_super) {
         __extends(WoodProceduralTexture, _super);
         function WoodProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "wood", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "woodtexture", scene, fallbackTexture, generateMipMaps);
             this._ampScale = 100.0;
             this._woodColor = new BABYLON.Color3(0.32, 0.17, 0.09);
             this.updateShaderUniforms();
@@ -46,7 +46,7 @@ var BABYLON;
     var FireProceduralTexture = (function (_super) {
         __extends(FireProceduralTexture, _super);
         function FireProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "fire", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "firetexture", scene, fallbackTexture, generateMipMaps);
             this._time = 0.0;
             this._speed = new BABYLON.Vector2(0.5, 0.3);
             this._autoGenerateTime = true;
@@ -179,7 +179,7 @@ var BABYLON;
     var CloudProceduralTexture = (function (_super) {
         __extends(CloudProceduralTexture, _super);
         function CloudProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "cloud", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "cloudtexture", scene, fallbackTexture, generateMipMaps);
             this._skyColor = new BABYLON.Color4(0.15, 0.68, 1.0, 1.0);
             this._cloudColor = new BABYLON.Color4(1, 1, 1, 1.0);
             this.updateShaderUniforms();
@@ -217,7 +217,7 @@ var BABYLON;
     var GrassProceduralTexture = (function (_super) {
         __extends(GrassProceduralTexture, _super);
         function GrassProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "grass", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "grasstexture", scene, fallbackTexture, generateMipMaps);
             this._herb1 = new BABYLON.Color3(0.29, 0.38, 0.02);
             this._herb2 = new BABYLON.Color3(0.36, 0.49, 0.09);
             this._herb3 = new BABYLON.Color3(0.51, 0.6, 0.28);
@@ -264,7 +264,7 @@ var BABYLON;
     var RoadProceduralTexture = (function (_super) {
         __extends(RoadProceduralTexture, _super);
         function RoadProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "road", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "roadtexture", scene, fallbackTexture, generateMipMaps);
             this._roadColor = new BABYLON.Color3(0.53, 0.53, 0.53);
             this.updateShaderUniforms();
             this.refreshRate = 0;
@@ -289,7 +289,7 @@ var BABYLON;
     var BrickProceduralTexture = (function (_super) {
         __extends(BrickProceduralTexture, _super);
         function BrickProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "brick", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "bricktexture", scene, fallbackTexture, generateMipMaps);
             this._numberOfBricksHeight = 15;
             this._numberOfBricksWidth = 5;
             this._jointColor = new BABYLON.Color3(0.72, 0.72, 0.72);
@@ -353,7 +353,7 @@ var BABYLON;
     var MarbleProceduralTexture = (function (_super) {
         __extends(MarbleProceduralTexture, _super);
         function MarbleProceduralTexture(name, size, scene, fallbackTexture, generateMipMaps) {
-            _super.call(this, name, size, "marble", scene, fallbackTexture, generateMipMaps);
+            _super.call(this, name, size, "marbletexture", scene, fallbackTexture, generateMipMaps);
             this._numberOfTilesHeight = 3;
             this._numberOfTilesWidth = 3;
             this._amplitude = 9.0;

+ 7 - 7
src/Materials/Textures/Procedurals/babylon.standardProceduralTexture.ts

@@ -4,7 +4,7 @@
         private _woodColor: Color3 = new Color3(0.32, 0.17, 0.09);
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "wood", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "woodtexture", scene, fallbackTexture, generateMipMaps);
             this.updateShaderUniforms();
             this.refreshRate = 0;
         }
@@ -41,7 +41,7 @@
         private _alphaThreshold: number = 0.5;
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "fire", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "firetexture", scene, fallbackTexture, generateMipMaps);
             this._fireColors = FireProceduralTexture.RedFireColors;
             this.updateShaderUniforms();
             this.refreshRate = 1;
@@ -153,7 +153,7 @@
         private _cloudColor = new Color4(1, 1, 1, 1.0);
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "cloud", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "cloudtexture", scene, fallbackTexture, generateMipMaps);
             this.updateShaderUniforms();
             this.refreshRate = 0;
         }
@@ -190,7 +190,7 @@
         private _groundColor = new Color3(1, 1, 1);
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "grass", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "grasstexture", scene, fallbackTexture, generateMipMaps);
 
             this._grassColors = [
                 new Color3(0.29, 0.38, 0.02),
@@ -232,7 +232,7 @@
         private _roadColor = new Color3(0.53, 0.53, 0.53);
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "road", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "roadtexture", scene, fallbackTexture, generateMipMaps);
             this.updateShaderUniforms();
             this.refreshRate = 0;
         }
@@ -258,7 +258,7 @@
         private _brickColor = new Color3(0.77, 0.47, 0.40);
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "brick", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "bricktexture", scene, fallbackTexture, generateMipMaps);
             this.updateShaderUniforms();
             this.refreshRate = 0;
         }
@@ -315,7 +315,7 @@
         private _jointColor = new Color3(0.72, 0.72, 0.72);
 
         constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {
-            super(name, size, "marble", scene, fallbackTexture, generateMipMaps);
+            super(name, size, "marbletexture", scene, fallbackTexture, generateMipMaps);
             this.updateShaderUniforms();
             this.refreshRate = 0;
         }

+ 3 - 0
src/Mesh/babylon.abstractMesh.js

@@ -89,6 +89,9 @@ var BABYLON;
                 if (_this.onCollide && collidedMesh) {
                     _this.onCollide(collidedMesh);
                 }
+                if (_this.onCollisionPositionChange) {
+                    _this.onCollisionPositionChange(_this.position);
+                }
             };
             scene.addMesh(this);
         }

+ 5 - 3
src/Mesh/babylon.abstractMesh.ts

@@ -59,7 +59,7 @@
         public applyFog = true;
         public computeBonesUsingShaders = true;
         public scalingDeterminant = 1;
-        public numBoneInfluencers = 4; 
+        public numBoneInfluencers = 4;
 
         public useOctreeForRenderingSelection = true;
         public useOctreeForPicking = true;
@@ -74,6 +74,7 @@
         public _physicsMass: number;
         public _physicsFriction: number;
         public _physicRestitution: number;
+        public onPhysicsCollide: (collidedMesh: AbstractMesh) => void; 
 
         // Collisions
         private _checkCollisions = false;
@@ -804,8 +805,8 @@
             if (this.onCollide && collidedMesh) {
                 this.onCollide(collidedMesh);
             }
-            
-            if(this.onCollisionPositionChange) {
+
+            if (this.onCollisionPositionChange) {
                 this.onCollisionPositionChange(this.position);
             }
         }
@@ -1056,3 +1057,4 @@
 
 
 
+

+ 64 - 9
src/Particles/babylon.solidParticleSystem.js

@@ -15,6 +15,8 @@ var BABYLON;
             this._uvs = new Array();
             this._index = 0; // indices index
             this._updatable = true;
+            this._pickable = false;
+            this._alwaysVisible = false;
             this._shapeCounter = 0;
             this._copy = new BABYLON.SolidParticle(null, null, null, null, null);
             this._color = new BABYLON.Color4(0, 0, 0, 0);
@@ -30,10 +32,10 @@ var BABYLON;
             this._axisZ = BABYLON.Axis.Z;
             this._fakeCamPos = BABYLON.Vector3.Zero();
             this._rotMatrix = new BABYLON.Matrix();
-            this._invertedMatrix = new BABYLON.Matrix();
             this._rotated = BABYLON.Vector3.Zero();
             this._quaternion = new BABYLON.Quaternion();
             this._vertex = BABYLON.Vector3.Zero();
+            this._normal = BABYLON.Vector3.Zero();
             this._yaw = 0.0;
             this._pitch = 0.0;
             this._roll = 0.0;
@@ -50,12 +52,16 @@ var BABYLON;
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
+            this._pickable = options ? options.isPickable : false;
             if (options && options.updatable) {
                 this._updatable = options.updatable;
             }
             else {
                 this._updatable = true;
             }
+            if (this._pickable) {
+                this.pickedParticles = [];
+            }
         }
         // build the SPS mesh : returns the mesh
         SolidParticleSystem.prototype.buildMesh = function () {
@@ -69,6 +75,7 @@ var BABYLON;
             this._colors32 = new Float32Array(this._colors);
             BABYLON.VertexData.ComputeNormals(this._positions32, this._indices, this._normals);
             this._normals32 = new Float32Array(this._normals);
+            this._fixedNormal32 = new Float32Array(this._normals);
             var vertexData = new BABYLON.VertexData();
             vertexData.set(this._positions32, BABYLON.VertexBuffer.PositionKind);
             vertexData.indices = this._indices;
@@ -83,6 +90,7 @@ var BABYLON;
             var mesh = new BABYLON.Mesh(name, this._scene);
             vertexData.applyToMesh(mesh, this._updatable);
             this.mesh = mesh;
+            this.mesh.isPickable = this._pickable;
             // free memory
             this._positions = null;
             this._normals = null;
@@ -170,6 +178,12 @@ var BABYLON;
             for (i = 0; i < meshInd.length; i++) {
                 indices.push(p + meshInd[i]);
             }
+            if (this._pickable) {
+                var nbfaces = meshInd.length / 3;
+                for (i = 0; i < nbfaces; i++) {
+                    this.pickedParticles.push({ idx: idx, faceId: i });
+                }
+            }
         };
         // returns a shape array from positions array
         SolidParticleSystem.prototype._posToShape = function (positions) {
@@ -189,8 +203,8 @@ var BABYLON;
             return shapeUV;
         };
         // adds a new particle object in the particles array
-        SolidParticleSystem.prototype._addParticle = function (p, idxpos, model, shapeId, idxInShape) {
-            this.particles.push(new BABYLON.SolidParticle(p, idxpos, model, shapeId, idxInShape));
+        SolidParticleSystem.prototype._addParticle = function (idx, idxpos, model, shapeId, idxInShape) {
+            this.particles.push(new BABYLON.SolidParticle(idx, idxpos, model, shapeId, idxInShape));
         };
         // add solid particles from a shape model in the particles array
         SolidParticleSystem.prototype.addShape = function (mesh, nb, options) {
@@ -204,12 +218,14 @@ var BABYLON;
             var vtxfunc = options ? options.vertexFunction : null;
             var modelShape = new BABYLON.ModelShape(this._shapeCounter, shape, shapeUV, posfunc, vtxfunc);
             // particles
+            var idx = this.nbParticles;
             for (var i = 0; i < nb; i++) {
-                this._meshBuilder(this._index, shape, this._positions, meshInd, this._indices, meshUV, this._uvs, meshCol, this._colors, this.nbParticles + i, i, options);
+                this._meshBuilder(this._index, shape, this._positions, meshInd, this._indices, meshUV, this._uvs, meshCol, this._colors, idx, i, options);
                 if (this._updatable) {
-                    this._addParticle(this.nbParticles + i, this._positions.length, modelShape, this._shapeCounter, i);
+                    this._addParticle(idx, this._positions.length, modelShape, this._shapeCounter, i);
                 }
                 this._index += shape.length;
+                idx++;
             }
             this.nbParticles += nb;
             this._shapeCounter++;
@@ -273,6 +289,9 @@ var BABYLON;
             if (start === void 0) { start = 0; }
             if (end === void 0) { end = this.nbParticles - 1; }
             if (update === void 0) { update = true; }
+            if (!this._updatable) {
+                return;
+            }
             // custom beforeUpdate
             this.beforeUpdateParticles(start, end, update);
             this._cam_axisX.x = 1;
@@ -292,8 +311,7 @@ var BABYLON;
                 this._roll = this.mesh.rotation.z;
                 this._quaternionRotationYPR();
                 this._quaternionToRotationMatrix();
-                this._rotMatrix.invertToRef(this._invertedMatrix);
-                BABYLON.Vector3.TransformCoordinatesToRef(this._camera.globalPosition, this._invertedMatrix, this._fakeCamPos);
+                BABYLON.Vector3.TransformCoordinatesToRef(this._camera.globalPosition, this._rotMatrix, this._fakeCamPos);
                 // set two orthogonal vectors (_cam_axisX and and _cam_axisY) to the cam-mesh axis (_cam_axisZ)
                 (this._fakeCamPos).subtractToRef(this.mesh.position, this._cam_axisZ);
                 BABYLON.Vector3.CrossToRef(this._cam_axisZ, this._axisX, this._cam_axisY);
@@ -347,10 +365,10 @@ var BABYLON;
                     if (this._computeParticleVertex) {
                         this.updateParticleVertex(this._particle, this._vertex, pt);
                     }
+                    // positions
                     this._vertex.x *= this._particle.scale.x;
                     this._vertex.y *= this._particle.scale.y;
                     this._vertex.z *= this._particle.scale.z;
-                    //Vector3.TransformCoordinatesToRef(this._vertex, this._rotMatrix, this._rotated);
                     this._w = (this._vertex.x * this._rotMatrix.m[3]) + (this._vertex.y * this._rotMatrix.m[7]) + (this._vertex.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
                     this._rotated.x = ((this._vertex.x * this._rotMatrix.m[0]) + (this._vertex.y * this._rotMatrix.m[4]) + (this._vertex.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
                     this._rotated.y = ((this._vertex.x * this._rotMatrix.m[1]) + (this._vertex.y * this._rotMatrix.m[5]) + (this._vertex.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
@@ -358,6 +376,19 @@ var BABYLON;
                     this._positions32[idx] = this._particle.position.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                     this._positions32[idx + 1] = this._particle.position.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
                     this._positions32[idx + 2] = this._particle.position.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                    // normals : if the particles can't be morphed then just rotate the normals
+                    if (!this._computeParticleVertex && !this.billboard) {
+                        this._normal.x = this._fixedNormal32[idx];
+                        this._normal.y = this._fixedNormal32[idx + 1];
+                        this._normal.z = this._fixedNormal32[idx + 2];
+                        this._w = (this._normal.x * this._rotMatrix.m[3]) + (this._normal.y * this._rotMatrix.m[7]) + (this._normal.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
+                        this._rotated.x = ((this._normal.x * this._rotMatrix.m[0]) + (this._normal.y * this._rotMatrix.m[4]) + (this._normal.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
+                        this._rotated.y = ((this._normal.x * this._rotMatrix.m[1]) + (this._normal.y * this._rotMatrix.m[5]) + (this._normal.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
+                        this._rotated.z = ((this._normal.x * this._rotMatrix.m[2]) + (this._normal.y * this._rotMatrix.m[6]) + (this._normal.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
+                        this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
+                        this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
+                        this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
+                    }
                     if (this._computeParticleColor) {
                         this._colors32[colidx] = this._particle.color.r;
                         this._colors32[colidx + 1] = this._particle.color.g;
@@ -382,7 +413,13 @@ var BABYLON;
                 }
                 this.mesh.updateVerticesData(BABYLON.VertexBuffer.PositionKind, this._positions32, false, false);
                 if (!this.mesh.areNormalsFrozen) {
-                    BABYLON.VertexData.ComputeNormals(this._positions32, this._indices, this._normals32);
+                    if (this._computeParticleVertex || this.billboard) {
+                        // recompute the normals only if the particles can be morphed, update then the normal reference array
+                        BABYLON.VertexData.ComputeNormals(this._positions32, this._indices, this._normals32);
+                        for (var i = 0; i < this._normals32.length; i++) {
+                            this._fixedNormal32[i] = this._normals32[i];
+                        }
+                    }
                     this.mesh.updateVerticesData(BABYLON.VertexBuffer.NormalKind, this._normals32, false, false);
                 }
             }
@@ -433,9 +470,27 @@ var BABYLON;
             this._colors = null;
             this._positions32 = null;
             this._normals32 = null;
+            this._fixedNormal32 = null;
             this._uvs32 = null;
             this._colors32 = null;
+            this.pickedParticles = null;
+        };
+        // Visibilty helpers
+        SolidParticleSystem.prototype.refreshVisibleSize = function () {
+            this.mesh.refreshBoundingInfo();
         };
+        Object.defineProperty(SolidParticleSystem.prototype, "isAlwaysVisible", {
+            // getter and setter
+            get: function () {
+                return this._alwaysVisible;
+            },
+            set: function (val) {
+                this._alwaysVisible = val;
+                this.mesh.alwaysSelectAsActiveMesh = val;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(SolidParticleSystem.prototype, "computeParticleRotation", {
             // getters
             get: function () {

+ 34 - 18
src/Particles/babylon.solidParticleSystem.ts

@@ -9,7 +9,7 @@ module BABYLON {
         public name: string;
         public mesh: Mesh;
         public vars: any = {};
-        public pickedParticles: {idx: number; faceId: number}[];
+        public pickedParticles: { idx: number; faceId: number }[];
         
         // private members
         private _scene: Scene;
@@ -26,6 +26,7 @@ module BABYLON {
         private _index: number = 0;  // indices index
         private _updatable: boolean = true;
         private _pickable: boolean = false;
+        private _alwaysVisible: boolean = false;
         private _shapeCounter: number = 0;
         private _copy: SolidParticle = new SolidParticle(null, null, null, null, null);
         private _shape: Vector3[];
@@ -45,7 +46,6 @@ module BABYLON {
         private _particle: SolidParticle;
         private _fakeCamPos: Vector3 = Vector3.Zero();
         private _rotMatrix: Matrix = new Matrix();
-        private _invertedMatrix: Matrix = new Matrix();
         private _rotated: Vector3 = Vector3.Zero();
         private _quaternion: Quaternion = new Quaternion();
         private _vertex: Vector3 = Vector3.Zero();
@@ -65,11 +65,11 @@ module BABYLON {
         private _w: number = 0.0;
 
 
-        constructor(name: string, scene: Scene, options?: { updatable?: boolean, pickable? :boolean }) {
+        constructor(name: string, scene: Scene, options?: { updatable?: boolean, isPickable?: boolean }) {
             this.name = name;
             this._scene = scene;
             this._camera = scene.activeCamera;
-            this._pickable = options ? options.pickable : false;
+            this._pickable = options ? options.isPickable : false;
             if (options && options.updatable) {
                 this._updatable = options.updatable;
             } else {
@@ -106,7 +106,8 @@ module BABYLON {
             var mesh = new Mesh(name, this._scene);
             vertexData.applyToMesh(mesh, this._updatable);
             this.mesh = mesh;
-
+            this.mesh.isPickable = this._pickable;
+            
             // free memory
             this._positions = null;
             this._normals = null;
@@ -115,7 +116,6 @@ module BABYLON {
 
             if (!this._updatable) {
                 this.particles.length = 0;
-                this.mesh.isPickable = true;
             }
 
             return mesh;
@@ -209,7 +209,7 @@ module BABYLON {
             if (this._pickable) {
                 var nbfaces = meshInd.length / 3;
                 for (i = 0; i < nbfaces; i++) {
-                    this.pickedParticles.push({idx: idx, faceId: i});
+                    this.pickedParticles.push({ idx: idx, faceId: i });
                 }
             }
         }
@@ -358,8 +358,7 @@ module BABYLON {
                 this._roll = this.mesh.rotation.z;
                 this._quaternionRotationYPR();
                 this._quaternionToRotationMatrix();
-                this._rotMatrix.invertToRef(this._invertedMatrix);
-                Vector3.TransformCoordinatesToRef(this._camera.globalPosition, this._invertedMatrix, this._fakeCamPos);
+                Vector3.TransformCoordinatesToRef(this._camera.globalPosition, this._rotMatrix, this._fakeCamPos);
 
                 // set two orthogonal vectors (_cam_axisX and and _cam_axisY) to the cam-mesh axis (_cam_axisZ)
                 (this._fakeCamPos).subtractToRef(this.mesh.position, this._cam_axisZ);
@@ -427,28 +426,28 @@ module BABYLON {
                     this._vertex.z *= this._particle.scale.z;
 
                     this._w = (this._vertex.x * this._rotMatrix.m[3]) + (this._vertex.y * this._rotMatrix.m[7]) + (this._vertex.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
-                    this._rotated.x = ( (this._vertex.x * this._rotMatrix.m[0]) + (this._vertex.y * this._rotMatrix.m[4]) + (this._vertex.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12] ) / this._w;
-                    this._rotated.y = ( (this._vertex.x * this._rotMatrix.m[1]) + (this._vertex.y * this._rotMatrix.m[5]) + (this._vertex.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13] ) / this._w;
-                    this._rotated.z = ( (this._vertex.x * this._rotMatrix.m[2]) + (this._vertex.y * this._rotMatrix.m[6]) + (this._vertex.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14] ) / this._w;
+                    this._rotated.x = ((this._vertex.x * this._rotMatrix.m[0]) + (this._vertex.y * this._rotMatrix.m[4]) + (this._vertex.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
+                    this._rotated.y = ((this._vertex.x * this._rotMatrix.m[1]) + (this._vertex.y * this._rotMatrix.m[5]) + (this._vertex.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
+                    this._rotated.z = ((this._vertex.x * this._rotMatrix.m[2]) + (this._vertex.y * this._rotMatrix.m[6]) + (this._vertex.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
 
                     this._positions32[idx] = this._particle.position.x + this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                     this._positions32[idx + 1] = this._particle.position.y + this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
                     this._positions32[idx + 2] = this._particle.position.z + this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
 
                     // normals : if the particles can't be morphed then just rotate the normals
-                    if (!this._computeParticleVertex) {
+                    if (!this._computeParticleVertex && !this.billboard) {
                         this._normal.x = this._fixedNormal32[idx];
                         this._normal.y = this._fixedNormal32[idx + 1];
                         this._normal.z = this._fixedNormal32[idx + 2];
 
                         this._w = (this._normal.x * this._rotMatrix.m[3]) + (this._normal.y * this._rotMatrix.m[7]) + (this._normal.z * this._rotMatrix.m[11]) + this._rotMatrix.m[15];
-                        this._rotated.x = ( (this._normal.x * this._rotMatrix.m[0]) + (this._normal.y * this._rotMatrix.m[4]) + (this._normal.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12] ) / this._w;
-                        this._rotated.y = ( (this._normal.x * this._rotMatrix.m[1]) + (this._normal.y * this._rotMatrix.m[5]) + (this._normal.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13] ) / this._w;
-                        this._rotated.z = ( (this._normal.x * this._rotMatrix.m[2]) + (this._normal.y * this._rotMatrix.m[6]) + (this._normal.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14] ) / this._w;
+                        this._rotated.x = ((this._normal.x * this._rotMatrix.m[0]) + (this._normal.y * this._rotMatrix.m[4]) + (this._normal.z * this._rotMatrix.m[8]) + this._rotMatrix.m[12]) / this._w;
+                        this._rotated.y = ((this._normal.x * this._rotMatrix.m[1]) + (this._normal.y * this._rotMatrix.m[5]) + (this._normal.z * this._rotMatrix.m[9]) + this._rotMatrix.m[13]) / this._w;
+                        this._rotated.z = ((this._normal.x * this._rotMatrix.m[2]) + (this._normal.y * this._rotMatrix.m[6]) + (this._normal.z * this._rotMatrix.m[10]) + this._rotMatrix.m[14]) / this._w;
 
                         this._normals32[idx] = this._cam_axisX.x * this._rotated.x + this._cam_axisY.x * this._rotated.y + this._cam_axisZ.x * this._rotated.z;
                         this._normals32[idx + 1] = this._cam_axisX.y * this._rotated.x + this._cam_axisY.y * this._rotated.y + this._cam_axisZ.y * this._rotated.z;
-                        this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z; 
+                        this._normals32[idx + 2] = this._cam_axisX.z * this._rotated.x + this._cam_axisY.z * this._rotated.y + this._cam_axisZ.z * this._rotated.z;
                     }
 
                     if (this._computeParticleColor) {
@@ -477,7 +476,7 @@ module BABYLON {
                 }
                 this.mesh.updateVerticesData(VertexBuffer.PositionKind, this._positions32, false, false);
                 if (!this.mesh.areNormalsFrozen) {
-                    if (this._computeParticleVertex) {
+                    if (this._computeParticleVertex || this.billboard) {
                         // recompute the normals only if the particles can be morphed, update then the normal reference array
                         VertexData.ComputeNormals(this._positions32, this._indices, this._normals32);
                         for (var i = 0; i < this._normals32.length; i++) {
@@ -543,6 +542,21 @@ module BABYLON {
             this.pickedParticles = null;
         }
 
+        // Visibilty helpers
+        public refreshVisibleSize(): void {
+            this.mesh.refreshBoundingInfo();
+        }
+
+        // getter and setter
+        public get isAlwaysVisible(): boolean {
+            return this._alwaysVisible;
+        }
+
+        public set isAlwaysVisible(val: boolean) {
+            this._alwaysVisible = val;
+            this.mesh.alwaysSelectAsActiveMesh = val;
+        }
+
         // Optimizer setters
         public set computeParticleRotation(val: boolean) {
             this._computeParticleRotation = val;
@@ -623,3 +637,5 @@ module BABYLON {
 
 
 
+
+

+ 23 - 6
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -54,12 +54,9 @@ var BABYLON;
             return value < BABYLON.PhysicsEngine.Epsilon ? BABYLON.PhysicsEngine.Epsilon : value;
         };
         CannonJSPlugin.prototype.runOneStep = function (delta) {
+            var _this = this;
             this._world.step(delta);
-            for (var index = 0; index < this._registeredMeshes.length; index++) {
-                var registeredMesh = this._registeredMeshes[index];
-                if (registeredMesh.isChild) {
-                    continue;
-                }
+            this._registeredMeshes.forEach(function (registeredMesh) {
                 // Body position
                 var bodyX = registeredMesh.body.position.x, bodyY = registeredMesh.body.position.y, bodyZ = registeredMesh.body.position.z;
                 registeredMesh.mesh.position.x = bodyX + registeredMesh.delta.x;
@@ -69,7 +66,27 @@ var BABYLON;
                 if (registeredMesh.deltaRotation) {
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                 }
-            }
+                //is the physics collision callback is set?
+                if (registeredMesh.mesh.onPhysicsCollide) {
+                    if (!registeredMesh.collisionFunction) {
+                        registeredMesh.collisionFunction = function (e) {
+                            //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.body.addEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                }
+                else {
+                    //unregister, in case the function was removed for some reason
+                    if (registeredMesh.collisionFunction) {
+                        registeredMesh.body.removeEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                }
+            });
         };
         CannonJSPlugin.prototype.setGravity = function (gravity) {
             this._world.gravity.set(gravity.x, gravity.y, gravity.z);

+ 35 - 8
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -1,10 +1,21 @@
 module BABYLON {
     declare var CANNON;
 
+    interface IRegisteredMesh {
+        mesh: AbstractMesh;
+        body: any; //Cannon body
+        material: any;
+        delta: Vector3;
+        deltaRotation: Quaternion;
+        heightmap: boolean;
+        collisionFunction?: (event: any) => void;
+
+    }
+
     export class CannonJSPlugin implements IPhysicsEnginePlugin {
 
         private _world: any;
-        private _registeredMeshes = [];
+        private _registeredMeshes: Array<IRegisteredMesh> = [];
         private _physicsMaterials = [];
 
         public initialize(iterations: number = 10): void {
@@ -20,12 +31,7 @@
         public runOneStep(delta: number): void {
             this._world.step(delta);
 
-            for (var index = 0; index < this._registeredMeshes.length; index++) {
-                var registeredMesh = this._registeredMeshes[index];
-
-                if (registeredMesh.isChild) {
-                    continue;
-                }
+            this._registeredMeshes.forEach((registeredMesh) => {
 
                 // Body position
                 var bodyX = registeredMesh.body.position.x,
@@ -40,7 +46,27 @@
                 if (registeredMesh.deltaRotation) {
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                 }
-            }
+
+                //is the physics collision callback is set?
+                if (registeredMesh.mesh.onPhysicsCollide) {
+                    if (!registeredMesh.collisionFunction) {
+                        registeredMesh.collisionFunction = (e) => {
+                            //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.body.addEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                } else {
+                    //unregister, in case the function was removed for some reason
+                    if (registeredMesh.collisionFunction) {
+                        registeredMesh.body.removeEventListener("collide", registeredMesh.collisionFunction);
+                    }
+                }
+            });
         }
 
         public setGravity(gravity: Vector3): void {
@@ -459,3 +485,4 @@
 
 
 
+

+ 19 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -60,6 +60,7 @@ var BABYLON;
             mesh.rotationQuaternion = new BABYLON.Quaternion(0, 0, 0, 1);
             mesh.computeWorldMatrix(true);
             var bodyConfig = {
+                name: mesh.uniqueId,
                 pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                 rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
                 move: options.mass != 0,
@@ -119,6 +120,7 @@ var BABYLON;
                 rotations.push.apply(rotations, bodyParameters.rot);
             }
             var body = new OIMO.Body({
+                name: initialMesh.uniqueId,
                 type: types,
                 size: sizes,
                 pos: positions,
@@ -145,6 +147,7 @@ var BABYLON;
             mesh.computeWorldMatrix(true);
             var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
             var bodyParameters = {
+                name: mesh.uniqueId,
                 pos: [mesh.position.x, mesh.position.y, mesh.position.z],
                 //A bug in Oimo (Body class) prevents us from using rot directly.
                 rot: [0, 0, 0],
@@ -300,6 +303,22 @@ var BABYLON;
                     mesh.rotationQuaternion.copyFrom(body.getQuaternion());
                     mesh.computeWorldMatrix();
                 }
+                //check if the collide callback is set. 
+                if (mesh.onPhysicsCollide) {
+                    var meshUniqueName = mesh.uniqueId;
+                    var contact = this._world.contacts;
+                    while (contact !== null) {
+                        //is this body colliding with any other?
+                        if ((contact.body1.name == mesh.uniqueId || contact.body2.name == mesh.uniqueId) && contact.touching && !contact.body1.sleeping && !contact.body2.sleeping) {
+                            var otherUniqueId = contact.body1.name == mesh.uniqueId ? contact.body2.name : contact.body1.name;
+                            //get the mesh and execute the callback
+                            var otherMesh = mesh.getScene().getMeshByUniqueID(otherUniqueId);
+                            if (otherMesh)
+                                mesh.onPhysicsCollide(otherMesh);
+                        }
+                        contact = contact.next;
+                    }
+                }
             }
         };
         return OimoJSPlugin;

+ 21 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.ts

@@ -41,6 +41,7 @@ module BABYLON {
             mesh.computeWorldMatrix(true);
 
             var bodyConfig: any = {
+                name: mesh.uniqueId,
                 pos: [bbox.center.x, bbox.center.y, bbox.center.z],
                 rot: [rot.x / OIMO.TO_RAD, rot.y / OIMO.TO_RAD, rot.z / OIMO.TO_RAD],
                 move: options.mass != 0,
@@ -121,6 +122,7 @@ module BABYLON {
             }
 
             var body = new OIMO.Body({
+                name: initialMesh.uniqueId,
                 type: types,
                 size: sizes,
                 pos: positions,
@@ -156,6 +158,7 @@ module BABYLON {
             var rot = new OIMO.Euler().setFromQuaternion({ x: mesh.rotationQuaternion.x, y: mesh.rotationQuaternion.y, z: mesh.rotationQuaternion.z, s: mesh.rotationQuaternion.w });
 
             var bodyParameters: any = {
+                name: mesh.uniqueId,
                 pos: [mesh.position.x, mesh.position.y, mesh.position.z],
                 //A bug in Oimo (Body class) prevents us from using rot directly.
                 rot: [0, 0, 0],
@@ -379,9 +382,27 @@ module BABYLON {
                     mesh.rotationQuaternion.copyFrom(body.getQuaternion());
                     mesh.computeWorldMatrix();
                 }
+                
+                //check if the collide callback is set. 
+                if (mesh.onPhysicsCollide) {
+                    var meshUniqueName = mesh.uniqueId;
+                    var contact = this._world.contacts;
+                    while (contact !== null) {
+                        //is this body colliding with any other?
+                        if ((contact.body1.name == mesh.uniqueId || contact.body2.name == mesh.uniqueId) && contact.touching && /* !contact.sleeping*/ !contact.body1.sleeping && !contact.body2.sleeping) {
+                            var otherUniqueId = contact.body1.name == mesh.uniqueId ? contact.body2.name : contact.body1.name;
+                            //get the mesh and execute the callback
+                            var otherMesh = mesh.getScene().getMeshByUniqueID(otherUniqueId);
+                            if (otherMesh)
+                                mesh.onPhysicsCollide(otherMesh);
+                        }
+                        contact = contact.next;
+                    }
+                }
             }
         }
     }
 }
 
 
+

+ 8 - 1
src/PostProcess/babylon.volumetricLightScatteringPostProcess.js

@@ -71,6 +71,12 @@ var BABYLON;
             this.mesh = (mesh !== null) ? mesh : VolumetricLightScatteringPostProcess.CreateDefaultMesh("VolumetricLightScatteringMesh", scene);
             // Configure
             this._createPass(scene, ratio.passRatio || ratio);
+            this.onActivate = function (camera) {
+                if (!_this.isSupported) {
+                    _this.dispose(camera);
+                }
+                _this.onActivate = null;
+            };
             this.onApply = function (effect) {
                 _this._updateMeshScreenCoordinates(scene);
                 effect.setTexture("lightScatteringSampler", _this._volumetricLightScatteringRTT);
@@ -303,7 +309,8 @@ var BABYLON;
         };
         VolumetricLightScatteringPostProcess.prototype._updateMeshScreenCoordinates = function (scene) {
             var transform = scene.getTransformMatrix();
-            var pos = BABYLON.Vector3.Project(this.useCustomMeshPosition ? this._customMeshPosition : this.mesh.position, BABYLON.Matrix.Identity(), transform, this._viewPort);
+            var meshPosition = this.mesh.parent ? this.mesh.getAbsolutePosition() : this.mesh.position;
+            var pos = BABYLON.Vector3.Project(this.useCustomMeshPosition ? this._customMeshPosition : meshPosition, BABYLON.Matrix.Identity(), transform, this._viewPort);
             this._screenCoordinates.x = pos.x / this._viewPort.width;
             this._screenCoordinates.y = pos.y / this._viewPort.height;
             if (this.invert)

+ 10 - 1
src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts

@@ -80,6 +80,14 @@
             // Configure
             this._createPass(scene, ratio.passRatio || ratio);
 
+            this.onActivate = (camera: Camera) => {
+                if (!this.isSupported) {
+                    this.dispose(camera);
+                }
+
+                this.onActivate = null;
+            };
+
             this.onApply = (effect: Effect) => {
                 this._updateMeshScreenCoordinates(scene);
 
@@ -360,7 +368,8 @@
 
         private _updateMeshScreenCoordinates(scene: Scene): void {
             var transform = scene.getTransformMatrix();
-            var pos = Vector3.Project(this.useCustomMeshPosition ? this._customMeshPosition : this.mesh.position, Matrix.Identity(), transform, this._viewPort);
+            var meshPosition = this.mesh.parent ? this.mesh.getAbsolutePosition() : this.mesh.position;
+            var pos = Vector3.Project(this.useCustomMeshPosition ? this._customMeshPosition : meshPosition, Matrix.Identity(), transform, this._viewPort);
 
             this._screenCoordinates.x = pos.x / this._viewPort.width;
             this._screenCoordinates.y = pos.y / this._viewPort.height;

src/Shaders/brick.fragment.fx → src/Shaders/bricktexture.fragment.fx


src/Shaders/cloud.fragment.fx → src/Shaders/cloudtexture.fragment.fx


src/Shaders/fire.fragment.fx → src/Shaders/firetexture.fragment.fx


src/Shaders/grass.fragment.fx → src/Shaders/grasstexture.fragment.fx


src/Shaders/marble.fragment.fx → src/Shaders/marbletexture.fragment.fx


src/Shaders/road.fragment.fx → src/Shaders/roadtexture.fragment.fx


src/Shaders/wood.fragment.fx → src/Shaders/woodtexture.fragment.fx


+ 3 - 0
src/Tools/babylon.sceneOptimizer.js

@@ -144,6 +144,9 @@ var BABYLON;
                 if (mesh.skeleton || mesh.hasLODLevels) {
                     return false;
                 }
+                if (mesh.parent) {
+                    return false;
+                }
                 return true;
             };
             this.apply = function (scene, updateSelectionTree) {

+ 4 - 0
src/Tools/babylon.sceneOptimizer.ts

@@ -118,6 +118,10 @@
                 return false;
             }
 
+            if (mesh.parent) {
+                return false;
+            }
+
             return true;
         }
 

+ 14 - 6
src/babylon.engine.js

@@ -1695,6 +1695,11 @@ var BABYLON;
             var framebuffer = gl.createFramebuffer();
             gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
             gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
+            // mipmaps
+            if (texture.generateMipMaps) {
+                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+            }
             // Unbind
             gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
@@ -1780,12 +1785,7 @@ var BABYLON;
             }
             gl.deleteTexture(texture);
             // Unbind channels
-            for (var channel = 0; channel < this._caps.maxTexturesImageUnits; channel++) {
-                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
-                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
-                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
-                this._activeTexturesCache[channel] = null;
-            }
+            this.unbindAllTextures();
             var index = this._loadedTexturesCache.indexOf(texture);
             if (index !== -1) {
                 this._loadedTexturesCache.splice(index, 1);
@@ -1808,6 +1808,14 @@ var BABYLON;
         Engine.prototype.setTextureFromPostProcess = function (channel, postProcess) {
             this._bindTexture(channel, postProcess._textures.data[postProcess._currentRenderTextureInd]);
         };
+        Engine.prototype.unbindAllTextures = function () {
+            for (var channel = 0; channel < this._caps.maxTexturesImageUnits; channel++) {
+                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
+                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
+                this._activeTexturesCache[channel] = null;
+            }
+        };
         Engine.prototype.setTexture = function (channel, texture) {
             if (channel < 0) {
                 return;

+ 16 - 6
src/babylon.engine.ts

@@ -2011,6 +2011,12 @@
             gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
             gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
 
+            // mipmaps
+            if (texture.generateMipMaps) {
+                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+            }
+
             // Unbind
             gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
@@ -2125,12 +2131,7 @@
             gl.deleteTexture(texture);
 
             // Unbind channels
-            for (var channel = 0; channel < this._caps.maxTexturesImageUnits; channel++) {
-                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
-                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
-                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
-                this._activeTexturesCache[channel] = null;
-            }
+            this.unbindAllTextures();
 
             var index = this._loadedTexturesCache.indexOf(texture);
             if (index !== -1) {
@@ -2160,6 +2161,15 @@
             this._bindTexture(channel, postProcess._textures.data[postProcess._currentRenderTextureInd]);
         }
 
+        public unbindAllTextures(): void {
+            for (var channel = 0; channel < this._caps.maxTexturesImageUnits; channel++) {
+                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
+                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
+                this._activeTexturesCache[channel] = null;
+            }
+        }
+
         public setTexture(channel: number, texture: BaseTexture): void {
             if (channel < 0) {
                 return;