• Advertisement
Sign in to follow this  

OOBB Creation/Intersection

This topic is 3575 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been trying to read about object oriented bounding boxes and I honestly can not find much on them. Can anyone show me or point me to a place where I can learn how to create and test oobb intersections?

Share this post

Link to post
Share on other sites
The reason you're having trouble finding references may be that you're using the wrong search term (the more frequently used term is 'OBB', or 'oriented bounding box').

There are many references on the topic available online - just try searching for 'OBB' (plus whatever other topics you're interested in, e.g. 'intersection') and you should get plenty of hits.

Share this post

Link to post
Share on other sites
I have been working on this and can not figure out why my rotation is not working. The box rotates just fine, however, the translation is wrong. I am using a Vector class and am switching it over a D3DXVECTOR3. I declare a min/max/objectbounds[8] in my header file. I create my obb like so

void COBB::SetupCollisionBox(float fX, float fY, float fZ, float fWidth, float fHeight, float fDepth)
m_Min = Vector3D(fX, fY, fZ);
m_Max = Vector3D(fX + fWidth, fY + fHeight, fZ + fDepth);

m_vObjectBounds[0] = Vector(m_Min.GetX(), m_Min.GetY(), m_Min.GetZ());
m_vObjectBounds[1] = Vector(m_Max.GetX(), m_Min.GetY(), m_Min.GetZ());
m_vObjectBounds[2] = Vector(m_Min.GetX(), m_Max.GetY(), m_Min.GetZ());
m_vObjectBounds[3] = Vector(m_Max.GetX(), m_Max.GetY(), m_Min.GetZ());
m_vObjectBounds[4] = Vector(m_Min.GetX(), m_Min.GetY(), m_Max.GetZ());
m_vObjectBounds[5] = Vector(m_Max.GetX(), m_Min.GetY(), m_Max.GetZ());
m_vObjectBounds[6] = Vector(m_Min.GetX(), m_Max.GetY(), m_Max.GetZ());
m_vObjectBounds[7] = Vector(m_Max.GetX(), m_Max.GetY(), m_Max.GetZ());

Here is how I do my rotation. Only the translation seems to be off, however, I can not figure out why.

// Convert to D3DXVECTOR3
D3DXVECTOR3 vInput[8];
D3DXVECTOR3 vOutput[8];

for(int i = 0; i < 8; ++i)
vInput = D3DXVECTOR3(m_vObjectBounds.GetX(), m_vObjectBounds.GetY(), m_vObjectBounds.GetZ());

// Rotate the vInput based off the matrix and store in vOutput
for(int i = 0; i < 8; ++i)
D3DXVec3TransformCoord(&vOutput, &vInput, &rotation);

// Covert to Vector
for(int i = 0; i < 8; ++i)
m_vObjectBounds = Vector(vOutput.x, vOutput.y, vOutput.z);

// Find the new min/max
D3DXVECTOR3 min = vOutput[0];
D3DXVECTOR3 max = vOutput[0];

for(int i = 0; i < 8; ++i)
if(vOutput.x < min.x)
min.x = vOutput.x;
else if(vOutput.x > max.x)
max.x = vOutput.x;

if(vOutput.y < min.y)
min.y = vOutput.y;
else if(vOutput.y > max.y)
max.y = vOutput.y;

if(vOutput.z < min.z)
min.z = vOutput.z;
else if(vOutput.z > max.z)
max.z = vOutput.z;


// Recreate Min/Max
m_Min = Vector(min.x, min.y, min.z);
m_Max = Vector(max.x, max.y, max.z);

I can tell that it is off on the translation by a visual representation (that I almost think is perfectly correct, however, with out collision testing I could be wrong).

Which leads me to my last question, I can not tell how to test two OBB's colliding with each other using this method. Does anyone know how I can tell if the are?

Share this post

Link to post
Share on other sites
where is the translation performed? I can only see rotation.

Are you sure your rotation is corect? Your box will rotate around the origin, not the centre of the box.

Share this post

Link to post
Share on other sites
I had this problem too, with little help from anybody in this forum. The secret is finding other OBB's position in this OBB's local space by projecting other OBB's center point first into this OBB's X axis, then onto this OBB's Y axis.

In other words, expressing center point of 2nd OBB in the local coordinate system of 1st OBB (here I call 1st OBB "this OBB" and 2nd OBB "other OBB").

Calculating other OBB's new center point using this OBB as frame of reference:

OtherOBBDistanceVector = OtherOBBPosition - ThisOBBPosition

OtherOBBLocalPosition.X = OtherOBBDistanceVector Dot ThisOBBXAxis
OtherOBBLocalPosition.Y = OtherOBBDistanceVector Dot ThisOBBYAxis

Calculating other OBB's new axes using this OBB as a frame of reference:

OtherOBBLocalXAxis.X = ThisOBBXAxis Dot OtherOBBXAxis
OtherOBBLocalXAxis.Y = ThisOBBYAxis Dot OtherOBBXAxis

OtherOBBLocalYAxis.X = -OtherOBBLocalXAxis.Y
OtherOBBLocalYAxis.Y = OtherOBBLocalXAxis.X

We only need to calculate one of the axis, second axis is just perpendicular. Also note that I am implementing this test in 2D, but as far as transforming into local space goes, it's the same for the Z axis.

Here's a complete C# program I wrote to test all of the above concepts:

Also note that when you cross 1st OBB's edges with 2nd OBB's edges to find more potential separating axes (applicable only to a 3D test which I don't do), sometimes the result is a near null vector when the edges are near parallel. The errors in precision cause this. To prevent your collision from being detected incorrectly, you should add in a small epsilon value, which will cause the test to be conservative for parallel edges and will disappear for other cases.

Share this post

Link to post
Share on other sites
Original post by oliii
where is the translation performed? I can only see rotation.

Are you sure your rotation is corect? Your box will rotate around the origin, not the centre of the box.

I never preform a transform. The way I tested this is because I set the position to 0, 0, 0 and it rotated just fine. However, when I moved the position to something else, the collision was was not where it was suppose to be. The origin/position is typically min, which is the (left, bottom, front).

Share this post

Link to post
Share on other sites
it's gonna rotate fine if you have no translation.

I seem to have replied to that problem a week ago :/

basically, it all depends where your centre of rotation is.

Vector cor = min; // min as the centre of rotation.
Vector corners[8];
Vector obb[8];

// the 8 corners of the aabb
corners[0] = vector(min.x, min.y, min.z);
corners[1] = vector(max.x, min.y, min.z);
corners[2] = vector(max.x, max.y, min.z);
corners[3] = vector(min.x, max.y, min.z);
corners[4] = vector(min.x, min.y, max.z);
corners[5] = vector(max.x, min.y, max.z);
corners[6] = vector(max.x, max.y, max.z);
corners[7] = vector(min.x, max.y, max.z);

// tansform into an obb.
for(int i = 0; i < 8; i ++)
obb = cor + (corners - cor) * orientation;

// the aabb of the obb
vector aabbmin = obb[0];
vector aabbmax = obb[0];
for(int i = 1; i < 8; i ++)
if(obb.x < aabbmin.x)
aabbmin.x = obb.x;
else if(obb.x > aabbmax.x)
aabbmax.x = obb.x;

if(obb.y < aabbmin.y)
aabbmin.x = obb.y;
else if(obb.y > aabbmax.y)
aabbmax.y = obb.y;

if(obb.z < aabbmin.z)
aabbmin.z = obb.z;
else if(obb.z > aabbmax.z)
aabbmax.z = obb.z;

Share this post

Link to post
Share on other sites
Ah, I had no idea it was basically the way you do an AABB Rotation but saving the objectbounds. I thought it was more complicated based off of the way I was reading the collision. It seems like every time I read about OBB collision that I see them using "extents". Is this necessary?

Share this post

Link to post
Share on other sites
depends what you need them for. as far as I'm concerned, an obb is better described as a centre position, three directional vector (or a orthonormal matrix, same thing), and extents (or the half-size of the box) along those three vectors. That works great for collision detection.

However, the mental leap of using the 8 corners and building an AABB around them is easier than using the gemetrical properties of an obb.

for example, if you describe an obb as [centre, dir[3], halfsize[3]], then the AABB would be :

float rx = fabs(dir[0].x * halfsize[0]) + fabs(dir[1].x * halfsize[1]) + fabs(dir[2].x * halfsize[2]);
float ry = fabs(dir[0].y * halfsize[0]) + fabs(dir[1].y * halfsize[1]) + fabs(dir[2].y * halfsize[2]);
float rz = fabs(dir[0].z * halfsize[0]) + fabs(dir[1].z * halfsize[1]) + fabs(dir[2].z * halfsize[2]);

min = centre - vector(rx, ry, rz);
max = centre + vector(rx, ry, rz);

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement