Collision detection on GPU.
Posted: Wed Sep 27, 2006 10:54 pm
(The GPU physics thread was getting kinda long...)
I have a good way to do collisions worked out - it's not easy to understand - but it's going to work and it'll be fairly efficient. The idea is to go N-times around the 'main loop' where 'N' is the maximum number of collisions that any object undergoes. The inner loop feeds one polygon to the hardware for every object on the first main loop iteration once more for every object that collides two or more times, again for every object that collides three times or more...and so on.
So in a brick wall case where every brick touches six others, every brick goes around the innermost loop six times. That's probably close to a worst case though.
The result is N textures - each location of which is either a collision pair or a zero. These textures are going to be pretty sparse - mostly zeroes.
My question is whether I can resolve each collision-pair in isolation - turning it into resultant forces then summing the forces from all of the collisions at the end?
Here is the collision algorithm:
(Every object has a unique ID which maps to a location in a texture map and is representable as a small integer - there is no object with an ID of zero).
------------------------------------------------------------------------------------------------------
Initialisation
1. Prepare one 'probe' polygon for every object in the scene in object ID order.
2. Mark all probe polygons as 'needed'.
3. Prepare a collision map - one location in the collision map for every object in the scene. Call this the 'source collision map' (SCM)
4. Fill the SCM entries with a number that's higher than the highest object ID.
Main loop
1. Set up an empty 'destination' collision map (DCM) to render into as an FBO.
2. Clear DCM to all zeroes using glClear.
3. Send the SCM to the frag shader as an input parameter.
4. Send all probe polygons that are marked as 'needed' down the pipe in low-to-high numbered order.
5. For each polygon - ideally, fetch the 'position', 'size', 'velocity' and any other data for this object it represents from vertex textures and pass them down to the fragment shader - but remembering that we can only have four per-vertex textures in nVidia-land and none at all elsewhere, some or all of these parameters may have to come from the CPU in vertex data or in VBO's.
6. At each fragment:
* If the probe polygon identifier is greater than or equal to the SCM at this pixel 'discard' this fragment.
* If the probe polygons identifier is equal to the identifier of the object at this pixel 'discard' this fragment.
* If the probe polygon's object doesn't collide with the object at this pixel 'discard' this fragment.
* If we get this far, write the polygons object identifier to the DCM.
7. Using the occlusion query feature, mark the probe polygons that caused DCM writes (which represent newly recorded collisions) as 'needed' and those that did not as not-needed.
8. If all are marked as not-needed then you have accumulated all of the forces and you can END.
9. After all probe polygons have been sent once, run the collision physics on the DCM, accumulating forces as we go.
10. Swap the DCM and SCM and go around again.
I have a good way to do collisions worked out - it's not easy to understand - but it's going to work and it'll be fairly efficient. The idea is to go N-times around the 'main loop' where 'N' is the maximum number of collisions that any object undergoes. The inner loop feeds one polygon to the hardware for every object on the first main loop iteration once more for every object that collides two or more times, again for every object that collides three times or more...and so on.
So in a brick wall case where every brick touches six others, every brick goes around the innermost loop six times. That's probably close to a worst case though.
The result is N textures - each location of which is either a collision pair or a zero. These textures are going to be pretty sparse - mostly zeroes.
My question is whether I can resolve each collision-pair in isolation - turning it into resultant forces then summing the forces from all of the collisions at the end?
Here is the collision algorithm:
(Every object has a unique ID which maps to a location in a texture map and is representable as a small integer - there is no object with an ID of zero).
------------------------------------------------------------------------------------------------------
Initialisation
1. Prepare one 'probe' polygon for every object in the scene in object ID order.
2. Mark all probe polygons as 'needed'.
3. Prepare a collision map - one location in the collision map for every object in the scene. Call this the 'source collision map' (SCM)
4. Fill the SCM entries with a number that's higher than the highest object ID.
Main loop
1. Set up an empty 'destination' collision map (DCM) to render into as an FBO.
2. Clear DCM to all zeroes using glClear.
3. Send the SCM to the frag shader as an input parameter.
4. Send all probe polygons that are marked as 'needed' down the pipe in low-to-high numbered order.
5. For each polygon - ideally, fetch the 'position', 'size', 'velocity' and any other data for this object it represents from vertex textures and pass them down to the fragment shader - but remembering that we can only have four per-vertex textures in nVidia-land and none at all elsewhere, some or all of these parameters may have to come from the CPU in vertex data or in VBO's.
6. At each fragment:
* If the probe polygon identifier is greater than or equal to the SCM at this pixel 'discard' this fragment.
* If the probe polygons identifier is equal to the identifier of the object at this pixel 'discard' this fragment.
* If the probe polygon's object doesn't collide with the object at this pixel 'discard' this fragment.
* If we get this far, write the polygons object identifier to the DCM.
7. Using the occlusion query feature, mark the probe polygons that caused DCM writes (which represent newly recorded collisions) as 'needed' and those that did not as not-needed.
8. If all are marked as not-needed then you have accumulated all of the forces and you can END.
9. After all probe polygons have been sent once, run the collision physics on the DCM, accumulating forces as we go.
10. Swap the DCM and SCM and go around again.