using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class createRotationOffset6 : MonoBehaviour { public GameObject userAvatar; public GameObject referenceSkeleton; Dictionary<string, string> parentIndexes; Dictionary<string, string> referenceParentIndexes; Dictionary<string, Quaternion> absoluteRotations; Dictionary<string, Quaternion> referenceAbsoluteRotations; Dictionary<string, string> avatarToMecanimBoneNameMap; Dictionary<string, string> mecanimToReferenceBoneNameMap; void setParentIDs(Transform modelBone, Dictionary<string, string> indexes) { for (int i = 0; i < modelBone.childCount; i++) { setParentIDs(modelBone.GetChild(i), indexes); } if (modelBone.parent != null) { indexes.Add(modelBone.name, modelBone.parent.name); //Debug.Log("the name is : " + modelBone.name); } else { Debug.Log("setting root parent " + modelBone.name); indexes.Add(modelBone.name, "root"); } } string findLastRequiredParentBone (string currentBone){ string ret = currentBone; while (ret != "root" && !avatarToMecanimBoneNameMap.ContainsKey(ret)){ Debug.Log("stuck in while loop " + ret); ret = parentIndexes[ret]; //if (avatarToMecanimBoneNameMap.ContainsKey(ret)) //{ //then quit the loop // break; //} } Debug.Log("parent is " + ret); return ret; } // Use this for initialization void Start() { parentIndexes = new Dictionary<string, string>(); referenceParentIndexes = new Dictionary<string, string>(); absoluteRotations = new Dictionary<string, Quaternion>(); referenceAbsoluteRotations = new Dictionary<string, Quaternion>(); avatarToMecanimBoneNameMap = new Dictionary<string, string>(); mecanimToReferenceBoneNameMap = new Dictionary<string, string>(); if (userAvatar != null) { setParentIDs(userAvatar.transform, parentIndexes); setParentIDs(referenceSkeleton.transform, referenceParentIndexes); AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(userAvatar)); AssetImporter importerForReferenceSkeleton = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(referenceSkeleton)); if ((importer != null) && (importerForReferenceSkeleton != null)) { ModelImporter modelImporter = importer as ModelImporter; ModelImporter referenceImporter = importerForReferenceSkeleton as ModelImporter; if ((modelImporter != null) && (referenceImporter != null)) { HumanDescription avatarDescription = modelImporter.humanDescription; HumanBone[] boneMap = avatarDescription.human; SkeletonBone[] skeletonMap = avatarDescription.skeleton; HumanDescription referenceAvatarDescription = referenceImporter.humanDescription; HumanBone[] referenceBoneMap = referenceAvatarDescription.human; SkeletonBone[] referenceSkeletonMap = referenceAvatarDescription.skeleton; //create the name map from the user avatar to human foreach (HumanBone bone in boneMap) { avatarToMecanimBoneNameMap.Add(bone.boneName, bone.humanName); Debug.Log("avatar to mecanim bone map key is: " + bone.boneName); } // create the name map from human to the reference skeleton foreach (HumanBone rBone in referenceBoneMap) { mecanimToReferenceBoneNameMap.Add(rBone.humanName, rBone.boneName); } foreach (SkeletonBone refBone in referenceSkeletonMap) { if (referenceParentIndexes.ContainsKey(refBone.name)) { //Debug.Log("ref joint name is: " + refBone.name); referenceAbsoluteRotations.Add(refBone.name, referenceAbsoluteRotations[referenceParentIndexes[refBone.name]] * refBone.rotation); } else { // if clone then we have the root if (refBone.name.Contains("(Clone)")) { string[] splitName = refBone.name.Split('('); referenceAbsoluteRotations.Add(splitName[0], refBone.rotation); } } } // Quaternion lastGoodReferenceBone = new Quaternion(0.0f,0.0f,0.0f,1.0f); foreach (SkeletonBone userBone in skeletonMap) { // if the parent is root then use userBone rotation if (parentIndexes.ContainsKey(userBone.name)) { Debug.Log("joint name is: " + userBone.name + " parent name is:" + parentIndexes[userBone.name]); absoluteRotations.Add(userBone.name, absoluteRotations[parentIndexes[userBone.name]] * userBone.rotation); } else { if (userBone.name.Contains("(Clone)")) { string[] splitName = userBone.name.Split('('); absoluteRotations.Add(splitName[0], userBone.rotation); } } if (avatarToMecanimBoneNameMap.ContainsKey(userBone.name) && mecanimToReferenceBoneNameMap.ContainsKey(avatarToMecanimBoneNameMap[userBone.name])) { // lastGoodReferenceBone = referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[userBone.name]]]; Quaternion jointOffset = Quaternion.Inverse(absoluteRotations[userBone.name]) * referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[userBone.name]]]; Debug.Log(userBone.name + " absolute: " + absoluteRotations[userBone.name] + " ref abs " + referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[userBone.name]]] + " offset " + jointOffset); } else { if (absoluteRotations.ContainsKey(userBone.name)) { string lastRequiredParent = findLastRequiredParentBone(userBone.name); Quaternion lastRequiredParentRotation = referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[lastRequiredParent]]]; Quaternion extraBoneOffset = Quaternion.Inverse(absoluteRotations[userBone.name]) * lastRequiredParentRotation; if (avatarToMecanimBoneNameMap[userBone.name] == "UpperChest"){ extraBoneOffset = Quaternion.Inverse(absoluteRotations[userBone.name]) * referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[userBone.name]]]; } Debug.Log("extra bone " + userBone.name + " : " + userBone.rotation + " abs is " + absoluteRotations[userBone.name] + " offset " + extraBoneOffset); // take the previous offset and multiply it by the current local when we have an extra joint. } } } } else { Debug.Log("model not imported correctly"); } } else { Debug.Log("didn't find the file"); } } else { Debug.Log("no user avartar specified"); } } // Update is called once per frame void Update() { } }