在旋转矩阵之间插值 [英] interpolate between rotation matrices

查看:36
本文介绍了在旋转矩阵之间插值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

解决方案

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

i have two rotation matrices that describe arbitrary rotations. (4x4 opengl compatible)

now i want to interpolate between them, so that it follows a radial path from one rotation to the other. think of a camera on a tripod looking one way and then rotating.

if i interpolate every component i get a squeezing result, so i think i need to interpolate only certain components of the matrix. but which ones?

解决方案

You have to use SLERP for the rotational parts of the matrices, and linear for the other parts. The best way is to turn your matrices into quaternions and use the (simpler) quaternion SLERP: http://en.wikipedia.org/wiki/Slerp.

I suggest reading Graphic Gems II or III,specifically the sections about decomposing matrices into simpler transformations. Here's Spencer W. Thomas' source for this chapter:

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

Of course, I suggest you learn how to do this yourself. It's really not that hard, just a lot of annoying algebra. And finally, here's a great paper on how to turn a matrix into a quaternion, and back, by Id software: http://www.mrelusive.com/publications/papers/SIMD-From-Quaternion-to-Matrix-and-Back.pdf


Edit: This is the formula pretty much everyone cites, it's from a 1985 SIGGRAPH paper.

Where:

- 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

Code:

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;
}

From: http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/

这篇关于在旋转矩阵之间插值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆