gpt4 book ai didi

c++ - 两个 vector 之间的最短旋转方向

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:12:06 24 4
gpt4 key购买 nike

我的问题是关于计算二维中两个 vector 之间的最小角度的方向。我正在用 C++ 制作游戏,其中一个障碍是热寻导弹发射器。我通过计算目标和子弹之间的 vector 、归一化 vector 然后乘以它的速度来让它工作。但是,我现在要回到这门课,让它变得更好。我不想立即锁定播放器,而是希望它仅在子弹 vector 在特定角度(子弹 vector 和 vector bulletloc->target 之间的角度)内时才这样做。否则,我希望它以一定程度缓慢地向目标平移,从而为玩家提供足够的空间来避开它。我已经完成了所有这些(在 vb.net 项目中,所以我可以简化问题,解决问题然后用 C++ 重新编写)。然而,即使最快的路线是逆时针方向,子弹也总是顺时针方向朝向目标旋转。所以问题是找出应用旋转的方向,以便覆盖最小的角度。这是我的代码,您可以尝试看看我在描述什么:

    Function Rotate(ByVal a As Double, ByVal tp As Point, ByVal cp As Point, ByVal cv As Point)
'params a = angle, tp = target point, cp = current point, cv = current vector of bullet'
Dim dir As RotDir 'direction to turn in'
Dim tv As Point 'target vector cp->tp'
Dim d As Point 'destination point (d) = cp + vector'
Dim normal As Point
Dim x1 As Double
Dim y1 As Double
Dim VeritcleResolution As Integer = 600

tp.Y = VeritcleResolution - tp.Y 'modify y parts to exist in plane with origin (0,0) in bottom left'
cp.Y = VeritcleResolution - cp.Y
cv.Y = cv.Y * -1

tv.X = tp.X - cp.X 'work out cp -> tp'
tv.Y = tp.Y - cp.Y

'calculate angle between vertor to target and vecrot currntly engaed on'
Dim tempx As Double
Dim tempy As Double

tempx = cv.X * tv.X
tempy = cv.Y * tv.Y

Dim DotProduct As Double

DotProduct = tempx + tempy 'dot product of cp-> d and cp -> tp'

Dim magCV As Double 'magnitude of current vector'
Dim magTV As Double 'magnitude of target vector'

magCV = Math.Sqrt(Math.Pow(cv.X, 2) + Math.Pow(cv.Y, 2))
magTV = Math.Sqrt(Math.Pow(tv.X, 2) + Math.Pow(tv.Y, 2))

Dim VectorAngle As Double

VectorAngle = Acos(DotProduct / (magCV * magTV))
VectorAngle = VectorAngle * 180 / PI 'angle between cp->d and cp->tp'

If VectorAngle < a Then 'if the angle is small enough translate directly towards target'
cv = New Point(tp.X - cp.X, tp.Y - cp.Y)
magCV = Math.Sqrt((cv.X ^ 2) + (cv.Y ^ 2))

If magCV = 0 Then
x1 = 0
y1 = 0
Else
x1 = cv.X / magCV
y1 = cv.Y / magCV
End If

normal = New Point(x1 * 35, y1 * 35)
normal.Y = normal.Y * -1

cv = normal
ElseIf VectorAngle > a Then 'otherwise smootly translate towards the target'
Dim x As Single
d = New Point(cp.X + cv.X, cp.Y + cv.Y)


a = (a * -1) * PI / 180 'THIS LINE CONTROL DIRECTION a = (a*-1) * PI / 180 would make the rotation counter clockwise'

'rotate the point'
d.X -= cp.X
d.Y -= cp.Y

d.X = (d.X * Cos(a)) - (d.Y * Sin(a))
d.Y = (d.X * Sin(a)) + (d.Y * Cos(a))

d.X += cp.X
d.Y += cp.Y

cv.X = d.X - cp.X
cv.Y = d.Y - cp.Y

cv.Y = cv.Y * -1
End If

Return cv

End Function

我的一个想法是计算出两个 vector 的方位角,如果差值大于 180 度,则顺时针旋转,否则逆时针旋转,任何想法都会有所帮助。谢谢。

编辑:我想补充一点,这个网站非常有帮助。我经常用别人提出的问题来解决我自己的问题,我想借此机会说声谢谢。

最佳答案

正如您在代码中所写,两个(归一化) vector 之间的角度是它们点积的反余弦值。

要获得一个有符号角,您可以使用第三个 vector 来表示其他两个 vector 所在平面的法线——在您的 2D 情况下,这将是一个指向直线的 3D vector “向上”,比如 (0, 0, 1)。

然后,将第一个 vector (您希望角度与其相关的 vector )与第二个 vector 进行叉积(注意叉积不可交换)。角度的符号应与所得 vector 与平面法线的点积符号相同。

在代码中(C#,抱歉)——注意所有 vector 都被假设为标准化:

public static double AngleTo(this Vector3 source, Vector3 dest)
{
if (source == dest) {
return 0;
}
double dot; Vector3.Dot(ref source, ref dest, out dot);
return Math.Acos(dot);
}

public static double SignedAngleTo(this Vector3 source, Vector3 dest, Vector3 planeNormal)
{
var angle = source.AngleTo(dest);
Vector3 cross; Vector3.Cross(ref source, ref dest, out cross);
double dot; Vector3.Dot(ref cross, ref planeNormal, out dot);
return dot < 0 ? -angle : angle;
}

它的工作原理是利用两个 vector 之间的叉积产生第三个 vector ,该 vector 垂直于(法向)由前两个 vector 定义的平面(因此它本质上是一个 3D 运算)。 a x b = -(b x a),因此 vector 将始终垂直于平面,但在不同的一侧,具体取决于 a< 之间的(有符号)角度b(有一个叫做 right-hand rule 的东西)。

因此,叉积为我们提供了一个垂直于平面的有符号 vector ,当 vector 之间的角度超过 180° 时,该平面会改变方向。如果我们事先知道一个垂直于平面的 vector 指向正上方,那么我们可以通过检查点的符号来判断叉积是否与该平面法线方向相同产品。

关于c++ - 两个 vector 之间的最短旋转方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11022446/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com