Browse Source

Merge pull request #4868 from TrevorDev/interactingWithChildElementNotFunctioningCorrectly

consider parent matrix when rotating and positioning child meshes wit…
David Catuhe 7 years ago
parent
commit
1544c39147

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

@@ -16,6 +16,7 @@
   - Ability to customize meshes on gizmos ([TrevorDev](https://github.com/TrevorDev))
   - Added ignoreChildren field to bounding box to save performance when using heavily nested meshes ([TrevorDev](https://github.com/TrevorDev))
   - Add uniform scaling drag support to scale gizmo ([TrevorDev](https://github.com/TrevorDev))
+  - Support interacting with child elements ([TrevorDev](https://github.com/TrevorDev))
 - Particle system improvements ([Deltakosh](https://github.com/deltakosh))
   - Added a ParticleHelper class to create some pre-configured particle systems in a one-liner method style. [Doc](https://doc.babylonjs.com/How_To/ParticleHelper) ([Deltakosh](https://github.com/deltakosh)) / ([DevChris](https://github.com/yovanoc))
   - Improved CPU particles rendering performance (up to x2 on low end devices)

+ 15 - 4
src/Gizmos/babylon.axisDragGizmo.ts

@@ -53,7 +53,7 @@ module BABYLON {
             arrowTail.material = coloredMaterial;
             arrow.lookAt(this._rootMesh.position.subtract(dragAxis));
 
-            this._rootMesh.addChild(arrow)
+            this._rootMesh.addChild(arrow);
 
             var currentSnapDragDistance = 0;
             var tmpVector = new Vector3();
@@ -62,17 +62,28 @@ module BABYLON {
             this.dragBehavior = new PointerDragBehavior({dragAxis: dragAxis});
             this.dragBehavior.moveAttached = false;
             this._rootMesh.addBehavior(this.dragBehavior);
+
+            var localDelta = new BABYLON.Vector3();
+            var tmpMatrix = new BABYLON.Matrix();
             this.dragBehavior.onDragObservable.add((event)=>{
                 if(this.attachedMesh){
+                    // Convert delta to local translation if it has a parent
+                    if(this.attachedMesh.parent){
+                        this.attachedMesh.parent.computeWorldMatrix().invertToRef(tmpMatrix);
+                        tmpMatrix.setTranslationFromFloats(0,0,0);
+                        Vector3.TransformCoordinatesToRef(event.delta, tmpMatrix, localDelta);
+                    }else{
+                        localDelta.copyFrom(event.delta);
+                    }
                     // Snapping logic
                     if(this.snapDistance == 0){
-                        this.attachedMesh.position.addInPlace(event.delta);
+                        this.attachedMesh.position.addInPlace(localDelta);
                     }else{
-                        currentSnapDragDistance+=event.dragDistance
+                        currentSnapDragDistance+=event.dragDistance;
                         if(Math.abs(currentSnapDragDistance)>this.snapDistance){
                             var dragSteps = Math.floor(Math.abs(currentSnapDragDistance)/this.snapDistance);
                             currentSnapDragDistance = currentSnapDragDistance % this.snapDistance;
-                            event.delta.normalizeToRef(tmpVector);
+                            localDelta.normalizeToRef(tmpVector);
                             tmpVector.scaleInPlace(this.snapDistance*dragSteps);
                             this.attachedMesh.position.addInPlace(tmpVector);
                             tmpSnapEvent.snapDistance = this.snapDistance*dragSteps;

+ 0 - 2
src/Gizmos/babylon.gizmoManager.ts

@@ -8,7 +8,6 @@ module BABYLON {
          */
         public gizmos:{positionGizmo: Nullable<PositionGizmo>, rotationGizmo: Nullable<RotationGizmo>, scaleGizmo: Nullable<ScaleGizmo>, boundingBoxGizmo: Nullable<BoundingBoxGizmo>};
         private _gizmosEnabled = {positionGizmo: false, rotationGizmo: false, scaleGizmo: false, boundingBoxGizmo: false};
-        private _gizmoLayer:UtilityLayerRenderer;
         private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
         private _attachedMesh:Nullable<AbstractMesh> = null;
         private _boundingBoxColor = BABYLON.Color3.FromHexString("#0984e3");
@@ -164,7 +163,6 @@ module BABYLON {
                 }
             }
             this._dragBehavior.detach();
-            this._gizmoLayer.dispose();
         }
     }
 }

+ 23 - 5
src/Gizmos/babylon.planeRotationGizmo.ts

@@ -80,14 +80,17 @@ module BABYLON {
 
             var tmpSnapEvent = {snapDistance: 0};
             var currentSnapDragDistance = 0;
+            var tmpMatrix = new BABYLON.Matrix();
+            var tmpVector = new BABYLON.Vector3();
+            var amountToRotate = new BABYLON.Quaternion();
             this.dragBehavior.onDragObservable.add((event)=>{
                 if(this.attachedMesh){
                     if(!this.attachedMesh.rotationQuaternion){
                         this.attachedMesh.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.attachedMesh.rotation.y, this.attachedMesh.rotation.x, this.attachedMesh.rotation.z);
                     }
                     // Calc angle over full 360 degree (https://stackoverflow.com/questions/43493711/the-angle-between-two-3d-vectors-with-a-result-range-0-360)
-                    var newVector = event.dragPlanePoint.subtract(this.attachedMesh.position).normalize();
-                    var originalVector = lastDragPosition.subtract(this.attachedMesh.position).normalize();
+                    var newVector = event.dragPlanePoint.subtract(this.attachedMesh.absolutePosition).normalize();
+                    var originalVector = lastDragPosition.subtract(this.attachedMesh.absolutePosition).normalize();
                     var cross = Vector3.Cross(newVector,originalVector);
                     var dot = Vector3.Dot(newVector,originalVector);
                     var angle = Math.atan2(cross.length(), dot);
@@ -121,9 +124,24 @@ module BABYLON {
                             angle = 0;
                         }
                     }
-                     // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
-                     var quaternionCoefficient = Math.sin(angle/2)
-                     var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x*quaternionCoefficient,planeNormalTowardsCamera.y*quaternionCoefficient,planeNormalTowardsCamera.z*quaternionCoefficient,Math.cos(angle/2));
+
+                    // If the mesh has a parent, convert needed world rotation to local rotation
+                    tmpMatrix.reset();
+                    if(this.attachedMesh.parent){
+                        this.attachedMesh.parent.computeWorldMatrix().invertToRef(tmpMatrix);
+                        tmpMatrix.getRotationMatrixToRef(tmpMatrix);
+                        Vector3.TransformCoordinatesToRef(planeNormalTowardsCamera, tmpMatrix, planeNormalTowardsCamera);
+                    }
+
+                    // Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
+                    var quaternionCoefficient = Math.sin(angle/2);
+                    amountToRotate.set(planeNormalTowardsCamera.x*quaternionCoefficient,planeNormalTowardsCamera.y*quaternionCoefficient,planeNormalTowardsCamera.z*quaternionCoefficient,Math.cos(angle/2));
+
+                    // If the meshes local scale is inverted (eg. loaded gltf file parent with z scale of -1) the rotation needs to be inverted on the y axis
+                    if(tmpMatrix.determinant() > 0){
+                        amountToRotate.toEulerAnglesToRef(tmpVector);
+                        BABYLON.Quaternion.RotationYawPitchRollToRef(tmpVector.y, -tmpVector.x, -tmpVector.z, amountToRotate);
+                    }
 
                      if(this.updateGizmoRotationToMatchAttachedMesh){
                         // Rotate selected mesh quaternion over fixed axis