Exemple #1
0
        /// <summary>
        /// Find the picker's angle of rotation from zero.
        /// </summary>
        /// <remarks>
        /// Once the picker is grasping the pickable object, it will stay on the "surface" of the
        /// pickable by maintaining a fixed displacement with a constrain point. The constrain point
        /// is a game object that will rotate together with this one. E.g. it can be the edge of the
        /// lever. When picker is moved to new position, the position of the new constrain point can
        /// be found in turn. Picker's angle of rotation can be calculated from the angle that needs
        /// to rotate from zero deg to the direction from centre of rotation to new constrain point.
        /// </remarks>
        /// <param name="picker">The picker that is grasping the object.</param>
        /// <returns>Picker's angle of rotation from zero.</returns>
        protected override float GetPickerAngleInRotationAxis(IPicker picker)
        {
            PickerDexmo pickerDexmo     = picker as PickerDexmo;
            Transform   pickerReference = pickerDexmo == null ? picker.Transform : pickerDexmo.PalmCenter;

            // We want the picker transform to maintain a fixed displacement in world space with the
            // constrain point, so when picker transform is moved to a new point, the new
            // constrain point can be obtained by subtracting the fixed displacement from
            // the picker transform.
            Vector3 newConstrainPoint = pickerReference.position - PickerFixedDisplacementWrtConstrainPoint;

            // Since the object itself is the centre of rotation and will rotate during runtime,
            // all the directions here is calculated in parent transform's coordinate.

            // transform.position is the centre of rotation. Find the direction pointing from
            // centre of rotation to new constrain point position.
            Vector3 pickerRelativeDirectionInParentCoordinate =
                Miscellaneous.InverseTransformDirectionInParentCoordinate(transform,
                                                                          newConstrainPoint - transform.position);
            // Find the angle of rotation from zero reference to the direction connecting the
            // centre of rotation to new constrain point position.
            float angle = RotationUtils.AngleInPlane(LocalRotationAxisInParentCoordinate,
                                                     ZeroReferenceDirectionInParentCoordinate, pickerRelativeDirectionInParentCoordinate);

            return(angle);
        }
        /// <summary>
        /// It contrains the picker by overwriting its position and rotation. In this function
        /// it constrains picker by keeping picker a fixed postion and rotation offset with
        /// the position and the rotation of the constrain point reference transform.
        /// </summary>
        /// <remarks>
        /// The position and rotation offset between the picker and the constrain point reference
        /// is determined when this object is just picked up in <see cref="OnPickedInit"/>.
        /// Then when this pickable moves towards the picker with certain constraint, the
        /// constraint reference will move accordingly. This function is called to bring back
        /// picker so it always have the some offset with the constrain reference.
        /// This is a virtual function and the mechanism to constrain picker may be overridden by
        /// derived classes.
        /// </remarks>
        /// <param name="picker">The picker to constrain</param>
        protected virtual void ConstrainPicker(IPicker picker)
        {
            PickerDexmo pickerDexmo     = picker as PickerDexmo;
            Transform   pickerReference = null;

            if (pickerDexmo == null)
            {
                pickerReference = picker.Transform;
            }
            else
            {
                switch (PickerDexmoConstrainPart)
                {
                case PickerDexmoConstrainPartType.Wrist:
                    pickerReference = pickerDexmo.transform;
                    break;

                case PickerDexmoConstrainPartType.PalmCenter:
                    pickerReference = pickerDexmo.PalmCenter;
                    break;
                }
            }
            if (_constrainPositionReference != null)
            {
                // Constrain picker's position to ensure it has fixed displacement
                // with constrain reference.
                pickerReference.position = _constrainPositionReference.position +
                                           PickerFixedDisplacementWrtConstrainPoint;
            }
            if (_constrainRotationReference != null)
            {
                // Constrain picker's position to ensure it has fixed relative rotation
                // with constrain reference.
                pickerReference.rotation = _constrainRotationReference.rotation *
                                           PickerFixedAngleDisplacementWrtConstrainPoint;
            }
            else
            {
                //pickerReference.rotation = InitialPickerRotation;
            }

            if (pickerDexmo != null)
            {
                Vector3    pickerReferenceTargetPosition = pickerReference.position;
                Quaternion pickerReferenceTargetRotation = pickerReference.rotation;
                // In Unity, moving child transform will not change its parent, but
                // moving parent's transform will change all of its children, so the
                // constrained position and rotation of the hand root tranform (the
                // most parent transform) needs to be calculated and modified to constrain
                // the entire hand model. Target position and rotation of hand root
                // transform can be calculated from the target position and rotation of
                // its children, e.g. palm center.
                Miscellaneous.MoveParentTransformGivenChildTransform(
                    pickerDexmo.HandRootTransform, pickerReference,
                    pickerReferenceTargetPosition, pickerReferenceTargetRotation,
                    HandRootPositionRelativeToPicker, HandRootRotationRelativeToPicker);
            }
        }
Exemple #3
0
        /// <summary>
        /// It will be called when this object is just picked up. It will save some relative
        /// rotation variables to be used later.
        /// </summary>
        /// <param name="picker">The picker that picks it up.</param>
        public override void OnPickedInit(IPicker picker)
        {
            PickerDexmo pickerDexmo     = picker as PickerDexmo;
            Transform   pickerReference =
                pickerDexmo == null ? picker.Transform : pickerDexmo.PalmCenter;

            _pickerRelativeRotationWrtKnob =
                Quaternion.Inverse(transform.rotation) * pickerReference.rotation;
            base.OnPickedInit(picker);
        }
Exemple #4
0
        /// <summary>
        /// Find the target angle of rotation from zero based on current picker's rotation.
        /// </summary>
        /// <remarks>
        /// The picker will maintain a fixed relative rotation with knob since the start of
        /// grasping, so given the current rotation of picker, we can compute the new target
        /// rotation of knob.
        /// </remarks>
        /// <param name="picker">The picker that is grasping it.</param>
        /// <returns>Target angle of rotation of knob based on the picker's rotation.</returns>
        protected override float GetPickerAngleInRotationAxis(IPicker picker)
        {
            PickerDexmo pickerDexmo     = picker as PickerDexmo;
            Transform   pickerReference = pickerDexmo == null ? picker.Transform : pickerDexmo.PalmCenter;
            // Calculate the target rotation of knob based on current rotation of the picker
            Quaternion newKnobTargetRotation = pickerReference.rotation *
                                               Quaternion.Inverse(_pickerRelativeRotationWrtKnob);
            // Convert the current angle reference from world coordinate to parent transform's
            // coordinate. Angle reference is the direction that indicates the current angle
            // of rotation from zero.
            Vector3 newAngleReferenceDirectionInWorld         = newKnobTargetRotation * ZeroReferenceDirection;
            Vector3 pickerRelativeDirectionInParentCoordinate =
                Miscellaneous.InverseTransformDirectionInParentCoordinate(transform,
                                                                          newAngleReferenceDirectionInWorld);
            // Find the target angle of rotation from zero in the plane normal to rotation axis
            float angle = RotationUtils.AngleInPlane(LocalRotationAxisInParentCoordinate,
                                                     ZeroReferenceDirectionInParentCoordinate, pickerRelativeDirectionInParentCoordinate);

            return(angle);
        }
Exemple #5
0
        /// <summary>
        /// Constrain picker such that its centre position stays at the centre of rotation and
        /// its rotation changes with the knob.
        /// </summary>
        /// <param name="picker">The picker that is grasping it.</param>
        protected override void ConstrainPicker(IPicker picker)
        {
            PickerDexmo pickerDexmo = picker as PickerDexmo;

            if (pickerDexmo == null)
            {
                //Transform pickerReference = picker.Transform;
                //if (ConstrainPositionReference != null)
                //{
                //    pickerReference.position = ConstrainPositionReference.position +
                //        PickerFixedDisplacementWrtConstrainPoint;
                //}
                //if (ConstrainRotationReference != null)
                //{
                //    pickerReference.rotation = ConstrainRotationReference.rotation *
                //        PickerFixedAngleDisplacementWrtConstrainPoint;
                //}

                // Don't constrain picker if it is not dexmo.
            }
            else
            {
                // Only constrain picker if it is dexmo
                Transform  pickerReference = pickerDexmo.PalmCenter;
                Vector3    pickerReferenceTargetPostion  = ConstrainPositionReference.position;
                Quaternion pickerReferenceTargetRotation =
                    transform.rotation *
                    _pickerRelativeRotationWrtKnob;
                // In Unity, moving child transform will not change its parent, but
                // moving parent's transform will change all of its children, so the
                // constrained position and rotation of the hand root tranform (the
                // most parent transform) needs to be calculated and modified to constrain
                // the entire hand model. Target position and rotation of hand root
                // transform can be calculated from the target position and rotation of
                // its children, e.g. palm center.
                Miscellaneous.MoveParentTransformGivenChildTransform(
                    pickerDexmo.HandRootTransform, pickerReference, pickerReferenceTargetPostion,
                    pickerReferenceTargetRotation, HandRootPositionRelativeToPicker,
                    HandRootRotationRelativeToPicker);
            }
        }
        /// <summary>
        /// It is called when this object is just picked up. It records some initial
        /// position and rotation offset with the picker, which will be used later.
        /// </summary>
        /// <remarks>
        /// Note that the implementation of this function is a little different from
        /// that of <see cref="Pickable"/>. Here it does not need to change the rigidbody properties
        /// to kinematic in order to follow the movement of the picker. Its movement
        /// is entirely defined in function <see cref="MoveTowardsTargetWithConstraint"/>.
        /// </remarks>
        /// <param name="picker">The picker that picks it up.</param>
        public override void OnPickedInit(IPicker picker)
        {
            Rigidbody activeRb = GetActiveRb();

            // Need to update the pickable mapping whenever a new object is picked up.
            PickableMapping.UpdatePickableMapping(activeRb, true, picker);
            PickerDexmo pickerDexmo     = picker as PickerDexmo;
            Transform   pickerReference = picker.Transform;

            if (pickerDexmo != null)
            {
                Transform handRootTransform = pickerDexmo.HandRootTransform;
                if (_pickerDexmoConstrainPart == PickerDexmoConstrainPartType.PalmCenter)
                {
                    pickerReference = pickerDexmo.PalmCenter;
                }
                HandRootPositionRelativeToPicker =
                    pickerReference.InverseTransformPoint(handRootTransform.position);
                HandRootRotationRelativeToPicker =
                    Quaternion.Inverse(pickerReference.rotation) * handRootTransform.rotation;
            }
            if (_constrainPositionReference != null)
            {
                PickerFixedDisplacementWrtConstrainPoint = pickerReference.position -
                                                           _constrainPositionReference.position;
            }
            if (_constrainRotationReference != null)
            {
                PickerFixedAngleDisplacementWrtConstrainPoint =
                    Quaternion.Inverse(_constrainRotationReference.rotation) *
                    pickerReference.rotation;
            }
            InitialPickerRotation = pickerReference.rotation;
            // Send the PickedInit event.
            OnPickedInitEvent(picker);
        }