四元数插值matlab实现

看了几个关于关键帧提取和关键帧插值的论文,有几篇讲到了四元数插值这个概念

关于欧拉角到四元数的转换,请看:刚体运动研究方法——欧拉角四元数

接下来介绍四元数的插值公式以及matlab实现

插值公式可以从论文论文理解——从运动捕获数据中提取关键帧中找到,在这里再写一遍

四元数插值matlab实现_第1张图片



这里的 t 代表的是在夹角的哪一部分插值,从下图可以看出来,图中的ang=θ

四元数插值matlab实现_第2张图片

话不多说,上代码(matlab实现):

网上摘取的,地方忘记了,并且经过了一个小小的修改

SlepInsert.m

function r= SlerpInsert(p,q,t)
%球面线性插值
%程序考虑了p、q点乘结果为负的情况
%返回的插值结果是r
w0=p(1);x0=p(2);y0=p(3);z0=p(4);
w1=q(1);x1=q(2);y1=q(3);z1=q(4);
%用点乘计算两个四元数夹角的cos值
cosOmega=w0*w1+x0*x1+y0*y1+z0*z1;
%如果点乘为负,则反转一个四元数以取得短的4D弧
if(cosOmega<0.0)
    w1=-w1;
    x1=-x1;
    y1=-y1;
    z1=-z1;
    cosOmega=-cosOmega;
end

%检查他们是否接近,以避免除零
m=size(t,2);%火啊去插值精度,即需要分别在哪一部分插值
for i=1:m
if cosOmega>0.99999999   %cos=1的时候就是夹角为0,重合
    k0=1.0-t(i);
    k1=t(i);
else
    %用三角公式sin?+cos?=1计算sin值
    sinOmega=sqrt(1.0-cosOmega*cosOmega);
    %通过sin和cos计算角度
    omega=atan2(sinOmega,cosOmega) %计算点(cosOmega,sinOmega)与x轴正向的夹角
    %计算分母的倒数,这样就只需要一次除法
    oneOverSinOmega=1.0/sinOmega;
    %计算插值变量
     k0=sin((1.0-t(i))*omega)*oneOverSinOmega;
     k1=sin(t(i)*omega)*oneOverSinOmega;
end
%插值
w=w0*k0+w1*k1;
x=x0*k0+x1*k1;
y=y0*k0+y1*k1;
z=z0*k0+z1*k1;
r(i,1)=w; r(i,2)=x; r(i,3)=y; r(i,4)=z;
end

SerpInsertTest.m

clear
clc
q=[1 2 3 4];
p=[1 3 6 8];
t=0:0.5:2*pi;
r=SlerpInsert(p,q,t);
结果:

r =

    1.0000    3.0000    6.0000    8.0000
    1.0000    2.5000    4.5000    6.0000
    1.0000    2.0000    3.0000    4.0000
    1.0000    1.5000    1.5000    2.0000
    1.0000    1.0000         0         0
    1.0000    0.5000   -1.5000   -2.0000
    1.0000         0   -3.0000   -4.0000
    1.0000   -0.5000   -4.5000   -6.0000
    1.0000   -1.0000   -6.0000   -8.0000
    1.0000   -1.5000   -7.5000  -10.0000
    1.0000   -2.0000   -9.0000  -12.0000
    1.0000   -2.5000  -10.5000  -14.0000
    1.0000   -3.0000  -12.0000  -16.0000


按照论文思想就是酱紫啦,如果需要在OpenGL里面实现的话,请参考网络里面的大牛们的文章。

你可能感兴趣的:(插值,四元数)