【问题标题】:Moving slowly an initial angle until it reach a final angle缓慢移动初始角度,直到达到最终角度
【发布时间】:2016-09-17 02:26:21
【问题描述】:

我将尝试对此进行非常详细的描述。我现在正在编辑游戏,场景是 3D 区域。

我有一个初始角度,写为一个方向向量,还有另一个具有不同坐标的向量。我们知道,两个向量之间的角度由公式给出:Theta = ACos(DotProduct(vec1, vec2) / (VectorLength(vec1) * VectorLength(vec2)))

让我们来描述一下这个场景:我目前正在编写某种固定武器,一个步哨枪,这个东西慢慢地移动他的“头”,向敌人发射子弹。那个角度旋转是我的问题。

让我们想象一下:我的哨兵枪在一个空的 3D 区域上,一个“敌人”在那里生成。我目前可以得到我的哨兵视角的方向向量,以及我的哨兵和玩家之间的方向向量。让我们猜测,使用描述的公式,他的分离角是 45 度。我的哨枪每 0.1 秒思考一次(调用一个函数),我想在每个思考函数处移动他的头部 5 度,直到它到达玩家(即两个向量几乎相等),这意味着它将在 0.9 秒内到达玩家(如果玩家保持其位置......)(距离 45 度 5 度)

如何缓慢移动哨兵的视角直到它到达目标?在 2D 中很容易,但我知道我正在与 3D 场景作斗争,而我目前对此感到迷茫。

任何帮助将不胜感激,关于编码,我将不胜感激伪代码。谢谢! (对不起我的英语)

【问题讨论】:

  • 如果您可以在 2D 中解决这个问题,您可以通过忽略在 2D 公式中使用的第三个坐标在 3D 中解决它,除非它在 ​​3 个方向上旋转。
  • 要使其缓慢旋转,您可以使用一些缓动公式,例如:position = currentPosition + (finalPosition - currentPosition) / easingFactor,其中easingFactor 是定义减速的整数。
  • 您需要计算垂直于包含 vec1vec2 的平面的向量——这定义了您将围绕其旋转哨兵的轴——枪的视线向量。围绕任意 3D 矢量执行旋转(例如,)的公式有些复杂,并且在整个网络上都有解释。例如:here。但是,如果您不需要角度在 vec1vec2 之间线性变化,那么像 @rcdmk 这样的捏造解决方案就足够了,线性变化坐标而不是角度。
  • 这将取决于两个向量之间的角度,@rcdmk。您的公式将其差异划分为小部分,但这些部分各不相同。考虑到“敌人”可以移动,这就是它不同的原因:它依赖于不断移动“哨兵”的头部,直到它到达目标。
  • 谢谢@this-vidor,去看看

标签: math vector 3d game-physics angle


【解决方案1】:

你需要的叫做SLERP——球面线性插值

那里你的起始方向向量是 p0,目标方向是 p1,Omega 是你的 Theta,t 参数在 0..1 范围内随所需步长变化

2D案例的Delphi示例(易于控制)

var
  p0, p1: TPoint;
  i, xx, yy: Integer;
  omega, InvSinOmega, t, a0, a1: Double;
begin
  P0 := Point(0, 200);
  P1 := Point(200, 0);
  omega := -Pi / 2;
  InvSinOmega := 1.0 / Sin(omega);
  Canvas.Brush.Color := clRed;
  Canvas.Ellipse(120 + P0.X, 120 + P0.Y, 120 + P0.X + 7, 120 + P0.Y + 7);
  Canvas.Ellipse(120 + P1.X, 120 + P1.Y, 120 + P1.X + 7, 120 + P1.Y + 7);

  for i := 1 to 9 do begin
    t := i / 10;

    a0 := sin((1 - t) * omega) * InvSinOmega;
    a1 := sin(t * omega) * InvSinOmega;
    xx := Round(P0.X * a0 + P1.X * a1);
    yy := Round(P0.Y * a0 + P1.Y * a1);

    Canvas.Brush.Color := RGB(25 * i, 25 * i, 25 * i);
    Canvas.Ellipse(120 + xx, 120 + yy, 120 + xx + 9, 120 + yy + 9);
  end;

【讨论】:

  • 耶稣,这太棒了。以前没有注意到这一点。不好的是,我对此有点困惑。我应该在每个坐标上应用 Slerp() 吗?含义..类似 ReturnVector.x = Slerp(Start.x, End.x, 0.5 /*example*/) ReturnVector.y = Slerp(Start.y, End.y, 0.5) ReturnVector.z = Slerp(Start. z, End.z, 0.5) ?
  • 是的,你是对的。但最好为给定的 t 计算一次系数并将它们应用于每个坐标
猜你喜欢
  • 2017-01-14
  • 2023-04-02
  • 2019-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-19
  • 2023-03-04
相关资源
最近更新 更多