SAT - finding face directions / normals

Started by
15 comments, last by Haegr 13 years, 1 month ago
I've searched for threads relating to this and currently not find an answer, though that could be due to me not looking hard enough.

I have used the code from http://www.essential...om/tutorial.htm to start my implementation of SAT.

Currently I am trying to find the 3 face directions of each object, as well as the edge directions.

Any help would be much appreciated.
Advertisement
For an OBB, both the face normals and the edges will be parallel to the local axes of the OBB, so if you have the transform for the box (which I assume you do), you have the face normals and edge directions.

There are some additional details related to optimization and robustness, but as for your specific question, the local-space axes of the box transforms are what you're looking for.
The box shares a matrix with the mesh it encapsulates, the vertices themselves are stored in an array of vectors.

I shall take the directions from the matrix and test the code.

A somewhat unrelated question, what would the cross product of the same vector be?

A somewhat unrelated question, what would the cross product of the same vector be?

If you mean AxA, it would be the zero vector. Similarly, AxB where A and B are nearly parallel will result in a vector with very small magnitude. (Dealing with parallel or near-parallel axis pairs has to be handled carefully for this reason.)
I currently have an error where the values of both my boxes are the same for some reason, something I am working through right now and has nothing to do with SAT.

I'd just like to confirm, these values will always be [1, 0, 0] [0, 1, 0] [0, 0, 1] as this is what I am always being presented with.

Editted to add code:


bBox._dir[0] = D3DXVECTOR3( passedMatrix._11, passedMatrix._21, passedMatrix._31 );
bBox._dir[1] = D3DXVECTOR3( passedMatrix._12, passedMatrix._22, passedMatrix._32 );
bBox._dir[2] = D3DXVECTOR3( passedMatrix._13, passedMatrix._23, passedMatrix._33 );


The above code is where I set the direction, where the passedMatrix is the matrix for the object (contains translation, scale and rotation).

I'd just like to confirm, these values will always be [1, 0, 0] [0, 1, 0] [0, 0, 1] as this is what I am always being presented with.

Which values are you referring to? If you're referring to the box axes, then they will only be the cardinal axes (as shown above) if the box transform is identity. In the general case though, the box axes will not be the cardinal axes.
Yes, I was referring to the box axes.

Currently the bounding boxes themselves seem not to be storing the correct data, or are at least over writing it with the incorrect data somewhere. In any case, the axes should not remain cardinal as the boxes themselves do move.

I shall post my functions that handle SAT below, if you have the time give them a quick glance to see if you can spot any obvious errors.


void BoundingBox::getInterval( BoundingBox passedbBox, D3DXVECTOR3 axis, float& min, float& max )
{
min = max = dotProduct( axis, passedbBox._objectBounds[0] );
//Check the number of vertices (constant, always 3)
for( int i = 1; i < 3; i++ )
{
float value = dotProduct( axis, passedbBox._objectBounds );
min = getMin( min, value );
max = getMax( max, value );
}

}

bool BoundingBox::testIntersection( BoundingBox bBoxA, BoundingBox bBoxB)
{
float min1, max1, min2, max2;

//Check face directions from object 1
for( int i = 0; i < 3; i++ )
{
getInterval( bBoxA, bBoxA._dir, min1, max1 );
getInterval( bBoxB, bBoxA._dir, min2, max2 );
if( max1 < min2 || max2 < min1 )
{
return false;
}
}
//Check face directions from object 2
for( int i = 0; i < 3; i++ )
{
getInterval( bBoxA, bBoxB._dir, min1, max1 );
getInterval( bBoxB, bBoxB._dir, min2, max2 );
if( max1 < min2 || max2 < min1 )
{
return false;
}
}
//Edges Directions
for( int i = 0; i < 3; i++ )
{
for( int i = 0; i < 3; i++ )
{
D3DXVECTOR3 axis = crossProduct( bBoxA._dir, bBoxB._dir );

getInterval( bBoxA, axis, min1, max1 );
getInterval( bBoxB, axis, min2, max2 );
if( max1 < min2 || max2 < min1 )
{
return false;
}
}
}

//There is collision
return true;
}
I would start by making sure your input data is correct. If the box orientations are changing but the matrix returned is always identity, that's the first problem you'll want to address.
Alright then. Update on this.

Collision works for both objects but only on the forward face of the bounding box. Collisions with the side faces and back face do nothing.
Bounding box co-ordinates and directions seem to be working.

Code for collisions below:


void BoundingBox::getInterval( BoundingBox passedbBox, D3DXVECTOR3 axis, float& min, float& max )
{
min = max = dotProduct( axis, passedbBox._worldBounds[0] );
//Check the number of vertices (constant, always 3)
for( int i = 1; i < 3; i++ )
{
float value = dotProduct( axis, passedbBox._worldBounds );
min = getMin( min, value );
max = getMax( max, value );
}

}

bool BoundingBox::testIntersection( BoundingBox bBoxA, BoundingBox bBoxB)
{
float min1, max1, min2, max2;

//Check face directions from object 1
for( int i = 0; i < 3; i++ )
{
getInterval( bBoxA, bBoxA._dir, min1, max1 );
getInterval( bBoxB, bBoxA._dir, min2, max2 );
if( max1 < min2 || max2 < min1 )
{
return false;
}
}
//Check face directions from object 2
for( int i = 0; i < 3; i++ )
{
getInterval( bBoxA, bBoxB._dir, min1, max1 );
getInterval( bBoxB, bBoxB._dir, min2, max2 );
if( max1 < min2 || max2 < min1 )
{
return false;
}
}
//Edges Directions
for( int i = 0; i < 3; i++ )
{
for( int i = 0; i < 3; i++ )
{
D3DXVECTOR3 axis = crossProduct( bBoxA._dir, bBoxB._dir );

getInterval( bBoxA, axis, min1, max1 );
getInterval( bBoxB, axis, min2, max2 );
if( max1 < min2 || max2 < min1 )
{
return false;
}
}
}

//There is collision
return true;
}
It doesn't look like you're computing the projected intervals correctly.

What does _worldBounds refer to?

This topic is closed to new replies.

Advertisement