Przeglądaj źródła

nested bounding box working

Trevor Baron 7 lat temu
rodzic
commit
3f33369d50

+ 1 - 1
src/Behaviors/Mesh/babylon.sixDofDragBehavior.ts

@@ -74,7 +74,7 @@ module BABYLON {
             this._pointerObserver = this._scene.onPointerObservable.add((pointerInfo, eventState)=>{                
                 if (pointerInfo.type == BABYLON.PointerEventTypes.POINTERDOWN) {
                     if(!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)){
-                        pickedMesh = pointerInfo.pickInfo.pickedMesh;
+                        pickedMesh = this._ownerNode;
                         lastSixDofOriginPosition.copyFrom(pointerInfo.pickInfo.ray.origin);
 
                         // Set position and orientation of the controller

+ 86 - 23
src/Gizmos/babylon.boundingBoxGizmo.ts

@@ -43,7 +43,7 @@ module BABYLON {
          * Fired when a rotation sphere or scale box drag is needed
          */
         public onDragEndObservable = new Observable<{}>();
-        
+        private _anchorMesh:AbstractMesh;
         /**
          * Creates an BoundingBoxGizmo
          * @param gizmoLayer The utility layer the gizmo will be added to
@@ -55,6 +55,7 @@ module BABYLON {
             // Do not update the gizmo's scale so it has a fixed size to the object its attached to
             this._updateScale = false;
 
+            this._anchorMesh = new AbstractMesh("anchor", gizmoLayer.utilityLayerScene);
             // Create Materials
             var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
             coloredMaterial.disableLighting = true;
@@ -122,6 +123,9 @@ module BABYLON {
                         if(!this.attachedMesh.rotationQuaternion){
                             this.attachedMesh.rotationQuaternion = Quaternion.RotationYawPitchRoll(this.attachedMesh.rotation.y,this.attachedMesh.rotation.x,this.attachedMesh.rotation.z);
                         }
+                        if(!this._anchorMesh.rotationQuaternion){
+                            this._anchorMesh.rotationQuaternion = Quaternion.RotationYawPitchRoll(this._anchorMesh.rotation.y,this._anchorMesh.rotation.x,this._anchorMesh.rotation.z);
+                        }
                        
                         // Do not allow the object to turn more than a full circle
                         totalTurnAmountOfDrag+=projectDist;
@@ -133,7 +137,11 @@ module BABYLON {
                             }else{
                                 Quaternion.RotationYawPitchRollToRef(0,projectDist,0, this._tmpQuaternion);
                             }
-                            this.attachedMesh.rotationQuaternion!.multiplyInPlace(this._tmpQuaternion);
+
+                            // Rotate around center of bounding box
+                            this._anchorMesh.addChild(this.attachedMesh);
+                            this._anchorMesh.rotationQuaternion!.multiplyToRef(this._tmpQuaternion,this._anchorMesh.rotationQuaternion!);
+                            this._anchorMesh.removeChild(this.attachedMesh);
                         }
                     }
                 });
@@ -169,25 +177,19 @@ module BABYLON {
                         _dragBehavior.onDragObservable.add((event)=>{
                             this.onDragObservable.notifyObservers({});
                             if(this.attachedMesh){
-                                // Current boudning box dimensions
-                                var boundingInfo = this.attachedMesh.getBoundingInfo().boundingBox;
-                                var boundBoxDimensions = boundingInfo.maximum.subtract(boundingInfo.minimum).multiplyInPlace(this.attachedMesh.scaling);
-                                
-                                // 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());
-                                
-                                // Update scale and position
-                                this.attachedMesh.scaling.addInPlace(deltaScale);
-                                if(this.attachedMesh.scaling.x < 0 || this.attachedMesh.scaling.y < 0 || this.attachedMesh.scaling.z < 0){
-                                    this.attachedMesh.scaling.subtractInPlace(deltaScale);
-                                }else{
-                                    this.attachedMesh.getAbsolutePosition().addToRef(worldMoveDirection, this._tmpVector)
-                                    this.attachedMesh.setAbsolutePosition(this._tmpVector);
+                                this._updateBoundingBox(); 
+
+                                 // 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);
                             }
                         })
 
@@ -232,6 +234,42 @@ module BABYLON {
             this._updateBoundingBox();
         }
 
+        // http://www.html5gamedevs.com/topic/23468-get-size-of-mesh-while-taking-its-children-into-account/
+        private getMinMax(mesh:AbstractMesh, min:Vector3, max:Vector3, computeWorldMatrix:boolean) {
+            if (computeWorldMatrix) {
+                mesh.computeWorldMatrix(true);
+            }
+            
+            var bi = mesh.getBoundingInfo();
+            var minimum = bi.boundingBox.minimumWorld;
+            var maximum = bi.boundingBox.maximumWorld;
+            
+            if (minimum.x < min.x) {
+                min.x = minimum.x;
+            }
+            if (minimum.y < min.y) {
+                min.y = minimum.y;
+            }
+            if (minimum.z < min.z) {
+                min.z = minimum.z;
+            }
+        
+            if (maximum.x > max.x) {
+                max.x = maximum.x;
+            }
+            if (maximum.y > max.y) {
+                max.y = maximum.y;
+            }
+            if (maximum.z > max.z) {
+                max.z = maximum.z;
+            }
+
+            var children = mesh.getChildMeshes();
+            for (var i = 0; i < children.length; i++){
+                this.getMinMax(children[i], min, max, computeWorldMatrix);
+            }
+        }
+
         private _selectNode(selectedMesh:Nullable<Mesh>){
             this._rotateSpheresParent.getChildMeshes()
             .concat(this._scaleBoxesParent.getChildMeshes()).forEach((m,i)=>{
@@ -240,12 +278,37 @@ module BABYLON {
         }
 
         private _updateBoundingBox(){
-            if(this.attachedMesh){
-                // Update bounding dimensions/positions
-                var boundingInfo = this.attachedMesh.getBoundingInfo().boundingBox;
-                var boundBoxDimensions = boundingInfo.maximum.subtract(boundingInfo.minimum).multiplyInPlace(this.attachedMesh.scaling);
-                this._boundingDimensions.copyFrom(boundBoxDimensions);
+            if(this.attachedMesh){             
+                // 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);
+                }
+
+                // Store original position and reset mesh to origin before computing the bounding box
+                this._tmpQuaternion.copyFrom(this.attachedMesh.rotationQuaternion);
+                this._tmpVector.copyFrom(this.attachedMesh.position);
+                this.attachedMesh.rotationQuaternion.set(0,0,0,1);
+                this.attachedMesh.position.set(0,0,0)
+                
+                // Update bounding dimensions/positions   
+                var min = new BABYLON.Vector3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
+                var max = new BABYLON.Vector3(Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE);
+                this.getMinMax(this.attachedMesh, min, max, true)
+                this._boundingDimensions.x = max.x-min.x
+                this._boundingDimensions.y = max.y-min.y
+                this._boundingDimensions.z = max.z-min.z
+
+                // Update gizmo to match bounding box scaling and rotation
                 this._lineBoundingBox.scaling.copyFrom(this._boundingDimensions);
+                this._lineBoundingBox.position.set((max.x+min.x)/2,(max.y+min.y)/2,(max.z+min.z)/2);
+                this._rotateSpheresParent.position.copyFrom(this._lineBoundingBox.position);
+                this._scaleBoxesParent.position.copyFrom(this._lineBoundingBox.position);
+                this._anchorMesh.position.copyFrom(this._lineBoundingBox.absolutePosition);
+                
+                // restore position/rotation values
+                this.attachedMesh.rotationQuaternion.copyFrom(this._tmpQuaternion);
+                this.attachedMesh.position.copyFrom(this._tmpVector);
+                this.getMinMax(this.attachedMesh, min, max, true);
             }
 
             // Update rotation sphere locations