using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class createRotationOffset4 : MonoBehaviour { public GameObject userAvatar; public GameObject referenceSkeleton; bool started; Dictionary parentIndexes; Dictionary referenceParentIndexes; Dictionary absoluteRotations; Dictionary referenceAbsoluteRotations; Dictionary avatarToMecanimBoneNameMap; Dictionary mecanimToReferenceBoneNameMap; void setParentIDs(Transform modelBone, Dictionary 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 { indexes.Add(modelBone.name, "root"); } } // Use this for initialization void Start() { started = false; referenceIndexes = new Dictionary(); parentIndexes = new Dictionary(); referenceParentIndexes = new Dictionary(); absoluteRotations = new Dictionary(); referenceAbsoluteRotations = new Dictionary(); avatarToMecanimBoneNameMap = new Dictionary(); mecanimToReferenceBoneNameMap = new Dictionary(); setParentIDs(userAvatar.transform, parentIndexes); setParentIDs(referenceSkeleton.transform, referenceParentIndexes); AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(userAvatar)); AssetImporter importerForReferenceSkeleton = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(referenceSkeleton)); } // Update is called once per frame void Update() { if (userAvatar != null) { if ((importer != null) && (importerForReferenceSkeleton != null)) { ModelImporter modelImporter = importer as ModelImporter; ModelImporter referenceImporter = importerForReferenceSkeleton as ModelImporter; if ((modelImporter != null) && (referenceImporter != null)) { Debug.Log("model importer"); int parentID = HumanTrait.GetParentBone(3); HumanDescription avatarDescription = modelImporter.humanDescription; HumanBone[] boneMap = avatarDescription.human; SkeletonBone[] skeletonMap = avatarDescription.skeleton; HumanDescription referenceAvatarDescription = referenceImporter.humanDescription; HumanBone[] referenceBoneMap = referenceAvatarDescription.human; SkeletonBone[] referenceSkeletonMap = referenceAvatarDescription.skeleton; for (int i = 0; i < referenceSkeletonMap.Length; i++) { referenceIndexes.Add(referenceSkeletonMap[i].name, i); if (referenceParentIndexes.ContainsKey(referenceSkeletonMap[i].name)) { if (referenceSkeletonMap[i].name.Contains("(Clone)")) { Debug.Log("found the root of the reference"); string[] splitName = referenceSkeletonMap[i].name.Split('('); referenceAbsoluteRotations.Add(splitName[0], referenceSkeletonMap[i].rotation); } else { Debug.Log("ref joint name is: " + referenceSkeletonMap[i].name); referenceAbsoluteRotations.Add(referenceSkeletonMap[i].name, referenceAbsoluteRotations[referenceParentIndexes[referenceSkeletonMap[i].name]] * referenceSkeletonMap[i].rotation); } // Debug.Log(skeletonMap[i].name + " : " + skeletonMap[i].rotation + " " + referenceSkeletonMap[i].name + " " + referenceSkeletonMap[i].rotation); } else { Debug.Log("found the root of the reference"); string[] splitName = referenceSkeletonMap[i].name.Split('('); referenceAbsoluteRotations.Add(splitName[0], referenceSkeletonMap[i].rotation); } } foreach (HumanBone bone in boneMap) { avatarToMecanimBoneNameMap.Add(bone.boneName, bone.humanName); //Debug.Log(bone.boneName + " : " + bone.humanName); } foreach (HumanBone rBone in referenceBoneMap) { mecanimToReferenceBoneNameMap.Add(rBone.humanName, rBone.boneName); //Debug.Log(bone.boneName + " : " + bone.humanName); } foreach (SkeletonBone sbone in skeletonMap) { // if the parent is root then use sbone rotation if (parentIndexes.ContainsKey(sbone.name)) { if (parentIndexes[sbone.name] == "root") { absoluteRotations.Add(sbone.name, sbone.rotation); } else { Debug.Log("joint name is: " + sbone.name + " parent name is:" + parentIndexes[sbone.name]); absoluteRotations.Add(sbone.name, absoluteRotations[parentIndexes[sbone.name]] * sbone.rotation); } } else { Debug.Log("the absolute name is" + sbone.name); string[] splitName = sbone.name.Split('('); Debug.Log("the fixed name is name is" + splitName[0]); absoluteRotations.Add(splitName[0], sbone.rotation); } if (avatarToMecanimBoneNameMap.ContainsKey(sbone.name)) { Debug.Log("d1" + sbone.name + " mecanim name " + avatarToMecanimBoneNameMap[sbone.name] + " to reference: " + mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[sbone.name]]); Quaternion jointOffset = Quaternion.Inverse(absoluteRotations[sbone.name]) * referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[sbone.name]]]; Debug.Log(sbone.name + " absolute: " + absoluteRotations[sbone.name] + " ref abs " + referenceAbsoluteRotations[mecanimToReferenceBoneNameMap[avatarToMecanimBoneNameMap[sbone.name]]] + " offset " + jointOffset); } else { if (absoluteRotations.ContainsKey(sbone.name)) { Debug.Log("extra bone " + sbone.name + " : " + sbone.rotation + " abs is " + absoluteRotations[sbone.name]); // take the previous offset and multiply it by the current local when we have an extra joint. } } } } Debug.Log("we imported the file"); } else { Debug.Log("didn't find the file"); } } } } //traverse the avatar fbx. get every parent index of each transform. // get skeletonbones that is all the bones of the model. go through them and multiply all the bones by their parent to get the global for each joint // do the same for the reference skeleton. this should not have any extra joints so you can just use the ones that are human // for each human joint in the avatar multiply the global inverse by the reference skeleton // if there is an extra bone multiply the previous offset by the local rotation. that is the offset for the extra joint // if there is a missing joint then ignore. I think.