SoRoMan

人若无名,便可专心练剑。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

问题:
3D空间中,在等长度的两个交角为theta的向量v1(x1,y1,z1),v2(x2,y2,z2)之间进行球面线性插值。

实例:
做一个行星在围绕太阳等速旋转的动画,假设只采样到旋转过程中的两个位置p1,p2,现在想要用软件模拟行星是怎么从p1运动到p2的。

思路:
1。一般线性插值:

我们知道一般两个量之间进行线性插值的方法为:
v(t) = v1 + t*(v2-v1)(0<=t<=1)(因为t是一次方的,所以是线性的。)


如上图所示。这里,考虑v,v1,v2是向量,由几何学的知识,v2-v1即为v1,v2组成的三角形的另外一条边。因为|v1| = |v2|,所以v1 + t*(v2-v1)的长度肯定小于|v1|或|v2|,当0<t<1时。得到的插值向量v(t)的端点沿着v2-v1行进。

***********************************************
一般线性插值由于长度发生变化,不能满足案列的要求,我们需要保持向量长度不变的插值,即球面线性插值。
***********************************************

2。一般球面线性插值:


如上图所示,将一般线性插值得到的结果乘以放大系数k(t),使其长度放大到|v1|或|v2|,即得保持向量长度不变的插值:
v(t) = k(t)*(v1 + t*(v2-v1))

其中k(t) = |v1|/|v(t)|=|v1|/|v1+t*(v2-v1)|.

这样,插值向量v(t)的端点就会沿着v1,v2端点构成的圆弧行进。因为v1,v2是等长的,这个圆弧实际上是位于v1,v2构成的球面上的一段,所以又叫球面线性插值,

*****************************************************************
这个插值解决了3D空间中旋转的插值,在关键帧动画中可以用来计算两个关键帧之间的动画。但是,由于它的插值不是等角速度的,而是变速的。所以如果用来实现案例中的效果的话还需进一步处理。
*****************************************************************

***************************************
注:一般球面线性插值v(t)与v1的夹角theta(t)不是t的线性函数。

证明:由向量点积可得cos(theta(t)) = (v(t)*v1)/|v(t)|*|v1|,
theta(t) = arcos((v(t)*v1)/|v1|^2),由反证法,假设theat(t)为线性函数,则 theat(t) = k*t + b,又theta(0) = 0,故 b = 0,theat(t) = k*t,将t'= 2t代入得,theta(2*t) = arcos((v(2*t)*v1)/|v1|^2)并不等于 2*theta(t),所以theat(t)不可能是t的线性函数。
***************************************

3。改进的球面线性插值:

要想进行等速的球面线性插值,有几个方法:

1)。用四元数工具:

变换方法:
---------------------------------------------
构造单位四元数q(cos(theta),sin(theta)*v1'),r(cos(theta),sin(theta)*v2')(v1'和v2'为单位v1,v2向量),以

及参数t(0<=t<=1),则构造四元数变换:

a.四元数 s(w,v') = r*(q-1)exp(t)*q
即为球面线性插值变换。其中,s的虚部v'即为v1'和v2'间的插值向量,乘以长度sqrt(x1^2+y1^2+z1^2)即得v1,v2间插值向量v。

b.另一种变形形式是对四元数进行插值变换:
s(w,v') = a*q + b*r

其中a = sin(alpha*(1-t))/sin(alpha),b = sin(alpha*t))/sin(alpha), cos(alpha) = x1*y1+y1*y2+z1*z2+w1*w2.
s的虚部v'即为v1'和v2'间的插值向量,乘以长度sqrt(x1^2+y1^2+z1^2)即得v1,v2间插值向量v。

两种变换都可以。
----------------------------------------------

复杂度:

以b方法为例:时间主要花在三角函数上,四元数乘以实数只需4次乘法。cost = 1*Tat + 3*Tt + 2Td + 3*4Tm


2)。利用旋转矩阵:

变换方法:
--------------------------------------------
v = v1*Trot

其中,Trot即饶任意轴旋转的矩阵变换矩阵(见上篇:探讨:物体绕任意向量的旋转-四元数法VS.旋转矩阵法的性能比较),因为v1到v2间的插值可以看成是v1饶垂直于v1,v2组成的平面的向量的旋转,所以实际上就是个饶轴旋转的问题,不过相应参数变成:theta = t*theta,轴q(q1,q2,q3)变成向量v1Xv2/|v1Xv2| = (y1*z2-z1*y2,z1*x2-x1*z2,x1*y2-y1*x2)/sin(theta)
--------------------------------------------

复杂度:

基本和饶任意轴旋转矩阵的复杂度一样。主要是多了个向量叉积操作。 cost =2*Tt + 6*Tm + 42*Tm = 2*Tt +48*Tm

综合来看,未经过优化前,效率应该差不多。

posted on 2006-09-21 16:26  SoRoMan  阅读(8405)  评论(2编辑  收藏  举报
free web counters
Vistaprint Discount Codes