2016-06-10 75 views
0

如何在两个3d矢量之间使用lerp? 我用这个方法用于2D载体:3D矢量线性插值

public Vector2d lerp(Vector2d other, double speed, double error) { 
    if (equals(other) || getDistanceSquared(other) <= error * error) 
     return other; 
    double dx = other.getX() - this.x, dy = other.getY() - this.y; 
    double direction = Math.atan2(dy, dx); 
    double x = this.x + (speed * Math.cos(direction)); 
    double y = this.y + (speed * Math.sin(direction)); 
    return new Vector2d(x, y); 
} 

注意:这是不完全的“线性内插”;此方法将以恒定速率进行内插,这正是我想要的。

我想要做到这一点,但为第三维增加了一个z组件。我怎样才能做到这一点?

回答

0

最简单的方法是转换你的两个向量,使它们位于(u, v)平面中;然后应用上面的方法;然后转换回原始坐标空间。

这需要你建立一个旋转矩阵:

  1. 把你的两个向量,以获得相互的法向量的积;致电cross_1;
  2. 沿着u轴定义this点;
  3. thiscross_1的叉积得到一个矢量cross_2,这是您的v轴的方向。
  4. 标准化这三个向量的每一个;称它们为this_norm,cross_2_normcross_1_norm

这三个矢量可以被写为一个3×3的正交矩阵(每个矢量的是一个3元素的列向量):

R = [ this_norm cross_2_norm cross_1_norm ] 

现在:可以通过乘以你的3D矢量thisother这个矩阵,并且你将得到具有形式

[ u ] 
[ v ] 
[ 0 ] 

即作为第三元件(或,至少,应。我可能忘记TR与零的3维列向量向量请上述3x3矩阵)。所以,你可以明显地丢弃第三个元素,并且有2个元素的列向量:你可以在Vector2d中存储这些元素。所以你可以应用上面的方法来进行插值。

这给你一个Vector2d(u, v)平面插值。你可以通过附加一个零三分之一的元素将它转换回(x, y, z)的空间,并且预乘R'(这是R的倒数,因为它是正交的)。


当然,您需要处理退化情况,如零和(反)平行向量。在这些情况下,一个或两个交叉产品都是零,这意味着你不能对它们进行标准化;只需选择任意方向。

0

如果我正确理解你的代码,当你计算dx和dy偏移,然后从中计算角度,最后正弦/余弦对 - 你基本上正火DX,DY矢量,所以你可以把它写这样的:

Vector2d delta = other - this;   // I'm not sure about your API here, 
delta.normalize();      // you may need to fix those lines 
double x = this.x + (speed * delta.x); 
double y = this.y + (speed * delta.y); 

现在应该很简单地添加一个Z分量。