分离轴定理问题
本文关键字:问题 定理 分离 | 更新日期: 2023-09-27 17:51:14
我目前正在尝试为轴对齐和定向的边界框添加重叠测试器,但解决方案似乎只有当OBB的角度在-10和+10之间时才能准确工作。当角度接近+90度时,碰撞区域似乎首先移动到OBB的右半部分,然后变得不存在。在90和270之间,我无法得到重叠,然后当它到达完整的360时,区域再次准确地寄存器。
在这个问题上有任何启示就太好了。我使用正X来增加0度的CCW。
欢呼。
编辑:我做了更多的研究,意识到将一个向量投影到另一个向量上需要的不仅仅是点积。谁能给我一个正确的检查轴方法的一个版本,非常非常,请:)
编辑2:实际上我认为应该只是一个点积,因为被投影到的向量是单位长度的。
public static bool overlapAABB_OBB(AABB a, OBB o)
{
float rads = MathHelper.ToRadians(-o.angle);
T = Vector2.Subtract(o.position, a.position);
Ax.X = 1;
Ax.Y = 0;
Ay.X = 0;
Ay.Y = 1;
Ox.X = (float)Math.Cos(rads);
Ox.Y = (float)Math.Sin(rads);
Oy.X = -Ox.Y;
Oy.Y = Ox.X;
if (checkAX(a, o) &&
checkAY(a, o) &&
checkOX(a, o) &&
checkOY(a, o))
return true;
else
return false;
}
private static bool checkAX(AABB a, OBB o)
{
float TAx = Vector2.Dot(T, Ax);
float WoOxAx = Vector2.Dot(Vector2.Multiply(Ox, o.halfWidth), Ax);
float HoOyAx = Vector2.Dot(Vector2.Multiply(Oy, o.halfHeight), Ax);
if (TAx > a.halfWidth + WoOxAx + HoOyAx)
return false;
else
return true;
}
private static bool checkAY(AABB a, OBB o)
{
float TAy = Vector2.Dot(T, Ay);
float WoOxAy = Vector2.Dot(Vector2.Multiply(Ox, o.halfWidth), Ay);
float HoOyAy = Vector2.Dot(Vector2.Multiply(Oy, o.halfHeight), Ay);
if (TAy > a.halfHeight + WoOxAy + HoOyAy)
return false;
else
return true;
}
private static bool checkOX(AABB a, OBB o)
{
float TOx = Vector2.Dot(T, Ox);
float WaAxOx = Vector2.Dot(Vector2.Multiply(Ax, a.halfWidth), Ox);
float HaAyOx = Vector2.Dot(Vector2.Multiply(Ay, a.halfHeight), Ox);
if (TOx > o.halfHeight + WaAxOx + HaAyOx)
return false;
else
return true;
}
private static bool checkOY(AABB a, OBB o)
{
float TOy = Vector2.Dot(T, Oy);
float WaAxOy = Vector2.Dot(Vector2.Multiply(Ax, a.halfWidth), Oy);
float HaAyOy = Vector2.Dot(Vector2.Multiply(Ay, a.halfHeight), Oy);
if (TOy > o.halfHeight + WaAxOy + HaAyOy)
return false;
else
return true;
}
我在GameDev上发布了这个问题。从rraallvv那里收到了这个答案,这个答案已经修复了这个问题。
当两个向量之间的夹角大于90º时,
点积为负,为了使代码正常工作,您需要取点积的绝对值。
//...
private static bool checkAX(AABB a, OBB o)
{
float TAx = Math.Abs( Vector2.Dot(T, Ax) );
float WoOxAx = Math.Abs( Vector2.Dot(Vector2.Multiply(Ox, o.halfWidth), Ax) );
float HoOyAx = Math.Abs( Vector2.Dot(Vector2.Multiply(Oy, o.halfHeight), Ax) );
if (TAx > a.halfWidth + WoOxAx + HoOyAx)
return false;
else
return true;
}
//...
这也适用于checkAY
, checkOX
和checkOY
除了Mazk1985提供的修复之外,checkOX()函数中还有一个错字。. halfheight应该是。halfwidth,如下所示:
private static bool checkOX(AABB a, OBB o)
{
float TOx = Vector2.Dot(T, Ox);
float WaAxOx = Vector2.Dot(Vector2.Multiply(Ax, a.halfWidth), Ox);
float HaAyOx = Vector2.Dot(Vector2.Multiply(Ay, a.halfHeight), Ox);
if (TOx > o.halfWidth + WaAxOx + HaAyOx)
return false;
else
return true;
}