using System.Collections.Generic; using Models; using UnityEngine; namespace Behaviours { public class BoneBehaviour : MonoBehaviour { private readonly UdpListener _listener = new UdpListener(); private readonly GameObject[] _nodes = new GameObject[PoseLandmarkType.MaxValue]; private readonly List _bonds = new List(); private Dictionary _rotationNodes; private List _landmarks; private Animator _animator; private bool _isReceived; private const float Scale = 0.2f; private void Start() { _animator = GetComponent(); CreateRotationNodes(); CreateNodes(); CreateBonds(); _listener.AddHandler(OnReceive); _listener.Connect(5000); } private void Update() { if (_isReceived) { _animator.GetBoneTransform(HumanBodyBones.Hips).rotation = _rotationNodes[HumanBodyBones.Hips].Rotation; /*var rotation = _rotationNodes[HumanBodyBones.Hips].CalculateRotate * Quaternion.Inverse(_rotationNodes[HumanBodyBones.RightUpperArm].CalculateRotate); _animator.GetBoneTransform(HumanBodyBones.RightUpperArm).Rotate(rotation.eulerAngles);*/ var mid = (_landmarks[PoseLandmarkType.LeftHip].Position + _landmarks[PoseLandmarkType.RightHip].Position) / 2; for (var i = 0; i < PoseLandmarkType.MaxValue; i++) { _nodes[i].transform.position = (_landmarks[i].Position - mid) * 5f; } foreach (var bond in _bonds) { bond.UpdateBond(); } _animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation = _bonds[9].Rotation; _animator.GetBoneTransform(HumanBodyBones.LeftLowerArm).rotation = _bonds[10].Rotation; _animator.GetBoneTransform(HumanBodyBones.RightUpperArm).rotation = _bonds[15].Rotation; _animator.GetBoneTransform(HumanBodyBones.RightLowerArm).rotation = _bonds[16].Rotation; _animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg).rotation = _bonds[22].Rotation; _animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg).rotation = _bonds[23].Rotation; _animator.GetBoneTransform(HumanBodyBones.RightUpperLeg).rotation = _bonds[28].Rotation; _animator.GetBoneTransform(HumanBodyBones.RightLowerLeg).rotation = _bonds[29].Rotation; _isReceived = false; } } private void OnDisable() { _listener.DisConnect(); } private void OnReceive(List landmarks) { // 计算腰部 var frontLeft = Vector3.Cross( landmarks[PoseLandmarkType.RightHip].Position - landmarks[PoseLandmarkType.LeftHip].Position, landmarks[PoseLandmarkType.RightShoulder].Position - landmarks[PoseLandmarkType.LeftHip].Position); var frontRight = Vector3.Cross( landmarks[PoseLandmarkType.LeftShoulder].Position - landmarks[PoseLandmarkType.RightHip].Position, landmarks[PoseLandmarkType.LeftHip].Position - landmarks[PoseLandmarkType.LeftHip].Position); var front = frontLeft + frontRight; front.Normalize(); var oldRotation = _rotationNodes[HumanBodyBones.Hips]; _rotationNodes[HumanBodyBones.Hips] = new RotationNode( oldRotation.UnityName, oldRotation.Rotation, Quaternion.LookRotation(front)); _rotationNodes[HumanBodyBones.RightUpperArm] = new RotationNode( _rotationNodes[HumanBodyBones.RightUpperArm], landmarks[PoseLandmarkType.RightShoulder], landmarks[PoseLandmarkType.RightElbow]); _landmarks = landmarks; _isReceived = true; } private void CreateRotationNodes() { _rotationNodes = new Dictionary(); var bonesArray = new[] { HumanBodyBones.Hips, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg }; foreach (var bone in bonesArray) { var rotation = _animator.GetBoneTransform(bone).rotation; _rotationNodes.Add(bone, new RotationNode(bone, rotation, rotation)); } } private void CreateNodes() { for (var i = 0; i < PoseLandmarkType.MaxValue; i++) { var ball = GameObject.CreatePrimitive(PrimitiveType.Sphere); ball.transform.localScale = new Vector3(Scale, Scale, Scale); if (i <= 10) { ball.GetComponent().material.color = Color.red; //给头部添加颜色 } else if (i <= 22) { ball.GetComponent().material.color = Color.blue; //给手部添加颜色 } else if (i <= 32) { ball.GetComponent().material.color = Color.green; //给脚部添加颜色 } _nodes[i] = ball; } } private void CreateBonds() { var headBonds = new[] { PoseLandmarkType.RightEar, PoseLandmarkType.RightEyeOuter, PoseLandmarkType.RightEye, PoseLandmarkType.RightEyeInner, PoseLandmarkType.Nose, PoseLandmarkType.LeftEyeInner, PoseLandmarkType.LeftEye, PoseLandmarkType.LeftEyeOuter, PoseLandmarkType.LeftEar }; _bonds.AddRange(GenerateBondsList(headBonds)); var monthBonds = new[] { PoseLandmarkType.MouthLeft, PoseLandmarkType.MouthRight, }; _bonds.AddRange(GenerateBondsList(monthBonds)); var leftArmBonds = new[] { PoseLandmarkType.LeftShoulder, PoseLandmarkType.LeftElbow, PoseLandmarkType.LeftWrist, PoseLandmarkType.LeftPinky, PoseLandmarkType.LeftIndex, PoseLandmarkType.LeftWrist, PoseLandmarkType.LeftThumb }; _bonds.AddRange(GenerateBondsList(leftArmBonds)); var rightArmBonds = new[] { PoseLandmarkType.RightShoulder, PoseLandmarkType.RightElbow, PoseLandmarkType.RightWrist, PoseLandmarkType.RightPinky, PoseLandmarkType.RightIndex, PoseLandmarkType.RightWrist, PoseLandmarkType.RightThumb }; _bonds.AddRange(GenerateBondsList(rightArmBonds)); var leftLegBonds = new[] { PoseLandmarkType.LeftShoulder, PoseLandmarkType.LeftHip, PoseLandmarkType.LeftKnee, PoseLandmarkType.LeftAnkle, PoseLandmarkType.LeftHeel, PoseLandmarkType.LeftFootIndex, PoseLandmarkType.LeftAnkle }; _bonds.AddRange(GenerateBondsList(leftLegBonds)); var rightLegBonds = new[] { PoseLandmarkType.RightShoulder, PoseLandmarkType.RightHip, PoseLandmarkType.RightKnee, PoseLandmarkType.RightAnkle, PoseLandmarkType.RightHeel, PoseLandmarkType.RightFootIndex, PoseLandmarkType.RightAnkle }; _bonds.AddRange(GenerateBondsList(rightLegBonds)); // 最后手动添加身体上的两条横线 _bonds.Add(new Bond( _nodes[PoseLandmarkType.LeftShoulder], _nodes[PoseLandmarkType.RightShoulder], Scale)); _bonds.Add(new Bond( _nodes[PoseLandmarkType.LeftHip], _nodes[PoseLandmarkType.RightHip], Scale)); } /// /// 创建棍子列表 /// /// 需要连接起来的关键点 需要按顺序设置 /// private List GenerateBondsList(int[] nodes) { var bonds = new List(); for (var i = 0; i < nodes.Length - 1; i++) { bonds.Add(new Bond( _nodes[nodes[i]], _nodes[nodes[i + 1]], Scale)); } return bonds; } } }