假设您有两个边界框对象,每个边界框对象都将框的当前顶点存储在矢量中,并且该对象的所有顶点都相对于公共轴旋转和平移。
这是一张图像来说明我的问题:
如果两个OBB重叠任何链接以帮助解释该问题的解决方案,我将如何解决?请不要太费解了...
假设您有两个边界框对象,每个边界框对象都将框的当前顶点存储在矢量中,并且该对象的所有顶点都相对于公共轴旋转和平移。
这是一张图像来说明我的问题:
如果两个OBB重叠任何链接以帮助解释该问题的解决方案,我将如何解决?请不要太费解了...
Answers:
OBB是凸包。凸包是3D形状,在其表面上没有“碎屑”。凸包上的每个“凸点”(顶点)都向外突出,从不向内突出。如果通过凸包对平面进行切片,则将获得(只有一个)凸多边形。如果您在凸形船体内部并向外部发射激光,则只能穿透船体表面一次(永远不会两次)。
分离轴定理测试可用于检测凸包的碰撞。SAT测试很简单。它适用于2D和3D。尽管下面的图片为2D,但它们也可以轻松应用于3D。
这是您在SAT中使用的关键概念:
形状在1D向量上的“投影”看起来像这样(我称之为“挤压”)
具有红色顶点和轴的形状
“将形状投影到轴上”是指从形状上的每个点垂直放置一个垂线以使其刚好落在轴上。您可以认为这是用一只手“压碎”了点,将所有东西收集起来并垂直将其压碎到轴。
剩下的是:轴上的点
要使2个凸包相交,它们必须在每个轴上重叠(其中,必须检查任一形状上的每个法线都作为一个轴)。
采取以下两种形状:
您会看到它们没有相交,因此让我们尝试几个轴以显示没有发生重叠。
尝试五边形的最高法线:
这些是范围。它们确实重叠。
尝试矩形的左侧。现在它们在该轴上不重叠,因此没有相交。
对于两种形状上的每个面法线:
就是这样。使SAT工作的代码非常简短。
这是一些代码,演示如何进行SAT轴投影:
void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
minAlong=HUGE, maxAlong=-HUGE;
for( int i = 0 ; i < ptSet.size() ; i++ )
{
// just dot it to get the min/max along this axis.
float dotVal = ptSet[i].dot( axis ) ;
if( dotVal < minAlong ) minAlong=dotVal;
if( dotVal > maxAlong ) maxAlong=dotVal;
}
}
调用代码:
// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
// Get the normals for one of the shapes,
for( int i = 0 ; i < shape1.normals.size() ; i++ )
{
float shape1Min, shape1Max, shape2Min, shape2Max ;
SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
{
return 0 ; // NO INTERSECTION
}
// otherwise, go on with the next test
}
// TEST SHAPE2.normals as well
// if overlap occurred in ALL AXES, then they do intersect
return 1 ;
}
bool overlaps( float min1, float max1, float min2, float max2 )
{
return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}
inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
return lowerBound <= val && val <= upperBound ;
}
更多SAT文章。
该网站上的最后一篇文章带有完整的代码,我认为它是在FLASH中,我不知道,但是当我第一次使用SAT时,将它转换为C ++时我遇到了0个问题,应该不难其他语言也一样。您唯一需要添加的就是在每次计算中存储位移向量(如果是最小的话,当然,当您了解SAT时您会明白这一点),本教程中的代码不会这样做,因此您最终得到的是最后计算出的向量。
http://rocketmandevelopment.com/tag/separation-axis-theorem/
不错的旧版N-Game教程。网络上最好的SAT理论。