Пример #1
0
        private static Quaternion GetRotationSpace(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)
        {
            Quaternion   parentDelta = Quaternion.identity;
            BonePoseData pose        = sBonePoses[boneIndex];

            if (!pose.compareInGlobalSpace)
            {
                int parentIndex = HumanTrait.GetParentBone(boneIndex);

                if (parentIndex > 0)
                {
                    BonePoseData parentPose = sBonePoses[parentIndex];
                    if (bones[parentIndex].bone != null && parentPose != null)
                    {
                        Vector3 parentDir = GetBoneAlignmentDirection(bones, avatarOrientation, parentIndex);
                        if (parentDir != Vector3.zero)
                        {
                            Vector3 parentPoseDir = avatarOrientation * parentPose.direction;
                            parentDelta = Quaternion.FromToRotation(parentPoseDir, parentDir);
                        }
                    }
                }
            }

            return(parentDelta * avatarOrientation);
        }
Пример #2
0
        private static Vector3 GetBoneAlignmentDirection(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)
        {
            if (sBonePoses[boneIndex] == null)
            {
                return(Vector3.zero);
            }

            BoneWrapper bone = bones[boneIndex];
            Vector3     dir;

            // Get the child bone
            BonePoseData pose           = sBonePoses[boneIndex];
            int          childBoneIndex = -1;

            if (pose.childIndices != null)
            {
                foreach (int i in pose.childIndices)
                {
                    if (bones[i].bone != null)
                    {
                        childBoneIndex = i;
                        break;
                    }
                }
            }
            else
            {
                childBoneIndex = GetHumanBoneChild(bones, boneIndex);
            }

            // TODO@MECANIM Something si wrong with the indexes
            //if (boneIndex == (int)HumanBodyBones.LeftHand)
            //  Debug.Log ("Child bone for left hand: "+childBoneIndex);

            if (childBoneIndex >= 0 && bones[childBoneIndex] != null && bones[childBoneIndex].bone != null)
            {
                // Get direction from bone to child
                BoneWrapper childBone = bones[childBoneIndex];
                dir = childBone.bone.position - bone.bone.position;

                // TODO@MECANIM Something si wrong with the indexes
                //if (boneIndex == (int)HumanBodyBones.LeftHand)
                //  Debug.Log (" - "+childBone.humanBoneName + " - " +childBone.bone.name);
            }
            else
            {
                if (bone.bone.childCount != 1)
                {
                    return(Vector3.zero);
                }

                dir = Vector3.zero;
                // Get direction from bone to child
                foreach (Transform child in bone.bone)
                {
                    dir = child.position - bone.bone.position;
                    break;
                }
            }

            return(dir.normalized);
        }
Пример #3
0
        public static void MakeBoneAlignmentValid(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex)
        {
            if (boneIndex < 0 || boneIndex >= sBonePoses.Length || boneIndex >= bones.Length)
            {
                return;
            }

            BoneWrapper  bone = bones[boneIndex];
            BonePoseData pose = sBonePoses[boneIndex];

            if (bone.bone == null || pose == null)
            {
                return;
            }

            if (boneIndex == (int)HumanBodyBones.Hips)
            {
                float angleX = Vector3.Angle(avatarOrientation * Vector3.right, Vector3.right);
                float angleY = Vector3.Angle(avatarOrientation * Vector3.up, Vector3.up);
                float angleZ = Vector3.Angle(avatarOrientation * Vector3.forward, Vector3.forward);
                if (angleX > pose.maxAngle || angleY > pose.maxAngle || angleZ > pose.maxAngle)
                {
                    bone.bone.rotation = Quaternion.Inverse(avatarOrientation) * bone.bone.rotation;
                }
                return;
            }

            Vector3 dir = GetBoneAlignmentDirection(bones, avatarOrientation, boneIndex);

            if (dir == Vector3.zero)
            {
                return;
            }
            Quaternion space   = GetRotationSpace(bones, avatarOrientation, boneIndex);
            Vector3    goalDir = space * pose.direction;

            if (pose.planeNormal != Vector3.zero)
            {
                dir = Vector3.ProjectOnPlane(dir, space * pose.planeNormal);
            }

            // If the bone direction is not close enough to the target direction,
            // rotate it so it matches the target direction.
            float deltaAngle = Vector3.Angle(dir, goalDir);

            if (deltaAngle > pose.maxAngle * 0.99f)
            {
                Quaternion adjust = Quaternion.FromToRotation(dir, goalDir);

                // If this bone is hip or knee, remember global foor rotation and apply it after this adjustment
                Transform  footBone = null;
                Quaternion footRot  = Quaternion.identity;
                if (boneIndex == (int)HumanBodyBones.LeftUpperLeg || boneIndex == (int)HumanBodyBones.LeftLowerLeg)
                {
                    footBone = bones[(int)HumanBodyBones.LeftFoot].bone;
                }
                if (boneIndex == (int)HumanBodyBones.RightUpperLeg || boneIndex == (int)HumanBodyBones.RightLowerLeg)
                {
                    footBone = bones[(int)HumanBodyBones.RightFoot].bone;
                }
                if (footBone != null)
                {
                    footRot = footBone.rotation;
                }

                // Adjust only enough to fall within maxAngle
                float adjustAmount = Mathf.Clamp01(1.05f - (pose.maxAngle / deltaAngle));
                adjust = Quaternion.Slerp(Quaternion.identity, adjust, adjustAmount);

                bone.bone.rotation = adjust * bone.bone.rotation;

                // Revert foot rotation to what it was
                if (footBone != null)
                {
                    footBone.rotation = footRot;
                }
            }
        }