Browse Source

Merge pull request #4968 from TrevorDev/scalePivot

add scalePivot to bounding box gizmo
sebavan 7 years ago
parent
commit
edfc529a32
2 changed files with 63 additions and 6 deletions
  1. 1 0
      dist/preview release/what's new.md
  2. 62 6
      src/Gizmos/babylon.boundingBoxGizmo.ts

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

@@ -106,6 +106,7 @@
 - StartDrag method added to pointerDragBehavior to simulate the start of a drag ([TrevorDev](https://github.com/TrevorDev))
 - Added EdgesLineRenderer to address [#4919](https://github.com/BabylonJS/Babylon.js/pull/4919) ([barteq100](https://github.com/barteq100))
 - Added ```ambientTextureImpactOnAnalyticalLights``` in PBRMaterial to allow fine grained control of the AmbientTexture on the analytical diffuse light ([sebavan](http://www.github.com/sebavan))
+- BoundingBoxGizmo scalePivot field that can be used to always scale objects from the bottom ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Loader
 

+ 62 - 6
src/Gizmos/babylon.boundingBoxGizmo.ts

@@ -13,6 +13,7 @@ module BABYLON {
 
         private _tmpQuaternion = new Quaternion();
         private _tmpVector = new Vector3(0, 0, 0);
+        private _tmpRotationMatrix = new Matrix();
         /**
          * If child meshes should be ignored when calculating the boudning box. This should be set to true to avoid perf hits with heavily nested meshes (Default: false)
          */
@@ -55,8 +56,41 @@ module BABYLON {
          * Fired when a rotation sphere drag is ended
          */
         public onRotationSphereDragEndObservable = new Observable<{}>();
+        /**
+         * Relative bounding box pivot used when scaling the attached mesh. When null object with scale from the opposite corner. 0.5,0.5,0.5 for center and 0.5,0,0.5 for bottom (Default: null)
+         */
+        public scalePivot:Nullable<Vector3> = null;
         private _anchorMesh: AbstractMesh;
         private _existingMeshScale = new Vector3();
+
+        private _oldPivotPoint = new Vector3();
+        private _pivotTranslation = new Vector3();
+        private removeAndStorePivotPoint(){
+            if(this.attachedMesh){
+                // Save old pivot and set pivot to 0,0,0
+                this.attachedMesh.getPivotPointToRef(this._oldPivotPoint);
+                if(this._oldPivotPoint.equalsToFloats(0,0,0)){
+                    return;
+                }
+                this.attachedMesh.setPivotMatrix(Matrix.IdentityReadOnly);
+                this._oldPivotPoint.subtractToRef(this.attachedMesh.getPivotPoint(), this._pivotTranslation);
+                this._tmpVector.copyFromFloats(1,1,1);
+                this._tmpVector.subtractInPlace(this.attachedMesh.scaling);
+                this._tmpVector.multiplyInPlace(this._pivotTranslation);
+                this.attachedMesh.position.addInPlace(this._tmpVector);
+            }
+        }
+        private restorePivotPoint(){
+            if(this.attachedMesh && !this._oldPivotPoint.equalsToFloats(0,0,0)){
+                this.attachedMesh.setPivotPoint(this._oldPivotPoint);    
+                this._oldPivotPoint.subtractToRef(this.attachedMesh.getPivotPoint(), this._pivotTranslation);
+                this._tmpVector.copyFromFloats(1,1,1);
+                this._tmpVector.subtractInPlace(this.attachedMesh.scaling);
+                this._tmpVector.multiplyInPlace(this._pivotTranslation);
+                this.attachedMesh.position.subtractInPlace(this._tmpVector);
+            }
+        }
+
         /**
          * Creates an BoundingBoxGizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
@@ -123,6 +157,8 @@ module BABYLON {
                 _dragBehavior.onDragObservable.add((event) => {
                     this.onRotationSphereDragObservable.notifyObservers({});
                     if (this.attachedMesh) {
+                        this.removeAndStorePivotPoint();
+
                         var worldDragDirection = startingTurnDirection;
 
                         // Project the world right on to the drag plane
@@ -160,6 +196,8 @@ module BABYLON {
                             this._anchorMesh.removeChild(this.attachedMesh);
                         }
                         this.updateBoundingBox();
+
+                        this.restorePivotPoint();
                     }
                 });
 
@@ -194,20 +232,36 @@ module BABYLON {
                         _dragBehavior.onDragObservable.add((event) => {
                             this.onScaleBoxDragObservable.notifyObservers({});
                             if(this.attachedMesh){
+                                this.removeAndStorePivotPoint();
+                                
                                 var relativeDragDistance = (event.dragDistance / this._boundingDimensions.length())*this._anchorMesh.scaling.length();
                                 var deltaScale = new Vector3(relativeDragDistance,relativeDragDistance,relativeDragDistance);
                                 deltaScale.scaleInPlace(this._scaleDragSpeed);
                                 this.updateBoundingBox();
 
-                                // Scale from the position of the opposite corner                   
-                                box.absolutePosition.subtractToRef(this._anchorMesh.position, this._tmpVector);
-                                this._anchorMesh.position.subtractInPlace(this._tmpVector);
+                                if(this.scalePivot){
+                                    this.attachedMesh.getWorldMatrix().getRotationMatrixToRef(this._tmpRotationMatrix);
+                                    // Move anchor to desired pivot point (Bottom left corner + dimension/2)
+                                    this._boundingDimensions.scaleToRef(0.5, this._tmpVector);
+                                    Vector3.TransformCoordinatesToRef(this._tmpVector, this._tmpRotationMatrix, this._tmpVector);
+                                    this._anchorMesh.position.subtractInPlace(this._tmpVector);
+                                    this._boundingDimensions.multiplyToRef(this.scalePivot, this._tmpVector);
+                                    Vector3.TransformCoordinatesToRef(this._tmpVector, this._tmpRotationMatrix, this._tmpVector);
+                                    this._anchorMesh.position.addInPlace(this._tmpVector);
+                                }else{
+                                    // Scale from the position of the opposite corner                   
+                                    box.absolutePosition.subtractToRef(this._anchorMesh.position, this._tmpVector);
+                                    this._anchorMesh.position.subtractInPlace(this._tmpVector);
+                                }
+
                                 this._anchorMesh.addChild(this.attachedMesh);
                                 this._anchorMesh.scaling.addInPlace(deltaScale);
                                 if (this._anchorMesh.scaling.x < 0 || this._anchorMesh.scaling.y < 0 || this._anchorMesh.scaling.z < 0) {
                                     this._anchorMesh.scaling.subtractInPlace(deltaScale);
                                 }
                                 this._anchorMesh.removeChild(this.attachedMesh);
+
+                                this.restorePivotPoint();
                             }
                         })
 
@@ -285,8 +339,9 @@ module BABYLON {
          * Updates the bounding box information for the Gizmo
          */
         public updateBoundingBox(){
-            this._update();
-            if(this.attachedMesh){             
+            if(this.attachedMesh){
+                this.removeAndStorePivotPoint();
+                this._update();
                 // Rotate based on axis
                 if (!this.attachedMesh.rotationQuaternion) {
                     this.attachedMesh.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.attachedMesh.rotation.y, this.attachedMesh.rotation.x, this.attachedMesh.rotation.z);
@@ -379,7 +434,8 @@ module BABYLON {
                 }
             }
             if (this.attachedMesh) {
-                this._existingMeshScale.copyFrom(this.attachedMesh.scaling);
+                this._existingMeshScale.copyFrom(this.attachedMesh.scaling);   
+                this.restorePivotPoint();
             }
         }