matlab练习程序(向量插值)

有两个向量,我们想从起始向量平滑的过度到终止向量,那么中间的向量就可以通过插值的方式得到。

这在图形学中图形旋转或者机器人中物体姿态旋转都可以用到。

有三种方法:Lerp,NLerp和SLerp。

Lerp为线性插值,公式如下:

NLerp为线性插值后归一化,公式如下:

SLerp为球面插值,公式如下:

公式中的v0和v1就在起始与结束向量,换成四元数同理。

t为插值的中间值,球面插值中theta为两个向量间的夹角。

实现代码如下:

clear all;
close all;
clc;

v1=[1 2 3];     %起始向量
v2=[4 -5 -6];    %终止向量

%转为单位向量
nv1 = v1/norm(v1);
nv2 = v2/norm(v2);

%画出起始终止向量
quiver3(0,0,0,nv1(1),nv1(2),nv1(3));
hold on;
quiver3(0,0,0,nv2(1),nv2(2),nv2(3));

%起始终止向量转为四元数
x = nv1(1);y=nv1(2);z=nv1(3);
q1 = angle2quat(x,y,z);

x = nv2(1);y=nv2(2);z=nv2(3);
q2 = angle2quat(x,y,z);

%计算向量夹角
w = acos(sum(nv1.*nv2));
figure;
%四元数插值
for t=0:0.1:1
    q = sin((1-t)*w)/sin(w)*q1 + sin(t*w)/sin(w)*q2;    %球面插值 slerp
    %  q = (1-t)*q1 + t*q2;                             %一般插值 lerp
    %  q = q/norm(q);                                   %一般插值归一化 nlerp
    
    [x,y,z] = quat2angle(q);
    l=[x y z];
    x = x/norm(l);
    y = y/norm(l);
    z = z/norm(l);
    
    quiver3(0,0,0,x,y,z);
    hold on;
end

figure;
%向量插值
for t=0:0.1:1
    q = sin((1-t)*w)/sin(w)*nv1 + sin(t*w)/sin(w)*nv2;   %球面插值 slerp
    %  q = (1-t)*nv1 + t*nv2;                            %一般插值 lerp
    %  q = q/norm(q);                                    %一般插值归一化 nlerp
    
    quiver3(0,0,0,q(1),q(2),q(3));
    hold on;
end

结果如下:

初始两个向量:

 

matlab练习程序(向量插值)_第1张图片

四元数球面插值:

matlab练习程序(向量插值)_第2张图片

向量球面插值:

matlab练习程序(向量插值)_第3张图片

向量直接插值:

matlab练习程序(向量插值)_第4张图片

从效果上看,向量球面插值应该是最好的,向量直接插值在转动角较大的时候无法均匀插值。

网上很多插值都是通过四元数球面插值来做的,看结果并不是很均匀,可能是我这里用法不对?还请知道的人解释一下。

你可能感兴趣的:(matlab练习程序(向量插值))