If you rigged your own hands, then things will work best if your bone lengths and orientations match those of our internal model. Even our rigged hands are only close (some are better than others). You can see how well the rigging matches the model by viewing the hands in scene view with the HandController object selected. The physics hand colliders should line up with the fingers. I do see some interpenetration using the skeletal-style hands as well. Maybe it seems less apparent because the skeletal hands are also skinnier.
After several failed attempts to rig a 3d model exactly (not something I've done before), I took the internal model and wrote a script that creates a bone visualization using the RiggedHand scripts. If nothing else, you can use the values in this script to create a better hand rig.
using UnityEngine;
using System.Collections;
using Leap;
public class TestRigHand : RiggedHand
{
const float mm_to_m = .001f;
Transform palmCenter;
public bool IsLeft = true;
void Awake ()
{
palmCenter = palm;
fingers [0] = MakeThumb ();
fingers [1] = MakeIndexFinger ();
fingers [2] = MakeMiddleFinger ();
fingers [3] = MakeRingFinger ();
fingers [4] = MakePinky ();
//Remove colliders to reduce visual clutter in Scene view
Collider[] allColliders = GetComponentsInChildren<Collider> ();
foreach (Collider collider in allColliders) {
Component.Destroy (collider);
}
}
RiggedFinger MakeThumb ()
{
//Thumb
Vector position;
Vector forward;
Vector up;
if (IsLeft) {
position = new Vector (19.3382610281f, -6.0f, 53.168484654f);
forward = new Vector (0.436329113772f, 0.0f, -0.899787143982f);
up = new Vector (0.804793943718f, 0.447213915513f, 0.390264553767f);
} else {
position = new Vector (-19.3382610281f, -6.0f, 53.168484654f);
forward = new Vector (-0.436329113772f, 0.0f, -0.899787143982f);
up = new Vector (-0.804793943718f, 0.447213915513f, 0.390264553767f);
}
Vector4 jointLengths = new Vector4 (0.0f, 46.22f, 31.57f, 21.67f);
return MakeFinger ("thumb", position.ToUnityScaled (), forward.ToUnity (), up.ToUnity (), jointLengths, palmCenter);
}
RiggedFinger MakeIndexFinger ()
{
//Index Finger
Vector position;
Vector forward;
Vector up;
if (IsLeft) {
position = new Vector (23.1812851873f, 2.0f, -23.1493459317f);
forward = new Vector (0.166044313785f, -0.14834045293f, -0.974897120667f);
up = new Vector (0.0249066470677f, 0.988936352868f, -0.1462345681f);
} else {
position = new Vector (-23.1812851873f, 2.0f, -23.1493459317f);
forward = new Vector (-0.166044313785f, -0.14834045293f, -0.974897120667f);
up = new Vector (-0.0249066470677f, 0.988936352868f, -0.1462345681f);
}
Vector4 jointLengths = new Vector4 (68.12f, 39.78f, 22.38f, 15.82f);
return MakeFinger ("index", position.ToUnityScaled (), forward.ToUnity (), up.ToUnity (), jointLengths, palmCenter);
}
RiggedFinger MakeMiddleFinger ()
{
//Middle Finger
Vector position;
Vector forward;
Vector up;
if (IsLeft) {
position = new Vector (2.78877821918f, 4.0f, -23.252105626f);
forward = new Vector (0.0295207858556f, -0.148340452932f, -0.988495641481f);
up = new Vector (-0.145765270107f, 0.977715980076f, -0.151075968756f);
} else {
position = new Vector (-2.78877821918f, 4.0f, -23.252105626f);
forward = new Vector (-0.0295207858556f, -0.148340452932f, -0.988495641481f);
up = new Vector (0.145765270107f, 0.977715980076f, -0.151075968756f);
}
Vector4 jointLengths = new Vector4 (64.60f, 44.63f, 26.33f, 17.40f);
return MakeFinger ("middle", position.ToUnityScaled (), forward.ToUnity (), up.ToUnity (), jointLengths, palmCenter);
}
RiggedFinger MakeRingFinger ()
{
//Ring Finger
Vector position;
Vector forward;
Vector up;
if (IsLeft) {
position = new Vector (-17.447168266f, 4.0f, -17.2791440615f);
forward = new Vector (-0.121317937368f, -0.148340347175f, -0.981466810174f);
up = new Vector (-0.216910468316f, 0.968834928679f, -0.119619102602f);
} else {
position = new Vector (17.447168266f, 4.0f, -17.2791440615f);
forward = new Vector (0.121317937368f, -0.148340347175f, -0.981466810174f);
up = new Vector (0.216910468316f, 0.968834928679f, -0.119619102602f);
}
Vector4 jointLengths = new Vector4 (58.00f, 41.37f, 25.65f, 17.30f);
return MakeFinger ("ring", position.ToUnityScaled (), forward.ToUnity (), up.ToUnity (), jointLengths, palmCenter);
}
RiggedFinger MakePinky ()
{
//Pinky Finger
Vector position;
Vector forward;
Vector up;
if (IsLeft) {
position = new Vector (-35.3374394559f, 0.0f, -9.72871382551f);
forward = new Vector (-0.259328923438f, -0.105851224797f, -0.959970847306f);
up = new Vector (-0.353350220937f, 0.935459475557f, -0.00769356576168f);
} else {
position = new Vector (35.3374394559f, 0.0f, -9.72871382551f);
forward = new Vector (0.259328923438f, -0.105851224797f, -0.959970847306f);
up = new Vector (0.353350220937f, 0.935459475557f, -0.00769356576168f);
}
Vector4 jointLengths = new Vector4 (53.69f, 32.74f, 18.11f, 15.96f);
return MakeFinger ("pinky", position.ToUnityScaled (), forward.ToUnity (), up.ToUnity (), jointLengths, palmCenter);
}
RiggedFinger MakeFinger (string name, Vector3 position, Vector3 forward, Vector3 up, Vector4 jointLengths, Transform parent)
{
GameObject finger = new GameObject ();
finger.name = name;
RiggedFinger fingerModel = finger.AddComponent<RiggedFinger> () as RiggedFinger;
fingerModel.modelFingerPointing = Vector3.forward;
fingerModel.modelPalmFacing = Vector3.down;
fingerModel.deformPosition = true;
finger.transform.rotation = Quaternion.LookRotation (forward, up);
finger.transform.position = position;
float proximalPosition = -jointLengths [0];
GameObject metacarpal = MakeBone ("metacarpal", proximalPosition, jointLengths [0], 8f, finger.transform);
proximalPosition += jointLengths [0];
fingerModel.bones [0] = metacarpal.transform;
metacarpal.transform.parent = finger.transform;
GameObject proximal = MakeBone ("proximal", proximalPosition, jointLengths [1], 8f, finger.transform);
proximalPosition += jointLengths [1];
fingerModel.bones [1] = proximal.transform;
proximal.transform.parent = metacarpal.transform;
GameObject intermediate = MakeBone ("intermediate", proximalPosition, jointLengths [2], 8f, finger.transform);
proximalPosition += jointLengths [2];
fingerModel.bones [2] = intermediate.transform;
intermediate.transform.parent = proximal.transform;
GameObject distal = MakeBone ("distal", proximalPosition, jointLengths [3], 8f, finger.transform);
fingerModel.bones [3] = distal.transform;
distal.transform.parent = intermediate.transform;
finger.transform.parent = parent;
finger.transform.localScale = Vector3.one * mm_to_m;
return fingerModel;
}
GameObject MakeBone (string name, float proximalPosition, float length, float width, Transform parent)
{
//Joint part of bone where the rotation occurs
GameObject pivot = GameObject.CreatePrimitive (PrimitiveType.Sphere);
pivot.transform.parent = parent;
pivot.name = name;
pivot.transform.localRotation = Quaternion.LookRotation (Vector3.forward);
pivot.transform.localScale = new Vector3 (1, 1, 1);
pivot.transform.localPosition = new Vector3 (0f, 0f, proximalPosition);
//long part of bone (for display)
GameObject rod = GameObject.CreatePrimitive (PrimitiveType.Sphere);
rod.transform.parent = pivot.transform;
rod.transform.localPosition = new Vector3 (0, 0, length / 2);
rod.transform.localScale = new Vector3 (1f, 1f, length);
rod.transform.localRotation = Quaternion.LookRotation (Vector3.forward);
return pivot;
}
}