using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; public class createRotationOffset2 : 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; Dictionary parentIndexes; Dictionary referenceParentIndexes; Dictionary absoluteRotations; Dictionary referenceAbsoluteRotations; // 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; parentIndexes = new Dictionary(); referenceParentIndexes = new Dictionary(); absoluteRotations = new Dictionary(); referenceAbsoluteRotations = new Dictionary(); } 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"); } } // Update is called once per frame void Update() { if (started == false) { started = true; if (userAvatar != null) { setParentIDs(userAvatar.transform, parentIndexes); setParentIDs(referenceSkeleton.transform, referenceParentIndexes); foreach (KeyValuePair kvp in parentIndexes) { Debug.Log("Key " + kvp.Key + " Value " + kvp.Value); } foreach (KeyValuePair kvp1 in referenceParentIndexes) { Debug.Log("reference Key " + kvp1.Key + "reference Value " + kvp1.Value); } 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); 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 (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 (referenceIndexes.ContainsKey(sbone.name)) { Quaternion jointOffset = Quaternion.Inverse(absoluteRotations[sbone.name]) * referenceAbsoluteRotations[sbone.name]; Debug.Log(sbone.name + " absolute: " + absoluteRotations[sbone.name] + " ref abs " + referenceAbsoluteRotations[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. } } } 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.