BoneMapping.cs
3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using UnityEngine;
using System.Linq;
using System;
namespace UniHumanoid
{
public class BoneMapping : MonoBehaviour
{
[SerializeField]
public GameObject[] Bones = new GameObject[(int)HumanBodyBones.LastBone];
[SerializeField]
public AvatarDescription Description;
private void Reset()
{
GetBones();
}
private void GetBones()
{
Bones = new GameObject[(int)HumanBodyBones.LastBone];
var animator = GetComponent<Animator>();
if (animator != null)
{
if (animator.avatar != null)
{
foreach (HumanBodyBones key in Enum.GetValues(typeof(HumanBodyBones)))
{
if (key == HumanBodyBones.LastBone)
{
break;
}
var transform = animator.GetBoneTransform(key);
if (transform != null)
{
Bones[(int)key] = transform.gameObject;
}
}
}
}
}
public void GuessBoneMapping()
{
var hips = Bones[(int)HumanBodyBones.Hips];
if (hips == null)
{
Debug.LogWarning("require hips");
return;
}
var estimater = new BvhSkeletonEstimator();
var skeleton = estimater.Detect(hips.transform);
var bones = hips.transform.Traverse().ToArray();
for (int i = 0; i < (int)HumanBodyBones.LastBone; ++i)
{
var index = skeleton.GetBoneIndex((HumanBodyBones)i);
if (index >= 0)
{
Bones[i] = bones[index].gameObject;
}
}
}
public void EnsureTPose()
{
var map = Bones
.Select((x, i) => new { i, x })
.Where(x => x.x != null)
.ToDictionary(x => (HumanBodyBones)x.i, x => x.x.transform)
;
{
var left = (map[HumanBodyBones.LeftLowerArm].position - map[HumanBodyBones.LeftUpperArm].position).normalized;
map[HumanBodyBones.LeftUpperArm].rotation = Quaternion.FromToRotation(left, Vector3.left) * map[HumanBodyBones.LeftUpperArm].rotation;
}
{
var right = (map[HumanBodyBones.RightLowerArm].position - map[HumanBodyBones.RightUpperArm].position).normalized;
map[HumanBodyBones.RightUpperArm].rotation = Quaternion.FromToRotation(right, Vector3.right) * map[HumanBodyBones.RightUpperArm].rotation;
}
}
public static void SetBonesToDescription(BoneMapping mapping, AvatarDescription description)
{
var map = mapping.Bones
.Select((x, i) => new { i, x })
.Where(x => x.x != null)
.ToDictionary(x => (HumanBodyBones)x.i, x => x.x.transform)
;
description.SetHumanBones(map);
}
private void Awake()
{
if (Bones == null
|| Bones.All(x => x==null))
{
GetBones();
}
}
}
}