Separating axis theorem 3D - polygons

Started by
17 comments, last by Dirk Gregorius 4 years, 2 months ago

I have been working on a collision engine in Java, utilizing the Separating Axis Theorem in 3D space. I have it working successfully in all cases (that I could think of testing) with object-oriented bounding boxes, but I'm finding that SAT isn't super accurate at detecting collisions as immediately with other convex 3D polygons. Corners of rotated polygons may overlap a small amount before any valid collision is found, and the subsequent clipping algorithm I use to calculate contact points will fail. I'll highlight the main points on my current SAT implementation below, and I'd just like to get some feedback to see if I was on the right track with this or if I'm fundamentally missing something in the theory. Trying to refrain from pasting code since its moderately long.

Do note that I am using object models imported from Blender in wavefront.obj files, so I'm using the vertex normals in these files to populate my collision bodies in simulation. I'm not sure if that could cause issues with ordering or normal calculations.

 

Input two collision bodies (BodyA, BodyB)

 

Calculate distance between the centers of bodyB and bodyA (the offset)

 

for each face normal (axis) in bodyA:

- Project the vertices of both bodyA and bodyB along this axis to get the 2D minimum and maximum projections along that direction

- add offset to projection of bodyA

- check for overlap along the projections of both bodies, exit the separating axis test if their is no overlap along this projection as this is a separation. Otherwise continue the loop.

 

for each face normal (axis) in bodyB:

- Project the vertices of both bodyA and bodyB along this axis to get the 2D minimum and maximum projections along that direction

- add offset to projection of bodyA

- check for overlap along the projections of both bodies, exit the separating axis test if their is no overlap along this projection as this is a separation. Otherwise continue the loop.

 

for each face normal in bodyA (axisA):

- for each face normal in bodyB (axisB):

- - get the cross product of axisA and axisB (axis)

- - Project the vertices of both bodyA and bodyB along this axis to get the 2D minimum and maximum projections along that direction

- - add offset to projection of bodyA

- - check for overlap along the projections of both bodies, exit the separating axis test if their is no overlap along this projection as this is a separation. Otherwise continue the loop.

 

 

Most SAT resources I have read seem to be concerned with AABB or OBB collision and don't care for more complex polygon shapes so any resources you might know of that deal with a more general 3D SAT implementation would be a great help.

Thanks.

 

Advertisement

I gave a talk a couple of years ago which might be helpful:

http://media.steampowered.com/apps/valve/2013/DGregorius_GDC2013.zip

Been taking a look at your slides, great stuff. I'm not done altering my implementation but swapping from min/max projections to separating planes seems to already be working better in the face cases after some preliminary testing.

 

Thanks Dirk, you've really set me on the right track with this. I was quite stuck

I am glad I could help. If you have questions just ask them here.

Hi there,

Great tutorial!
Could someone clarify the two-level ‘for’ loop with cross product?
For instance if bodyA and bodyB have the same shape and they slightly shifted.
In this case both bodies will have same normals and the cross product of the two equal vectors(normals) will be 0. My assumption is one should skip such axes combinations.
Is this the case?

Correct! Two parallel edges don't build a face on the Minkowski sum. Note that there are no cross products between normals, only between edges.

Dirk Gregorius said:

Correct! Two parallel edges don't build a face on the Minkowski sum. Note that there are no cross products between normals, only between edges.

Hm, looks like initial algirithm not quite correct as iterating over normals will produce completely different set of separating axes.

The separating axes are:

  1. The face normals on A
  2. The face normals on B
  3. The cross products between edges from A and B

The algorithm in the presentation is indeed correct! I recommend reading the presentation a couple of times until you understand this…

By initial algorithm I mean the one from initial message(from @Deku).He clearly suggests to iterate through the face normals

I see. Sorry, this thread is quite old and didn't see this. I recommend reading through my original presentation and the references I give there. In case you don't have it can be found here:

http://media.steampowered.com/apps/valve/2013/DGregorius_GDC2013.zip

I think it also comes with some source samples.

This topic is closed to new replies.

Advertisement