I stumbled across this implementation for a projection intersection test to use in a SAT test:

// aCorn and bCorn are arrays containing all corners (vertices) of the two OBBs
private static bool IntersectsWhenProjected( Vector3[] aCorn, Vector3[] bCorn, Vector3 axis ) {

    // Handles the cross product = {0,0,0} case
    if( axis == Vector3.zero ) 
        return true;

    float aMin = float.MaxValue;
    float aMax = float.MinValue;
    float bMin = float.MaxValue;
    float bMax = float.MinValue;

    // Define two intervals, a and b. Calculate their min and max values
    for( int i = 0; i < 8; i++ ) {
        float aDist = Vector3.Dot( aCorn[i], axis );
        aMin = ( aDist < aMin ) ? aDist : aMin;
        aMax = ( aDist > aMax ) ? aDist : aMax;
        float bDist = Vector3.Dot( bCorn[i], axis );
        bMin = ( bDist < bMin ) ? bDist : bMin;
        bMax = ( bDist > bMax ) ? bDist : bMax;

    // One-dimensional intersection test between a and b
    float longSpan = Mathf.Max( aMax, bMax ) - Mathf.Min( aMin, bMin );
    float sumSpan = aMax - aMin + bMax - bMin;
    return longSpan < sumSpan; // Change this to <= if you want the case were they are touching but not overlapping, to count as an intersection

I now don't really get why there is a check for the zero vector, i.e. these lines right here:

if( axis == Vector3.zero ) 
    return true;

Why can we immediately say that the projections intersect, when there is a zero vector as projection axis?

The code is from Acegikmo answer on this question right here: How many and which axes to use for 3D OBB collision with SAT

He just states, that:

The cross product will give you a zero vector {0,0,0} when any two axes between the objects point in the same direction.

Can anyone clarify this?

  • \$\begingroup\$ That code is wrong. Assuming that an intersection is true on a zero vector is flawed reasoning. Instead, the 'if( axis == Vector3.zero ) return true;' code should be moved outside the function to wherever the axes are generated via cross product. If the result is a zero vector then all it means is that the two vectors point in the same direction, so use either of them for your test. \$\endgroup\$
    – Ian Young
    May 12 '17 at 14:28
  • \$\begingroup\$ Well, the code you see here was used in a SAT test, so that's not really an issue I think, since you're running this function 15 times for all possible cross products \$\endgroup\$ May 18 '17 at 12:00

I did some reading on this, and in the book Game Physics Pearls, the following is stated:

Edge-Edge (EE) is a degenerate case if the edges are parallel. Degenerate EE is the special case of either Edge-Vertex (EV) or Vertex-Edge (VE), which in turn may be a case of Vertex-Vertex(VV).

We can just skip and ignore all special cases for the purposes of obtaining (smin, dmin)

In plain English, this means that if you produce a zero vector from the cross product, there is no point testing that vector, and should skip it. This makes sense, as attempting to obtain penetration depth would produce a spurious minimum penetration axis.

However, I still feel the code is incorrect, as there is no guarantee that the cross products will produce a "zero" vector, in the truest sense. the glm maths library, for example, will produce undefined results if two parallel vectors are crossed.

A better solution would be to zero test the vector outside that function, and also test it for being undefined. if either test is true, don't even call the function, and skip to the next axis to be tested.


Why can we immediately say that the projections intersect, when there is a zero vector as projection axis?

Intuitively, the zero vector has no direction, and so can't be used to determine a line on which to project your vertices. The zero vector in this case could be thought of as a single point, and obviously the projection of anything on to that single point will only ever be that point, so all vertices projected on to that point can be said to yield segments that intersect.

As far as how the zero vector would get passed to this function in the first place; the cross product of parallel vectors is zero. So, assuming you understand how to obtain the list of possible separating axes by finding every possible cross product between the object's edges, if any particular axis was obtained from the cross product of two edges that happen to be parallel (one edge from object A and one edge from object B,) it will be the zero vector.

  • \$\begingroup\$ Maybe I am just misunderstanding you, but it seems that you just say why the zero vector is not suitable to project to, but not why we can exclude this projection from consideration? \$\endgroup\$ Mar 23 '16 at 19:38
  • \$\begingroup\$ @ChristianDreher You cannot. a zero vector is the result of the cross between two identical vectors, so instead of using the cross product, use any one of the identical vectors. problem solved. \$\endgroup\$
    – Ian Young
    May 12 '17 at 14:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.