private void ScaleFingerTip(Transform jointTransform, TrackedHandJoint fingerTipJoint, Vector3 boneRootPos) { // Set fingertip base bone scale to match the bone length to the fingertip. // This will only scale correctly if the model was constructed to match // the standard "test" edit-time hand model from the LeapMotion TestHandFactory. if (!MixedRealityHand.TryGetJoint(fingerTipJoint, out MixedRealityPose pose)) { return; } var boneTipPos = pose.Position; var boneVec = boneTipPos - boneRootPos; if (transform.lossyScale.x != 0f && transform.lossyScale.x != 1f) { boneVec /= transform.lossyScale.x; } var newScale = jointTransform.transform.localScale; var lengthComponentIdx = GetLargestComponentIndex(ModelFingerPointing); newScale[lengthComponentIdx] = boneVec.magnitude / fingerTipLengths[fingerTipJoint]; jointTransform.transform.localScale = newScale; }
protected virtual bool UpdateHandJoints() { using (UpdateHandJointsPerfMarker.Auto()) { if (!handJointsUpdated || MixedRealityHand.IsNull()) { return(false); } IMixedRealityInputSystem inputSystem = CoreServices.InputSystem; MixedRealityHandTrackingProfile handTrackingProfile = inputSystem?.InputSystemProfile != null ? inputSystem.InputSystemProfile.HandTrackingProfile : null; if (handTrackingProfile != null && !handTrackingProfile.EnableHandJointVisualization) { // clear existing joint GameObjects / meshes foreach (Transform joint in JointsArray) { if (joint != null) { Destroy(joint.gameObject); } } JointsArray = System.Array.Empty <Transform>(); // Even though the base class isn't handling joint visualization, we still received new joints. // Return true here in case any derived classes want to update. return(true); } if (JointsArray.Length != ArticulatedHandPose.JointCount) { JointsArray = new Transform[ArticulatedHandPose.JointCount]; } // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; // Skip this hand joint if the event data doesn't have an entry for it if (!MixedRealityHand.TryGetJoint(handJoint, out MixedRealityPose handJointPose)) { continue; } Transform jointTransform = JointsArray[i]; if (jointTransform != null) { jointTransform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); } else { GameObject prefab; if (handJoint == TrackedHandJoint.None || handTrackingProfile == null) { // No visible mesh for the "None" joint prefab = null; } else if (handJoint == TrackedHandJoint.Palm) { prefab = handTrackingProfile.PalmJointPrefab; } else if (handJoint == TrackedHandJoint.IndexTip) { prefab = handTrackingProfile.FingerTipPrefab; } else { prefab = handTrackingProfile.JointPrefab; } GameObject jointObject; if (prefab != null) { jointObject = Instantiate(prefab); } else { jointObject = new GameObject(); } jointObject.name = handJoint.ToString() + " Proxy Transform"; jointObject.transform.SetPositionAndRotation(handJointPose.Position, handJointPose.Rotation); jointObject.transform.parent = transform; JointsArray[i] = jointObject.transform; } } handJointsUpdated = false; return(true); } }
protected override bool UpdateHandJoints() { using (UpdateHandJointsPerfMarker.Auto()) { // The base class takes care of updating all of the joint data _ = base.UpdateHandJoints(); // Exit early and disable the rigged hand model if we've gotten a hand mesh from the underlying platform if (ReceivingPlatformHandMesh || MixedRealityHand.IsNull()) { HandRenderer.enabled = false; return(false); } IMixedRealityInputSystem inputSystem = CoreServices.InputSystem; MixedRealityHandTrackingProfile handTrackingProfile = inputSystem?.InputSystemProfile != null ? inputSystem.InputSystemProfile.HandTrackingProfile : null; // Only runs if render hand mesh is true bool renderHandmesh = handTrackingProfile != null && handTrackingProfile.EnableHandMeshVisualization; HandRenderer.enabled = renderHandmesh; if (renderHandmesh) { // Render the rigged hand mesh itself // Apply updated TrackedHandJoint pose data to the assigned transforms // This starts at 1 to skip over TrackedHandJoint.None. for (int i = 1; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; // Skip this hand joint if the event data doesn't have an entry for it if (!MixedRealityHand.TryGetJoint(handJoint, out MixedRealityPose handJointPose)) { continue; } Transform jointTransform = riggedVisualJointsArray[i]; if (jointTransform != null) { if (handJoint == TrackedHandJoint.Palm) { if (ModelPalmAtLeapWrist && MixedRealityHand.TryGetJoint(TrackedHandJoint.Wrist, out MixedRealityPose wristPose)) { Palm.position = wristPose.Position; } else { Palm.position = handJointPose.Position; } Palm.rotation = handJointPose.Rotation * UserBoneRotation; } else if (handJoint == TrackedHandJoint.Wrist) { if (!ModelPalmAtLeapWrist) { Wrist.position = handJointPose.Position; } } else { // Finger riggedVisualJointsArray jointTransform.rotation = handJointPose.Rotation * Reorientation(); if (DeformPosition) { jointTransform.position = handJointPose.Position; } if (ScaleLastFingerBone && (handJoint == TrackedHandJoint.ThumbDistalJoint || handJoint == TrackedHandJoint.IndexDistalJoint || handJoint == TrackedHandJoint.MiddleDistalJoint || handJoint == TrackedHandJoint.RingDistalJoint || handJoint == TrackedHandJoint.PinkyDistalJoint)) { ScaleFingerTip(jointTransform, handJoint + 1, jointTransform.position); } } } } // Update the hand material float pinchStrength = HandPoseUtils.CalculateIndexPinch(Controller.ControllerHandedness); // Hand Curl Properties: float indexFingerCurl = HandPoseUtils.IndexFingerCurl(Controller.ControllerHandedness); float middleFingerCurl = HandPoseUtils.MiddleFingerCurl(Controller.ControllerHandedness); float ringFingerCurl = HandPoseUtils.RingFingerCurl(Controller.ControllerHandedness); float pinkyFingerCurl = HandPoseUtils.PinkyFingerCurl(Controller.ControllerHandedness); if (handMaterial != null && handRendererInitialized) { float gripStrength = indexFingerCurl + middleFingerCurl + ringFingerCurl + pinkyFingerCurl; gripStrength /= 4.0f; gripStrength = gripStrength > 0.8f ? 1.0f : gripStrength; pinchStrength = Mathf.Pow(Mathf.Max(pinchStrength, gripStrength), 2.0f); if (handRenderer.sharedMaterial.HasProperty(pinchStrengthMaterialProperty)) { handRenderer.sharedMaterial.SetFloat(pinchStrengthMaterialProperty, pinchStrength); } // Only show this warning once else if (!displayedMaterialPropertyWarning) { Debug.LogWarning(String.Format("The property {0} for reacting to pinch strength was not found. A material with this property is required to visualize pinch strength.", pinchStrengthMaterialProperty)); displayedMaterialPropertyWarning = true; } } } return(true); } }