using System.Collections.Generic;
public struct JointTransformMapping
public Transform transform;
public class MPIIAvatarMapper : MonoBehaviour
public MPIIModel mpiiModel; // Reference to the MPIIModel ScriptableObject
public Animator animator; // Reference to the Animator component with the Avatar
// Dictionary for fast lookup of joint Transforms
private Dictionary<MPIIJoint, Transform> jointTransformDictionary;
// Dictionary to map MPIIJoint to HumanBodyBones
private Dictionary<MPIIJoint, HumanBodyBones> mpiiToHumanBoneMap = new Dictionary<MPIIJoint, HumanBodyBones>
{ MPIIJoint.Pelvis, HumanBodyBones.Hips },
{ MPIIJoint.Thorax, HumanBodyBones.Spine },
{ MPIIJoint.Neck, HumanBodyBones.Neck },
{ MPIIJoint.HeadTop, HumanBodyBones.Head },
{ MPIIJoint.RightShoulder, HumanBodyBones.RightUpperArm },
{ MPIIJoint.RightElbow, HumanBodyBones.RightLowerArm },
{ MPIIJoint.RightWrist, HumanBodyBones.RightHand },
{ MPIIJoint.LeftShoulder, HumanBodyBones.LeftUpperArm },
{ MPIIJoint.LeftElbow, HumanBodyBones.LeftLowerArm },
{ MPIIJoint.LeftWrist, HumanBodyBones.LeftHand },
{ MPIIJoint.RightHip, HumanBodyBones.RightUpperLeg },
{ MPIIJoint.RightKnee, HumanBodyBones.RightLowerLeg },
{ MPIIJoint.RightAnkle, HumanBodyBones.RightFoot },
{ MPIIJoint.LeftHip, HumanBodyBones.LeftUpperLeg },
{ MPIIJoint.LeftKnee, HumanBodyBones.LeftLowerLeg },
{ MPIIJoint.LeftAnkle, HumanBodyBones.LeftFoot }
private void OnValidate()
if (mpiiModel != null && animator != null && animator.avatar != null && animator.avatar.isHuman)
mpiiModel.jointMapper = this; // Link the ScriptableObject to this mapper
Debug.LogWarning("Animator or MPIIModel is not properly assigned, or the Avatar is not a humanoid.");
private void PopulateJointMappings()
// Initialize the dictionary
jointTransformDictionary = new Dictionary<MPIIJoint, Transform>();
for (int i = 0; i < mpiiModel.keypoints.Length; i++)
MPIIJoint mpiiJoint = mpiiModel.keypoints[i];
Transform jointTransform = null;
// Try to find the corresponding HumanBodyBone and its Transform
if (mpiiToHumanBoneMap.TryGetValue(mpiiJoint, out HumanBodyBones humanBone))
jointTransform = animator.GetBoneTransform(humanBone);
// Store the mapping in the dictionary
if (jointTransform != null)
jointTransformDictionary[mpiiJoint] = jointTransform;
Debug.Log($"Mapped MPIIJoint {mpiiJoint} to Transform {jointTransform.name}");
Debug.LogWarning($"Failed to map MPIIJoint {mpiiJoint}. No corresponding Transform found.");
// Method to get the Transform associated with a specific MPIIJoint
public Transform GetTransformForJoint(MPIIJoint joint)
if (jointTransformDictionary != null && jointTransformDictionary.TryGetValue(joint, out Transform transform))
// Method to fetch the world space position of a joint
public Vector3 GetJointWorldPosition(MPIIJoint joint)
Transform jointTransform = GetTransformForJoint(joint);
if (jointTransform != null)
return jointTransform.position;
Debug.LogWarning($"Transform for joint {joint} not found.");
return Vector3.zero; // Return a default value
// Method to visualize the bones with colorization
public void VisualizeBones()
for (int i = 0; i < mpiiModel.bones.Length; i++)
MPIIBone bone = mpiiModel.bones[i];
Transform startTransform = GetTransformForJoint(bone.startJoint);
Transform endTransform = GetTransformForJoint(bone.endJoint);
if (startTransform != null && endTransform != null)
// Determine the color based on the joint
Color boneColor = GetBoneColor(bone.startJoint, bone.endJoint);
Debug.DrawLine(startTransform.position, endTransform.position, boneColor);
Debug.LogWarning($"Bone visualization skipped for {bone.startJoint} -> {bone.endJoint} due to missing Transform.");
// Determine the color based on whether the bone is on the left, right, or center of the body
private Color GetBoneColor(MPIIJoint startJoint, MPIIJoint endJoint)
if (IsRightSideJoint(startJoint) || IsRightSideJoint(endJoint))
return Color.blue; // Right side joints in blue
else if (IsLeftSideJoint(startJoint) || IsLeftSideJoint(endJoint))
return Color.red; // Left side joints in red
return Color.white; // Center joints in white
// Helper method to determine if a joint is on the right side
private bool IsRightSideJoint(MPIIJoint joint)
return joint == MPIIJoint.RightShoulder ||
joint == MPIIJoint.RightElbow ||
joint == MPIIJoint.RightWrist ||
joint == MPIIJoint.RightHip ||
joint == MPIIJoint.RightKnee ||
joint == MPIIJoint.RightAnkle;
// Helper method to determine if a joint is on the left side
private bool IsLeftSideJoint(MPIIJoint joint)
return joint == MPIIJoint.LeftShoulder ||
joint == MPIIJoint.LeftElbow ||
joint == MPIIJoint.LeftWrist ||
joint == MPIIJoint.LeftHip ||
joint == MPIIJoint.LeftKnee ||
joint == MPIIJoint.LeftAnkle;