【问题标题】:interpolate between rotation matrices在旋转矩阵之间插值
【发布时间】:2010-11-04 17:24:17
【问题描述】:

我有两个描述任意旋转的旋转矩阵。 (4x4 opengl 兼容)

现在我想在它们之间进行插值,以便它遵循从一个旋转到另一个旋转的径向路径。想象三脚架上的相机朝一个方向看,然后旋转。

如果我对每个分量进行插值,我会得到一个压缩结果,所以我认为我只需要对矩阵的某些分量进行插值。但是哪些?

【问题讨论】:

    标签: matrix rotation 3d


    【解决方案1】:

    您必须对矩阵的旋转部分使用 SLERP,而对其他部分使用线性。最好的方法是将矩阵转换为四元数并使用(更简单的)四元数 SLERP:http://en.wikipedia.org/wiki/Slerp

    我建议阅读 Graphic Gems II 或 III,特别是关于将矩阵分解为更简单转换的部分。以下是 Spencer W. Thomas 的本章来源:

    http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c

    当然,我建议你自己学习如何做到这一点。这真的不是那么难,只是很多烦人的代数。最后,这里有一篇很棒的论文,关于如何将矩阵转换为四元数,然后返回,Id 软件:http://www.mrelusive.com/publications/papers/SIMD-From-Quaternion-to-Matrix-and-Back.pdf


    编辑:这是几乎每个人都引用的公式,来自 1985 年的 SIGGRAPH 论文。

    在哪里

    - qm = interpolated quaternion
    - qa = quaternion a (first quaternion to be interpolated between)
    - qb = quaternion b (second quaternion to be interpolated between)
    - t = a scalar between 0.0 (at qa) and 1.0 (at qb)
    - θ is half the angle between qa and qb
    

    代码:

    quat slerp(quat qa, quat qb, double t) {
        // quaternion to return
        quat qm = new quat();
        // Calculate angle between them.
        double cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
        // if qa=qb or qa=-qb then theta = 0 and we can return qa
        if (abs(cosHalfTheta) >= 1.0){
            qm.w = qa.w;qm.x = qa.x;qm.y = qa.y;qm.z = qa.z;
            return qm;
        }
        // Calculate temporary values.
        double halfTheta = acos(cosHalfTheta);
        double sinHalfTheta = sqrt(1.0 - cosHalfTheta*cosHalfTheta);
        // if theta = 180 degrees then result is not fully defined
        // we could rotate around any axis normal to qa or qb
        if (fabs(sinHalfTheta) < 0.001){ // fabs is floating point absolute
            qm.w = (qa.w * 0.5 + qb.w * 0.5);
            qm.x = (qa.x * 0.5 + qb.x * 0.5);
            qm.y = (qa.y * 0.5 + qb.y * 0.5);
            qm.z = (qa.z * 0.5 + qb.z * 0.5);
            return qm;
        }
        double ratioA = sin((1 - t) * halfTheta) / sinHalfTheta;
        double ratioB = sin(t * halfTheta) / sinHalfTheta; 
        //calculate Quaternion.
        qm.w = (qa.w * ratioA + qb.w * ratioB);
        qm.x = (qa.x * ratioA + qb.x * ratioB);
        qm.y = (qa.y * ratioA + qb.y * ratioB);
        qm.z = (qa.z * ratioA + qb.z * ratioB);
        return qm;
    }
    

    发件人:http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/

    【讨论】:

    • 好的,谢谢,假设我改用四元数。我是否只需对 4 个组件中的每一个进行插值以获得平滑过渡?
    • 用公式和一些更容易消化的代码编辑了我的答案。
    【解决方案2】:

    您需要将矩阵转换为不同的表示形式 - 四元数可以很好地解决此问题,而插值四元数是一种定义明确的操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多