碰撞解决sphere-aabb和aabb-aabb

我目前正在研究一个不考虑旋转的基本物理引擎。 目前我正在解决aabbs和球体之间的碰撞问题。 不幸的是,我不知道什么是dynamic的aabb和dynamic球体之间的碰撞。 当一个球体从上方从对角线方向击中一个落下的球时,球体会按照球体的飞行方向推向两侧,还是只会进一步向下加速? 而且,当球体有一定的力量时,它不会从球杆反弹,而是推到球面前。 我也不知道该如何处理。

目前,我已经实施了球面碰撞实施,在这里描述: http ://www.gamasutra.com/view/feature/131424/pool_hall_lessons_fast_accurate_.php?page =3

我想我的解决scheme将是类似的,但不关心对象之间的距离。 另外我猜想,aabb-aabb的碰撞解决方法与sphere-aabb是一样的。

有没有人有解决aabb-sphere和aabb-aabb之间的碰撞的想法或经验?

Solutions Collecting From Web of "碰撞解决sphere-aabb和aabb-aabb"

这是如何解决两个AABB之间的碰撞(非连续的)。 我已经仔细评论过,所以可以更好地理解。

private static bool TestStaticAABBAABB(Shape s1, Shape s2, ref Contact contact) { AABB a = s1 as AABB; AABB b = s2 as AABB; // [Minimum Translation Vector] float mtvDistance = float.MaxValue; // Set current minimum distance (max float value so next value is always less) Vector3 mtvAxis = new Vector3(); // Axis along which to travel with the minimum distance // [Axes of potential separation] // • Each shape must be projected on these axes to test for intersection: // // (1, 0, 0) A0 (= B0) [X Axis] // (0, 1, 0) A1 (= B1) [Y Axis] // (0, 0, 1) A1 (= B2) [Z Axis] // [X Axis] if (!TestAxisStatic(Vector3.UnitX, a.MinPoint.X, a.MaxPoint.X, b.MinPoint.X, b.MaxPoint.X, ref mtvAxis, ref mtvDistance)) { return false; } // [Y Axis] if (!TestAxisStatic(Vector3.UnitY, a.MinPoint.Y, a.MaxPoint.Y, b.MinPoint.Y, b.MaxPoint.Y, ref mtvAxis, ref mtvDistance)) { return false; } // [Z Axis] if (!TestAxisStatic(Vector3.UnitZ, a.MinPoint.Z, a.MaxPoint.Z, b.MinPoint.Z, b.MaxPoint.Z, ref mtvAxis, ref mtvDistance)) { return false; } contact.isIntersecting = true; // Calculate Minimum Translation Vector (MTV) [normal * penetration] contact.nEnter = Vector3.Normalize(mtvAxis); // Multiply the penetration depth by itself plus a small increment // When the penetration is resolved using the MTV, it will no longer intersect contact.penetration = (float)Math.Sqrt(mtvDistance) * 1.001f; return true; } private static bool TestAxisStatic(Vector3 axis, float minA, float maxA, float minB, float maxB, ref Vector3 mtvAxis, ref float mtvDistance) { // [Separating Axis Theorem] // • Two convex shapes only overlap if they overlap on all axes of separation // • In order to create accurate responses we need to find the collision vector (Minimum Translation Vector) // • Find if the two boxes intersect along a single axis // • Compute the intersection interval for that axis // • Keep the smallest intersection/penetration value float axisLengthSquared = Vector3.Dot(axis, axis); // If the axis is degenerate then ignore if (axisLengthSquared < 1.0e-8f) { return true; } // Calculate the two possible overlap ranges // Either we overlap on the left or the right sides float d0 = (maxB - minA); // 'Left' side float d1 = (maxA - minB); // 'Right' side // Intervals do not overlap, so no intersection if (d0 <= 0.0f || d1 <= 0.0f) { return false; } // Find out if we overlap on the 'right' or 'left' of the object. float overlap = (d0 < d1) ? d0 : -d1; // The mtd vector for that axis Vector3 sep = axis * (overlap / axisLengthSquared); // The mtd vector length squared float sepLengthSquared = Vector3.Dot(sep, sep); // If that vector is smaller than our computed Minimum Translation Distance use that vector as our current MTV distance if (sepLengthSquared < mtvDistance) { mtvDistance = sepLengthSquared; mtvAxis = sep; } return true; } 

那就是解决方法

AABB.Position += contact.normal * contact.penetration;

编辑:

  float ma = a.InverseMass; float mb = b.InverseMass; // (1/Ma + 1/Mb) float m = ma + mb; // Position resolution a.Position += contact.nEnter * contact.penetration * (ma / m); b.Position += -contact.nEnter * contact.penetration * (mb / m); 

AABB-AABB碰撞非常简单:对于每个轴,你必须检查一个AABB的最小边界是否大于另一个的最大边界。 如果是这样,则不可能发生碰撞(即,如果aabb1.x1> aabb2.x2,则aabb1的左侧位于aabb2的右侧右侧,因此不会发生碰撞)。 你检查 :

  • aabb1.x1> aabb2.x2
  • aabb2.x1> aabb1.x2
  • aabb1.y1> aabb2.y2
  • aabb2.y1> aabb1.y2
  • aabb1.z1> aabb2.z2
  • aabb2.z1> aabb1.z2

如果其中任何一个返回true,则不会发生碰撞。 如果一切都是错误的,就会发生碰撞。

AABB球面碰撞是不同的。 对于每个轴,您将search球体中心与AABB之间的距离。 对于X轴,例如,首先检查aabb.x1 <= center.x <= aabb.x2。 如果是这样,你的距离是0.否则,你的距离是Min(Abs(aabb.x1 – center.x),Abs(aabb.x2 – center.x))。

那么,如果dx,dy和dz是你的距离,你只要检查dx²+dy²+dz²<=sphereRadius²。 如果是这样,你有一个碰撞。

我想我终于find了答案:我采取了与gamasutra中所述的相同的公式,但我不使用centerdiff作为碰撞正常。 相反,我采取相互碰撞的表面的相关法线。 例如:假设速度为[1/1/0]的aabb1和速度为[-1/1/0]的aabb2。 我们也可以说他们会在对方身上打对方。 这将导致其他aabb的碰撞正常[1/0/0]或[-1/0/0]。

相应的代码是:

 if (aabb1Max.y > aabb2Max.y && aabb1->velocity().y < 0) { // collision top contactNormal.set(0, 1, 0); } else if (aabb1Min.y < aabb2Min.y && aabb1->velocity().y > 0) { // collision bottom contactNormal.set(0, -1, 0); } // etc. for the other dimensions SLVec3f vel1 = aabb1->velocity(); SLVec3f vel2 = aabb2->velocity(); SLfloat m1 = aabb1->mass(); SLfloat m2 = aabb2->mass(); SLfloat optimizedP = (2.0 * (vel1.dot(contactNormal) - vel2.dot(contactNormal))) / (m1 + m2); SLVec3f v1_ = vel1 - optimizedP * m2 * contactNormal; SLVec3f v2_ = vel2 + optimizedP * m1 * contactNormal; aabb1->velocity(v1_); aabb2->velocity(v2_); 

我还没有find一种方法来certificate这是正确的。