Browse Source

avoid jitter caused by moving drag plane, allow the gizmo to be updated to match the attached mesh's rotation

Trevor Baron 7 years ago
parent
commit
366e25b8ef

+ 6 - 15
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -22,7 +22,6 @@ module BABYLON {
         public dragging = false;
         // Debug mode will display drag planes to help visualize behavior
         private _debugMode = false;
-        private _maxDragAngle = Math.PI/5;
         private _moving = false;
         /**
          *  Fires each time the attached mesh is dragged with the pointer
@@ -44,10 +43,6 @@ module BABYLON {
          *  If the attached mesh should be moved when dragged
          */
         public moveAttached = true;
-        /**
-         *  Mesh with the position where the drag plane should be placed
-         */
-        public _dragPlaneParent:Nullable<Mesh>=null;
 
         /**
          *  If the drag behavior will react to drag events (Default: true)
@@ -129,8 +124,8 @@ module BABYLON {
                 
                 if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
                     
-                    if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
-                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
+                    if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.pickedPoint && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
+                        this._updateDragPlanePosition(pointerInfo.pickInfo.ray, pointerInfo.pickInfo.pickedPoint);
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         if(pickedPoint){
                             this.dragging = true;
@@ -149,13 +144,9 @@ module BABYLON {
                         this._moving = true;
                         var pickedPoint = this._pickWithRayOnDragPlane(pointerInfo.pickInfo.ray);
                         
-                         // Get angle between drag plane and ray. Only update the drag plane at non steep angles to avoid jumps in delta position
-                        var angle = Math.acos(Vector3.Dot(this._dragPlane.forward, pointerInfo.pickInfo.ray.direction));
-                        if(angle < this._maxDragAngle){
-                            this._updateDragPlanePosition(pointerInfo.pickInfo.ray);
-                        }
-                        
                         if (pickedPoint) {
+                            this._updateDragPlanePosition(pointerInfo.pickInfo.ray, pickedPoint);
+
                             // depending on the drag mode option drag accordingly
                             if(this.options.dragAxis){
                                 // Convert local drag axis to world
@@ -216,8 +207,8 @@ module BABYLON {
         private _localAxis = new Vector3(0,0,0);
         private _lookAt = new Vector3(0,0,0); 
         // Position the drag plane based on the attached mesh position, for single axis rotate the plane along the axis to face the camera
-        private _updateDragPlanePosition(ray:Ray){
-            this._pointA.copyFrom(this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition);
+        private _updateDragPlanePosition(ray:Ray, dragPlanePosition:Vector3){
+            this._pointA.copyFrom(dragPlanePosition);
             if(this.options.dragAxis){
                 this.useObjectOrienationForDragging ? Vector3.TransformCoordinatesToRef(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix(), this._localAxis) : this._localAxis.copyFrom(this.options.dragAxis);
 

+ 2 - 1
src/Gizmos/babylon.axisDragGizmo.ts

@@ -12,7 +12,8 @@ module BABYLON {
          */
         constructor(gizmoLayer:UtilityLayerRenderer, dragAxis:Vector3, color:Color3){
             super(gizmoLayer);
-
+            this.updateGizmoRotationToMatchAttachedMesh = false;
+            
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;

+ 2 - 1
src/Gizmos/babylon.axisScaleGizmo.ts

@@ -12,7 +12,8 @@ module BABYLON {
          */
         constructor(gizmoLayer:UtilityLayerRenderer, dragAxis:Vector3, color:Color3){
             super(gizmoLayer);
-
+            this.updateGizmoRotationToMatchAttachedMesh=false;
+            
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;

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

@@ -9,6 +9,7 @@ module BABYLON {
         private _boundingDimensions = new BABYLON.Vector3(1,1,1);
         private _renderObserver:Nullable<Observer<Scene>> = null;
         private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
+        private _scaleDragSpeed = 0.2;
 
         /**
          * Creates an BoundingBoxGizmo
@@ -121,6 +122,7 @@ module BABYLON {
                                 
                                 // Get the change in bounding box size/2 and add this to the mesh's position to offset from scaling with center pivot point
                                 var deltaScale = new Vector3(event.dragDistance,event.dragDistance,event.dragDistance);
+                                deltaScale.scaleInPlace(this._scaleDragSpeed);
                                 var scaleRatio = deltaScale.divide(this.attachedMesh.scaling).scaleInPlace(0.5);
                                 var moveDirection = boundBoxDimensions.multiply(scaleRatio).multiplyInPlace(dragAxis);
                                 var worldMoveDirection = Vector3.TransformCoordinates(moveDirection, this.attachedMesh.getWorldMatrix().getRotationMatrix());
@@ -184,12 +186,6 @@ module BABYLON {
                 var boundBoxDimensions = boundingInfo.maximum.subtract(boundingInfo.minimum).multiplyInPlace(this.attachedMesh.scaling);
                 this._boundingDimensions.copyFrom(boundBoxDimensions);
                 this._lineBoundingBox.scaling.copyFrom(this._boundingDimensions);
-                if(!this.attachedMesh.rotationQuaternion){
-                    this.attachedMesh.rotationQuaternion = new BABYLON.Quaternion();
-                }
-                this._lineBoundingBox.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
-                this._rotateSpheresParent.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
-                this._scaleBoxesParent.rotationQuaternion!.copyFrom(this.attachedMesh.rotationQuaternion);
             }
 
             // Update rotation sphere locations

+ 17 - 1
src/Gizmos/babylon.gizmo.ts

@@ -12,6 +12,14 @@ module BABYLON {
          */
         public attachedMesh:Nullable<AbstractMesh>;
         /**
+         * If set the gizmo's rotation will be updated to match the attached mesh each frame (Default: true)
+         */
+        public updateGizmoRotationToMatchAttachedMesh = false;
+        /**
+         * If set the gizmo's position will be updated to match the attached mesh each frame (Default: true)
+         */
+        public updateGizmoPositionToMatchAttachedMesh = true;
+        /**
          * When set, the gizmo will always appear the same size no matter where the camera is (default: false)
          */
         protected _updateScale = true;
@@ -44,7 +52,15 @@ module BABYLON {
                     this._rootMesh.scaling.set(dist, dist, dist);
                 }
                 if(this.attachedMesh){
-                    this._rootMesh.position.copyFrom(this.attachedMesh.position);
+                    if(this.updateGizmoRotationToMatchAttachedMesh){
+                        if(!this._rootMesh.rotationQuaternion){
+                            this._rootMesh.rotationQuaternion = new BABYLON.Quaternion();
+                        }
+                        Quaternion.FromRotationMatrixToRef(this.attachedMesh.getWorldMatrix().getRotationMatrix(), this._rootMesh.rotationQuaternion);
+                    }
+                    if(this.updateGizmoPositionToMatchAttachedMesh){
+                        this._rootMesh.position.copyFrom(this.attachedMesh.absolutePosition);
+                    }
                 }
             })
         }

+ 2 - 1
src/Gizmos/babylon.planeRotationGizmo.ts

@@ -12,7 +12,8 @@ module BABYLON {
          */
         constructor(gizmoLayer:UtilityLayerRenderer, planeNormal:Vector3, color:Color3){
             super(gizmoLayer);
-
+            this.updateGizmoRotationToMatchAttachedMesh=false;
+            
             // Create Material
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;