使用Eigen进行旋转插值(球面线性插值Slerp)

6

我将尝试使用Eigen在两个四元数之间进行插值(认为这是最简单的方法)。

我找到了两个不同的示例。

第一个示例:

for(int i = 0; i < list.size(); i++)
{
  Matrix3f m;
  Quaternion<float,0> q1 = m.toRotationMatrix();

  Quaternion<float,0> q3(q1.slerp(1,q2));
  m_node->Rotation(q3.toRotationMatrix());
}

其次,

Vec3 slerp(const Vec3& a, const Vec3& b, const Real& t)
{
 Quaternionf qa;
 Quaternionf qb;
 qa = Quaternionf::Identity();
 qb.setFromTwoVectors(a,b); 
  return (qa.slerp(t,qb)) * a; 
 }

我无法确定哪个是正确的。关于这个问题没有太多的文档说明。是否有人能告诉我是否应该使用不同的库?或者如何使用 eigen 进行 slerp 插补。

3个回答

15

在两个四元数之间进行SLERP只需要调用slerp方法:

Quaterniond qa, qb, qres;
// initialize qa, qb;
qres = qa.slerp(t, qb);

t是您的插值参数。


1
请使用第二种方法。
这两个代码片段都实现了SLERP,但第一个代码片段对列表中的元素进行了某些操作,而您的代码片段没有显示。此外,第二种变体是计算效率更高的一种,因为它不需要绕过旋转矩阵。

我有不止一个四元数,所以我将它们保存在列表中。我想从q1移动到q2,当我到达q2时,我想移动到q3。 - james456
@james456:这是一个经典的分段插值问题。您可以将四元数存储在一对“t,q”的列表中,其中t指定了相关四元数的起始“时间”。然后,您将从t_{n} … t_{n+1}的范围映射到0 … 1的范围,并将其乘以给定的q - datenwolf

0

我认为在OpenGL应用程序中GLM是最好的选择,因为GLM函数与GLSL中的函数相同。

glm slerp将参数作为mix函数(这是lerp的glm函数)进行处理。对于像下面这样的调用,mix函数会给出:

 result = mix (first, second, alpha); // result = (1-alpha)*first + alpha*second;

alpha参数在slerp中的工作方式与之相同,因此使用slerp在时间上插值四元数的典型示例可以是:

glm::quat interpolated_quaternion; //the result
std::vector<glm::quat> my_quaternion; //vector of quaternions, one per frame.
float frame_time; //the time passed since the previous frame
int frame; //the actual frame
interpolated_quaternion = slerp( my_quaternion[frame],my_quaternion[frame+1],frame_time);

我尝试使用slerp glm,但是无法弄清如何使用它。你能给我一个例子吗? - james456
当我获得插值四元数时,这个函数会移动摄像机本身吗,还是我需要编写一个函数来移动它? - james456
@james456 你需要自己移动相机。 - darius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接