protected void UpdateHand(OVRHand ovrHand, OVRSkeleton ovrSkeleton, OVRMeshRenderer ovrMeshRenderer, Handedness handedness) { // Until the ovrMeshRenderer is initialized we do nothing with the hand // This is a bit of a hack because the Oculus Integration fails if we touch the renderer before it has initialized itself if (ovrMeshRenderer == null || !ovrMeshRenderer.IsInitialized) { return; } if (ovrHand.IsTracked) { var hand = GetOrAddHand(handedness, ovrHand); hand.UpdateController(ovrHand, ovrSkeleton, cameraRig.trackingSpace); } else { RemoveHandDevice(handedness); } }
// Start is called before the first frame update void Start() { skeleton = trackedHand.GetComponent <OVRSkeleton>(); mr = trackedHand.GetComponent <OVRMeshRenderer>(); smr = trackedHand.GetComponent <SkinnedMeshRenderer>(); foreach (OVRBone bone in skeleton.Bones) { if (bone.Id == OVRSkeleton.BoneId.Hand_IndexTip) { indexTipBone = bone; } if (bone.Id == OVRSkeleton.BoneId.Hand_MiddleTip) { middleTipBone = bone; } if (bone.Id == OVRSkeleton.BoneId.Hand_RingTip) { ringTipBone = bone; } if (bone.Id == OVRSkeleton.BoneId.Hand_PinkyTip) { pinkyTipBone = bone; } if (bone.Id == OVRSkeleton.BoneId.Hand_ThumbTip) { thumbTipBone = bone; } if (bone.Id == OVRSkeleton.BoneId.Hand_Start) { handBone = bone; } } for (int i = 0; i < smoothSteps; i++) { lastPositions.Add(IndexTipObject.transform.position); } }
private void SetupInput() { cameraRig = GameObject.FindObjectOfType <OVRCameraRig>(); if (cameraRig == null) { var mainCamera = Camera.main; Transform cameraParent = null; if (mainCamera != null) { cameraParent = mainCamera.transform.parent; // Destroy main camera GameObject.Destroy(cameraParent.gameObject); } // Instantiate camera rig as a child of the MixedRealityPlayspace cameraRig = GameObject.Instantiate(MRTKOculusConfig.Instance.OVRCameraRigPrefab); } // Ensure all related game objects are configured cameraRig.EnsureGameObjectIntegrity(); bool useAvatarHands = MRTKOculusConfig.Instance.RenderAvatarHandsInsteadOfController; // If using Avatar hands, de-activate ovr controller rendering foreach (var controllerHelper in cameraRig.gameObject.GetComponentsInChildren <OVRControllerHelper>()) { controllerHelper.gameObject.SetActive(!useAvatarHands); } if (useAvatarHands && !MRTKOculusConfig.Instance.AllowDevToManageAvatarPrefab) { // Initialize the local avatar controller GameObject.Instantiate(MRTKOculusConfig.Instance.LocalAvatarPrefab, cameraRig.trackingSpace); } var ovrHands = cameraRig.GetComponentsInChildren <OVRHand>(); foreach (var ovrHand in ovrHands) { // Manage Hand skeleton data var skeltonDataProvider = ovrHand as OVRSkeleton.IOVRSkeletonDataProvider; var skeltonType = skeltonDataProvider.GetSkeletonType(); var meshRenderer = ovrHand.GetComponent <OVRMeshRenderer>(); var ovrSkelton = ovrHand.GetComponent <OVRSkeleton>(); if (ovrSkelton == null) { continue; } switch (skeltonType) { case OVRSkeleton.SkeletonType.HandLeft: leftHand = ovrHand; leftSkeleton = ovrSkelton; leftMeshRenderer = meshRenderer; break; case OVRSkeleton.SkeletonType.HandRight: rightHand = ovrHand; rightSkeleton = ovrSkelton; righMeshRenderer = meshRenderer; break; } } }
private void SetupInput() { cameraRig = GameObject.FindObjectOfType <OVRCameraRig>(); if (cameraRig == null) { var mainCamera = CameraCache.Main; // Instantiate camera rig as a child of the MixedRealityPlayspace var cameraRigObject = GameObject.Instantiate(SettingsProfile.OVRCameraRigPrefab); cameraRig = cameraRigObject.GetComponent <OVRCameraRig>(); // Ensure all related game objects are configured cameraRig.EnsureGameObjectIntegrity(); if (mainCamera != null) { // We already had a main camera MRTK probably started using, let's replace the CenterEyeAnchor MainCamera with it GameObject prefabMainCamera = cameraRig.trackingSpace.Find("CenterEyeAnchor").gameObject; prefabMainCamera.SetActive(false); mainCamera.transform.SetParent(cameraRig.trackingSpace.transform); mainCamera.name = prefabMainCamera.name; GameObject.Destroy(prefabMainCamera); } cameraRig.transform.SetParent(MixedRealityPlayspace.Transform); } else { // Ensure all related game objects are configured cameraRig.EnsureGameObjectIntegrity(); } bool useAvatarHands = SettingsProfile.RenderAvatarHandsInsteadOfController; // If using Avatar hands, de-activate ovr controller rendering foreach (var controllerHelper in cameraRig.gameObject.GetComponentsInChildren <OVRControllerHelper>()) { controllerHelper.gameObject.SetActive(!useAvatarHands); } if (useAvatarHands) { // Initialize the local avatar controller GameObject.Instantiate(SettingsProfile.LocalAvatarPrefab, cameraRig.trackingSpace); } var ovrHands = cameraRig.GetComponentsInChildren <OVRHand>(); foreach (var ovrHand in ovrHands) { // Manage Hand skeleton data var skeletonDataProvider = ovrHand as OVRSkeleton.IOVRSkeletonDataProvider; var skeletonType = skeletonDataProvider.GetSkeletonType(); var meshRenderer = ovrHand.GetComponent <OVRMeshRenderer>(); var ovrSkeleton = ovrHand.GetComponent <OVRSkeleton>(); if (ovrSkeleton == null) { continue; } switch (skeletonType) { case OVRSkeleton.SkeletonType.HandLeft: leftHand = ovrHand; leftSkeleton = ovrSkeleton; leftMeshRenderer = meshRenderer; break; case OVRSkeleton.SkeletonType.HandRight: rightHand = ovrHand; rightSkeleton = ovrSkeleton; righMeshRenderer = meshRenderer; break; } } }
protected bool UpdateHandData(OVRHand ovrHand, OVRSkeleton ovrSkeleton, OVRMeshRenderer ovrMeshRenderer) { bool isTracked = ovrHand.IsTracked; if (ovrHand.HandConfidence == OVRHand.TrackingConfidence.High) { _lastHighConfidenceTime = Time.unscaledTime; } if (ovrHand.HandConfidence == OVRHand.TrackingConfidence.Low) { if (settingsProfile.MinimumHandConfidence == OVRHand.TrackingConfidence.High) { isTracked = false; } else { float lowConfidenceTime = Time.time - _lastHighConfidenceTime; if (settingsProfile.LowConfidenceTimeThreshold > 0 && settingsProfile.LowConfidenceTimeThreshold < lowConfidenceTime) { isTracked = false; } } } if (ControllerHandedness == Handedness.Left) { settingsProfile.CurrentLeftHandTrackingConfidence = ovrHand.HandConfidence; } else { settingsProfile.CurrentRightHandTrackingConfidence = ovrHand.HandConfidence; } // Managing hand visuals based on the handtracking visualization profile and if the hand is tracked if (handRenderer != null) { bool showHandMesh = handTrackingProfile.IsNull() ? false : handTrackingProfile.EnableHandMeshVisualization; bool showHandJoints = handTrackingProfile.IsNull() ? false : handTrackingProfile.EnableHandJointVisualization; ovrMeshRenderer.enabled = isTracked && showHandMesh; handRenderer.enabled = isTracked && showHandMesh; Visualizer.GameObjectProxy.SetActive(isTracked && showHandJoints); } if (ovrSkeleton != null) { var bones = ovrSkeleton.Bones; foreach (var bone in bones) { UpdateBone(bone); } UpdatePalm(); } CoreServices.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses); // Note: After some testing, it seems when moving your hand fast, Oculus's pinch estimation data gets frozen, which leads to stuck pinches. // To counter this, we perform a distance check between thumb and index to determine if we should force the pinch to a false state. float pinchStrength; if (AreIndexAndThumbFarApart()) { pinchStrength = 0f; IsPinching = false; } else { pinchStrength = ovrHand.GetFingerPinchStrength(OVRHand.HandFinger.Index); if (IsPinching) { // If we are already pinching, we make the pinch a bit sticky IsPinching = ovrHand.GetFingerPinchStrength(OVRHand.HandFinger.Index) > 0.85f; } else { // If not yet pinching, only consider pinching if finger confidence is high IsPinching = ovrHand.GetFingerIsPinching(OVRHand.HandFinger.Index) && ovrHand.GetFingerConfidence(OVRHand.HandFinger.Index) == OVRHand.TrackingConfidence.High; } } isIndexGrabbing = HandPoseUtils.IsIndexGrabbing(ControllerHandedness); isMiddleGrabbing = HandPoseUtils.IsMiddleGrabbing(ControllerHandedness); isThumbGrabbing = HandPoseUtils.IsThumbGrabbing(ControllerHandedness); // Hand Curl Properties: float indexFingerCurl = HandPoseUtils.IndexFingerCurl(ControllerHandedness); float middleFingerCurl = HandPoseUtils.MiddleFingerCurl(ControllerHandedness); float ringFingerCurl = HandPoseUtils.RingFingerCurl(ControllerHandedness); float pinkyFingerCurl = HandPoseUtils.PinkyFingerCurl(ControllerHandedness); // Pinch was also used as grab, we want to allow hand-curl grab not just pinch. // Determine pinch and grab separately if (isTracked) { IsGrabbing = isIndexGrabbing && isMiddleGrabbing; } if (settingsProfile.UpdateMaterialPinchStrengthValue && handMaterial != null) { float gripStrength = indexFingerCurl + middleFingerCurl + ringFingerCurl + pinkyFingerCurl; gripStrength /= 4.0f; gripStrength = gripStrength > 0.8f ? 1.0f : gripStrength; pinchStrength = Mathf.Max(pinchStrength, gripStrength); handMaterial.SetFloat(pinchStrengthProp, pinchStrength); } return(isTracked); }
/// <summary> /// Update the controller data from the provided platform state /// </summary> /// <param name="interactionSourceState">The InteractionSourceState retrieved from the platform</param> public void UpdateController(OVRHand hand, OVRSkeleton ovrSkeleton, OVRMeshRenderer ovrMeshRenderer, Transform trackingOrigin) { if (!Enabled || hand == null || ovrSkeleton == null) { return; } bool isTracked = UpdateHandData(hand, ovrSkeleton, ovrMeshRenderer); IsPositionAvailable = IsRotationAvailable = isTracked; if (isTracked) { // Leverage Oculus Platform Hand Ray - instead of simulating it in a crummy way currentPointerPose.Position = trackingOrigin.TransformPoint(hand.PointerPose.position); Vector3 pointerForward = trackingOrigin.TransformDirection(hand.PointerPose.forward); Vector3 pointerUp = trackingOrigin.TransformDirection(hand.PointerPose.up); currentPointerPose.Rotation = Quaternion.LookRotation(pointerForward, pointerUp); currentGripPose = jointPoses[TrackedHandJoint.Palm]; CoreServices.InputSystem?.RaiseSourcePoseChanged(InputSource, this, currentGripPose); UpdateVelocity(); } UpdateTeleport(); for (int i = 0; i < Interactions?.Length; i++) { switch (Interactions[i].InputType) { case DeviceInputType.SpatialPointer: Interactions[i].PoseData = currentPointerPose; if (Interactions[i].Changed) { CoreServices.InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentPointerPose); } break; case DeviceInputType.SpatialGrip: Interactions[i].PoseData = currentGripPose; if (Interactions[i].Changed) { CoreServices.InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose); } break; case DeviceInputType.Select: Interactions[i].BoolData = IsPinching || IsGrabbing; if (Interactions[i].Changed) { if (Interactions[i].BoolData) { CoreServices.InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } else { CoreServices.InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } } break; case DeviceInputType.TriggerPress: Interactions[i].BoolData = IsPinching || IsGrabbing; if (Interactions[i].Changed) { if (Interactions[i].BoolData) { CoreServices.InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } else { CoreServices.InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } } break; case DeviceInputType.IndexFinger: UpdateIndexFingerData(Interactions[i]); break; } } }