0

我怎样才能在两个 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 组件。我怎样才能做到这一点?

4

2 回答 2

0

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

这需要您构造一个旋转矩阵:

  1. 取两个向量的叉积以获得相互法线向量;打电话给这个cross_1
  2. 定义this沿u轴的点;
  3. this取和的叉积cross_1得到一个向量cross_2,它是你的v轴的方向。
  4. 对这三个向量中的每一个进行归一化;打电话给他们this_normcross_2_normcross_1_norm

这三个向量可以写成一个 3x3 正交矩阵(每个向量都是一个 3 元素列向量):

R = [ this_norm cross_2_norm cross_1_norm ]

现在:你可以将你的 3d 向量乘以这个矩阵thisother你将得到具有以下形式的向量

[  u  ]
[  v  ]
[  0  ]

即一个 3 维列向量,零作为第三个元素(或者,至少,你应该。我可能忘记转置上面的 3x3 矩阵)。

因此,您显然可以丢弃第三个元素,并拥有 2 元素列向量:您可以将它们存储在Vector2d. 因此,您可以应用上面的方法进行插值。

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


当然,您需要处理退化的情况,例如零和(反)平行向量。在这些情况下,一个或两个叉积为零,这意味着您无法对它们进行归一化;只需选择任意方向即可。

于 2016-06-10T19:44:24.463 回答
0

如果我正确理解了您的代码,那么当您计算 dx 和 dy 偏移量时,然后从中计算角度,最后计算 sin/cos 对 - 您基本上是在对 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 组件了。

于 2016-06-15T15:40:55.917 回答