Unity踩坑-多级四元数旋转(多级骨骼)

Unity踩坑-多级四元数旋转(多级骨骼)


== 仅供学习、笔记之用 ,如有错误望指正==

前言

上文讲了单个物体利用四元数进行局部或本地的旋转。如果被旋转对象带有子物体,子物体想要正确的旋转那么处理又变得不一样了。
对于骨骼还需要注意的是,与静态模型不一样,静态模型导入之前可以在DCC中可以冻结位移和旋转属性。但是骨骼不允许这么做,所以他在世界空间中初始位移和旋转本身就是带数值的,所以理解会更难些。
这里还是使用欧拉角转四元数进行演示。
这次要利用这个API Transform.localRotation。 将骨架的关节的全局信息变为相对信息,然后填到这个API。

当单个物体变为多级物体。。。

按照上节,给LeftLowerArm 增加新的旋转(0,0,0)这里的本意应该是该关节在关节空间中不会发生任何旋转变化,同时他也是世界属性的,但事实上,如果按上节的思路来,会发生错误,如下图
在这里插入图片描述

public class test : MonoBehaviour
{
    
    
    Animator animator;
    Vector3 upperArm = new Vector3(0f, 0f,67.5f);
    Vector3 lowerArm = new Vector3(0f, 0f, 0f);
    Quaternion prevQUp;//upper关节原始世界空间的旋转
    Quaternion prevQLo;//lower关节原始世界空间的旋转

    void Start()
    {
    
    
       
        // 获取动画控件
        animator = this.GetComponent<Animator>();
        // 获取原始旋转
        prevQUp = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation;
        prevQLo = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm).rotation;
        //upper的父关节
        Quaternion Lshoulder = animator.GetBoneTransform(HumanBodyBones.LeftShoulder).rotation;
        //lower的父关节
        Quaternion Lelbow= animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation;
        //欧拉角转为四元数
        Quaternion currentQ1 = Quaternion.Euler(upperArm.x, upperArm.y, upperArm.z);
        Quaternion currentQ2 = Quaternion.Euler(lowerArm.x, lowerArm.y, lowerArm.z);

        animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation = currentQ1 * prevQUp;
        animator.GetBoneTransform(HumanBodyBones.LeftLowerArm).rotation = currentQ2 * prevQLo;
    }
}


启发

这个时候世界空间不怎么顶用了。但是这篇文章的摘要给出了答案。
在这里插入图片描述
可以根据正向动力学,对世界信息转换为局部相对信息。做法就是左乘一个父关节世界旋转逆,换句话说这个操作是把该关节的信息从世界拉回到局部。

旋转更正

按照这个思路,修改代码

public class test : MonoBehaviour
{
    
    
    Animator animator;
    Vector3 upperArm = new Vector3(0f, 0f,67.5f);
    Vector3 lowerArm = new Vector3(0f, 0f, 0f);
    Quaternion prevQUp;//upper关节原始世界空间的旋转
    Quaternion prevQLo;//lower关节原始世界空间的旋转

    void Start()
    {
    
    
       
        // 获取动画控件
        animator = this.GetComponent<Animator>();
        // 获取原始旋转
        prevQUp = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation;
        prevQLo = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm).rotation;
        //upper的父关节
        Quaternion Lshoulder = animator.GetBoneTransform(HumanBodyBones.LeftShoulder).rotation;
        //lower的父关节
        Quaternion Lelbow= animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation;
        //欧拉角转为四元数
        Quaternion currentQ1 = Quaternion.Euler(upperArm.x, upperArm.y, upperArm.z);
        Quaternion currentQ2 = Quaternion.Euler(lowerArm.x, lowerArm.y, lowerArm.z);

        //animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).rotation = currentQ1 * prevQUp;
        //animator.GetBoneTransform(HumanBodyBones.LeftLowerArm).rotation = currentQ2 * prevQLo;

        animator.GetBoneTransform(HumanBodyBones.LeftUpperArm).localRotation =  Quaternion.Inverse(Lshoulder) * currentQ1 * prevQUp;
        //后两项代表全局,第一项代表转换成本地
        animator.GetBoneTransform(HumanBodyBones.LeftLowerArm).localRotation = Quaternion.Inverse(Lelbow)* currentQ2 * prevQLo;
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43544518/article/details/125872207