Loading

[CG] Lookat矩阵

Lookat矩阵

在三维游戏引擎中,需要摄像机看向某个点,或者需要物体看向某个点,此时需要对物体的变换,以调整到我们需要的姿态。以Unity为例,Unity的坐标系是左手系,朝上的轴是y轴(up,绿色),朝前的轴是z轴(foward,蓝色),朝右的轴是x轴(right,红色)。现在我们想让foward看像某个点,需要对物体进行位姿的变换,那应该怎么做呢?

我们需要提供两个变量,target目标点,up可以理解为世界坐标下的朝上的方向,一般为(0,1,0)

  • foward:用target - position并归一化。
  • right:用 up 和求得的 foward 叉乘,cross(up,foward)
  • up:用求得的 foward 和 求得的 right 叉乘,cross(foward, right)

为了验证正确性,用自己实现的函数和Unity提供的Lookat函数比较。

注意:这里为了方便,认为物体的局部坐标就是世界坐标(物体没有父节点),没有考虑缩放,认为缩放系数都为1.

//物体的位置, 目标点,朝上的方向
Matrix4x4 m_lookat(Vector3 pos,Vector3 target, Vector3 up)
    {
        Vector3 foward = (target - pos).normalized;
        //注意叉乘的顺序,左手系满足左手定理,来判断向量的朝向
        Vector3 right = Vector3.Cross(up, foward).normalized;
        Vector3 newUp = Vector3.Cross(foward, right).normalized;
        Matrix4x4 lookat = Matrix4x4.identity;
        //将结果拷贝的新的矩阵上
        lookat.SetColumn(0, new Vector4(right.x,right.y, right.z,0));
        lookat.SetColumn(1, new Vector4(newUp.x, newUp.y, newUp.z, 0));
        lookat.SetColumn(2, new Vector4(foward.x, foward.y, foward.z, 0));
        lookat.SetColumn(3, new Vector4(pos.x, pos.y, pos.z, 1));
        return lookat;
    }

可以获取unity的物体的transofrm的localToWorldMatrix,得到物体的世界矩阵,因为物体没有父节点,所以local和world相等。然后再利用自定义的函数手动计算lookat矩阵,判断是否相等,结果证明相等(在无缩放和父节点的前提下)。

posted @ 2021-04-28 19:31  芒果和小猫  阅读(556)  评论(0编辑  收藏  举报