Polyart 2D Physics Engine
Section 3: Collision Detection
An octree set class will be created that stores pointers to multiple octrees. It will have a function
CollideWith(COctreeSet)
Implementation
CBody2D
- Mass information
- Fudge information
- Next collision contact info
- If an earlier collision is found on body A, what happens to body B that A was going to collide with? The contact info remains on that body? But what if the new collision prevented that from happening?
Queues - These will be implemented as a lazy sorted tree
- Detection Queue - Objects on this queue need to be checked for possible collisions. A single pointer to a contact cluster may be sufficient.
- Handling Queue: CCollisionInfo - Each object on this queue has a future collision that needs to be prevented
Sim2D::Step() - Collision handling overview
- Iterate though every possible collision N*(# of close objects) finding times and putting them in the Handling Queue
- Process the first collision on the Handling Queue. Place all objects involved on the Detection Queue.
- Process all objects on the Detection Queue. An object being processed wont check collisions with another object on the queue since that object will eventually check collisions with the current one.
- If any collisions are unhandled, Loop to step 2
Sim2D::DetectCollisions(CBody2D *Body) - Collision detection optimization types - Each object has a way to easily find close objects. Detected collisions get placed on the handling queue.
- Check All: All objects will be checked for a collision
- Octree
Sim2D::ProcessCollision(CCollisionInfo *CI) - Collision response processing procedure
- Each object can only be on the queue once so the queue info is stored on the object.
-
"purly vector based" collision system
No floating point ranges will be used. The collision system should be designed so that floating point round off will not cause collision errors.
Specific Detection Procedure for each object type
- World Octree/World Octree collision results in a call to Body/Body response
- Body/Body: the bounding boxes are colliding so check the body/body resulting in Segment/Segment
- Segment/Segment: changable response apply force
- ---out of place---Primary bounding response: Do a detailed collision between bodies
-
NOTE: If you add all of your objects then check each object with everything on the list, each pair will be checked twice. Use the following procedure to implement it more efficiently
- Call CollideWith on Object N
- Add Object N to the list
- N++
Bounding Box Collisions
Object Type: CBoundingBox
Detection : CBoundingBoxCollider(currently COctree) - Implemented as a quadtree
Response : CBoundingBoxResponse - One bounding box response will be to call the body collision detection function.
CBoundingBoxCollider(Impemented as an Octree)
has a pluggable collision response class whos response function looks like
class CBoundingBoxResponse{
virtual DWORD Response(CBoundingBox *Box1, CBoundingBox *Box2);
};
class CResponse: CBoundingBoxResponse{
public:
virtual DWORD Response(CBoundingBox *Box1, CBoundingBox *Box2);
};
void main(){
CBoundingBox B,A;
CBoundingBoxCollider Collider;
CResponse MyResponse;
Collider.Add(&B);
SetResponse(&MyResponse);
Collider.CollideWith(&B);
//Collider.CollideWith(&B,&MyResponse);//Is this better?
}
Segment Collider - Segment Collisions
These handle the collisions between two sets of linearly moving line segments. It will perform the function of CBody2D::Collide
File : BodyCollider.h
Object Type:
Detection : - Implemented as a quadtree of linearly moving points. Line segments will be stored in a list to check collisions with the points
Response : - Initial response will be to apply a force. Future responses include adding a contact point.
Body Collider - Body Collisions
These handle the collisions between two bodies. Plop a body in there and find the result of its collisions.
It is implemented as two steps. First a bounding box collision is made. A bounding response is created that performs a more detailed collision detection using the segment collision functions. It should actually be very simple to make once the other sets are completed.
File : BodyCollider.h
Object Type: CBody2D
Detection : CBody2DCollider - Implemented as a quadtree of linearly moving points and line segments
Response : CBody2DResponse - Initial response will be to apply a force. Future responses include adding a contact point.
Multi Body Collisions?
Object Type: CBody2DCollider
Detection : CMultiBody2DCollider -
Response : CMultiBody2DResponse -
Collision Response
Types of collision prevention fallbacks (Response types)- When one type fails to prevent interpenetration, the next is used
- Impulse - An impulse will be applied to prevent the segments from interpenetrating. Friction is only applied at this step.
- Relative Freeze A - The velocities at the points of collision in the direction of the normal will be set to the average.
- Relative Freeze B - The velocities at the points of collision will be set to the average.
- Movement Fudge - The velocity will be changed JUST for the current frame making the objects move apart. This is useful if the necessary velocity will launch the object unrealisticly fast. Since it modifies a velocity invisible to the other response types and might cause them to malfunction, only a total freeze should be attempted after this.
- Total Freeze - No movement will take place. Since the objects on this frame are not colliding, preventing movement will ensure this on the next frame.
Alternative fallback - Soft/Solid collision structure
- Due to floating point roundoff it may be impossible to prevent collision with tightly wedged objects.
- Another collision structure just inside of the current structure could be created.
- Any points inside of this structure will always cause a movement fudge.
- This structure should be considered complely solid and no points will ever be permitted to interpenetrate.
Possible collision scenario
- Force is applied and does not prevent interpenetration
- Movement fudge is applied and also fails
- The object is permitted to penetrate the soft structure and use the solid. Movement fudge is applied again.
- At this last attempt the objects linear velocities are set to be the same and the rotational is set to 0.
Objects already penetrating
- These objects will bypass the normal force application and their fudge velocities will be set to move out of each other
CGeometry2D
- StopPoint(V2 P, V2 N, V2 V)- Sets the velocity of a point P to V in the direction of N.
- Project V onto P. Subtract from the linear velocity
- Subtact the linear contribution from the points velocity to find the rotational
- New rotation speed = cross product velocity and P
Resistance at a point is defined as
F/V = Mass for the linear component + 1 / (1/m + R/I) (for the angular component
Suedocode for proper collision routine
- Create octree sets A + B
- Set collision response to time of collision
- A.CollideWith(B) - response function has two bounding boxes one from A and one from B
- Handle first Collision time
- A.CollideWith(BoxFromB);
- B.CollideWith(BoxFromA);
- Update A and B's position in the octrees
- loop to step 4 if more collisions exist
Temporary Collision response
- Create octree sets A + B
- Set collision response to apply collision impulse
- A.CollideWith(B) - response function has two bounding boxes one from A and one from B
- loop to step 3 if a collision happened
Body Set Detection
- Loop through each body set: CurSet
- Loop through each body on the queue for the current set: CurBody
- Loop though each body set that collides with the current set: CurSet2 Collide CurBody with CurSet2
Optimizations
- All nodes can be added to the root of an octree then only if a collision with that box occures does it create the subnodes
- This would be VERY good for optimizting shipgame bullets. The bullets positions could be calculated on demand when the draw screen requests it. The octree does not get created each from but rather gets updated when a bullet moves out of its bounding box. If there is no terrain or other objects the entire tree would be one node with possibly 1000 bullets. The full tree would not be needed.
- If another bounding box completly contains the current one its not subdivided. This is so that drawscreen does not cause a box to split apart? or should the drawscreen keep its own octree for display.
- If a line segment is on part of a convex part of the object and all other line segments are behind it, it obtains a special witness property. When two witnesses fail to collide, they remember that until they collide, the two objects do not collide.
- Line segments do not need to have the full check if both points are moving with exactly the same velocity
Copyright 2004 © Polyart. All rights reserved.
Designed by Kenneth Manta