Jelajahi Sumber

Merge pull request #5689 from TrevorDev/boundingBoxGizmoKeepParent

do not remove parent when adding bounding box
David Catuhe 6 tahun lalu
induk
melakukan
7e121ee332

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

@@ -138,6 +138,7 @@
 - Updated comment in TransformNode.rotationQuaternion to include undefined as one of the potential return values ([nathankmiller](https://github.com/nathankmiller))
 - CannonJS ignores connectedPivot joint parameter ([TrevorDev](https://github.com/TrevorDev))
 - Fix case sensitive paths ([mrdunk](https://github.com))
+- Attaching a BoundingBoxGizmo on a child should not remove its parent ([TrevorDev](https://github.com/TrevorDev)))
 
 ### Core Engine
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))

+ 8 - 4
src/Behaviors/Mesh/babylon.sixDofDragBehavior.ts

@@ -208,11 +208,15 @@ module BABYLON {
                         tmpQuaternion.multiplyToRef(this._startingOrientation, tmpQuaternion);
                         // Slowly move mesh to avoid jitter
                         var oldParent = pickedMesh.parent;
-                        pickedMesh.setParent(null);
-                        Quaternion.SlerpToRef(pickedMesh.rotationQuaternion!, tmpQuaternion, this.dragDeltaRatio, pickedMesh.rotationQuaternion!);
-                        pickedMesh.setParent(oldParent);
-                        BoundingBoxGizmo._RestorePivotPoint(pickedMesh);
+
+                        // Only rotate the mesh if it's parent has uniform scaling
+                        if (!oldParent || ((oldParent as Mesh).scaling && !(oldParent as Mesh).scaling.isNonUniformWithinEpsilon(0.001))) {
+                            pickedMesh.setParent(null);
+                            Quaternion.SlerpToRef(pickedMesh.rotationQuaternion!, tmpQuaternion, this.dragDeltaRatio, pickedMesh.rotationQuaternion!);
+                            pickedMesh.setParent(oldParent);
+                        }
                     }
+                    BoundingBoxGizmo._RestorePivotPoint(pickedMesh);
                 }
             });
         }

+ 30 - 1
src/Gizmos/babylon.boundingBoxGizmo.ts

@@ -171,6 +171,11 @@ module BABYLON {
                 _dragBehavior.onDragObservable.add((event) => {
                     this.onRotationSphereDragObservable.notifyObservers({});
                     if (this.attachedMesh) {
+                        var originalParent = this.attachedMesh.parent;
+                        if (originalParent && ((originalParent as Mesh).scaling && (originalParent as Mesh).scaling.isNonUniformWithinEpsilon(0.001))) {
+                            Tools.Warn("BoundingBoxGizmo controls are not supported on child meshes with non-uniform parent scaling");
+                            return;
+                        }
                         BoundingBoxGizmo._RemoveAndStorePivotPoint(this.attachedMesh);
 
                         var worldDragDirection = startingTurnDirection;
@@ -208,6 +213,7 @@ module BABYLON {
                             this._anchorMesh.addChild(this.attachedMesh);
                             this._anchorMesh.rotationQuaternion!.multiplyToRef(this._tmpQuaternion, this._anchorMesh.rotationQuaternion!);
                             this._anchorMesh.removeChild(this.attachedMesh);
+                            this.attachedMesh.setParent(originalParent);
                         }
                         this.updateBoundingBox();
 
@@ -248,6 +254,11 @@ module BABYLON {
                         _dragBehavior.onDragObservable.add((event) => {
                             this.onScaleBoxDragObservable.notifyObservers({});
                             if (this.attachedMesh) {
+                                var originalParent = this.attachedMesh.parent;
+                                if (originalParent && ((originalParent as Mesh).scaling && (originalParent as Mesh).scaling.isNonUniformWithinEpsilon(0.001))) {
+                                    Tools.Warn("BoundingBoxGizmo controls are not supported on child meshes with non-uniform parent scaling");
+                                    return;
+                                }
                                 BoundingBoxGizmo._RemoveAndStorePivotPoint(this.attachedMesh);
                                 var relativeDragDistance = (event.dragDistance / this._boundingDimensions.length()) * this._anchorMesh.scaling.length();
                                 var deltaScale = new Vector3(relativeDragDistance, relativeDragDistance, relativeDragDistance);
@@ -274,7 +285,7 @@ module BABYLON {
                                     this._anchorMesh.scaling.subtractInPlace(deltaScale);
                                 }
                                 this._anchorMesh.removeChild(this.attachedMesh);
-
+                                this.attachedMesh.setParent(originalParent);
                                 BoundingBoxGizmo._RestorePivotPoint(this.attachedMesh);
                             }
                             this._updateDummy();
@@ -339,10 +350,15 @@ module BABYLON {
                 // Reset anchor mesh to match attached mesh's scale
                 // This is needed to avoid invalid box/sphere position on first drag
                 BoundingBoxGizmo._RemoveAndStorePivotPoint(value);
+                var originalParent = value.parent;
                 this._anchorMesh.addChild(value);
                 this._anchorMesh.removeChild(value);
+                value.setParent(originalParent);
                 BoundingBoxGizmo._RestorePivotPoint(value);
                 this.updateBoundingBox();
+                value.getChildMeshes(false).forEach((m) => {
+                    m.markAsDirty("scaling");
+                });
 
                 this.gizmoLayer.utilityLayerScene.onAfterRenderObservable.addOnce(() => {
                     this._updateDummy();
@@ -363,6 +379,8 @@ module BABYLON {
         public updateBoundingBox() {
             if (this.attachedMesh) {
                 BoundingBoxGizmo._RemoveAndStorePivotPoint(this.attachedMesh);
+                var originalParent = this.attachedMesh.parent;
+                this.attachedMesh.setParent(null);
                 this._update();
                 // Rotate based on axis
                 if (!this.attachedMesh.rotationQuaternion) {
@@ -394,6 +412,7 @@ module BABYLON {
                 // restore position/rotation values
                 this.attachedMesh.rotationQuaternion.copyFrom(this._tmpQuaternion);
                 this.attachedMesh.position.copyFrom(this._tmpVector);
+                this.attachedMesh.setParent(originalParent);
             }
 
             this._updateRotationSpheres();
@@ -476,6 +495,16 @@ module BABYLON {
             });
         }
 
+        /**
+         * Enables/disables scaling
+         * @param enable if scaling should be enabled
+         */
+        public setEnabledScaling(enable: boolean) {
+            this._scaleBoxesParent.getChildMeshes().forEach((m, i) => {
+                m.setEnabled(enable);
+            });
+        }
+
         private _updateDummy() {
             if (this._dragMesh) {
                 this._dragMesh.position.copyFrom(this._lineBoundingBox.getAbsolutePosition());

+ 25 - 0
src/Math/babylon.math.ts

@@ -1926,6 +1926,31 @@ module BABYLON {
         }
 
         /**
+         * Due to float precision, scale of a mesh could be uniform but float values are off by a small fraction
+         * Check if is non uniform within a certain amount of decimal places to account for this
+         * @param epsilon the amount the values can differ
+         * @returns if the the vector is non uniform to a certain number of decimal places
+         */
+        public isNonUniformWithinEpsilon(epsilon: number) {
+            let absX = Math.abs(this.x);
+            let absY = Math.abs(this.y);
+            if (!Scalar.WithinEpsilon(absX, absY, epsilon)) {
+                return true;
+            }
+
+            let absZ = Math.abs(this.z);
+            if (!Scalar.WithinEpsilon(absX, absZ, epsilon)) {
+                return true;
+            }
+
+            if (!Scalar.WithinEpsilon(absY, absZ, epsilon)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        /**
          * Gets a boolean indicating that the vector is non uniform meaning x, y or z are not all the same
          */
         public get isNonUniform(): boolean {