void Physics::IterateCollisions() { for( int I = 0; I < Iterations; I++ ) { //Repeat this a few times to give more exact results //A small 'hack' that keeps the vertices inside the screen. You could of course implement static objects and create //four to serve as screen boundaries, but the max/min method is faster for( int T = 0; T < VertexCount; T++ ) { Vec2& Pos = Vertices[ T ]->Position; Pos.X = MAX( MIN( Pos.X, (float)GWidth ), 0.0f ); Pos.Y = MAX( MIN( Pos.Y, (float)GHeight ), 0.0f ); } UpdateEdges(); //Edge correction step for( int I = 0; I < BodyCount; I++ ) { Bodies[ I ]->CalculateCenter(); //Recalculate the center } for( int B1 = 0; B1 < BodyCount; B1++ ) { //Iterate trough all bodies for( int B2 = 0; B2 < BodyCount; B2++ ) { if( B1 != B2 ) if( BodiesOverlap( Bodies[ B1 ], Bodies[ B2 ] ) ) //Test the bounding boxes if( DetectCollision( Bodies[ B1 ], Bodies[ B2 ] ) ) //If there is a collision, respond to it ProcessCollision(); } } } }
void CW::PhysicsEngine::Iterate(void) { for(int i = 0; i < m_Iterations; ++i) { // Apply edge constraints UpdateEdges(); for (PhysicsBody* b : m_Bodies) { b->CalculateCenter(); } for (PhysicsBody* b1 : m_Bodies) { for(PhysicsBody* b2 : m_Bodies) { if(b1 != b2) { if (BoundingBox::CheckIntersection(&(b1->BoundingBox), &(b2->BoundingBox))) { if (DetectCollision(b1, b2)) { // Process collision info with CollisionInfo data ProcessCollision(); } } } } } } }
//---------------------------------------------------------------------------- void CreateEnvelope::UpdateAllEdges (int numEdges, EdgeMap** edgeMaps) { // Construct the axis-aligned bounding boxes of the edgeMaps. RPoint2* rmin = new1<RPoint2>(numEdges); RPoint2* rmax = new1<RPoint2>(numEdges); int i; for (i = 0; i < numEdges; ++i) { EdgeMap& edgeMap = *edgeMaps[i]; RPoint2& end0 = edgeMap[ZERO]; RPoint2& end1 = edgeMap[ONE]; if (end0.X() <= end1.X()) { rmin[i].X() = end0.X(); rmax[i].X() = end1.X(); } else { rmin[i].X() = end1.X(); rmax[i].X() = end0.X(); } if (end0.Y() <= end1.Y()) { rmin[i].Y() = end0.Y(); rmax[i].Y() = end1.Y(); } else { rmin[i].Y() = end1.Y(); rmax[i].Y() = end0.Y(); } } // Store the x-extremes for the AABBs in a data structure to be sorted. // The "Type" field indicates whether the x-value is the minimum (Type // is 0) or maximum (Type is 1). The "Index" field stores the edge // index for use as a lookup in the overlap tests. int numEndpoints = 2*numEdges; std::vector<Endpoint> xEndpoints(numEndpoints); int j; for (i = 0, j = 0; i < numEdges; ++i) { xEndpoints[j].Type = 0; xEndpoints[j].Value = rmin[i].X(); xEndpoints[j].Index = i; ++j; xEndpoints[j].Type = 1; xEndpoints[j].Value = rmax[i].X(); xEndpoints[j].Index = i; ++j; } // Sort the x-values. std::sort(xEndpoints.begin(), xEndpoints.end()); // The active set of rectangles (stored by index in array). std::set<int> active; // The set of overlapping rectangles (stored by index pairs in array). std::set<std::pair<int,int> > overlap; // Sweep through the endpoints to determine overlapping x-intervals. for (i = 0; i < numEndpoints; ++i) { Endpoint& end = xEndpoints[i]; int index = end.Index; if (end.Type == 0) // an interval 'begin' value { // The current AABB overlaps in the x-direction with all the // active intervals. Now check for y-overlap. std::set<int>::iterator iter = active.begin(); for (/**/; iter != active.end(); ++iter) { // Rectangles iAIndex and index overlap in the x-dimension. // Test for overlap in the y-dimension. int activeIndex = *iter; if (rmax[activeIndex].Y() >= rmin[activeIndex].Y() && rmin[activeIndex].Y() <= rmax[activeIndex].Y()) { // If the edgeMaps share an endpoint, there is no need to // test later for overlap. EdgeMap& edgeMap0 = *edgeMaps[index]; EdgeMap& edgeMap1 = *edgeMaps[activeIndex]; RPoint2& E0P0 = edgeMap0[ZERO]; RPoint2& E0P1 = edgeMap0[ONE]; RPoint2& E1P0 = edgeMap1[ZERO]; RPoint2& E1P1 = edgeMap1[ONE]; if (E0P0 == E1P0 || E0P0 == E1P1 || E0P1 == E1P0 || E0P1 == E1P1) { continue; } overlap.insert(std::make_pair(activeIndex, index)); } } active.insert(index); } else // an interval 'end' value { active.erase(index); } } // Search for edge-edge intersections by comparing only those edgeMaps whose // AABBs overlap. std::set<std::pair<int,int> >::const_iterator iter = overlap.begin(); std::set<std::pair<int,int> >::const_iterator end = overlap.end(); for (/**/; iter != end; ++iter) { int i0 = iter->first; int i1 = iter->second; EdgeMap& edgeMap0 = *edgeMaps[i0]; EdgeMap& edgeMap1 = *edgeMaps[i1]; UpdateEdges(edgeMap0, edgeMap1); } delete1(rmax); delete1(rmin); }