Переглянути джерело

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 7 роки тому
батько
коміт
aa7f1cac05
28 змінених файлів з 18517 додано та 18421 видалено
  1. 12112 12079
      Playground/babylon.d.txt
  2. 6041 6036
      dist/preview release/babylon.d.ts
  3. 20 20
      dist/preview release/babylon.js
  4. 41 29
      dist/preview release/babylon.max.js
  5. 41 29
      dist/preview release/babylon.no-module.max.js
  6. 21 21
      dist/preview release/babylon.worker.js
  7. 41 29
      dist/preview release/es6.js
  8. 3 3
      dist/preview release/inspector/babylon.inspector.bundle.js
  9. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  10. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  11. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js
  12. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  13. 1 1
      dist/preview release/loaders/babylonjs.loaders.js
  14. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  15. 2 31
      dist/preview release/typedocValidationBaseline.json
  16. 49 49
      dist/preview release/viewer/babylon.viewer.js
  17. 42 30
      dist/preview release/viewer/babylon.viewer.max.js
  18. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  19. 2 1
      sandbox/index-local.html
  20. 13 15
      sandbox/index.css
  21. 5 4
      sandbox/index.html
  22. 34 6
      sandbox/index.js
  23. 8 1
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  24. 6 0
      src/Gamepad/Controllers/babylon.poseEnabledController.ts
  25. 1 14
      src/Math/babylon.math.ts
  26. 3 0
      src/Mesh/babylon.abstractMesh.ts
  27. 1 1
      src/Tools/babylon.sceneOptimizer.ts
  28. 23 15
      src/babylon.scene.ts

Різницю між файлами не показано, бо вона завелика
+ 12112 - 12079
Playground/babylon.d.txt


Різницю між файлами не показано, бо вона завелика
+ 6041 - 6036
dist/preview release/babylon.d.ts


Різницю між файлами не показано, бо вона завелика
+ 20 - 20
dist/preview release/babylon.js


+ 41 - 29
dist/preview release/babylon.max.js

@@ -2852,18 +2852,7 @@ var BABYLON;
          * @returns a new Quaternion object, computed from the Vector3 coordinates
          */
         Vector3.prototype.toQuaternion = function () {
-            var result = new Quaternion(0.0, 0.0, 0.0, 1.0);
-            var cosxPlusz = Math.cos((this.x + this.z) * 0.5);
-            var sinxPlusz = Math.sin((this.x + this.z) * 0.5);
-            var coszMinusx = Math.cos((this.z - this.x) * 0.5);
-            var sinzMinusx = Math.sin((this.z - this.x) * 0.5);
-            var cosy = Math.cos(this.y * 0.5);
-            var siny = Math.sin(this.y * 0.5);
-            result.x = coszMinusx * siny;
-            result.y = -sinzMinusx * siny;
-            result.z = sinxPlusz * cosy;
-            result.w = cosxPlusz * cosy;
-            return result;
+            return BABYLON.Quaternion.RotationYawPitchRoll(this.x, this.y, this.z);
         };
         /**
          * Adds the given vector to the current Vector3
@@ -20318,6 +20307,8 @@ var BABYLON;
          */
         AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            // Ensures that all world matrix will be recomputed.
+            this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
             var min;
             var max;
@@ -25372,21 +25363,23 @@ var BABYLON;
                     }
                     _this._processPointerUp(pickResult, evt, clickInfo);
                     // Sprites
-                    if (_this.spriteManagers.length > 0) {
-                        var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
-                        if (spritePickResult) {
-                            if (spritePickResult.hit && spritePickResult.pickedSprite) {
-                                if (spritePickResult.pickedSprite.actionManager) {
-                                    spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                    if (!clickInfo.ignore) {
+                        if (_this.spriteManagers.length > 0) {
+                            var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
+                            if (spritePickResult) {
+                                if (spritePickResult.hit && spritePickResult.pickedSprite) {
                                     if (spritePickResult.pickedSprite.actionManager) {
-                                        if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
-                                            spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        if (spritePickResult.pickedSprite.actionManager) {
+                                            if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
+                                                spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                            }
                                         }
                                     }
                                 }
-                            }
-                            if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
-                                _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
+                                    _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                }
                             }
                         }
                     }
@@ -26104,17 +26097,25 @@ var BABYLON;
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
         };
         /**
-         * Remove a mesh for the list of scene's meshes
-         * @param toRemove defines the mesh to remove
-         * @returns the index where the mesh was in the mesh list
-         */
-        Scene.prototype.removeMesh = function (toRemove) {
+           * Remove a mesh for the list of scene's meshes
+           * @param toRemove defines the mesh to remove
+           * @param recursive if all child meshes should also be removed from the scene
+           * @returns the index where the mesh was in the mesh list
+           */
+        Scene.prototype.removeMesh = function (toRemove, recursive) {
+            var _this = this;
+            if (recursive === void 0) { recursive = false; }
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 this.meshes.splice(index, 1);
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
+            if (recursive) {
+                toRemove.getChildMeshes().forEach(function (m) {
+                    _this.removeMesh(m);
+                });
+            }
             return index;
         };
         /**
@@ -71358,6 +71359,10 @@ var BABYLON;
              */
             _this._pointingPoseNode = null;
             _this._workingMatrix = BABYLON.Matrix.Identity();
+            /**
+             * @hidden
+             */
+            _this._meshAttachedObservable = new BABYLON.Observable();
             _this.type = BABYLON.Gamepad.POSE_ENABLED;
             _this.controllerType = PoseEnabledControllerType.GENERIC;
             _this.position = BABYLON.Vector3.Zero();
@@ -71432,6 +71437,7 @@ var BABYLON;
             if (!this._mesh.rotationQuaternion) {
                 this._mesh.rotationQuaternion = new BABYLON.Quaternion();
             }
+            this._meshAttachedObservable.notifyObservers(mesh);
         };
         /**
          * Attaches the controllers mesh to a camera
@@ -88019,6 +88025,9 @@ var BABYLON;
                 webVRController.attachToMesh(preloadMesh);
             }
             _this._setLaserPointerParent(webVRController.mesh);
+            _this._meshAttachedObserver = webVRController._meshAttachedObservable.add(function (mesh) {
+                _this._setLaserPointerParent(mesh);
+            });
             return _this;
         }
         VRExperienceHelperControllerGazer.prototype._getForwardRay = function (length) {
@@ -88061,6 +88070,9 @@ var BABYLON;
         VRExperienceHelperControllerGazer.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
             this._laserPointer.dispose();
+            if (this._meshAttachedObserver) {
+                this.webVRController._meshAttachedObservable.remove(this._meshAttachedObserver);
+            }
         };
         return VRExperienceHelperControllerGazer;
     }(VRExperienceHelperGazer));
@@ -91010,7 +91022,7 @@ var BABYLON;
                     continue;
                 }
                 // Merge meshes
-                BABYLON.Mesh.MergeMeshes(currentPool);
+                BABYLON.Mesh.MergeMeshes(currentPool, undefined, true);
             }
             if (updateSelectionTree != undefined) {
                 if (updateSelectionTree) {

+ 41 - 29
dist/preview release/babylon.no-module.max.js

@@ -2819,18 +2819,7 @@ var BABYLON;
          * @returns a new Quaternion object, computed from the Vector3 coordinates
          */
         Vector3.prototype.toQuaternion = function () {
-            var result = new Quaternion(0.0, 0.0, 0.0, 1.0);
-            var cosxPlusz = Math.cos((this.x + this.z) * 0.5);
-            var sinxPlusz = Math.sin((this.x + this.z) * 0.5);
-            var coszMinusx = Math.cos((this.z - this.x) * 0.5);
-            var sinzMinusx = Math.sin((this.z - this.x) * 0.5);
-            var cosy = Math.cos(this.y * 0.5);
-            var siny = Math.sin(this.y * 0.5);
-            result.x = coszMinusx * siny;
-            result.y = -sinzMinusx * siny;
-            result.z = sinxPlusz * cosy;
-            result.w = cosxPlusz * cosy;
-            return result;
+            return BABYLON.Quaternion.RotationYawPitchRoll(this.x, this.y, this.z);
         };
         /**
          * Adds the given vector to the current Vector3
@@ -20285,6 +20274,8 @@ var BABYLON;
          */
         AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            // Ensures that all world matrix will be recomputed.
+            this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
             var min;
             var max;
@@ -25339,21 +25330,23 @@ var BABYLON;
                     }
                     _this._processPointerUp(pickResult, evt, clickInfo);
                     // Sprites
-                    if (_this.spriteManagers.length > 0) {
-                        var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
-                        if (spritePickResult) {
-                            if (spritePickResult.hit && spritePickResult.pickedSprite) {
-                                if (spritePickResult.pickedSprite.actionManager) {
-                                    spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                    if (!clickInfo.ignore) {
+                        if (_this.spriteManagers.length > 0) {
+                            var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
+                            if (spritePickResult) {
+                                if (spritePickResult.hit && spritePickResult.pickedSprite) {
                                     if (spritePickResult.pickedSprite.actionManager) {
-                                        if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
-                                            spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        if (spritePickResult.pickedSprite.actionManager) {
+                                            if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
+                                                spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                            }
                                         }
                                     }
                                 }
-                            }
-                            if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
-                                _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
+                                    _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                }
                             }
                         }
                     }
@@ -26071,17 +26064,25 @@ var BABYLON;
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
         };
         /**
-         * Remove a mesh for the list of scene's meshes
-         * @param toRemove defines the mesh to remove
-         * @returns the index where the mesh was in the mesh list
-         */
-        Scene.prototype.removeMesh = function (toRemove) {
+           * Remove a mesh for the list of scene's meshes
+           * @param toRemove defines the mesh to remove
+           * @param recursive if all child meshes should also be removed from the scene
+           * @returns the index where the mesh was in the mesh list
+           */
+        Scene.prototype.removeMesh = function (toRemove, recursive) {
+            var _this = this;
+            if (recursive === void 0) { recursive = false; }
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 this.meshes.splice(index, 1);
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
+            if (recursive) {
+                toRemove.getChildMeshes().forEach(function (m) {
+                    _this.removeMesh(m);
+                });
+            }
             return index;
         };
         /**
@@ -71325,6 +71326,10 @@ var BABYLON;
              */
             _this._pointingPoseNode = null;
             _this._workingMatrix = BABYLON.Matrix.Identity();
+            /**
+             * @hidden
+             */
+            _this._meshAttachedObservable = new BABYLON.Observable();
             _this.type = BABYLON.Gamepad.POSE_ENABLED;
             _this.controllerType = PoseEnabledControllerType.GENERIC;
             _this.position = BABYLON.Vector3.Zero();
@@ -71399,6 +71404,7 @@ var BABYLON;
             if (!this._mesh.rotationQuaternion) {
                 this._mesh.rotationQuaternion = new BABYLON.Quaternion();
             }
+            this._meshAttachedObservable.notifyObservers(mesh);
         };
         /**
          * Attaches the controllers mesh to a camera
@@ -87986,6 +87992,9 @@ var BABYLON;
                 webVRController.attachToMesh(preloadMesh);
             }
             _this._setLaserPointerParent(webVRController.mesh);
+            _this._meshAttachedObserver = webVRController._meshAttachedObservable.add(function (mesh) {
+                _this._setLaserPointerParent(mesh);
+            });
             return _this;
         }
         VRExperienceHelperControllerGazer.prototype._getForwardRay = function (length) {
@@ -88028,6 +88037,9 @@ var BABYLON;
         VRExperienceHelperControllerGazer.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
             this._laserPointer.dispose();
+            if (this._meshAttachedObserver) {
+                this.webVRController._meshAttachedObservable.remove(this._meshAttachedObserver);
+            }
         };
         return VRExperienceHelperControllerGazer;
     }(VRExperienceHelperGazer));
@@ -90977,7 +90989,7 @@ var BABYLON;
                     continue;
                 }
                 // Merge meshes
-                BABYLON.Mesh.MergeMeshes(currentPool);
+                BABYLON.Mesh.MergeMeshes(currentPool, undefined, true);
             }
             if (updateSelectionTree != undefined) {
                 if (updateSelectionTree) {

Різницю між файлами не показано, бо вона завелика
+ 21 - 21
dist/preview release/babylon.worker.js


+ 41 - 29
dist/preview release/es6.js

@@ -2819,18 +2819,7 @@ var BABYLON;
          * @returns a new Quaternion object, computed from the Vector3 coordinates
          */
         Vector3.prototype.toQuaternion = function () {
-            var result = new Quaternion(0.0, 0.0, 0.0, 1.0);
-            var cosxPlusz = Math.cos((this.x + this.z) * 0.5);
-            var sinxPlusz = Math.sin((this.x + this.z) * 0.5);
-            var coszMinusx = Math.cos((this.z - this.x) * 0.5);
-            var sinzMinusx = Math.sin((this.z - this.x) * 0.5);
-            var cosy = Math.cos(this.y * 0.5);
-            var siny = Math.sin(this.y * 0.5);
-            result.x = coszMinusx * siny;
-            result.y = -sinzMinusx * siny;
-            result.z = sinxPlusz * cosy;
-            result.w = cosxPlusz * cosy;
-            return result;
+            return BABYLON.Quaternion.RotationYawPitchRoll(this.x, this.y, this.z);
         };
         /**
          * Adds the given vector to the current Vector3
@@ -20285,6 +20274,8 @@ var BABYLON;
          */
         AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            // Ensures that all world matrix will be recomputed.
+            this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
             var min;
             var max;
@@ -25339,21 +25330,23 @@ var BABYLON;
                     }
                     _this._processPointerUp(pickResult, evt, clickInfo);
                     // Sprites
-                    if (_this.spriteManagers.length > 0) {
-                        var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
-                        if (spritePickResult) {
-                            if (spritePickResult.hit && spritePickResult.pickedSprite) {
-                                if (spritePickResult.pickedSprite.actionManager) {
-                                    spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                    if (!clickInfo.ignore) {
+                        if (_this.spriteManagers.length > 0) {
+                            var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
+                            if (spritePickResult) {
+                                if (spritePickResult.hit && spritePickResult.pickedSprite) {
                                     if (spritePickResult.pickedSprite.actionManager) {
-                                        if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
-                                            spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        if (spritePickResult.pickedSprite.actionManager) {
+                                            if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
+                                                spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                            }
                                         }
                                     }
                                 }
-                            }
-                            if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
-                                _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
+                                    _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                }
                             }
                         }
                     }
@@ -26071,17 +26064,25 @@ var BABYLON;
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
         };
         /**
-         * Remove a mesh for the list of scene's meshes
-         * @param toRemove defines the mesh to remove
-         * @returns the index where the mesh was in the mesh list
-         */
-        Scene.prototype.removeMesh = function (toRemove) {
+           * Remove a mesh for the list of scene's meshes
+           * @param toRemove defines the mesh to remove
+           * @param recursive if all child meshes should also be removed from the scene
+           * @returns the index where the mesh was in the mesh list
+           */
+        Scene.prototype.removeMesh = function (toRemove, recursive) {
+            var _this = this;
+            if (recursive === void 0) { recursive = false; }
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 this.meshes.splice(index, 1);
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
+            if (recursive) {
+                toRemove.getChildMeshes().forEach(function (m) {
+                    _this.removeMesh(m);
+                });
+            }
             return index;
         };
         /**
@@ -71325,6 +71326,10 @@ var BABYLON;
              */
             _this._pointingPoseNode = null;
             _this._workingMatrix = BABYLON.Matrix.Identity();
+            /**
+             * @hidden
+             */
+            _this._meshAttachedObservable = new BABYLON.Observable();
             _this.type = BABYLON.Gamepad.POSE_ENABLED;
             _this.controllerType = PoseEnabledControllerType.GENERIC;
             _this.position = BABYLON.Vector3.Zero();
@@ -71399,6 +71404,7 @@ var BABYLON;
             if (!this._mesh.rotationQuaternion) {
                 this._mesh.rotationQuaternion = new BABYLON.Quaternion();
             }
+            this._meshAttachedObservable.notifyObservers(mesh);
         };
         /**
          * Attaches the controllers mesh to a camera
@@ -87986,6 +87992,9 @@ var BABYLON;
                 webVRController.attachToMesh(preloadMesh);
             }
             _this._setLaserPointerParent(webVRController.mesh);
+            _this._meshAttachedObserver = webVRController._meshAttachedObservable.add(function (mesh) {
+                _this._setLaserPointerParent(mesh);
+            });
             return _this;
         }
         VRExperienceHelperControllerGazer.prototype._getForwardRay = function (length) {
@@ -88028,6 +88037,9 @@ var BABYLON;
         VRExperienceHelperControllerGazer.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
             this._laserPointer.dispose();
+            if (this._meshAttachedObserver) {
+                this.webVRController._meshAttachedObservable.remove(this._meshAttachedObserver);
+            }
         };
         return VRExperienceHelperControllerGazer;
     }(VRExperienceHelperGazer));
@@ -90977,7 +90989,7 @@ var BABYLON;
                     continue;
                 }
                 // Merge meshes
-                BABYLON.Mesh.MergeMeshes(currentPool);
+                BABYLON.Mesh.MergeMeshes(currentPool, undefined, true);
             }
             if (updateSelectionTree != undefined) {
                 if (updateSelectionTree) {

Різницю між файлами не показано, бо вона завелика
+ 3 - 3
dist/preview release/inspector/babylon.inspector.bundle.js


+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -1241,7 +1241,7 @@ var BABYLON;
                 });
                 loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind, function (babylonVertexBuffer, data) {
                     var dataIndex = 0;
-                    babylonVertexBuffer.forEach(data.length, function (value, index) {
+                    babylonVertexBuffer.forEach(data.length / 3 * 4, function (value, index) {
                         // Tangent data for morph targets is stored as xyz delta.
                         // The vertexData.tangent is stored as xyzw.
                         // So we need to skip every fourth vertexData.tangent.

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3456,7 +3456,7 @@ var BABYLON;
                 });
                 loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind, function (babylonVertexBuffer, data) {
                     var dataIndex = 0;
-                    babylonVertexBuffer.forEach(data.length, function (value, index) {
+                    babylonVertexBuffer.forEach(data.length / 3 * 4, function (value, index) {
                         // Tangent data for morph targets is stored as xyz delta.
                         // The vertexData.tangent is stored as xyzw.
                         // So we need to skip every fourth vertexData.tangent.

Різницю між файлами не показано, бо вона завелика
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js

@@ -4438,7 +4438,7 @@ var BABYLON;
                 });
                 loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind, function (babylonVertexBuffer, data) {
                     var dataIndex = 0;
-                    babylonVertexBuffer.forEach(data.length, function (value, index) {
+                    babylonVertexBuffer.forEach(data.length / 3 * 4, function (value, index) {
                         // Tangent data for morph targets is stored as xyz delta.
                         // The vertexData.tangent is stored as xyzw.
                         // So we need to skip every fourth vertexData.tangent.

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 2 - 31
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4325,
+  "errors": 4320,
   "babylon.typedoc.json": {
-    "errors": 4325,
+    "errors": 4320,
     "Animatable": {
       "Class": {
         "Comments": {
@@ -17898,35 +17898,6 @@
             "MissingText": true
           }
         }
-      },
-      "Method": {
-        "serialize": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "Parse": {
-          "Comments": {
-            "MissingReturn": true
-          },
-          "Parameter": {
-            "source": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "scene": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "rootUrl": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
       }
     },
     "StateCondition": {

Різницю між файлами не показано, бо вона завелика
+ 49 - 49
dist/preview release/viewer/babylon.viewer.js


+ 42 - 30
dist/preview release/viewer/babylon.viewer.max.js

@@ -2940,18 +2940,7 @@ var BABYLON;
          * @returns a new Quaternion object, computed from the Vector3 coordinates
          */
         Vector3.prototype.toQuaternion = function () {
-            var result = new Quaternion(0.0, 0.0, 0.0, 1.0);
-            var cosxPlusz = Math.cos((this.x + this.z) * 0.5);
-            var sinxPlusz = Math.sin((this.x + this.z) * 0.5);
-            var coszMinusx = Math.cos((this.z - this.x) * 0.5);
-            var sinzMinusx = Math.sin((this.z - this.x) * 0.5);
-            var cosy = Math.cos(this.y * 0.5);
-            var siny = Math.sin(this.y * 0.5);
-            result.x = coszMinusx * siny;
-            result.y = -sinzMinusx * siny;
-            result.z = sinxPlusz * cosy;
-            result.w = cosxPlusz * cosy;
-            return result;
+            return BABYLON.Quaternion.RotationYawPitchRoll(this.x, this.y, this.z);
         };
         /**
          * Adds the given vector to the current Vector3
@@ -20406,6 +20395,8 @@ var BABYLON;
          */
         AbstractMesh.prototype.getHierarchyBoundingVectors = function (includeDescendants) {
             if (includeDescendants === void 0) { includeDescendants = true; }
+            // Ensures that all world matrix will be recomputed.
+            this.getScene().incrementRenderId();
             this.computeWorldMatrix(true);
             var min;
             var max;
@@ -25460,21 +25451,23 @@ var BABYLON;
                     }
                     _this._processPointerUp(pickResult, evt, clickInfo);
                     // Sprites
-                    if (_this.spriteManagers.length > 0) {
-                        var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
-                        if (spritePickResult) {
-                            if (spritePickResult.hit && spritePickResult.pickedSprite) {
-                                if (spritePickResult.pickedSprite.actionManager) {
-                                    spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                    if (!clickInfo.ignore) {
+                        if (_this.spriteManagers.length > 0) {
+                            var spritePickResult = _this.pickSprite(_this._unTranslatedPointerX, _this._unTranslatedPointerY, _this._spritePredicate, false, _this.cameraToUseForPointers || undefined);
+                            if (spritePickResult) {
+                                if (spritePickResult.hit && spritePickResult.pickedSprite) {
                                     if (spritePickResult.pickedSprite.actionManager) {
-                                        if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
-                                            spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickUpTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                        if (spritePickResult.pickedSprite.actionManager) {
+                                            if (Math.abs(_this._startingPointerPosition.x - _this._pointerX) < Scene.DragMovementThreshold && Math.abs(_this._startingPointerPosition.y - _this._pointerY) < Scene.DragMovementThreshold) {
+                                                spritePickResult.pickedSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickTrigger, BABYLON.ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, _this, evt));
+                                            }
                                         }
                                     }
                                 }
-                            }
-                            if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
-                                _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                if (_this._pickedDownSprite && _this._pickedDownSprite.actionManager && _this._pickedDownSprite !== spritePickResult.pickedSprite) {
+                                    _this._pickedDownSprite.actionManager.processTrigger(BABYLON.ActionManager.OnPickOutTrigger, BABYLON.ActionEvent.CreateNewFromSprite(_this._pickedDownSprite, _this, evt));
+                                }
                             }
                         }
                     }
@@ -26192,17 +26185,25 @@ var BABYLON;
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
         };
         /**
-         * Remove a mesh for the list of scene's meshes
-         * @param toRemove defines the mesh to remove
-         * @returns the index where the mesh was in the mesh list
-         */
-        Scene.prototype.removeMesh = function (toRemove) {
+           * Remove a mesh for the list of scene's meshes
+           * @param toRemove defines the mesh to remove
+           * @param recursive if all child meshes should also be removed from the scene
+           * @returns the index where the mesh was in the mesh list
+           */
+        Scene.prototype.removeMesh = function (toRemove, recursive) {
+            var _this = this;
+            if (recursive === void 0) { recursive = false; }
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
                 // Remove from the scene if mesh found
                 this.meshes.splice(index, 1);
             }
             this.onMeshRemovedObservable.notifyObservers(toRemove);
+            if (recursive) {
+                toRemove.getChildMeshes().forEach(function (m) {
+                    _this.removeMesh(m);
+                });
+            }
             return index;
         };
         /**
@@ -71446,6 +71447,10 @@ var BABYLON;
              */
             _this._pointingPoseNode = null;
             _this._workingMatrix = BABYLON.Matrix.Identity();
+            /**
+             * @hidden
+             */
+            _this._meshAttachedObservable = new BABYLON.Observable();
             _this.type = BABYLON.Gamepad.POSE_ENABLED;
             _this.controllerType = PoseEnabledControllerType.GENERIC;
             _this.position = BABYLON.Vector3.Zero();
@@ -71520,6 +71525,7 @@ var BABYLON;
             if (!this._mesh.rotationQuaternion) {
                 this._mesh.rotationQuaternion = new BABYLON.Quaternion();
             }
+            this._meshAttachedObservable.notifyObservers(mesh);
         };
         /**
          * Attaches the controllers mesh to a camera
@@ -88107,6 +88113,9 @@ var BABYLON;
                 webVRController.attachToMesh(preloadMesh);
             }
             _this._setLaserPointerParent(webVRController.mesh);
+            _this._meshAttachedObserver = webVRController._meshAttachedObservable.add(function (mesh) {
+                _this._setLaserPointerParent(mesh);
+            });
             return _this;
         }
         VRExperienceHelperControllerGazer.prototype._getForwardRay = function (length) {
@@ -88149,6 +88158,9 @@ var BABYLON;
         VRExperienceHelperControllerGazer.prototype.dispose = function () {
             _super.prototype.dispose.call(this);
             this._laserPointer.dispose();
+            if (this._meshAttachedObserver) {
+                this.webVRController._meshAttachedObservable.remove(this._meshAttachedObserver);
+            }
         };
         return VRExperienceHelperControllerGazer;
     }(VRExperienceHelperGazer));
@@ -91098,7 +91110,7 @@ var BABYLON;
                     continue;
                 }
                 // Merge meshes
-                BABYLON.Mesh.MergeMeshes(currentPool);
+                BABYLON.Mesh.MergeMeshes(currentPool, undefined, true);
             }
             if (updateSelectionTree != undefined) {
                 if (updateSelectionTree) {
@@ -104843,7 +104855,7 @@ var BABYLON;
                 });
                 loadAttribute("TANGENT", BABYLON.VertexBuffer.TangentKind, function (babylonVertexBuffer, data) {
                     var dataIndex = 0;
-                    babylonVertexBuffer.forEach(data.length, function (value, index) {
+                    babylonVertexBuffer.forEach(data.length / 3 * 4, function (value, index) {
                         // Tangent data for morph targets is stored as xyz delta.
                         // The vertexData.tangent is stored as xyzw.
                         // So we need to skip every fourth vertexData.tangent.

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -729,7 +729,7 @@ module BABYLON.GLTF2 {
 
             loadAttribute("TANGENT", VertexBuffer.TangentKind, (babylonVertexBuffer, data) => {
                 let dataIndex = 0;
-                babylonVertexBuffer.forEach(data.length, (value, index) => {
+                babylonVertexBuffer.forEach(data.length / 3 * 4, (value, index) => {
                     // Tangent data for morph targets is stored as xyz delta.
                     // The vertexData.tangent is stored as xyzw.
                     // So we need to skip every fourth vertexData.tangent.

+ 2 - 1
sandbox/index-local.html

@@ -9,6 +9,7 @@
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
 </head>
 <body>
+    <p id="droptext">Drag and drop gltf, glb, obj or babylon files to view them</p>
     <canvas id="renderCanvas"></canvas>
     <div id="logo">
     </div>
@@ -33,7 +34,7 @@
         </div>               
         <div class="footerRight">
             <a href="#" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
-            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></i></a> 
+            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></a> 
             <a href="#">
                 <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
                     <input type="file" id="files" multiple />

+ 13 - 15
sandbox/index.css

@@ -106,6 +106,14 @@ a {
     background-size: 50%;
 }
 
+#droptext {
+    position: absolute;;
+    text-align: center;
+    color: #fff;
+    height: 50px;
+    width: 100%;
+    bottom: 5%;    
+}
 #btnDownArrow {
     position: absolute;
     bottom: 35px;
@@ -271,6 +279,8 @@ a {
     z-index: 1;
     min-width: 135px;
     width: 200px;
+    flex-direction: column;
+    transition: all 0.3s ease; /* Add transition for hover effects */
 }
 
 #dropdownContent a,
@@ -278,12 +288,6 @@ a {
     cursor: pointer;
 }
 
-.dropdown:hover #dropdownContent {
-    display: flex;
-    flex-direction: column;
-    transition: all 0.3s ease; /* Add transition for hover effects */
-}
-
 #chevronUp {
     display: inline;
     margin-right: 0px;
@@ -295,13 +299,6 @@ a {
     margin-left: 0px;
 }
 
-.dropdown:hover #chevronUp {
-    display: none;
-}
-.dropdown:hover #chevronDown {
-    display: inline;
-}
-
 #playBtn.play #pauseImg,
 #playBtn.pause #playImg{
     display: none;
@@ -311,9 +308,10 @@ a {
     -webkit-appearance: none;
     cursor: pointer;
     width: 1000px;
+    height: 50px;
     outline: none;
-    border-radius: 5px;
     margin-left: 20px;
+    background-color: transparent;
 }
 
 /*Chrome -webkit */
@@ -329,7 +327,7 @@ a {
 #slider::-webkit-slider-runnable-track {
     height: 2px;
     -webkit-appearance: none;
-    color: white;
+    background-color: white;
 }
 
 

+ 5 - 4
sandbox/index.html

@@ -1,7 +1,9 @@
 <!DOCTYPE html>
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-    <title>BabylonJS - Sandbox</title>
+    <title>BabylonJS Sandbox - View glTF, glb, obj and babylon files</title>
+    <meta name="description" content="Viewer for glTF, glb, obj and babylon files powered by BabylonJS" />
+    <meta name="keywords" content="Babylon.js, Babylon, BabylonJS, glTF, glb, obj, viewer, online viewer, 3D model viewer, 3D, webgl" />
     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
 
     <link rel="shortcut icon" href="http://www.babylonjs.com/img/favicon/favicon.ico">
@@ -23,7 +25,6 @@
     <meta name="msapplication-TileImage" content="http://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
     <meta name="msapplication-config" content="http://www.babylonjs.com/img/favicon/browserconfig.xml">
     <meta name="theme-color" content="#ffffff">
-    <meta name="keywords" content="3D, Babylon.js, webgl, gltf, viewer">
 
     <link href="index.css" rel="stylesheet" />
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
@@ -36,8 +37,8 @@
     <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
     <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
 </head>
-
 <body>
+    <p id="droptext">Drag and drop gltf, glb, obj or babylon files to view them</p>
     <canvas id="renderCanvas" touch-action="none"></canvas>
     <div id="logo">
     </div>
@@ -62,7 +63,7 @@
         </div>               
         <div class="footerRight">
             <a href="#" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
-            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></i></a> 
+            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></a> 
             <a href="#">
                 <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
                     <input type="file" id="files" multiple />

+ 34 - 6
sandbox/index.js

@@ -9,6 +9,9 @@ var currentGroupIndex;
 var currentScene;
 // html balise
 var animationBar = document.getElementById("animationBar");
+var dropdownBtn = document.getElementById("dropdownBtn");
+var chevronUp = document.getElementById("chevronUp");
+var chevronDown = document.getElementById("chevronDown");
 var dropdownLabel = document.getElementById("dropdownLabel");
 var dropdownContent = document.getElementById("dropdownContent");
 var playBtn = document.getElementById("playBtn");
@@ -187,6 +190,7 @@ if (BABYLON.Engine.isSupported()) {
                 displayDebugLayerAndLogs();
             }
             document.getElementById("logo").className = "hidden";
+            document.getElementById("droptext").className = "hidden";
             canvas.style.opacity = 1;
             if (currentScene.activeCamera.keysUp) {
                 currentScene.activeCamera.keysUp.push(90); // Z
@@ -229,7 +233,7 @@ if (BABYLON.Engine.isSupported()) {
                 });
             });
         }).catch(function (reason) {
-            sceneError({ name: fileName }, null, reason);
+            sceneError({ name: fileName }, null, reason.message || reason);
         });
     }
     else {
@@ -246,7 +250,7 @@ if (BABYLON.Engine.isSupported()) {
 
         window.addEventListener("keydown", function (evt) {
             // Press R to reload
-            if (evt.keyCode === 82) {
+            if (evt.keyCode === 82 && !enableDebugLayer) {
                 filesInput.reload();
             }
         });
@@ -287,8 +291,8 @@ if (BABYLON.Engine.isSupported()) {
     }, false);
 
     window.addEventListener("keydown", function (evt) {
-        // Press Esc to toggle footer
-        if (evt.keyCode === 27 &&!enableDebugLayer) {
+        // Press space to toggle footer
+        if (evt.keyCode === 32 && !enableDebugLayer) {
             if (footer.style.display === "none") {
                 footer.style.display = "block";
             }
@@ -326,6 +330,27 @@ function formatId(name){
     return "data-" + name.replace(/\s/g,'');
 }
 
+function displayDropdownContent(display) {
+    if(display) {
+        dropdownContent.style.display = "flex";
+        chevronDown.style.display = "inline";
+        chevronUp.style.display = "none";
+    }
+    else {
+        dropdownContent.style.display = "none";
+        chevronDown.style.display = "none";
+        chevronUp.style.display = "inline";
+    }
+}
+dropdownBtn.addEventListener("click", function() {
+    if(dropdownContent.style.display === "flex") {
+        displayDropdownContent(false);
+    }
+    else {
+        displayDropdownContent(true);
+    }
+});
+
 function createDropdownLink(group,index) {
     var animation = document.createElement("a");
     animation.innerHTML = group.name;
@@ -348,8 +373,11 @@ function createDropdownLink(group,index) {
         // set the slider
         slider.setAttribute("min", currentGroup.from);
         slider.setAttribute("max", currentGroup.to);
-        currentSliderValue = 0;
-        slider.value = 0;
+        currentSliderValue = currentGroup.from;
+        slider.value = currentGroup.from;
+
+        // hide the content of the dropdown
+        displayDropdownContent(false);
     });
     dropdownContent.appendChild(animation);
 }

+ 8 - 1
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -104,7 +104,7 @@ module BABYLON {
 
     class VRExperienceHelperControllerGazer extends VRExperienceHelperGazer{
         private _laserPointer: Mesh;
-
+        private _meshAttachedObserver: Nullable<Observer<AbstractMesh>>;
         constructor(public webVRController: WebVRController, scene: Scene, gazeTrackerToClone:Mesh){
             super(scene, gazeTrackerToClone);
             // Laser pointer
@@ -127,6 +127,10 @@ module BABYLON {
             }
 
             this._setLaserPointerParent(webVRController.mesh!);
+
+            this._meshAttachedObserver = webVRController._meshAttachedObservable.add((mesh)=>{
+                this._setLaserPointerParent(mesh);
+            });
         }
 
         _getForwardRay(length:number):Ray{
@@ -176,6 +180,9 @@ module BABYLON {
         dispose(){
             super.dispose();
             this._laserPointer.dispose();
+            if(this._meshAttachedObserver){
+                this.webVRController._meshAttachedObservable.remove(this._meshAttachedObserver);
+            }
         }
     }
 

+ 6 - 0
src/Gamepad/Controllers/babylon.poseEnabledController.ts

@@ -239,6 +239,11 @@ module BABYLON {
         }
 
         /**
+         * @hidden
+         */
+        public _meshAttachedObservable = new Observable<AbstractMesh>()
+
+        /**
          * Attaches a mesh to the controller
          * @param mesh the mesh to be attached
          */
@@ -253,6 +258,7 @@ module BABYLON {
             if (!this._mesh.rotationQuaternion) {
                 this._mesh.rotationQuaternion = new Quaternion();
             }
+            this._meshAttachedObservable.notifyObservers(mesh);
         }
 
         /**

+ 1 - 14
src/Math/babylon.math.ts

@@ -1565,20 +1565,7 @@
          * @returns a new Quaternion object, computed from the Vector3 coordinates
          */
         public toQuaternion(): Quaternion {
-            var result = new Quaternion(0.0, 0.0, 0.0, 1.0);
-
-            var cosxPlusz = Math.cos((this.x + this.z) * 0.5);
-            var sinxPlusz = Math.sin((this.x + this.z) * 0.5);
-            var coszMinusx = Math.cos((this.z - this.x) * 0.5);
-            var sinzMinusx = Math.sin((this.z - this.x) * 0.5);
-            var cosy = Math.cos(this.y * 0.5);
-            var siny = Math.sin(this.y * 0.5);
-
-            result.x = coszMinusx * siny;
-            result.y = -sinzMinusx * siny;
-            result.z = sinxPlusz * cosy;
-            result.w = cosxPlusz * cosy;
-            return result;
+            return BABYLON.Quaternion.RotationYawPitchRoll(this.x, this.y, this.z);
         }
 
         /**

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

@@ -1059,6 +1059,9 @@
          * @returns the new bounding vectors
          */
         public getHierarchyBoundingVectors(includeDescendants = true): { min: Vector3, max: Vector3 } {
+            // Ensures that all world matrix will be recomputed.
+            this.getScene().incrementRenderId();
+
             this.computeWorldMatrix(true);
 
             let min: Vector3;

+ 1 - 1
src/Tools/babylon.sceneOptimizer.ts

@@ -433,7 +433,7 @@
                 }
 
                 // Merge meshes
-                Mesh.MergeMeshes(currentPool);
+                Mesh.MergeMeshes(currentPool, undefined, true);
             }
 
             if (updateSelectionTree != undefined) {

+ 23 - 15
src/babylon.scene.ts

@@ -2116,25 +2116,28 @@
                     this._processPointerUp(pickResult, evt, clickInfo);
 
                     // Sprites
-                    if (this.spriteManagers.length > 0) {
-                        let spritePickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers || undefined);
-
-                        if (spritePickResult) {
-                            if (spritePickResult.hit && spritePickResult.pickedSprite) {
-                                if (spritePickResult.pickedSprite.actionManager) {
-                                    spritePickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickUpTrigger, ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, this, evt));
+                    if(!clickInfo.ignore){
+                        if (this.spriteManagers.length > 0) {
+                            let spritePickResult = this.pickSprite(this._unTranslatedPointerX, this._unTranslatedPointerY, this._spritePredicate, false, this.cameraToUseForPointers || undefined);
+    
+                            if (spritePickResult) {
+                                if (spritePickResult.hit && spritePickResult.pickedSprite) {
                                     if (spritePickResult.pickedSprite.actionManager) {
-                                        if (Math.abs(this._startingPointerPosition.x - this._pointerX) < Scene.DragMovementThreshold && Math.abs(this._startingPointerPosition.y - this._pointerY) < Scene.DragMovementThreshold) {
-                                            spritePickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickTrigger, ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, this, evt));
+                                        spritePickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickUpTrigger, ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, this, evt));
+                                        if (spritePickResult.pickedSprite.actionManager) {
+                                            if (Math.abs(this._startingPointerPosition.x - this._pointerX) < Scene.DragMovementThreshold && Math.abs(this._startingPointerPosition.y - this._pointerY) < Scene.DragMovementThreshold) {
+                                                spritePickResult.pickedSprite.actionManager.processTrigger(ActionManager.OnPickTrigger, ActionEvent.CreateNewFromSprite(spritePickResult.pickedSprite, this, evt));
+                                            }
                                         }
                                     }
                                 }
-                            }
-                            if (this._pickedDownSprite && this._pickedDownSprite.actionManager && this._pickedDownSprite !== spritePickResult.pickedSprite) {
-                                this._pickedDownSprite.actionManager.processTrigger(ActionManager.OnPickOutTrigger, ActionEvent.CreateNewFromSprite(this._pickedDownSprite, this, evt));
+                                if (this._pickedDownSprite && this._pickedDownSprite.actionManager && this._pickedDownSprite !== spritePickResult.pickedSprite) {
+                                    this._pickedDownSprite.actionManager.processTrigger(ActionManager.OnPickOutTrigger, ActionEvent.CreateNewFromSprite(this._pickedDownSprite, this, evt));
+                                }
                             }
                         }
                     }
+                    
                     this._previousPickResult = this._currentPickResult;
                 });
             };
@@ -2941,12 +2944,13 @@
             this.onNewMeshAddedObservable.notifyObservers(newMesh);
         }
 
-        /**
+      /**
          * Remove a mesh for the list of scene's meshes
          * @param toRemove defines the mesh to remove
+         * @param recursive if all child meshes should also be removed from the scene
          * @returns the index where the mesh was in the mesh list
          */
-        public removeMesh(toRemove: AbstractMesh): number {
+        public removeMesh(toRemove: AbstractMesh, recursive = false): number {
             var index = this.meshes.indexOf(toRemove);
             if (index !== -1) {
                 // Remove from the scene if mesh found
@@ -2954,7 +2958,11 @@
             }
 
             this.onMeshRemovedObservable.notifyObservers(toRemove);
-
+            if(recursive){
+                toRemove.getChildMeshes().forEach((m)=>{
+                    this.removeMesh(m);
+                })
+            }
             return index;
         }