using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class createRotationOffset : MonoBehaviour { public Transform referenceHips; public Transform avatarHips; public Transform referenceSpine; public Transform avatarSpine; public Transform referenceLeftLeg; public Transform avatarLeftLeg; public GameObject userAvatar; public GameObject referenceSkeleton; bool started; // Use this for initialization void Start() { Debug.Log("reference hips rotation" + referenceHips.rotation); Debug.Log("avatar hips rotation" + avatarHips.rotation); Quaternion offset = Quaternion.Inverse(avatarHips.rotation) * referenceHips.rotation; Debug.Log("offset Hips rotation" + offset); Debug.Log("reference spine rotation" + referenceSpine.rotation); Debug.Log("avatar spine rotation" + avatarSpine.rotation); Quaternion offset2 = Quaternion.Inverse(avatarSpine.rotation) * referenceSpine.rotation; Debug.Log("offset Spine rotation" + offset2); Debug.Log("reference leftupleg rotation" + referenceLeftLeg.rotation); Debug.Log("avatar leftleg rotation" + avatarLeftLeg.rotation); Quaternion offset3 = Quaternion.Inverse(avatarLeftLeg.rotation) * referenceLeftLeg.rotation; Debug.Log("offset LeftLeg rotation" + offset3); started = false; } // Update is called once per frame void Update () { if (started == false) { started = true; if (userAvatar != null) { Debug.Log("trying to import"); AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(userAvatar)); AssetImporter importerForReferenceSkeleton = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(referenceSkeleton)); Dictionary referenceIndexes = new Dictionary(); 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; SkeletonBone[] referenceSkeletonMap = referenceAvatarDescription.skeleton; for (int i = 0; i < referenceSkeletonMap.Length; i++ ) { referenceIndexes.Add(referenceSkeletonMap[i].name, i); // Debug.Log(skeletonMap[i].name + " : " + skeletonMap[i].rotation + " " + referenceSkeletonMap[i].name + " " + referenceSkeletonMap[i].rotation); } foreach (SkeletonBone sbone in skeletonMap) { if (referenceIndexes.ContainsKey(sbone.name)) { Quaternion jointOffset = Quaternion.Inverse(sbone.rotation) * referenceSkeletonMap[referenceIndexes[sbone.name]].rotation; Debug.Log(sbone.name + " : " + sbone.rotation + " " + referenceSkeletonMap[referenceIndexes[sbone.name]].name + " " + referenceSkeletonMap[referenceIndexes[sbone.name]].rotation + " offset " + jointOffset); } else { Debug.Log(sbone.name + " : " + sbone.rotation); } } foreach (HumanBone bone in boneMap){ //Debug.Log(bone.boneName + " : " + bone.humanName); } } 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.