我正在尝试用Java编写一个2D游戏,它使用分离轴定理进行碰撞检测。为了解决两个多边形之间的碰撞,我需要知道碰撞的最小平移向量,我需要知道它相对于多边形指向哪个方向(这样我就可以给一个多边形一个沿该方向的惩罚力和另一个相反方向的惩罚力量)。作为参考,我正在尝试实现算法here。
我想保证,如果我调用我的碰撞检测功能collide(Polygon polygon1, Polygon polygon2)
并且它检测到碰撞,则返回的MTV将始终从polygon1指向远,指向< / em> polygon2。为了做到这一点,我需要保证我生成的分离轴(多边形边的法线)始终指向远离生成它们的多边形。 (这样,我知道在将它用作MTV之前否定polygon2中的任何轴)。
不幸的是,似乎我为多边形边缘生成的法线是否指向多边形的内部或外部取决于多边形的点是以顺时针还是逆时针顺序声明。我正在使用描述here的算法生成法线,并假设我为“垂直”方法选择(x, y) => (y, -x)
,如果我迭代顶点,则生成的法线将仅指向多边形顺时针顺序。
鉴于我无法强制客户端以顺时针顺序声明多边形的点(我使用java.awt.Polygon,它只是为x和y坐标公开了两个数组),是否有数学方法保证我生成的法向量的方向是朝向多边形的外部?我不太擅长矢量数学,所以可能有一个明显的解决方案,我错过了。关于SAT的大多数Internet资源只是假设您可以按顺时针顺序迭代多边形的顶点。
答案 0 :(得分:2)
您可以计算每个多边形的方向,例如,使用this问题的答案,然后如果两个多边形的顺序不同,则将法线乘以-1。
您还可以检查传递给算法的每个多边形,看看它是否被错误地排序,再次使用上面的算法,并在必要时反转顶点顺序。
请注意,在计算顶点顺序时,某些算法适用于所有多边形,有些算法适用于凸多边形。
答案 1 :(得分:1)
我终于明白了,但是发布的答案并不是完整的解决方案,所以我不会接受它。我能够使用this SO answer中描述的基本算法确定多边形的排序(在David Norman的链接中也不太清楚地描述),即:
for each edge in polygon:
sum += (x2 - x1) * (y2 + y1)
但是,有一个重要的警告,这些答案都没有提到。通常,如果此总和为正,则可以确定多边形的顶点是顺时针,如果总和为负,则可以确定逆时针。但是在Java的2D图形系统中 比较被反转 ,实际上在许多图形系统中,因为正y轴指向下。所以在普通的数学坐标系中,你可以说
if sum > 0 then polygon is clockwise
但在具有倒y轴的图形坐标系中,它实际上是
if sum < 0 then polygon is clockwise
我的实际代码,使用Java的Polygon,看起来像这样:
//First, find the normals as if the polygon was clockwise
int sum = 0;
for(int i = 0; i < polygon.npoints; i++) {
int nextI = (i + 1 == polygon.npoints ? 0 : i + 1);
sum += (polygon.xpoints[nextI] - polygon.xpoints[i]) *
(polygon.ypoints[nextI] + polygon.ypoints[i]);
}
if(sum > 0) {
//reverse all the normals (multiply them by -1)
}