public static void CalculateElbowLength(HandBinder handBinder) { if (handBinder.BoundHand.elbow.boundTransform != null && handBinder.BoundHand.wrist.boundTransform != null) { handBinder.ElbowLength = (handBinder.BoundHand.wrist.boundTransform.position - handBinder.BoundHand.elbow.boundTransform.position).magnitude; } }
/// <summary> /// Estimate the rotation offset needed to get the rigged hand into the same orientation as the leap hand /// </summary> public static void EstimateWristRotationOffset(HandBinder handBinder) { Transform indexBone = handBinder.BoundHand.fingers[(int)Finger.FingerType.TYPE_INDEX].boundBones[(int)Bone.BoneType.TYPE_PROXIMAL].boundTransform; Transform middleBone = handBinder.BoundHand.fingers[(int)Finger.FingerType.TYPE_MIDDLE].boundBones[(int)Bone.BoneType.TYPE_PROXIMAL].boundTransform; Transform pinkyBone = handBinder.BoundHand.fingers[(int)Finger.FingerType.TYPE_PINKY].boundBones[(int)Bone.BoneType.TYPE_PROXIMAL].boundTransform; Transform wrist = handBinder.BoundHand.wrist.boundTransform; if (middleBone != null && indexBone != null && pinkyBone != null && wrist != null) { //Calculate model's rotation var forward = (middleBone.position - wrist.position); var right = (indexBone.position - pinkyBone.position); if (handBinder.Handedness == Chirality.Right) { right = -right; } var up = Vector3.Cross(forward, right); Vector3.OrthoNormalize(ref up, ref forward, ref right); var modelRotation = Quaternion.LookRotation(forward, up); //Calculate the difference between the Calculated hand basis and the wrists rotation handBinder.WristRotationOffset = (Quaternion.Inverse(modelRotation) * wrist.transform.rotation).eulerAngles; //Assuming the fingers have been created using the same rotation axis as the wrist handBinder.GlobalFingerRotationOffset = handBinder.WristRotationOffset; } }
/// <summary> /// Estimate the rotation offset needed to get the rigged hand into the same orientation as the leap hand /// </summary> public static void EstimateWristRotationOffset(HandBinder handBinder) { //Try to using the meta first Transform indexBone = handBinder.boundHand.fingers[(int)Finger.FingerType.TYPE_INDEX].boundBones[(int)Bone.BoneType.TYPE_METACARPAL].boundTransform; Transform middleBone = handBinder.boundHand.fingers[(int)Finger.FingerType.TYPE_MIDDLE].boundBones[(int)Bone.BoneType.TYPE_METACARPAL].boundTransform; Transform pinkyBone = handBinder.boundHand.fingers[(int)Finger.FingerType.TYPE_PINKY].boundBones[(int)Bone.BoneType.TYPE_METACARPAL].boundTransform; //If the meta does not exist, use the proximal bones if (indexBone == null || middleBone == null || pinkyBone == null) { indexBone = handBinder.boundHand.fingers[(int)Finger.FingerType.TYPE_INDEX].boundBones[(int)Bone.BoneType.TYPE_PROXIMAL].boundTransform; middleBone = handBinder.boundHand.fingers[(int)Finger.FingerType.TYPE_MIDDLE].boundBones[(int)Bone.BoneType.TYPE_PROXIMAL].boundTransform; pinkyBone = handBinder.boundHand.fingers[(int)Finger.FingerType.TYPE_PINKY].boundBones[(int)Bone.BoneType.TYPE_PROXIMAL].boundTransform; } Transform wrist = handBinder.boundHand.wrist.boundTransform; if (middleBone != null && indexBone != null && pinkyBone != null && wrist != null) { //Get the Direction from the middle finger to the wrist Vector3 wristForward = middleBone.position - wrist.position; //Get the Direction from the Proximal pinky finger to the Proximal Index finger Vector3 wristRight = indexBone.position - pinkyBone.position; //Swap the direction based on left and right hands if (handBinder.Handedness == Chirality.Right) { wristRight = -wristRight; } //Get the direciton that goes outwards from the back of the hand Vector3 wristUp = Vector3.Cross(wristForward, wristRight); //Make the vectors orthoginal to eacother, this is the basis for the model hand Vector3.OrthoNormalize(ref wristRight, ref wristUp, ref wristForward); //Create a new leap hand based off the Desktop hand pose Hand hand = TestHandFactory.MakeTestHand(handBinder.Handedness == Chirality.Left, unitType: TestHandFactory.UnitType.LeapUnits); hand.Transform(TestHandFactory.GetTestPoseLeftHandTransform(TestHandFactory.TestHandPose.DesktopModeA)); Quaternion leapRotation = hand.Rotation.ToQuaternion(); //Get the rotation of the calculated hand Basis Quaternion modelRotation = Quaternion.LookRotation(wristForward, wristUp); //Now calculate the difference between the models rotation and the leaps rotation Quaternion wristRotationDifference = Quaternion.Inverse(modelRotation) * leapRotation; Vector3 wristRelativeDifference = (Quaternion.Inverse(wrist.rotation) * wristRotationDifference).eulerAngles; //Round to the nearest 90 degrees wristRelativeDifference.x = Mathf.Round(wristRelativeDifference.x / 90) * 90; wristRelativeDifference.y = Mathf.Round(wristRelativeDifference.y / 90) * 90; wristRelativeDifference.z = Mathf.Round(wristRelativeDifference.z / 90) * 90; //Assign these values to the hand binder handBinder.GlobalFingerRotationOffset = wristRelativeDifference; handBinder.boundHand.wrist.offset.rotation = wristRelativeDifference; } }
/// <summary> /// Draw extra gizmos in the scene to help the user while they edit variables /// </summary> private void OnSceneGUI() { myTarget = (HandBinder)target; if (myTarget.LeapHand == null) { return; } DrawLeapHandGizmos(); DrawLeapBasis(); DrawModelHandGizmos(); DrawModelHandBasis(); }
private void OnEnable() { serializedObject.Update(); myTarget = (HandBinder)target; if (myTarget.gameObject.name.ToUpper().Contains("Left".ToUpper())) { myTarget.Handedness = Unity.Chirality.Left; } if (myTarget.gameObject.name.ToUpper().Contains("Right".ToUpper())) { myTarget.Handedness = Unity.Chirality.Right; } SetSerializedProperties(); }
/// <summary> /// Turn the bound handBinder bones into a flattened array /// </summary> /// <param name="handBinder"></param> /// <returns></returns> static public Transform[] FlattenHandBinderTransforms(HandBinder handBinder) { var bones = new List <Transform>(); int index = 0; for (int FINGERID = 0; FINGERID < handBinder.BoundHand.fingers.Length; FINGERID++) { for (int BONEID = 0; BONEID < handBinder.BoundHand.fingers[FINGERID].boundBones.Length; BONEID++) { var BONE = handBinder.BoundHand.fingers[FINGERID].boundBones[BONEID]; bones.Add(BONE.boundTransform); index++; } index++; } bones.Add(handBinder.BoundHand.wrist.boundTransform); return(bones.ToArray()); }
/// <summary> /// This function is used to search the HandBinder scipts children transforms to auto assign them for the user /// </summary> /// <param name="handBinder">The binder that the found transforms will get assigned too</param> public static void AutoRig(HandBinder handBinder) { handBinder.ResetHand(); BoneDefinitions boneDefinitions = null; //Check to see if we have an autorigger Definitions scriptable object if (handBinder.CustomBoneDefinitions == null) { boneDefinitions = new BoneDefinitions(); } else { boneDefinitions = handBinder.CustomBoneDefinitions.BoneDefinitions; } //Get all children of the hand var children = GetAllChildren(handBinder.transform); var thumbBones = SelectBones(children, boneDefinitions.DefinitionThumb, true); var indexBones = SelectBones(children, boneDefinitions.DefinitionIndex); var middleBones = SelectBones(children, boneDefinitions.DefinitionMiddle); var ringBones = SelectBones(children, boneDefinitions.DefinitionRing); var pinkyBones = SelectBones(children, boneDefinitions.DefinitionPinky); var wrist = SelectBones(children, boneDefinitions.DefinitionWrist).FirstOrDefault(); var Elbow = SelectBones(children, boneDefinitions.DefinitionElbow).FirstOrDefault(); handBinder.boundHand.fingers[0].boundBones = AssignUnityBone(thumbBones); handBinder.boundHand.fingers[1].boundBones = AssignUnityBone(indexBones); handBinder.boundHand.fingers[2].boundBones = AssignUnityBone(middleBones); handBinder.boundHand.fingers[3].boundBones = AssignUnityBone(ringBones); handBinder.boundHand.fingers[4].boundBones = AssignUnityBone(pinkyBones); handBinder.boundHand.wrist = AssignBoundBone(wrist); handBinder.boundHand.elbow = AssignBoundBone(Elbow); if (wrist != null && Elbow != null) { handBinder.elbowLength = (wrist.position - Elbow.position).magnitude; } EstimateWristRotationOffset(handBinder); handBinder.UpdateHand(); handBinder.DebugModelTransforms = true; handBinder.SetEditorPose = true; }
/// <summary> /// Makes a new leap hand so we can use it to set an editor pose /// </summary> /// <param name="binder"></param> private void MakeLeapHand(HandBinder binder) { LeapProvider provider = null; //First try to get the provider from a parent HandModelManager if (binder.transform.parent != null) { var manager = binder.transform.parent.GetComponent <HandModelManager>(); if (manager != null) { provider = manager.leapProvider; } } //If not found, use any old provider from the Hands.Provider getter if (provider == null) { provider = Hands.Provider; } Hand hand = null; //If we found a provider, pull the hand from that if (provider != null) { var frame = provider.CurrentFrame; if (frame != null) { hand = frame.Get(binder.Handedness); } } //If we still have a null hand, construct one manually if (hand == null) { hand = TestHandFactory.MakeTestHand(binder.Handedness == Chirality.Left, unitType: TestHandFactory.UnitType.LeapUnits); hand.Transform(binder.transform.GetLeapMatrix()); } binder.LeapHand = hand; }
/// <summary> /// This function is used to search the child Transforms of the HandBinder script to automatically try and assign them for the user /// </summary> /// <param name="handBinder">The HandBinder that the found Transform target will get assigned to</param> public static void AutoBind(HandBinder handBinder) { handBinder.ResetHand(); BoneNameDefinitions boneDefinitions = new BoneNameDefinitions(); //Get all children of the hand var children = new List <Transform>(); children.Add(handBinder.transform); children.AddRange(GetAllChildren(handBinder.transform)); var thumbBones = SortBones(SelectBones(children, boneDefinitions.DefinitionThumb), false, true); var indexBones = SortBones(SelectBones(children, boneDefinitions.DefinitionIndex), handBinder.UseMetaBones); var middleBones = SortBones(SelectBones(children, boneDefinitions.DefinitionMiddle), handBinder.UseMetaBones); var ringBones = SortBones(SelectBones(children, boneDefinitions.DefinitionRing), handBinder.UseMetaBones); var pinkyBones = SortBones(SelectBones(children, boneDefinitions.DefinitionPinky), handBinder.UseMetaBones); var wrist = SelectBones(children, boneDefinitions.DefinitionWrist).FirstOrDefault(); var elbow = SelectBones(children, boneDefinitions.DefinitionElbow).FirstOrDefault(); handBinder.BoundHand.fingers[0].boundBones = AssignTransformToBoundBone(thumbBones); handBinder.BoundHand.fingers[1].boundBones = AssignTransformToBoundBone(indexBones); handBinder.BoundHand.fingers[2].boundBones = AssignTransformToBoundBone(middleBones); handBinder.BoundHand.fingers[3].boundBones = AssignTransformToBoundBone(ringBones); handBinder.BoundHand.fingers[4].boundBones = AssignTransformToBoundBone(pinkyBones); handBinder.BoundHand.wrist = AssignBoundBone(wrist); handBinder.BoundHand.elbow = AssignBoundBone(elbow); if (wrist != null && elbow != null) { handBinder.ElbowLength = (wrist.position - elbow.position).magnitude; } EstimateWristRotationOffset(handBinder); CalculateElbowLength(handBinder); handBinder.GetLeapHand(); handBinder.UpdateHand(); handBinder.DebugModelTransforms = true; handBinder.SetEditorPose = true; }
/// <summary> /// Set up the Editor textures and reference to the hand binder /// </summary> /// <param name="handBinderRef"></param> public void SetUp(ref HandBinder handBinderRef) { handBinder = handBinderRef; dividerLine = Resources.Load <Texture>("EditorDividerline"); editorSkin = Resources.Load <GUISkin>("UltraleapEditorStyle"); }
/// <summary> /// Draw extra gizmos in the scene to help the user while they edit variables /// </summary> private void OnSceneGUI() { myTarget = (HandBinder)target; if (myTarget == null) { return; } //Update the editor pose, this will only get called when the object is selected. if (!Application.isPlaying) { EditorHandPose(); } //Draw the leap hand if (myTarget.DebugLeapHand) { Handles.color = leapHandDebugCol; foreach (var finger in myTarget.LeapHand.Fingers) { var index = 0; foreach (var bone in finger.bones) { Handles.SphereHandleCap(-1, bone.PrevJoint.ToVector3(), Quaternion.identity, myTarget.GizmoSize, EventType.Repaint); if ((index + 1) <= finger.bones.Length - 1) { Handles.DrawLine(finger.bones[index].PrevJoint.ToVector3(), finger.bones[index + 1].PrevJoint.ToVector3()); } if (DebugLeapRotationAxis.boolValue) { DrawLeapBasis(bone, gizmoSize.floatValue * 4); } index++; } } Handles.SphereHandleCap(-1, myTarget.LeapHand.WristPosition.ToVector3(), Quaternion.identity, myTarget.GizmoSize, EventType.Repaint); var elbowPosition = myTarget.LeapHand.WristPosition.ToVector3() - (myTarget.LeapHand.Arm.Basis.zBasis.ToVector3().normalized *myTarget.elbowLength); Handles.SphereHandleCap(-1, elbowPosition, Quaternion.identity, myTarget.GizmoSize, EventType.Repaint); Handles.DrawLine(elbowPosition, myTarget.LeapHand.WristPosition.ToVector3()); } //Draw the bound Gameobjects if (myTarget.DebugModelTransforms) { Handles.color = handModelDebugCol; for (int finger = 0; finger < myTarget.boundHand.fingers.Length; finger++) { for (int bone = 0; bone < myTarget.boundHand.fingers[finger].boundBones.Length; bone++) { var target = myTarget.boundHand.fingers[finger].boundBones[bone].boundTransform; if (target != null) { if (myTarget.DebugModelTransforms) { Handles.DrawWireDisc(target.position, target.right, gizmoSize.floatValue); Handles.DrawWireDisc(target.position, target.up, gizmoSize.floatValue); Handles.DrawWireDisc(target.position, target.forward, gizmoSize.floatValue); } if (DebugModelRotationAxis.boolValue) { DrawTransformBasis(target, gizmoSize.floatValue * 4); } } } } } }