Bladeren bron

Merge pull request #4498 from TrevorDev/dragPlaneOrientation

Rotate drag plane by attached mesh's orienation and move world space …
David Catuhe 7 jaren geleden
bovenliggende
commit
da0c35cfd3

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

@@ -27,7 +27,7 @@
 - Get a root mesh from an asset container, load a mesh from a file with a single string url ([TrevorDev](https://github.com/TrevorDev))
 - UtilityLayer class to render another scene as a layer on top of an existing scene ([TrevorDev](https://github.com/TrevorDev))
 - AnimationGroup has now onAnimationGroupEnd observable ([RaananW](https://github.com/RaananW))
-- PointerDragBehavior, SixDofDragBehavior, MultiPointerScaleBehavior to enable drag and drop/scaling with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
+- PointerDragBehavior, SixDofDragBehavior and MultiPointerScaleBehavior to enable drag and drop/scaling with mouse or 6dof controller on a mesh ([TrevorDev](https://github.com/TrevorDev))
 - Gizmo and GizmoManager classes used to manipulate meshes in a scene. Position, rotation, scale, and bounding box gizmos ([TrevorDev](https://github.com/TrevorDev))
 - Added a new `mesh.ignoreNonUniformScaling` to turn off non uniform scaling compensation ([Deltakosh](https://github.com/deltakosh))
 - AssetsManager tasks will only run when their state is INIT. It is now possible to remove a task from the assets manager ([RaananW](https://github.com/RaananW))

+ 40 - 18
src/Behaviors/Mesh/babylon.pointerDragBehavior.ts

@@ -50,11 +50,16 @@ module BABYLON {
         public _dragPlaneParent:Nullable<Mesh>=null;
 
         /**
-         *  If the drag behavior will react to drag events
+         *  If the drag behavior will react to drag events (Default: true)
          */
         public enabled = true;
         
         /**
+         * If set, the drag plane/axis will be rotated based on the attached mesh's world rotation (Default: true)
+         */
+        public useObjectOrienationForDragging = true;
+
+        /**
          * Creates a pointer drag behavior that can be attached to a mesh
          * @param options The drag axis or normal of the plane that will be dragged across. If no options are specified the drag plane will always face the ray's origin (eg. camera)
          */
@@ -86,6 +91,8 @@ module BABYLON {
          */
         public init() {}
 
+        private _tmpVector = new Vector3(0,0,0);
+        private _worldDragAxis = new Vector3(0,0,0);
         /**
          * Attaches the drag behavior the passed in mesh
          * @param ownerNode The mesh that will be dragged around once attached
@@ -149,17 +156,19 @@ module BABYLON {
                             // depending on the drag mode option drag accordingly
                             if(this.options.dragAxis){
                                 // Convert local drag axis to world
-                                var worldDragAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
+                                Vector3.TransformCoordinatesToRef(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix(), this._worldDragAxis);
 
                                 // Project delta drag from the drag plane onto the drag axis
-                                dragLength = BABYLON.Vector3.Dot(pickedPoint.subtract(this.lastDragPosition), worldDragAxis)
-                                worldDragAxis.scaleToRef(dragLength, delta);
+                                pickedPoint.subtractToRef(this.lastDragPosition, this._tmpVector);
+                                dragLength = BABYLON.Vector3.Dot(this._tmpVector, this._worldDragAxis)
+                                this._worldDragAxis.scaleToRef(dragLength, delta);
                             }else{
                                 dragLength = delta.length();
                                 pickedPoint.subtractToRef(this.lastDragPosition, delta);
                             }
                             if(this.moveAttached){
-                                (<Mesh>this._attachedNode).position.addInPlace(delta);
+                                (<Mesh>this._attachedNode).absolutePosition.addToRef(delta, this._tmpVector);
+                                (<Mesh>this._attachedNode).setAbsolutePosition(this._tmpVector);
                             }
                             this.onDragObservable.notifyObservers({dragDistance: dragLength, delta: delta, dragPlanePoint: pickedPoint, dragPlaneNormal: this._dragPlane.forward, pointerId: this.currentDraggingPointerID});
                             this.lastDragPosition.copyFrom(pickedPoint);
@@ -187,29 +196,42 @@ module BABYLON {
             }
         }
 
+        // Variables to avoid instantiation in the below method
+        private _pointA = new Vector3(0,0,0);
+        private _pointB = new Vector3(0,0,0);
+        private _pointC = new Vector3(0,0,0);
+        private _lineA = new Vector3(0,0,0);
+        private _lineB = new Vector3(0,0,0);
+        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){
-            var pointA = this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition;
+            this._pointA.copyFrom(this._dragPlaneParent ? this._dragPlaneParent.absolutePosition : (<Mesh>this._attachedNode).absolutePosition);
             if(this.options.dragAxis){
-                var localAxis = Vector3.TransformCoordinates(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix());
+                this.useObjectOrienationForDragging ? Vector3.TransformCoordinatesToRef(this.options.dragAxis, this._attachedNode.getWorldMatrix().getRotationMatrix(), this._localAxis) : this._localAxis.copyFrom(this.options.dragAxis);
 
                 // Calculate plane normal in direction of camera but perpendicular to drag axis
-                var pointB = pointA.add(localAxis); // towards drag axis
-                var pointC = pointA.add(ray.origin.subtract(pointA).normalize()); // towards camera
+                this._pointA.addToRef(this._localAxis, this._pointB); // towards drag axis
+                ray.origin.subtractToRef(this._pointA, this._pointC)
+                this._pointA.addToRef(this._pointC.normalize(), this._pointC); // towards camera
                 // Get perpendicular line from direction to camera and drag axis
-                var lineA = pointB.subtract(pointA);
-                var lineB = pointC.subtract(pointA);
-                var perpLine = BABYLON.Vector3.Cross(lineA, lineB);
+                this._pointB.subtractToRef(this._pointA, this._lineA);
+                this._pointC.subtractToRef(this._pointA, this._lineB);
+                BABYLON.Vector3.CrossToRef(this._lineA, this._lineB, this._lookAt);
                 // Get perpendicular line from previous result and drag axis to adjust lineB to be perpendiculat to camera
-                var norm = BABYLON.Vector3.Cross(lineA, perpLine).normalize();
+                BABYLON.Vector3.CrossToRef(this._lineA, this._lookAt, this._lookAt);
+                this._lookAt.normalize();
 
-                this._dragPlane.position.copyFrom(pointA);
-                this._dragPlane.lookAt(pointA.subtract(norm));
+                this._dragPlane.position.copyFrom(this._pointA);
+                this._pointA.subtractToRef(this._lookAt, this._lookAt);
+                this._dragPlane.lookAt(this._lookAt);
             }else if(this.options.dragPlaneNormal){
-                this._dragPlane.position.copyFrom(pointA);
-                this._dragPlane.lookAt(pointA.subtract(this.options.dragPlaneNormal));
+                this.useObjectOrienationForDragging ? Vector3.TransformCoordinatesToRef(this.options.dragPlaneNormal, this._attachedNode.getWorldMatrix().getRotationMatrix(),this._localAxis) : this._localAxis.copyFrom(this.options.dragPlaneNormal);
+                this._dragPlane.position.copyFrom(this._pointA);
+                this._pointA.subtractToRef(this._localAxis, this._lookAt);
+                this._dragPlane.lookAt(this._lookAt);
             }else{
-                this._dragPlane.position.copyFrom(pointA);
+                this._dragPlane.position.copyFrom(this._pointA);
                 this._dragPlane.lookAt(ray.origin);
             }
             this._dragPlane.computeWorldMatrix(true);

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

@@ -29,7 +29,7 @@ module BABYLON {
             this._rootMesh.lookAt(this._rootMesh.position.subtract(planeNormal));
 
             // Add drag behavior to handle events when the gizmo is dragged
-            this._dragBehavior = new PointerDragBehavior({dragPlaneNormal: planeNormal});
+            this._dragBehavior = new PointerDragBehavior({dragPlaneNormal: new Vector3(0,0,1)});
             this._dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this._dragBehavior);