C# 如何在与给定输入向量3正交的所有向量中找到与给定目标向量最近的向量3?
假设我有两个非零量级的输入向量:C# 如何在与给定输入向量3正交的所有向量中找到与给定目标向量最近的向量3?,c#,unity3d,math,vector,C#,Unity3d,Math,Vector,假设我有两个非零量级的输入向量: Vector3 t; Vector3 o; 我需要找到归一化向量v,这样在所有与o正交的归一化向量中,v是最接近t目标向量的向量。我还需要知道t和o是否共线,在这种情况下,不存在这样一个v 这种关系的说明: 作为一个具体的例子,假设我有一个游戏,玩家偶尔会在环境中的某个表面上看到一个类似指南针的物体。玩家必须将指南针上的指针指向游戏世界中随机放置的图片对象。当玩家选择针的位置时,我需要知道玩家的选择距离物体的真实方向有多远 指南针固定在绕着世界方向为o的轴旋转
Vector3 t;
Vector3 o;
我需要找到归一化向量v,这样在所有与o正交的归一化向量中,v是最接近t目标向量的向量。我还需要知道t和o是否共线,在这种情况下,不存在这样一个v
这种关系的说明:
作为一个具体的例子,假设我有一个游戏,玩家偶尔会在环境中的某个表面上看到一个类似指南针的物体。玩家必须将指南针上的指针指向游戏世界中随机放置的图片对象。当玩家选择针的位置时,我需要知道玩家的选择距离物体的真实方向有多远
指南针固定在绕着世界方向为o的轴旋转——也许这是指南针的transform.forward,而图中游戏对象的方向是t
当t和o不正交时,指南针将无法直接指向t,因此我想知道:如何获得指南针可能指向的最近方向,即v?这样,我可以测量这个目标方向和球员选择的方向之间的角度。并且,当该角度低于某个阈值时,播放器成功。您可以使用向量叉积来解决此问题。请注意,Vector3.Cross matters的参数顺序不一致会产生意外的结果 取t和o的叉积 如果o和t是共线的,x将等于向量3.0 否则,x将是与o和t正交的向量,因此也与v正交: 现在我们有了两个与v正交的向量,也就是o和x,我们可以做另一个叉积来找到一个与v共线的向量。如果我们仔细考虑第二个叉积的顺序,与我们用来计算x的叉积相比,第二个叉积的输出也会指向与v相同的方向。接下来剩下的就是将其正常化:
Vector3 v = Vector3.Cross(o, x).normalized;
// Use v
}
总共:
Vector3 x = Vector3.Cross(t, o);
if (x == Vector3.zero)
{
// Handle colinear situation
}
else
{
Vector3 v = Vector3.Cross(o, x).normalized;
// Use v
}
if (Vector3.Cross(o,t) == Vector3.zero)
{
// Handle colinear situation
}
else
{
Vector3 oCopy = o;
Vector3 tCopy = t;
Vector3.OrthoNormalize(ref oCopy, ref tCopy);
Vector3 v = tCopy; // unnecessary; just included to have a variable named v
// Use v
}
让我用简单的方法来解决它 与o正交并共享相同起点的向量,为简单起见,具有与t相同长度的向量在o起点处填充正交圆。假设你找到一个,你可以把它绕着o旋转一个角度,它仍然是正交的 现在你们有了向量v,寻找的是旋转角度。找到旋转角度后,你就得到了答案 根据旋转角度写出v和t之间距离的方程式。最小化这个距离——无论是数值上的,还是解析上的求导,并将它们指定为0,都将为您提供旋转角度和最终v
您应该期望有两个角度作为输出-一个用于最小距离的向量,另一个用于最大距离的向量。简单的检查应该找出哪一个是最小的解决这个问题的一种方法可能比微积分或多个叉积更容易阅读 公共静态无效正交规范化ref Vector3法线,ref Vector3切线; 描述 使向量规格化并相互正交 正常化。规格化切线并确保其与法线正交,即两者之间的角度为90度 通过查看o和t的叉积是否为矢量3.0来检查它们是否共线: 否则,复制o和t以便仅修改副本:
Vector3 oCopy = o;
Vector3 tCopy = t;
使用Vector3.OrthoNormalize使用副本,t的副本作为切线:
总共:
Vector3 x = Vector3.Cross(t, o);
if (x == Vector3.zero)
{
// Handle colinear situation
}
else
{
Vector3 v = Vector3.Cross(o, x).normalized;
// Use v
}
if (Vector3.Cross(o,t) == Vector3.zero)
{
// Handle colinear situation
}
else
{
Vector3 oCopy = o;
Vector3 tCopy = t;
Vector3.OrthoNormalize(ref oCopy, ref tCopy);
Vector3 v = tCopy; // unnecessary; just included to have a variable named v
// Use v
}
这听起来更适合,因为实际实现似乎非常复杂secondary@derHugo,即使解决方案是基于数学的,询问如何实施该解决方案的问题也是基于主题的;老实说,如果你还没有回答的话,我会建议你把它移走,因为它主要是关于理解它背后的数学。。还要注意。。在Unity中的实现非常简单,因为方法的调用与解决方案背后的数学构造完全相同。这似乎更像是一个关于叉积如何工作的问题,我会说这是一个纯粹的数学问题。
Vector3 oCopy = o;
Vector3 tCopy = t;
Vector3.OrthoNormalize(ref oCopy, ref tCopy);
Vector3 v = tCopy; // unnecessary; just included to have a variable named v
// Use v
}
if (Vector3.Cross(o,t) == Vector3.zero)
{
// Handle colinear situation
}
else
{
Vector3 oCopy = o;
Vector3 tCopy = t;
Vector3.OrthoNormalize(ref oCopy, ref tCopy);
Vector3 v = tCopy; // unnecessary; just included to have a variable named v
// Use v
}