public abstract Transform GetBoneUnsafe(Hand hand, BoneId Id);
Exemple #2
0
    public override bool TryGetBone(Hand hand, BoneId Id, out Transform bone)
    {
        var bones = Hand.left == hand ? _bonesLeft : _bonesRight;

        return(bones.TryGetValue(Id, out bone));
    }
 public abstract bool TryGetBone(Hand hand, BoneId Id, out Transform bone);
 public virtual bool IsFingerHighConfidence(BoneId bone)
 {
     return(true);
 }
    private void Initialize()
    {
        var skeleton = new OVRPlugin.Skeleton();

        if (OVRPlugin.GetSkeleton((OVRPlugin.SkeletonType)_skeletonType, out skeleton))
        {
            if (!_bonesGO)
            {
                _bonesGO = new GameObject("Bones");
                _bonesGO.transform.SetParent(transform, false);
                _bonesGO.transform.localPosition = Vector3.zero;
                _bonesGO.transform.localRotation = Quaternion.identity;
            }

            if (!_bindPosesGO)
            {
                _bindPosesGO = new GameObject("BindPoses");
                _bindPosesGO.transform.SetParent(transform, false);
                _bindPosesGO.transform.localPosition = Vector3.zero;
                _bindPosesGO.transform.localRotation = Quaternion.identity;
            }

            if (_enablePhysicsCapsules)
            {
                if (!_capsulesGO)
                {
                    _capsulesGO = new GameObject("Capsules");
                    _capsulesGO.transform.SetParent(transform, false);
                    _capsulesGO.transform.localPosition = Vector3.zero;
                    _capsulesGO.transform.localRotation = Quaternion.identity;
                }
            }

            _bones = new List <OVRBone>(new OVRBone[skeleton.NumBones]);
            Bones  = _bones.AsReadOnly();

            _bindPoses = new List <OVRBone>(new OVRBone[skeleton.NumBones]);
            BindPoses  = _bindPoses.AsReadOnly();

            // pre-populate bones list before attempting to apply bone hierarchy
            for (int i = 0; i < skeleton.NumBones; ++i)
            {
                BoneId     id        = (OVRSkeleton.BoneId)skeleton.Bones[i].Id;
                short      parentIdx = skeleton.Bones[i].ParentBoneIndex;
                Vector3    pos       = skeleton.Bones[i].Pose.Position.FromFlippedZVector3f();
                Quaternion rot       = skeleton.Bones[i].Pose.Orientation.FromFlippedZQuatf();

                var boneGO = new GameObject(id.ToString());
                boneGO.transform.localPosition = pos;
                boneGO.transform.localRotation = rot;
                _bones[i] = new OVRBone(id, parentIdx, boneGO.transform);

                var bindPoseGO = new GameObject(id.ToString());
                bindPoseGO.transform.localPosition = pos;
                bindPoseGO.transform.localRotation = rot;
                _bindPoses[i] = new OVRBone(id, parentIdx, bindPoseGO.transform);
            }

            for (int i = 0; i < skeleton.NumBones; ++i)
            {
                if (((OVRPlugin.BoneId)skeleton.Bones[i].ParentBoneIndex) == OVRPlugin.BoneId.Invalid)
                {
                    _bones[i].Transform.SetParent(_bonesGO.transform, false);
                    _bindPoses[i].Transform.SetParent(_bindPosesGO.transform, false);
                }
                else
                {
                    _bones[i].Transform.SetParent(_bones[_bones[i].ParentBoneIndex].Transform, false);
                    _bindPoses[i].Transform.SetParent(_bindPoses[_bones[i].ParentBoneIndex].Transform, false);
                }
            }

            if (_enablePhysicsCapsules)
            {
                _capsules = new List <OVRBoneCapsule>(new OVRBoneCapsule[skeleton.NumBoneCapsules]);
                Capsules  = _capsules.AsReadOnly();

                for (int i = 0; i < skeleton.NumBoneCapsules; ++i)
                {
                    var       capsule = skeleton.BoneCapsules[i];
                    Transform bone    = Bones[capsule.BoneIndex].Transform;

                    var capsuleRigidBodyGO = new GameObject((_bones[capsule.BoneIndex].Id).ToString() + "_CapsuleRigidBody");
                    capsuleRigidBodyGO.transform.SetParent(_capsulesGO.transform, false);
                    capsuleRigidBodyGO.transform.localPosition = bone.position;
                    capsuleRigidBodyGO.transform.localRotation = bone.rotation;

                    var capsuleRigidBody = capsuleRigidBodyGO.AddComponent <Rigidbody>();
                    capsuleRigidBody.mass        = 1.0f;
                    capsuleRigidBody.isKinematic = true;
                    capsuleRigidBody.useGravity  = false;
#if UNITY_2018_3_OR_NEWER
                    capsuleRigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
#else
                    capsuleRigidBody.collisionDetectionMode = CollisionDetectionMode.Continuous;
#endif

                    var capsuleColliderGO = new GameObject((_bones[capsule.BoneIndex].Id).ToString() + "_CapsuleCollider");
                    capsuleColliderGO.transform.SetParent(capsuleRigidBodyGO.transform, false);
                    var capsuleCollider = capsuleColliderGO.AddComponent <CapsuleCollider>();
                    var p0    = capsule.Points[0].FromFlippedZVector3f();
                    var p1    = capsule.Points[1].FromFlippedZVector3f();
                    var delta = p1 - p0;
                    var mag   = delta.magnitude;
                    var rot   = Quaternion.FromToRotation(capsuleRigidBodyGO.transform.localRotation * Vector3.right, delta);
                    capsuleCollider.radius    = capsule.Radius;
                    capsuleCollider.height    = mag + capsule.Radius * 2.0f;
                    capsuleCollider.isTrigger = false;
                    capsuleCollider.direction = 0;
                    capsuleColliderGO.transform.localPosition = p0;
                    capsuleColliderGO.transform.localRotation = rot;
                    capsuleCollider.center  = Vector3.right * mag * 0.5f;
                    capsuleColliderGO.layer = gameObject.layer;

                    _capsules[i] = new OVRBoneCapsule(capsule.BoneIndex, capsuleRigidBody, capsuleCollider);
                }
            }

            _isInitialized = true;
        }
    }
        private void SetTracked()
        {
            if (trackedRoot != null && handAnchor != null)
            {
                trackedRoot.position = handAnchor.position;
                trackedRoot.rotation = handAnchor.rotation;
            }

            if (boneRotationValues.bones != null && boneRotationValues.bones.Length > 0)
            {
                //string debugTips = "";
                List <(BoneId, bool)> fingerTipTests = new List <(BoneId, bool)>(); //Adding this helps reduce the amount of raycasts done on each finger tip by around 3 times, since each finger has 3 or 4 bones
                var boneIds = (BoneId[])Enum.GetValues(typeof(BoneId));
                for (int i = 0; i < boneIds.Length; i++)
                {
                    var currentBoneId = boneIds[i];
                    var bonesWithId   = boneRotationValues.bones.Where((bone) => bone.id == currentBoneId);
                    if (bonesWithId.Count() > 0)
                    {
                        var currentBone  = bones[(int)currentBoneId];
                        var boneRotValue = bonesWithId.First();

                        #region Getting the rotation value from given hand bone values
                        Quaternion localRotation;
                        if (!boneRotValue.IsOrientation)
                        {
                            Vector3 rotationAxis = -Vector3.forward;
                            if (currentBoneId == BoneId.Hand_Thumb0)
                            {
                                rotationAxis = -Vector3.up;
                            }
                            float currentAngle = boneRotValue.value * 90;
                            localRotation = Quaternion.AngleAxis(currentAngle, rotationAxis) * currentBone.startRotation;
                        }
                        else
                        {
                            localRotation = boneRotValue.localRotation;
                        }
                        #endregion

                        #region Adjusting rotation based on collision (less rotation toward collider if tip colliding)
                        BoneId currentFingerTip = GetTip(currentBoneId);
                        if (currentFingerTip != BoneId.Invalid)
                        {
                            var fingerTipTransform = bones[(int)currentFingerTip].mesh;
                            var fingerTipRay       = new Ray(fingerTipTransform.position, fingerTipTransform.up * (flipTipRays ? -1 : 1));

                            //debugTips += currentBoneId + " => " + currentFingerTip + "\n";
                            (BoneId, bool)fingerTipTest;
                            var matchingTests = fingerTipTests.Where(currentTest => { return(currentTest.Item1 == currentFingerTip); });
                            if (matchingTests.Count() <= 0)
                            {
                                bool tipCollided = Physics.Raycast(fingerTipRay, tipCollisionDistance);
                                fingerTipTest = (currentFingerTip, tipCollided);
                                fingerTipTests.Add(fingerTipTest);
                                Debug.DrawRay(fingerTipRay.origin, fingerTipRay.direction * tipCollisionDistance, tipCollided ? Color.green : Color.red);
                            }
                            else
                            {
                                fingerTipTest = matchingTests.First();
                            }

                            //Calculate the difference in rotation between the next tracked local rotation and the previous tracked local rotation
                            Quaternion deltaRotation = currentBone.tracked.localRotation * Quaternion.Inverse(localRotation);
                            //Convert the difference to an angle on an axis
                            float   angle;
                            Vector3 axis;
                            deltaRotation.ToAngleAxis(out angle, out axis);
                            //Local to world of axis direction
                            axis = currentBone.tracked.TransformDirection(axis);
                            //Comparing the axis of the rotation with the forward axis of the current bone (the forward axis
                            //of the bone is the one it uses to close and open)
                            bool isClosing = Vector3.Dot(currentBone.tracked.forward, axis) > 0;

                            //If finger tip is colliding with an object and the finger is closing then set the current joint's
                            //rotation to be the previous frame's
                            if (fingerTipTest.Item2 && isClosing)
                            {
                                //localRotation = currentBone.tracked.localRotation;
                                Quaternion meshDelta             = currentBone.mesh.localRotation * Quaternion.Inverse(currentBone.startRotation);
                                float      maxAngle              = meshDelta.PollAxisAngle(currentBone.tracked.forward, currentBone.tracked.up);
                                Quaternion preferredAxisRotation = Quaternion.AngleAxis(maxAngle, currentBone.tracked.forward);

                                Quaternion trackedDelta        = currentBone.tracked.localRotation * Quaternion.Inverse(currentBone.startRotation);
                                float      currentAngle        = meshDelta.PollAxisAngle(currentBone.tracked.forward, currentBone.tracked.up);
                                Quaternion currentAxisRotation = Quaternion.AngleAxis(currentAngle, currentBone.tracked.forward);

                                Quaternion shiftDelta = currentAxisRotation * Quaternion.Inverse(preferredAxisRotation);
                                localRotation = currentBone.tracked.localRotation * shiftDelta;
                            }

                            Debug.DrawRay(currentBone.mesh.position, currentBone.tracked.forward * 0.02f, fingerTipTest.Item2 && isClosing ? Color.red : Color.green);
                        }
                        #endregion

                        currentBone.tracked.localRotation = localRotation;
                    }
                }
                //Debug.Log(debugTips);
            }
        }
 /// <summary>
 /// Checks whether the given bone id is part of a finger
 /// </summary>
 /// <param name="currentBoneId">The bone id to be checked</param>
 /// <returns>True if the given id is part of a finger, false otherwise</returns>
 private static bool IsFingerBone(BoneId currentBoneId)
 {
     return(currentBoneId != BoneId.Hand_End && currentBoneId != BoneId.Hand_ForearmStub && currentBoneId != BoneId.Hand_MaxSkinnable && currentBoneId != BoneId.Hand_Start && currentBoneId != BoneId.Hand_WristRoot && currentBoneId != BoneId.Invalid && currentBoneId != BoneId.Max);
 }