我正在尝试实施GJK算法,但我立即陷入困境。
问题是实现不是O(n ^ 2)的支持功能。
现在我正在计算完整的Minkowski差异,然后在做GJK算法时没有意义。 (或者是吗?)
我的意思是支持功能是返回在指定方向上最远的Minkowski差异点的函数。我认为这不应该是O(n ^ 2),因为它在我当前的实现中。
答案 0 :(得分:4)
最简单的支持函数是0(n),即在一个方向上找到最佳点积。
public Vector3 MaxPointAlongDirection(Vector3 directionToMove)
{
float max = float.NegativeInfinity;
int index = 0;
for (int i = 0; i < vertices.Length; i++)
{
float dot = Vector3.Dot(vertices[i], directionToMove);
if (dot > max)
{
max = dot;
index = i;
}
}
return vertices[index];
}
三角形凸壳的另一个更快的方法就是爬山; 1计算每个点的邻接信息。 2从随机点开始,找到所有相邻点的最佳点积。 3将此新点作为当前点重复步骤2 当没有找到更好的产品时4停止(这是有效的,因为对象是凸的,因此没有局部最大值)
或Dobkin-Kirkpatrick等级。
在对象旋转的情况下,directionToMove向量可以相对于旋转的对象进行变换(仍在处理此对象)。从而不需要旋转所有点。
答案 1 :(得分:2)
那么,GJK会给你最接近Minkowski总和的点。如果没有别的动作,那么你的Minkowski总和将是相同的,也是最接近的点。
通常人们认为身体可以自由移动和旋转。在这种情况下,结果一直在变化。
在翻译案例中,您应该可以重复使用您的Minkowski差异。在旋转情况下,您需要重新计算。对于许多实时应用程序来说,这将是一个问题。
如果您的算法通过支持函数隐式使用Minkowski差异,那么您不必重新计算任何内容。这是使用支持功能的优势之一。
某些形状的支持功能非常简单。在这种情况下,您不需要计算任何东西。这是另一个优势。最后,您可以添加支持函数以获得Minkowski总和的支持功能。这是一个很好的属性,因为你可以使用原语形成一个形状族,并让GJK对它们进行处理。
如果平面上有n个凸点的凸包,则可以通过找到船体多边形的边缘并对法向矢量的角度进行排序来预先计算支撑函数。船体上的每个顶点都有两个法线。只需按顺序查找您的方向是否在这些法线向量之间。那会给你O(n)。
您也可以更改比较顺序并将其设为O(log(n))。