2016-06-10 109 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分量。