瀏覽代碼

Update preview builds

nockawa 8 年之前
父節點
當前提交
b4663d209d

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


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


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


+ 245 - 115
dist/preview release/babylon.max.js

@@ -8721,65 +8721,65 @@ var BABYLON;
                 isPot = (BABYLON.Tools.IsExponentOfTwo(width) && BABYLON.Tools.IsExponentOfTwo(height));
                 _this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
                 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
-                if (!noMipmap && isPot) {
-                    if (mipmmapGenerator) {
-                        var arrayTemp = [];
-                        // Data are known to be in +X +Y +Z -X -Y -Z
-                        // mipmmapGenerator data is expected to be order in +X -X +Y -Y +Z -Z
-                        arrayTemp.push(rgbeDataArrays[0]); // +X
-                        arrayTemp.push(rgbeDataArrays[3]); // -X
-                        arrayTemp.push(rgbeDataArrays[1]); // +Y
-                        arrayTemp.push(rgbeDataArrays[4]); // -Y
-                        arrayTemp.push(rgbeDataArrays[2]); // +Z
-                        arrayTemp.push(rgbeDataArrays[5]); // -Z
-                        var mipData = mipmmapGenerator(arrayTemp);
-                        for (var level = 0; level < mipData.length; level++) {
-                            var mipSize = width >> level;
-                            // mipData is order in +X -X +Y -Y +Z -Z
-                            gl.texImage2D(facesIndex[0], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][0]);
-                            gl.texImage2D(facesIndex[1], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][2]);
-                            gl.texImage2D(facesIndex[2], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][4]);
-                            gl.texImage2D(facesIndex[3], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][1]);
-                            gl.texImage2D(facesIndex[4], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][3]);
-                            gl.texImage2D(facesIndex[5], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][5]);
-                        }
+                if (mipmmapGenerator) {
+                    var arrayTemp = [];
+                    // Data are known to be in +X +Y +Z -X -Y -Z
+                    // mipmmapGenerator data is expected to be order in +X -X +Y -Y +Z -Z
+                    arrayTemp.push(rgbeDataArrays[0]); // +X
+                    arrayTemp.push(rgbeDataArrays[3]); // -X
+                    arrayTemp.push(rgbeDataArrays[1]); // +Y
+                    arrayTemp.push(rgbeDataArrays[4]); // -Y
+                    arrayTemp.push(rgbeDataArrays[2]); // +Z
+                    arrayTemp.push(rgbeDataArrays[5]); // -Z
+                    var mipData = mipmmapGenerator(arrayTemp);
+                    for (var level = 0; level < mipData.length; level++) {
+                        var mipSize = width >> level;
+                        // mipData is order in +X -X +Y -Y +Z -Z
+                        gl.texImage2D(facesIndex[0], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][0]);
+                        gl.texImage2D(facesIndex[1], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][2]);
+                        gl.texImage2D(facesIndex[2], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][4]);
+                        gl.texImage2D(facesIndex[3], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][1]);
+                        gl.texImage2D(facesIndex[4], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][3]);
+                        gl.texImage2D(facesIndex[5], level, internalSizedFomat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level][5]);
                     }
-                    else {
-                        if (internalFormat === gl.RGB) {
-                            internalFormat = gl.RGBA;
-                            // Data are known to be in +X +Y +Z -X -Y -Z
-                            for (var index = 0; index < facesIndex.length; index++) {
-                                var faceData = rgbeDataArrays[index];
-                                // Create a new RGBA Face.
-                                var newFaceData = new Float32Array(width * height * 4);
-                                for (var x = 0; x < width; x++) {
-                                    for (var y = 0; y < height; y++) {
-                                        var index_1 = (y * width + x) * 3;
-                                        var newIndex = (y * width + x) * 4;
-                                        // Map Old Value to new value.
-                                        newFaceData[newIndex + 0] = faceData[index_1 + 0];
-                                        newFaceData[newIndex + 1] = faceData[index_1 + 1];
-                                        newFaceData[newIndex + 2] = faceData[index_1 + 2];
-                                        // Add fully opaque alpha channel.
-                                        newFaceData[newIndex + 3] = 1;
-                                    }
+                }
+                else {
+                    if (internalFormat === gl.RGB) {
+                        internalFormat = gl.RGBA;
+                        // Data are known to be in +X +Y +Z -X -Y -Z
+                        for (var index = 0; index < facesIndex.length; index++) {
+                            var faceData = rgbeDataArrays[index];
+                            // Create a new RGBA Face.
+                            var newFaceData = new Float32Array(width * height * 4);
+                            for (var x = 0; x < width; x++) {
+                                for (var y = 0; y < height; y++) {
+                                    var index_1 = (y * width + x) * 3;
+                                    var newIndex = (y * width + x) * 4;
+                                    // Map Old Value to new value.
+                                    newFaceData[newIndex + 0] = faceData[index_1 + 0];
+                                    newFaceData[newIndex + 1] = faceData[index_1 + 1];
+                                    newFaceData[newIndex + 2] = faceData[index_1 + 2];
+                                    // Add fully opaque alpha channel.
+                                    newFaceData[newIndex + 3] = 1;
                                 }
-                                // Reupload the face.
-                                gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, newFaceData);
                             }
+                            // Reupload the face.
+                            gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, newFaceData);
                         }
-                        else {
-                            // Data are known to be in +X +Y +Z -X -Y -Z
-                            for (var index = 0; index < facesIndex.length; index++) {
-                                var faceData = rgbeDataArrays[index];
-                                gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, faceData);
-                            }
+                    }
+                    else {
+                        // Data are known to be in +X +Y +Z -X -Y -Z
+                        for (var index = 0; index < facesIndex.length; index++) {
+                            var faceData = rgbeDataArrays[index];
+                            gl.texImage2D(facesIndex[index], 0, internalSizedFomat, width, height, 0, internalFormat, textureType, faceData);
                         }
+                    }
+                    if (!noMipmap && isPot) {
                         gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                     }
-                }
-                else {
-                    noMipmap = true;
+                    else {
+                        noMipmap = true;
+                    }
                 }
                 if (textureType === gl.FLOAT && !_this._caps.textureFloatLinearFiltering) {
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
@@ -10324,6 +10324,7 @@ var BABYLON;
             if (this._show) {
                 this._show = false;
                 this._scene.unregisterBeforeRender(this._renderFunction);
+                this._scene = null;
             }
             if (this._renderLine) {
                 this._renderLine.dispose();
@@ -10333,8 +10334,9 @@ var BABYLON;
         };
         Ray.prototype._render = function () {
             var point = this._renderPoints[1];
+            var len = Math.min(this.length, 1000000);
             point.copyFrom(this.direction);
-            point.scaleInPlace(this.length);
+            point.scaleInPlace(len);
             point.addInPlace(this.origin);
             BABYLON.Mesh.CreateLines("ray", this._renderPoints, this._scene, true, this._renderLine);
         };
@@ -10460,6 +10462,105 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.ray.js.map
 
+var BABYLON;
+(function (BABYLON) {
+    var RayHelper = (function () {
+        function RayHelper(ray) {
+            this.ray = ray;
+        }
+        RayHelper.prototype.show = function (scene, color) {
+            if (!this._renderFunction) {
+                var ray = this.ray;
+                this._renderFunction = this._render.bind(this);
+                this._scene = scene;
+                this._renderPoints = [ray.origin, ray.origin.add(ray.direction.scale(ray.length))];
+                this._renderLine = BABYLON.Mesh.CreateLines("ray", this._renderPoints, scene, true);
+                this._scene.registerBeforeRender(this._renderFunction);
+            }
+            if (color) {
+                this._renderLine.color.copyFrom(color);
+            }
+        };
+        RayHelper.prototype.hide = function () {
+            if (this._renderFunction) {
+                this._scene.unregisterBeforeRender(this._renderFunction);
+                this._scene = null;
+                this._renderFunction = null;
+                this._renderLine.dispose();
+                this._renderLine = null;
+                this._renderPoints = null;
+            }
+        };
+        RayHelper.prototype._render = function () {
+            var ray = this.ray;
+            var point = this._renderPoints[1];
+            var len = Math.min(ray.length, 1000000);
+            point.copyFrom(ray.direction);
+            point.scaleInPlace(len);
+            point.addInPlace(ray.origin);
+            BABYLON.Mesh.CreateLines("ray", this._renderPoints, this._scene, true, this._renderLine);
+        };
+        RayHelper.prototype.attachToMesh = function (mesh, meshSpaceDirection, meshSpaceOrigin, length) {
+            this._attachedToMesh = mesh;
+            var ray = this.ray;
+            if (!ray.direction) {
+                ray.direction = BABYLON.Vector3.Zero();
+            }
+            if (!ray.origin) {
+                ray.origin = BABYLON.Vector3.Zero();
+            }
+            if (length) {
+                ray.length = length;
+            }
+            if (!meshSpaceOrigin) {
+                meshSpaceOrigin = BABYLON.Vector3.Zero();
+            }
+            if (!meshSpaceDirection) {
+                // -1 so that this will work with Mesh.lookAt
+                meshSpaceDirection = new BABYLON.Vector3(0, 0, -1);
+            }
+            if (!this._meshSpaceDirection) {
+                this._meshSpaceDirection = meshSpaceDirection.clone();
+                this._meshSpaceOrigin = meshSpaceOrigin.clone();
+            }
+            else {
+                this._meshSpaceDirection.copyFrom(meshSpaceDirection);
+                this._meshSpaceOrigin.copyFrom(meshSpaceOrigin);
+            }
+            if (!this._updateToMeshFunction) {
+                this._updateToMeshFunction = this._updateToMesh.bind(this);
+                this._attachedToMesh.getScene().registerBeforeRender(this._updateToMeshFunction);
+            }
+            this._updateToMesh();
+        };
+        RayHelper.prototype.detachFromMesh = function () {
+            if (this._attachedToMesh) {
+                this._attachedToMesh.getScene().unregisterBeforeRender(this._updateToMeshFunction);
+                this._attachedToMesh = null;
+                this._updateToMeshFunction = null;
+            }
+        };
+        RayHelper.prototype._updateToMesh = function () {
+            var ray = this.ray;
+            if (this._attachedToMesh._isDisposed) {
+                this.detachFromMesh();
+                return;
+            }
+            this._attachedToMesh.getDirectionToRef(this._meshSpaceDirection, ray.direction);
+            BABYLON.Vector3.TransformCoordinatesToRef(this._meshSpaceOrigin, this._attachedToMesh.getWorldMatrix(), ray.origin);
+        };
+        RayHelper.prototype.dispose = function () {
+            this.hide();
+            this.detachFromMesh();
+            this.ray = null;
+        };
+        return RayHelper;
+    }());
+    BABYLON.RayHelper = RayHelper;
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=babylon.rayHelper.js.map
+
 
 var BABYLON;
 (function (BABYLON) {
@@ -20069,6 +20170,14 @@ var BABYLON;
             _this._partitioningSubdivisions = 10; // number of subdivisions per axis in the partioning space  
             _this._partitioningBBoxRatio = 1.01; // the partioning array space is by default 1% bigger than the bounding box
             _this._facetDataEnabled = false; // is the facet data feature enabled on this mesh ?
+            _this._facetParameters = {}; // keep a reference to the object parameters to avoid memory re-allocation
+            _this._bbSize = BABYLON.Vector3.Zero(); // bbox size approximated for facet data
+            _this._subDiv = {
+                max: 1,
+                X: 1,
+                Y: 1,
+                Z: 1
+            };
             // Will be used to save a source mesh reference, If any
             _this._source = null;
             if (source) {
@@ -21291,6 +21400,10 @@ var BABYLON;
                     highlightLayer.removeExcludedMesh(this);
                 }
             }
+            // facet data
+            if (this._facetDataEnabled) {
+                this.disableFacetData();
+            }
             _super.prototype.dispose.call(this, doNotRecurse);
         };
         /**
@@ -21652,8 +21765,28 @@ var BABYLON;
             var positions = this.getVerticesData(BABYLON.VertexBuffer.PositionKind);
             var indices = this.getIndices();
             var normals = this.getVerticesData(BABYLON.VertexBuffer.NormalKind);
-            var options = this.getFacetDataParameters();
-            BABYLON.VertexData.ComputeNormals(positions, indices, normals, options);
+            var bInfo = this.getBoundingInfo();
+            this._bbSize.x = (bInfo.maximum.x - bInfo.minimum.x > BABYLON.Epsilon) ? bInfo.maximum.x - bInfo.minimum.x : BABYLON.Epsilon;
+            this._bbSize.y = (bInfo.maximum.y - bInfo.minimum.y > BABYLON.Epsilon) ? bInfo.maximum.y - bInfo.minimum.y : BABYLON.Epsilon;
+            this._bbSize.z = (bInfo.maximum.z - bInfo.minimum.z > BABYLON.Epsilon) ? bInfo.maximum.z - bInfo.minimum.z : BABYLON.Epsilon;
+            var bbSizeMax = (this._bbSize.x > this._bbSize.y) ? this._bbSize.x : this._bbSize.y;
+            bbSizeMax = (bbSizeMax > this._bbSize.z) ? bbSizeMax : this._bbSize.z;
+            this._subDiv.max = this._partitioningSubdivisions;
+            this._subDiv.X = Math.floor(this._subDiv.max * this._bbSize.x / bbSizeMax); // adjust the number of subdivisions per axis
+            this._subDiv.Y = Math.floor(this._subDiv.max * this._bbSize.y / bbSizeMax); // according to each bbox size per axis
+            this._subDiv.Z = Math.floor(this._subDiv.max * this._bbSize.z / bbSizeMax);
+            this._subDiv.X = this._subDiv.X < 1 ? 1 : this._subDiv.X; // at least one subdivision
+            this._subDiv.Y = this._subDiv.Y < 1 ? 1 : this._subDiv.Y;
+            this._subDiv.Z = this._subDiv.Z < 1 ? 1 : this._subDiv.Z;
+            // set the parameters for ComputeNormals()
+            this._facetParameters.facetNormals = this.getFacetLocalNormals();
+            this._facetParameters.facetPositions = this.getFacetLocalPositions();
+            this._facetParameters.facetPartitioning = this.getFacetLocalPartitioning();
+            this._facetParameters.bInfo = bInfo;
+            this._facetParameters.bbSize = this._bbSize;
+            this._facetParameters.subDiv = this._subDiv;
+            this._facetParameters.ratio = this.partitioningBBoxRatio;
+            BABYLON.VertexData.ComputeNormals(positions, indices, normals, this._facetParameters);
             return this;
         };
         /**
@@ -21719,15 +21852,8 @@ var BABYLON;
          */
         Mesh.prototype.getFacetNormalToRef = function (i, ref) {
             var localNorm = (this.getFacetLocalNormals())[i];
-            var localPos = (this.getFacetLocalPositions())[i];
-            var world = this.getWorldMatrix();
-            var x = localPos.x + localNorm.x;
-            var y = localPos.y + localNorm.y;
-            var z = localPos.z + localNorm.z;
-            BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, world, ref);
-            var worldPos = BABYLON.Tmp.Vector3[8];
-            this.getFacetPositionToRef(i, worldPos);
-            ref.subtractInPlace(worldPos);
+            (this.getWorldMatrix()).getRotationMatrixToRef(BABYLON.Tmp.Matrix[0]);
+            BABYLON.Vector3.TransformCoordinatesToRef(localNorm, BABYLON.Tmp.Matrix[0], ref);
             return this;
         };
         /**
@@ -21735,28 +21861,31 @@ var BABYLON;
          */
         Mesh.prototype.getFacetsAtLocalCoordinates = function (x, y, z) {
             var bInfo = this.getBoundingInfo();
-            var subRatio = this._partitioningSubdivisions * this._partitioningBBoxRatio;
-            var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) / (bInfo.maximum.x - bInfo.minimum.x) * subRatio);
-            var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) / (bInfo.maximum.y - bInfo.minimum.y) * subRatio);
-            var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) / (bInfo.maximum.z - bInfo.minimum.z) * subRatio);
-            if (ox < 0 || ox > this._partitioningSubdivisions || oy < 0 || oy > this._partitioningSubdivisions || oz < 0 || oz > this._partitioningSubdivisions) {
+            var ox = Math.floor((x - bInfo.minimum.x * this._partitioningBBoxRatio) * this._subDiv.X * this._partitioningBBoxRatio / this._bbSize.x);
+            var oy = Math.floor((y - bInfo.minimum.y * this._partitioningBBoxRatio) * this._subDiv.Y * this._partitioningBBoxRatio / this._bbSize.y);
+            var oz = Math.floor((z - bInfo.minimum.z * this._partitioningBBoxRatio) * this._subDiv.Z * this._partitioningBBoxRatio / this._bbSize.z);
+            if (ox < 0 || ox > this._subDiv.max || oy < 0 || oy > this._subDiv.max || oz < 0 || oz > this._subDiv.max) {
                 return null;
             }
-            return this._facetPartitioning[ox + this._partitioningSubdivisions * oy + this._partitioningSubdivisions * this._partitioningSubdivisions * oz];
+            return this._facetPartitioning[ox + this._subDiv.max * oy + this._subDiv.max * this._subDiv.max * oz];
         };
         /**
          * Returns the closest mesh facet index at (x,y,z) World coordinates, null if not found.
          * If the parameter projected (vector3) is passed, it is set as the (x,y,z) World projection on the facet.
-         * If onlyFacing is true, only the facet "facing" (x,y,z) are returned : positive dot normal * (x,y,z).
+         * If checkFace is true (default false), only the facet "facing" to (x,y,z) or only the ones "turning their backs", according to the parameter "facing" are returned.
+         * If facing and checkFace are true, only the facet "facing" to (x, y, z) are returned : positive dot (x, y, z) * facet position.
+         * If facing si false and checkFace is true, only the facet "turning their backs" to (x, y, z) are returned : negative dot (x, y, z) * facet position.
          */
-        Mesh.prototype.getClosestFacetAtCoordinates = function (x, y, z, projected, onlyFacing) {
+        Mesh.prototype.getClosestFacetAtCoordinates = function (x, y, z, projected, checkFace, facing) {
+            if (checkFace === void 0) { checkFace = false; }
+            if (facing === void 0) { facing = true; }
             var world = this.getWorldMatrix();
             var invMat = BABYLON.Tmp.Matrix[5];
             world.invertToRef(invMat);
             var invVect = BABYLON.Tmp.Vector3[8];
             var closest = null;
             BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(x, y, z, invMat, invVect); // transform (x,y,z) to coordinates in the mesh local space
-            closest = this.getClosestFacetAtLocalCoordinates(invVect.x, invVect.y, invVect.z, projected, onlyFacing);
+            closest = this.getClosestFacetAtLocalCoordinates(invVect.x, invVect.y, invVect.z, projected, checkFace, facing);
             if (projected) {
                 // tranform the local computed projected vector to world coordinates
                 BABYLON.Vector3.TransformCoordinatesFromFloatsToRef(projected.x, projected.y, projected.z, world, projected);
@@ -21766,9 +21895,13 @@ var BABYLON;
         /**
          * Returns the closest mesh facet index at (x,y,z) local coordinates, null if not found.
          * If the parameter projected (vector3) is passed, it is set as the (x,y,z) local projection on the facet.
-         * If onlyFacing is true, only the facet "facing" (x,y,z) are returned : positive dot normal * (x,y,z).
+         * If checkFace is true (default false), only the facet "facing" to (x,y,z) or only the ones "turning their backs", according to the parameter "facing" are returned.
+         * If facing and checkFace are true, only the facet "facing" to (x, y, z) are returned : positive dot (x, y, z) * facet position.
+         * If facing si false and checkFace is true, only the facet "turning their backs"  to (x, y, z) are returned : negative dot (x, y, z) * facet position.
          */
-        Mesh.prototype.getClosestFacetAtLocalCoordinates = function (x, y, z, projected, onlyFacing) {
+        Mesh.prototype.getClosestFacetAtLocalCoordinates = function (x, y, z, projected, checkFace, facing) {
+            if (checkFace === void 0) { checkFace = false; }
+            if (facing === void 0) { facing = true; }
             var closest = null;
             var tmpx = 0.0;
             var tmpy = 0.0;
@@ -21797,7 +21930,7 @@ var BABYLON;
                 norm = facetNormals[fib];
                 p0 = facetPositions[fib];
                 d = (x - p0.x) * norm.x + (y - p0.y) * norm.y + (z - p0.z) * norm.z;
-                if (!onlyFacing || (onlyFacing && d >= 0)) {
+                if (!checkFace || (checkFace && facing && d >= 0.0) || (checkFace && !facing && d <= 0.0)) {
                     // compute (x,y,z) projection on the facet = (projx, projy, projz)
                     d = norm.x * p0.x + norm.y * p0.y + norm.z * p0.z;
                     t0 = -(norm.x * x + norm.y * y + norm.z * z - d) / (norm.x * norm.x + norm.y * norm.y + norm.z * norm.z);
@@ -21825,16 +21958,6 @@ var BABYLON;
          * Returns the object "parameter" set with all the expected parameters for facetData computation by ComputeNormals()
          */
         Mesh.prototype.getFacetDataParameters = function () {
-            if (!this._facetParameters) {
-                this._facetParameters = {
-                    facetNormals: this.getFacetLocalNormals(),
-                    facetPositions: this.getFacetLocalPositions(),
-                    facetPartitioning: this.getFacetLocalPartitioning(),
-                    bInfo: this.getBoundingInfo(),
-                    partitioningSubdivisions: this.partitioningSubdivisions,
-                    ratio: this.partitioningBBoxRatio
-                };
-            }
             return this._facetParameters;
         };
         /**
@@ -21842,11 +21965,13 @@ var BABYLON;
          * Returns the mesh.
          */
         Mesh.prototype.disableFacetData = function () {
-            this._facetDataEnabled = false;
-            this._facetPositions = null;
-            this._facetNormals = null;
-            this._facetPartitioning = null;
-            this._facetParameters = null;
+            if (this._facetDataEnabled) {
+                this._facetDataEnabled = false;
+                this._facetPositions = null;
+                this._facetNormals = null;
+                this._facetPartitioning = null;
+                this._facetParameters = null;
+            }
             return this;
         };
         // Statics
@@ -35019,9 +35144,10 @@ var BABYLON;
          * facetPositions : optional array of facet positions (vector3)
          * facetNormals : optional array of facet normals (vector3)
          * facetPartitioning : optional partitioning array. facetPositions is required for facetPartitioning computation
-         * partitioningSubdivisions : optional partitioning number of subdivsions on  each axis (int), required for facetPartitioning computation
+         * subDiv : optional partitioning data about subdivsions on  each axis (int), required for facetPartitioning computation
          * ratio : optional partitioning ratio / bounding box, required for facetPartitioning computation
-         * bInfo : optional bounding box info, required for facetPartitioning computation
+         * bbSize : optional bounding box size data, required for facetPartitioning computation
+         * bInfo : optional bounding info, required for facetPartitioning computation
          */
         VertexData.ComputeNormals = function (positions, indices, normals, options) {
             // temporary scalar variables
@@ -35071,10 +35197,12 @@ var BABYLON;
                 var block_idx_v1 = 0; // v1 vertex block index
                 var block_idx_v2 = 0; // v2 vertex block index
                 var block_idx_v3 = 0; // v3 vertex block index  
-                var xSubRatio = 0.0; // tmp x divider
-                var ySubRatio = 0.0; // tmp x divider
-                var zSubRatio = 0.0; // tmp x divider  
-                var subSq = options.partitioningSubdivisions * options.partitioningSubdivisions;
+                var bbSizeMax = (options.bbSize.x > options.bbSize.y) ? options.bbSize.x : options.bbSize.y;
+                bbSizeMax = (bbSizeMax > options.bbSize.z) ? bbSizeMax : options.bbSize.z;
+                var xSubRatio = options.subDiv.X * options.ratio / options.bbSize.x;
+                var ySubRatio = options.subDiv.Y * options.ratio / options.bbSize.y;
+                var zSubRatio = options.subDiv.Z * options.ratio / options.bbSize.z;
+                var subSq = options.subDiv.max * options.subDiv.max;
                 options.facetPartitioning.length = 0;
             }
             // reset the normals
@@ -35124,9 +35252,6 @@ var BABYLON;
                 if (computeFacetPartitioning) {
                     // store the facet indexes in arrays in the main facetPartitioning array :
                     // compute each facet vertex (+ facet barycenter) index in the partiniong array
-                    xSubRatio = options.partitioningSubdivisions * options.ratio / (options.bInfo.maximum.x - options.bInfo.minimum.x);
-                    ySubRatio = options.partitioningSubdivisions * options.ratio / (options.bInfo.maximum.y - options.bInfo.minimum.y);
-                    zSubRatio = options.partitioningSubdivisions * options.ratio / (options.bInfo.maximum.z - options.bInfo.minimum.z);
                     ox = Math.floor((options.facetPositions[index].x - options.bInfo.minimum.x * options.ratio) * xSubRatio);
                     oy = Math.floor((options.facetPositions[index].y - options.bInfo.minimum.y * options.ratio) * ySubRatio);
                     oz = Math.floor((options.facetPositions[index].z - options.bInfo.minimum.z * options.ratio) * zSubRatio);
@@ -35139,10 +35264,10 @@ var BABYLON;
                     b3x = Math.floor((positions[v3x] - options.bInfo.minimum.x * options.ratio) * xSubRatio);
                     b3y = Math.floor((positions[v3y] - options.bInfo.minimum.y * options.ratio) * ySubRatio);
                     b3z = Math.floor((positions[v3z] - options.bInfo.minimum.z * options.ratio) * zSubRatio);
-                    block_idx_v1 = b1x + options.partitioningSubdivisions * b1y + subSq * b1z;
-                    block_idx_v2 = b2x + options.partitioningSubdivisions * b2y + subSq * b2z;
-                    block_idx_v3 = b3x + options.partitioningSubdivisions * b3y + subSq * b3z;
-                    block_idx_o = ox + options.partitioningSubdivisions * oy + subSq * oz;
+                    block_idx_v1 = b1x + options.subDiv.max * b1y + subSq * b1z;
+                    block_idx_v2 = b2x + options.subDiv.max * b2y + subSq * b2z;
+                    block_idx_v3 = b3x + options.subDiv.max * b3y + subSq * b3z;
+                    block_idx_o = ox + options.subDiv.max * oy + subSq * oz;
                     options.facetPartitioning[block_idx_o] = options.facetPartitioning[block_idx_o] ? options.facetPartitioning[block_idx_o] : new Array();
                     options.facetPartitioning[block_idx_v1] = options.facetPartitioning[block_idx_v1] ? options.facetPartitioning[block_idx_v1] : new Array();
                     options.facetPartitioning[block_idx_v2] = options.facetPartitioning[block_idx_v2] ? options.facetPartitioning[block_idx_v2] : new Array();
@@ -48359,6 +48484,7 @@ var BABYLON;
             if (disableDepthRender)
                 this._scene.disableDepthRenderer();
             this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
+            _super.prototype.dispose.call(this);
         };
         // Private Methods
         SSAORenderingPipeline.prototype._createBlurPostProcess = function (ratio) {
@@ -49501,17 +49627,21 @@ var BABYLON;
         * Releases the rendering pipeline and its internal effects. Detaches pipeline from cameras
         */
         HDRRenderingPipeline.prototype.dispose = function () {
-            this._originalPostProcess = undefined;
-            this._brightPassPostProcess = undefined;
-            this._downSampleX4PostProcess = undefined;
-            this._guassianBlurHPostProcess = undefined;
-            this._guassianBlurVPostProcess = undefined;
-            this._textureAdderPostProcess = undefined;
-            for (var i = HDRRenderingPipeline.LUM_STEPS - 1; i >= 0; i--) {
-                this._downSamplePostProcesses[i] = undefined;
+            for (var i = 0; i < this._scene.cameras.length; i++) {
+                var camera = this._scene.cameras[i];
+                this._originalPostProcess.dispose(camera);
+                this._brightPassPostProcess.dispose(camera);
+                this._downSampleX4PostProcess.dispose(camera);
+                this._guassianBlurHPostProcess.dispose(camera);
+                this._guassianBlurVPostProcess.dispose(camera);
+                this._textureAdderPostProcess.dispose(camera);
+                for (var j = HDRRenderingPipeline.LUM_STEPS - 1; j >= 0; j--) {
+                    this._downSamplePostProcesses[j].dispose(camera);
+                }
+                this._hdrPostProcess.dispose(camera);
             }
-            this._hdrPostProcess = undefined;
             this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras);
+            _super.prototype.dispose.call(this);
         };
         /**
         * Creates the HDR post-process and computes the luminance adaptation
@@ -50813,7 +50943,6 @@ var BABYLON;
                             }
                         }
                         // normals : if the particles can't be morphed then just rotate the normals, what is much more faster than ComputeNormals()
-                        // the same for the facet data
                         if (!this._computeParticleVertex) {
                             this._normal.x = this._fixedNormal32[idx];
                             this._normal.y = this._fixedNormal32[idx + 1];
@@ -53005,7 +53134,7 @@ var BABYLON;
             var texture = null;
             if (parsedTexture.name && !parsedTexture.isRenderTarget) {
                 var size = parsedTexture.isBABYLONPreprocessed ? null : parsedTexture.size;
-                texture = new BABYLON.HDRCubeTexture(rootUrl + parsedTexture.name, scene, size, parsedTexture.generateHarmonics, parsedTexture.useInGammaSpace, parsedTexture.usePMREMGenerator);
+                texture = new BABYLON.HDRCubeTexture(rootUrl + parsedTexture.name, scene, size, parsedTexture.noMipmap, parsedTexture.generateHarmonics, parsedTexture.useInGammaSpace, parsedTexture.usePMREMGenerator);
                 texture.name = parsedTexture.name;
                 texture.hasAlpha = parsedTexture.hasAlpha;
                 texture.level = parsedTexture.level;
@@ -53029,6 +53158,7 @@ var BABYLON;
             serializationObject.usePMREMGenerator = this._usePMREMGenerator;
             serializationObject.isBABYLONPreprocessed = this._isBABYLONPreprocessed;
             serializationObject.customType = "BABYLON.HDRCubeTexture";
+            serializationObject.noMipmap = this._noMipmap;
             return serializationObject;
         };
         /**

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


+ 27 - 1
dist/preview release/canvas2D/babylon.canvas2d.d.ts

@@ -678,11 +678,36 @@ declare module BABYLON {
          */
         max(): Vector2;
         /**
+         * return the min/max extend of the bounding info.
+         * x, y, z, w are left, bottom, right and top
+         */
+        minMax(): Vector4;
+        /**
          * Update a vector2 with the max extend of the bounding info
          * @param result must be a valid/allocated vector2 that will contain the result of the operation
          */
         maxToRef(result: Vector2): void;
         /**
+         * Update a vector4 with the min/max extend of the bounding info
+         * x, y, z, w are left, bottom, right and top
+         * @param result must be a valid/allocated vector4 that will contain the result of the operation
+         */
+        minMaxToRef(result: Vector4): void;
+        /**
+         * Return the size of the boundingInfo rect surface
+         */
+        size(): Size;
+        /**
+         * Stores in the result object the size of the boundingInfo rect surface
+         * @param result
+         */
+        sizeToRef(result: Size): void;
+        /**
+         * Inflate the boundingInfo with the given vector
+         * @param offset the extent will be incremented with offset and the radius will be computed again
+         */
+        inflate(offset: Vector2): void;
+        /**
          * Apply a transformation matrix to this BoundingInfo2D and return a new instance containing the result
          * @param matrix the transformation matrix to apply
          * @return the new instance containing the result of the transformation applied on this BoundingInfo2D
@@ -2008,7 +2033,9 @@ declare module BABYLON {
          * Get the local transformation of the primitive
          */
         readonly localTransform: Matrix;
+        private static _bMinMax;
         private static _bMax;
+        private static _bSize;
         private static _tpsBB;
         /**
          * Get the boundingInfo associated to the primitive and its children.
@@ -3685,7 +3712,6 @@ declare module BABYLON {
         private _debugExecObserver(prim, mask);
         private _bubbleNotifyPrimPointerObserver(prim, mask, eventData);
         private _triggerActionManager(prim, ppi, mask, eventData);
-        _notifParents(prim: Prim2DBase, mask: number): void;
         /**
          * Don't forget to call the dispose method when you're done with the Canvas instance.
          * But don't worry, if you dispose its scene, the canvas will be automatically disposed too.

+ 158 - 78
dist/preview release/canvas2D/babylon.canvas2d.js

@@ -1905,6 +1905,15 @@ var BABYLON;
             return r;
         };
         /**
+         * return the min/max extend of the bounding info.
+         * x, y, z, w are left, bottom, right and top
+         */
+        BoundingInfo2D.prototype.minMax = function () {
+            var r = BABYLON.Vector4.Zero();
+            this.minMaxToRef(r);
+            return r;
+        };
+        /**
          * Update a vector2 with the max extend of the bounding info
          * @param result must be a valid/allocated vector2 that will contain the result of the operation
          */
@@ -1913,6 +1922,41 @@ var BABYLON;
             result.y = this.center.y + this.extent.y;
         };
         /**
+         * Update a vector4 with the min/max extend of the bounding info
+         * x, y, z, w are left, bottom, right and top
+         * @param result must be a valid/allocated vector4 that will contain the result of the operation
+         */
+        BoundingInfo2D.prototype.minMaxToRef = function (result) {
+            result.x = this.center.x - this.extent.x;
+            result.y = this.center.y - this.extent.y;
+            result.z = this.center.x + this.extent.x;
+            result.w = this.center.y + this.extent.y;
+        };
+        /**
+         * Return the size of the boundingInfo rect surface
+         */
+        BoundingInfo2D.prototype.size = function () {
+            var r = BABYLON.Size.Zero();
+            this.sizeToRef(r);
+            return r;
+        };
+        /**
+         * Stores in the result object the size of the boundingInfo rect surface
+         * @param result
+         */
+        BoundingInfo2D.prototype.sizeToRef = function (result) {
+            result.width = this.extent.x * 2;
+            result.height = this.extent.y * 2;
+        };
+        /**
+         * Inflate the boundingInfo with the given vector
+         * @param offset the extent will be incremented with offset and the radius will be computed again
+         */
+        BoundingInfo2D.prototype.inflate = function (offset) {
+            this.extent.addInPlace(offset);
+            this.radius = this.extent.length();
+        };
+        /**
          * Apply a transformation matrix to this BoundingInfo2D and return a new instance containing the result
          * @param matrix the transformation matrix to apply
          * @return the new instance containing the result of the transformation applied on this BoundingInfo2D
@@ -4928,7 +4972,7 @@ var BABYLON;
                     var child = _a[_i];
                     _this.addChild(child);
                     // Good time to patch the hierarchy, it won't go very far if there's no need to
-                    if (_this.owner != null) {
+                    if (_this.owner != null && _this._hierarchyDepth != null) {
                         child._patchHierarchy(_this.owner);
                     }
                 }
@@ -5868,7 +5912,8 @@ var BABYLON;
                     if (this.owner) {
                         this.owner.boundingInfoRecomputeCounter.addCount(1, false);
                     }
-                    if (this.isSizedByContent) {
+                    var sizedByContent = this.isSizedByContent;
+                    if (sizedByContent) {
                         this._boundingInfo.clear();
                     }
                     else {
@@ -5882,8 +5927,24 @@ var BABYLON;
                         bb.transformToRef(curChild.localTransform, tps);
                         bi.unionToRef(tps, bi);
                     }
-                    this._boundingInfo.maxToRef(Prim2DBase_1._bMax);
-                    this._boundingSize.copyFromFloats((!this._size || this._size.width == null) ? Math.ceil(Prim2DBase_1._bMax.x) : this._size.width, (!this._size || this._size.height == null) ? Math.ceil(Prim2DBase_1._bMax.y) : this._size.height);
+                    // If the size is determined by the content we have to update the contentArea
+                    //  and compute the size considering the padding (if any)
+                    if (sizedByContent) {
+                        bi.maxToRef(Prim2DBase_1._bMax);
+                        this._contentArea.width = Prim2DBase_1._bMax.x;
+                        this._contentArea.height = Prim2DBase_1._bMax.y;
+                        if (this._hasPadding) {
+                            var padding = this.padding;
+                            var mm = Prim2DBase_1._bMinMax;
+                            bi.minMaxToRef(mm);
+                            mm.z += padding.leftPixels + padding.rightPixels;
+                            mm.w += padding.bottomPixels + padding.topPixels;
+                            this._paddingOffset.copyFromFloats(padding.leftPixels, padding.bottomPixels, padding.rightPixels, padding.topPixels);
+                            BABYLON.BoundingInfo2D.CreateFromMinMaxToRef(mm.x, mm.z, mm.y, mm.w, bi);
+                        }
+                    }
+                    this._boundingInfo.sizeToRef(Prim2DBase_1._bSize);
+                    this._boundingSize.copyFromFloats((!this._size || this._size.width == null) ? Math.ceil(Prim2DBase_1._bSize.width) : this._size.width, (!this._size || this._size.height == null) ? Math.ceil(Prim2DBase_1._bSize.height) : this._size.height);
                     this._clearFlags(BABYLON.SmartPropertyPrim.flagBoundingInfoDirty);
                 }
                 return this._boundingInfo;
@@ -6666,11 +6727,6 @@ var BABYLON;
             if (this._hasPadding) {
                 // Two cases from here: the size of the Primitive is Auto, its content can't be shrink, so we resize the primitive itself
                 if (isSizeAuto) {
-                    var content = this.size.clone();
-                    this._getActualSizeFromContentToRef(content, Prim2DBase_1._icArea);
-                    this.padding.enlarge(Prim2DBase_1._icArea, this._paddingOffset, Prim2DBase_1._size);
-                    this._contentArea.copyFrom(content);
-                    this.actualSize = Prim2DBase_1._size.clone();
                     // Changing the padding has resize the prim, which forces us to recompute margin again
                     if (this._hasMargin) {
                         this.margin.computeWithAlignment(this.layoutArea, Prim2DBase_1._size, this.marginAlignment, this._marginOffset, Prim2DBase_1._size);
@@ -6715,6 +6771,19 @@ var BABYLON;
              * Children of this primitive will be positioned relative to the bottom/left corner of this area.
              */
             get: function () {
+                if (!this._size || this._size.width == null || this._size.height == null) {
+                    if (Prim2DBase_1.boundinbBoxReentrency) {
+                        return Prim2DBase_1.nullSize;
+                    }
+                    if (!this._isFlagSet(BABYLON.SmartPropertyPrim.flagBoundingInfoDirty)) {
+                        return this._boundingSize;
+                    }
+                    Prim2DBase_1.boundinbBoxReentrency = true;
+                    var b = this.boundingInfo;
+                    Prim2DBase_1.boundinbBoxReentrency = false;
+                    return this._contentArea;
+                }
+                else 
                 // Check for positioning update
                 if (this._isFlagSet(BABYLON.SmartPropertyPrim.flagPositioningDirty)) {
                     this._updatePositioning();
@@ -6921,7 +6990,9 @@ var BABYLON;
     Prim2DBase._nullPosition = BABYLON.Vector2.Zero();
     Prim2DBase.boundinbBoxReentrency = false;
     Prim2DBase.nullSize = BABYLON.Size.Zero();
+    Prim2DBase._bMinMax = BABYLON.Vector4.Zero();
     Prim2DBase._bMax = BABYLON.Vector2.Zero();
+    Prim2DBase._bSize = BABYLON.Size.Zero();
     Prim2DBase._tpsBB = new BABYLON.BoundingInfo2D();
     /**
      * Make an intersection test with the primitive, all inputs/outputs are stored in the IntersectInfo2D class, see its documentation for more information.
@@ -8208,8 +8279,8 @@ var BABYLON;
             var w = size.width;
             var h = size.height;
             var invZBias = 1 / zBias;
-            var tx = new BABYLON.Vector4(t.m[0] * rgScale.x * 2 / w, t.m[4] * rgScale.x * 2 / w, 0 /*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
-            var ty = new BABYLON.Vector4(t.m[1] * rgScale.y * 2 / h, t.m[5] * rgScale.y * 2 / h, 0 /*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
+            var tx = new BABYLON.Vector4(t.m[0] * rgScale.x * 2 /* / w*/, t.m[4] * rgScale.x * 2 /* / w*/, 0 /*t.m[8]*/, ((t.m[12] + offX) * rgScale.x * 2 / w) - 1);
+            var ty = new BABYLON.Vector4(t.m[1] * rgScale.y * 2 /* / h*/, t.m[5] * rgScale.y * 2 /* / h*/, 0 /*t.m[9]*/, ((t.m[13] + offY) * rgScale.y * 2 / h) - 1);
             if (!this.applyActualScaleOnTransform()) {
                 t.m[0] = tx.x, t.m[4] = tx.y, t.m[12] = tx.w;
                 t.m[1] = ty.x, t.m[5] = ty.y, t.m[13] = ty.w;
@@ -8220,6 +8291,10 @@ var BABYLON;
                 tx = new BABYLON.Vector4(t.m[0], t.m[4], 0, t.m[12]);
                 ty = new BABYLON.Vector4(t.m[1], t.m[5], 0, t.m[13]);
             }
+            tx.x /= w;
+            tx.y /= w;
+            ty.x /= h;
+            ty.y /= h;
             part.transformX = tx;
             part.transformY = ty;
             part.opacity = this.actualOpacity;
@@ -13000,7 +13075,9 @@ var BABYLON;
             _this._renderingSize = new BABYLON.Size(0, 0);
             _this._designSize = settings.designSize || null;
             _this._designUseHorizAxis = settings.designUseHorizAxis === true;
-            _this._trackedGroups = new Array();
+            if (!_this._trackedGroups) {
+                _this._trackedGroups = new Array();
+            }
             _this._maxAdaptiveWorldSpaceCanvasSize = null;
             _this._groupCacheMaps = new BABYLON.StringDictionary();
             _this._patchHierarchy(_this);
@@ -13356,6 +13433,8 @@ var BABYLON;
             else {
                 // The pointer is inside the Canvas, do an intersection test
                 this.intersect(ii);
+                // Sort primitives to get them from top to bottom
+                ii.intersectedPrimitives = ii.intersectedPrimitives.sort(function (a, b) { return a.prim.actualZOffset - b.prim.actualZOffset; });
             }
             {
                 // Update prev/actual intersection info, fire "overPrim" property change if needed
@@ -13382,15 +13461,42 @@ var BABYLON;
             if (prevPrim !== actualPrim) {
                 // Detect if the current pointer is captured, only fire event if they belong to the capture primitive
                 var capturedPrim = this.getCapturedPrimitive(this._primPointerInfo.pointerId);
-                // Notify the previous "over" prim that the pointer is no longer over it
-                if ((capturedPrim && capturedPrim === prevPrim) || (!capturedPrim && prevPrim && !prevPrim.isDisposed)) {
-                    this._primPointerInfo.updateRelatedTarget(prevPrim, this._previousOverPrimitive.intersectionLocation);
-                    this._bubbleNotifyPrimPointerObserver(prevPrim, BABYLON.PrimitivePointerInfo.PointerOut, null);
+                // See the NOTE section of: https://www.w3.org/TR/pointerevents/#setting-pointer-capture
+                if (capturedPrim) {
+                    if (capturedPrim === prevPrim) {
+                        this._primPointerInfo.updateRelatedTarget(prevPrim, this._previousOverPrimitive.intersectionLocation);
+                        this._bubbleNotifyPrimPointerObserver(prevPrim, BABYLON.PrimitivePointerInfo.PointerOut, null);
+                    }
+                    else if (capturedPrim === actualPrim) {
+                        this._primPointerInfo.updateRelatedTarget(actualPrim, this._actualOverPrimitive.intersectionLocation);
+                        this._bubbleNotifyPrimPointerObserver(actualPrim, BABYLON.PrimitivePointerInfo.PointerOver, null);
+                    }
                 }
-                // Notify the new "over" prim that the pointer is over it
-                if ((capturedPrim && capturedPrim === actualPrim) || (!capturedPrim && actualPrim)) {
-                    this._primPointerInfo.updateRelatedTarget(actualPrim, this._actualOverPrimitive.intersectionLocation);
-                    this._bubbleNotifyPrimPointerObserver(actualPrim, BABYLON.PrimitivePointerInfo.PointerOver, null);
+                else {
+                    var _loop_1 = function (prev) {
+                        if (!BABYLON.Tools.first(this_1._actualIntersectionList, function (pii) { return pii.prim === prev.prim; })) {
+                            this_1._primPointerInfo.updateRelatedTarget(prev.prim, prev.intersectionLocation);
+                            this_1._bubbleNotifyPrimPointerObserver(prev.prim, BABYLON.PrimitivePointerInfo.PointerOut, null);
+                        }
+                    };
+                    var this_1 = this;
+                    // Check for Out & Leave
+                    for (var _i = 0, _a = this._previousIntersectionList; _i < _a.length; _i++) {
+                        var prev = _a[_i];
+                        _loop_1(prev);
+                    }
+                    var _loop_2 = function (actual) {
+                        if (!BABYLON.Tools.first(this_2._previousIntersectionList, function (pii) { return pii.prim === actual.prim; })) {
+                            this_2._primPointerInfo.updateRelatedTarget(actual.prim, actual.intersectionLocation);
+                            this_2._bubbleNotifyPrimPointerObserver(actual.prim, BABYLON.PrimitivePointerInfo.PointerOver, null);
+                        }
+                    };
+                    var this_2 = this;
+                    // Check for Over & Enter
+                    for (var _b = 0, _c = this._actualIntersectionList; _b < _c.length; _b++) {
+                        var actual = _c[_b];
+                        _loop_2(actual);
+                    }
                 }
             }
             this._hoverStatusRenderId = this.scene.getRenderId();
@@ -13418,54 +13524,39 @@ var BABYLON;
                 debug += "  ";
             }
             var pii = this._primPointerInfo;
-            debug += "[RID:" + this.scene.getRenderId() + "] [" + prim.hierarchyDepth + "] event:" + BABYLON.PrimitivePointerInfo.getEventTypeName(mask) + ", id: " + prim.id + " (" + BABYLON.Tools.getClassName(prim) + "), primPos: " + pii.primitivePointerPos.toString() + ", canvasPos: " + pii.canvasPointerPos.toString();
+            debug += "[RID:" + this.scene.getRenderId() + "] [" + prim.hierarchyDepth + "] event:" + BABYLON.PrimitivePointerInfo.getEventTypeName(mask) + ", id: " + prim.id + " (" + BABYLON.Tools.getClassName(prim) + "), primPos: " + pii.primitivePointerPos.toString() + ", canvasPos: " + pii.canvasPointerPos.toString() + ", relatedTarget: " + pii.relatedTarget.id;
             console.log(debug);
         };
         Canvas2D.prototype._bubbleNotifyPrimPointerObserver = function (prim, mask, eventData) {
             var ppi = this._primPointerInfo;
             var event = eventData ? eventData.event : null;
-            // In case of PointerOver/Out we will first notify the parent with PointerEnter/Leave
-            if ((mask & (BABYLON.PrimitivePointerInfo.PointerOver | BABYLON.PrimitivePointerInfo.PointerOut)) !== 0) {
-                this._notifParents(prim, mask);
-            }
-            var bubbleCancelled = false;
             var cur = prim;
             while (cur && !cur.isDisposed) {
-                // Only trigger the observers if the primitive is intersected (except for out)
-                if (!bubbleCancelled) {
-                    this._updatePrimPointerPos(cur);
-                    // Exec the observers
-                    this._debugExecObserver(cur, mask);
-                    if (!cur._pointerEventObservable.notifyObservers(ppi, mask) && eventData instanceof BABYLON.PointerInfoPre) {
-                        eventData.skipOnPointerObservable = true;
-                        return false;
+                this._updatePrimPointerPos(cur);
+                // For the first level we have to fire Enter or Leave for corresponding Over or Out
+                if (cur === prim) {
+                    // Fire the proper notification
+                    if (mask === BABYLON.PrimitivePointerInfo.PointerOver) {
+                        this._debugExecObserver(prim, BABYLON.PrimitivePointerInfo.PointerEnter);
+                        prim._pointerEventObservable.notifyObservers(ppi, BABYLON.PrimitivePointerInfo.PointerEnter);
                     }
-                    this._triggerActionManager(cur, ppi, mask, event);
-                    // Bubble canceled? If we're not executing PointerOver or PointerOut, quit immediately
-                    // If it's PointerOver/Out we have to trigger PointerEnter/Leave no matter what
-                    if (ppi.cancelBubble) {
-                        if ((mask & (BABYLON.PrimitivePointerInfo.PointerOver | BABYLON.PrimitivePointerInfo.PointerOut)) === 0) {
-                            return false;
-                        }
-                        // We're dealing with PointerOver/Out, let's keep looping to fire PointerEnter/Leave, but not Over/Out anymore
-                        bubbleCancelled = true;
-                    }
-                }
-                // If bubble is cancel we didn't update the Primitive Pointer Pos yet, let's do it
-                if (bubbleCancelled) {
-                    this._updatePrimPointerPos(cur);
-                }
-                // NOTE TO MYSELF, this is commented right now because it doesn't seemed needed but I can't figure out why I put this code in the first place
-                //// Trigger a PointerEnter corresponding to the PointerOver
-                //if (mask === PrimitivePointerInfo.PointerOver) {
-                //    this._debugExecObserver(cur, PrimitivePointerInfo.PointerEnter);
-                //    cur._pointerEventObservable.notifyObservers(ppi, PrimitivePointerInfo.PointerEnter);
-                //}
-                //// Trigger a PointerLeave corresponding to the PointerOut
-                //else if (mask === PrimitivePointerInfo.PointerOut) {
-                //    this._debugExecObserver(cur, PrimitivePointerInfo.PointerLeave);
-                //    cur._pointerEventObservable.notifyObservers(ppi, PrimitivePointerInfo.PointerLeave);
-                //}
+                    else if (mask === BABYLON.PrimitivePointerInfo.PointerOut) {
+                        this._debugExecObserver(prim, BABYLON.PrimitivePointerInfo.PointerLeave);
+                        prim._pointerEventObservable.notifyObservers(ppi, BABYLON.PrimitivePointerInfo.PointerLeave);
+                    }
+                }
+                // Exec the observers
+                this._debugExecObserver(cur, mask);
+                if (!cur._pointerEventObservable.notifyObservers(ppi, mask) && eventData instanceof BABYLON.PointerInfoPre) {
+                    eventData.skipOnPointerObservable = true;
+                    return false;
+                }
+                this._triggerActionManager(cur, ppi, mask, event);
+                // Bubble canceled? If we're not executing PointerOver or PointerOut, quit immediately
+                // If it's PointerOver/Out we have to trigger PointerEnter/Leave no matter what
+                if (ppi.cancelBubble) {
+                    return false;
+                }
                 // Loop to the parent
                 cur = cur.parent;
             }
@@ -13551,23 +13642,6 @@ var BABYLON;
                 }
             }
         };
-        Canvas2D.prototype._notifParents = function (prim, mask) {
-            var pii = this._primPointerInfo;
-            var curPrim = this;
-            while (curPrim) {
-                this._updatePrimPointerPos(curPrim);
-                // Fire the proper notification
-                if (mask === BABYLON.PrimitivePointerInfo.PointerOver) {
-                    this._debugExecObserver(curPrim, BABYLON.PrimitivePointerInfo.PointerEnter);
-                    curPrim._pointerEventObservable.notifyObservers(pii, BABYLON.PrimitivePointerInfo.PointerEnter);
-                }
-                else if (mask === BABYLON.PrimitivePointerInfo.PointerOut) {
-                    this._debugExecObserver(curPrim, BABYLON.PrimitivePointerInfo.PointerLeave);
-                    curPrim._pointerEventObservable.notifyObservers(pii, BABYLON.PrimitivePointerInfo.PointerLeave);
-                }
-                curPrim = curPrim.parent;
-            }
-        };
         /**
          * Don't forget to call the dispose method when you're done with the Canvas instance.
          * But don't worry, if you dispose its scene, the canvas will be automatically disposed too.
@@ -13831,7 +13905,10 @@ var BABYLON;
              * Return
              */
             get: function () {
-                return this._actualOverPrimitive ? this._actualOverPrimitive.prim : null;
+                if (this._actualIntersectionList && this._actualIntersectionList.length > 0) {
+                    return this._actualIntersectionList[0].prim;
+                }
+                return null;
             },
             enumerable: true,
             configurable: true
@@ -14204,6 +14281,9 @@ var BABYLON;
             if (group._isFlagSet(BABYLON.SmartPropertyPrim.flagTrackedGroup)) {
                 return;
             }
+            if (!this._trackedGroups) {
+                this._trackedGroups = new Array();
+            }
             this._trackedGroups.push(group);
             group._setFlags(BABYLON.SmartPropertyPrim.flagTrackedGroup);
         };

File diff suppressed because it is too large
+ 9 - 9
dist/preview release/canvas2D/babylon.canvas2d.min.js