private void AutoDetect(ModelRenderer target) { var skinnedMesh = target.transform.GetComponentInChildren <SkinnedMeshRenderer>(); if (skinnedMesh == null) { Debug.LogError("Cannot find SkinnedMeshRenderer in " + target.name); return; } target.Hand = skinnedMesh.gameObject; // set finger bones SetBone(target, "wrist", 0, 1); SetBone(target, "thumb", 1, 4); SetBone(target, "index", 5, 4); SetBone(target, "middle", 9, 4); SetBone(target, "ring", 13, 4); SetBone(target, "pinky", 17, 4); // check left or right int leftCount = CountName(target, "l_", "_l", "_left", "left_"); int rightCount = CountName(target, "r_", "_r", "_right", "right_"); if (leftCount == rightCount) { Debug.LogErrorFormat("Cannot determine left/right for {0}, use current: {1}", target.name, target.IsLeft ? "left" : "right"); } else { target.IsLeft = leftCount > rightCount; } // set initial rotation var upDir = target.Nodes[9].position - target.Nodes[0].position; var indexDir = target.Nodes[5].position - target.Nodes[0].position; var palmDir = target.IsLeft ? Vector3.Cross(indexDir, upDir) : Vector3.Cross(upDir, indexDir); var rotation = Quaternion.FromToRotation(upDir, Vector3.up); var frontDir = rotation * palmDir; var angle = Vector3.Angle(frontDir, Vector3.forward); var sign = Mathf.Sign(Vector3.Dot(Vector3.up, Vector3.Cross(frontDir, Vector3.forward))); rotation = Quaternion.AngleAxis(sign * angle, Vector3.up) * rotation * target.transform.rotation; var eulerAngles = rotation.eulerAngles; eulerAngles.x = ParseAngle(eulerAngles.x); eulerAngles.y = ParseAngle(eulerAngles.y); eulerAngles.z = ParseAngle(eulerAngles.z); TransformUtils.SetInspectorRotation(target.transform, eulerAngles); target.initialRotation = TransformUtils.GetInspectorRotation(target.transform); }
private void SetBone(ModelRenderer target, string name, int boneIndex, int count) { var bones = target.GetComponentsInChildren <Transform>() .Where(t => t.name.ToLower().Contains(name) && t.GetComponent <SkinnedMeshRenderer>() == null) .OrderBy(t => t.hierarchyCount) .ToList(); if (bones.Count < count) { Debug.LogErrorFormat("Requires at least {1} bones for {0} finger, found only {2}", name, count, bones.Count); return; } for (int i = bones.Count - count; i < bones.Count; i++, boneIndex++) { target.Nodes[boneIndex] = bones[i]; } }
private int CountName(ModelRenderer target, params string[] names) { int maxCount = 0; foreach (var name in names) { int count = target.Hand.name.ToLower().Contains(name) ? 1 : 0; foreach (var node in target.Nodes) { count += node.name.ToLower().Contains(name) ? 1 : 0; } if (count > maxCount) { maxCount = count; } } return(maxCount); }