Dav*_*rey 6 c++ vb.net geometry rotation
我的问题是关于计算2D中两个矢量之间最小角度的方向.我正在用C++制作游戏,其中一个障碍是寻热导弹发射器.我通过计算目标和子弹之间的向量,对矢量进行标准化,然后将其乘以速度来实现它.但是,我现在回到本课程,以使其更好.而不是立即锁定到玩家,我只希望它只在子弹矢量在一定角度(子弹矢量和矢量bulletloc->目标之间的角度)内时才这样做.否则我希望它慢慢向目标平移一度,从而给予玩家足够的空间来避开它.我已经做了所有这些(在一个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
Run Code Online (Sandbox Code Playgroud)
我的一个想法是计算出两个矢量的方位,如果差值大于180度,顺时针旋转,否则逆时针旋转,任何想法都会有所帮助.谢谢.
编辑:我想补充一点,这个网站是非常有帮助的.我经常使用别人提出的问题来解决我自己的问题,我想借此机会说声谢谢.
Cam*_*ron 10
正如您在代码中所写的那样,两个(标准化)向量之间的角度是它们的点积的反余弦.
为了得到一个签名的角度,你可以使用代表正常,其他两个向量趴在飞机的第三个向量-在2D情况下,这将是直指"涨"声一片的3D矢量,说(0,0, 1).
然后,将第一个向量(您希望角度相对的向量)与第二个向量的交叉乘积(注意交叉积不是可交换的).角度的符号应与结果向量和平面法线之间的点积的符号相同.
在代码中(C#,抱歉) - 注意假设所有向量都被规范化:
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;
}
Run Code Online (Sandbox Code Playgroud)
这通过利用两个矢量之间的叉积产生第三矢量的事实来工作,该第三矢量与前两个矢量所定义的平面垂直(正常)(因此它本身就是3D操作).a x b= -(b x a),所以向量将始终垂直于平面,但在不同的一侧取决于(签名)角度a和b(有一些称为右手规则).
因此,交叉积给出了一个垂直于平面的有符号向量,当向量之间的角度超过180°时,该向量会改变方向.如果我们事先知道垂直于直线指向的平面的矢量,那么我们可以通过检查其点积的符号来判断交叉积是否与该平面法线的方向相同.
| 归档时间: |
|
| 查看次数: |
6748 次 |
| 最近记录: |