X-Git-Url: http://gitweb.pgornicz.com/gitweb.cgi?a=blobdiff_plain;f=src%2FcollisionManager.cpp;h=1076ccc971f34b3878343b337490f86fffd55a17;hb=f32a9b7c8eab3536ad354f85ee65c41d5b5da006;hp=95a21935d877ce01b6597d222d39248ac6d97898;hpb=19c2da50f7f1ce9854c718e6c1c545ccc2afbb5f;p=physics.git diff --git a/src/collisionManager.cpp b/src/collisionManager.cpp index 95a2193..1076ccc 100644 --- a/src/collisionManager.cpp +++ b/src/collisionManager.cpp @@ -16,9 +16,10 @@ */ #include "collisionManager.h" -#include "debug.h" -#include "Vector2.h" +#include +#include +#include #include "Entities/Ball.h" #include "Entities/Polygon.h" @@ -26,31 +27,27 @@ #include "CollisionInfo.h" -#include "mathw.h" - -/// ***** Private Class Header ***** - /// ***** Private Method Headers ***** -void clearEntities(); -void placeEntity(PhysicsEntity* p); -void updateEntities(); +static void clearEntities(); +static void placeEntity(PhysicsEntity*); +static void updateEntities(); -void applyCollision(PhysicsEntity* p1, PhysicsEntity* p2); -void applyCollision(Ball* b1, Ball* b2); -void applyCollision(Polygon* pPoly, Ball* pBall); +static void applyCollision(PhysicsEntity*, PhysicsEntity*); +static void applyCollision(Ball*, Ball*); +static void applyCollision(Polygon*, Ball*); -bool getInfo(const Ball* b1, const Ball* b2, CollisionInfo* cInfo); -bool getInfo(const Polygon* pPoly, const Ball* pBall, CollisionInfo* cInfo); +static bool getInfo(const Ball*, const Ball*, CollisionInfo*); +static bool getInfo(const Polygon*, const Ball*, CollisionInfo*); /// ***** Private Variables ***** -const int xDivisions = 20; -const int yDivisions = 16; -const int screenX = 800; -const int screenY = 600; +static const int sc_ixDivisions = 20; +static const int sc_iyDivisions = 16; +static const int sc_ixScreenSize = 800; +static const int sc_iyScreenSize = 600; -setPhys divisions[xDivisions][yDivisions]; +setPhys divisions[sc_ixDivisions][sc_iyDivisions]; /// ***** Initializers/Cleaners ***** @@ -84,11 +81,11 @@ void collision::update(setPhys& sp) void clearEntities() { for( int x = 0; - x < xDivisions; + x < sc_ixDivisions; x++ ) { for( int y = 0; - y < yDivisions; + y < sc_iyDivisions; y++ ) { divisions[x][y].clear(); @@ -96,36 +93,38 @@ void clearEntities() } } -void placeEntity(PhysicsEntity* p) +void placeEntity(PhysicsEntity* ppe) { - Vector2 minP; - Vector2 maxP; + DASSERT(ppe != NULL); + + Vector2 vecMin; + Vector2 vecMax; { // Ball case - Ball* b = dynamic_cast(p); + Ball* pBall = dynamic_cast(ppe); - if( b != NULL ) + if( pBall != NULL ) { - const float& xb = b->positionRaw().x; - const float& yb = b->positionRaw().y; - const float& rad = b->radius; + const float& xb = pBall->positionRaw().m_fX; + const float& yb = pBall->positionRaw().m_fY; + const float& rad = pBall->radius; - minP.x = xb - rad; - minP.y = yb - rad; - maxP.x = xb + rad; - maxP.y = yb + rad; + vecMin.m_fX = xb - rad; + vecMin.m_fY = yb - rad; + vecMax.m_fX = xb + rad; + vecMax.m_fY = yb + rad; goto start; } } { // Polygon case - Polygon* pPoly = dynamic_cast(p); + Polygon* pPoly = dynamic_cast(ppe); if( pPoly != NULL ) { - minP = pPoly->minP; - maxP = pPoly->maxP; + vecMin = pPoly->minP; + vecMax = pPoly->maxP; goto start; } @@ -135,21 +134,21 @@ void placeEntity(PhysicsEntity* p) return; start: - for( int x = static_cast( minP.x / (screenX / xDivisions) ); - x <= static_cast( maxP.x / (screenX / xDivisions) ); + for( int x = static_cast( vecMin.m_fX / (sc_ixScreenSize / sc_ixDivisions) ); + x <= static_cast( vecMax.m_fX / (sc_ixScreenSize / sc_ixDivisions) ); x++ ) { - if(x < 0 || xDivisions <= x) + if(x < 0 || sc_ixDivisions <= x) break; - for( int y = static_cast( minP.y / (screenY / yDivisions) ); - y <= static_cast( maxP.y / (screenY / yDivisions) ); + for( int y = static_cast( vecMin.m_fY / (sc_iyScreenSize / sc_iyDivisions) ); + y <= static_cast( vecMax.m_fY / (sc_iyScreenSize / sc_iyDivisions) ); y++ ) { - if(y < 0 || yDivisions <= y) + if(y < 0 || sc_iyDivisions <= y) break; - divisions[x][y].insert(p); + divisions[x][y].insert(ppe); } } } @@ -157,11 +156,11 @@ start: void updateEntities() { for( int x = 0; - x < xDivisions; + x < sc_ixDivisions; x++ ) { for( int y = 0; - y < yDivisions; + y < sc_iyDivisions; y++ ) { for( setPhys::iterator it1 = divisions[x][y].begin(); @@ -182,22 +181,24 @@ void updateEntities() } } -void applyCollision(PhysicsEntity* p1, PhysicsEntity* p2) +void applyCollision(PhysicsEntity* ppe1, PhysicsEntity* ppe2) { - { - Ball* b1 = dynamic_cast(p1); - Ball* b2 = dynamic_cast(p2); + DASSERT(ppe1 != NULL && ppe2 != NULL); + + {// Ball vs Ball + Ball* pb1 = dynamic_cast(ppe1); + Ball* pb2 = dynamic_cast(ppe2); - if( b1 != NULL && b2 != NULL ) + if( pb1 != NULL && pb2 != NULL ) { - applyCollision(b1, b2); + applyCollision(pb1, pb2); return; } } - { - Polygon* pPoly = dynamic_cast(p1); - Ball* pBall = dynamic_cast(p2); + {// Polygon vs Ball + Polygon* pPoly = dynamic_cast(ppe1); + Ball* pBall = dynamic_cast(ppe2); if( pPoly != NULL && pBall != NULL ) { @@ -206,9 +207,9 @@ void applyCollision(PhysicsEntity* p1, PhysicsEntity* p2) } } - { - Polygon* pPoly = dynamic_cast(p2); - Ball* pBall = dynamic_cast(p1); + {// Ball vs Polygon + Polygon* pPoly = dynamic_cast(ppe2); + Ball* pBall = dynamic_cast(ppe1); if( pPoly != NULL && pBall != NULL ) { @@ -220,47 +221,52 @@ void applyCollision(PhysicsEntity* p1, PhysicsEntity* p2) DPF(0, "ENTITY TYPE NOT SUPPORTED BY applyCollision()!!"); } -void applyCollision(Ball* b1, Ball* b2) +void applyCollision(Ball* pb1, Ball* pb2) { + DASSERT(pb1 != NULL && pb2 != NULL); + CollisionInfo cInfo; - if(!getInfo(b1, b2, &cInfo)) + if(!getInfo(pb1, pb2, &cInfo)) return; // a few values to simplify the equations - const Vector2& normal = cInfo.normal; - const Vector2& point = cInfo.point; + const Vector2& vecNormal = cInfo.m_vecNormal; + const Vector2& vecPoint = cInfo.m_vecPoint; - float m1 = b1->mass; - float m2 = b2->mass; + float m1 = pb1->mass; + float m2 = pb2->mass; - float e = (b1->CoR + b2->CoR) / 2; + float e = (pb1->CoR + pb2->CoR) / 2; - Vector2 v1 = b1->velocityRaw(); - Vector2 v2 = b2->velocityRaw(); + Vector2 v1 = pb1->velocityRaw(); + Vector2 v2 = pb2->velocityRaw(); - float iTop = -(e + 1) * (v1 - v2).dot(normal); + float iTop = -(e + 1) * (v1 - v2).dot(vecNormal); // otherwise the collision happened and we do the math the below assumes // collisions have no friction - float impulse = iTop / (normal.dot(normal) * (1 / m1 + 1 / m2)); + float impulse = iTop / (vecNormal.dot(vecNormal) * (1 / m1 + 1 / m2)); - b1->applyImpulse(impulse / m1 * normal, point); - b2->applyImpulse(-impulse / m2 * normal, point); + pb1->applyImpulse(impulse / m1 * vecNormal, vecPoint); + pb2->applyImpulse(-impulse / m2 * vecNormal, vecPoint); } void applyCollision(Polygon* pPoly, Ball* pBall) { + DASSERT(pPoly != NULL && pBall != NULL); + CollisionInfo cInfo; if(!getInfo(pPoly, pBall, &cInfo)) return; - float fCoR = pBall->CoR; - Vector2 vecNorm = cInfo.normal; + // a few values to simplify the equations + const Vector2& vecNorm = cInfo.m_vecNormal; + float fCoR = pBall->CoR; Vector2 vecVelo = pBall->velocityRaw(); // impulse divided by mass @@ -270,43 +276,43 @@ void applyCollision(Polygon* pPoly, Ball* pBall) pBall->applyImpulse(idm * vecNorm); // HACK - // CoR penetration fix, adds the jitters + // CoR penetration fix, adds the polygon-ball jitters // from center to point Vector2 vecCollP = vecNorm / vecNorm.length() * pBall->radius; - pBall->applyNudge(cInfo.point + vecCollP - pBall->positionRaw()); + pBall->applyNudge(cInfo.m_vecPoint + vecCollP - pBall->positionRaw()); } -bool getInfo(const Ball* b1, const Ball* b2, CollisionInfo* pcInfo) +bool getInfo(const Ball* pb1, const Ball* pb2, CollisionInfo* pcInfo) { // a few values to simplify the equations - float r1 = b1->radius; - float r2 = b2->radius; + float r1 = pb1->radius; + float r2 = pb2->radius; - Vector2 p1 = b1->positionRaw(); - Vector2 p2 = b2->positionRaw(); - Vector2 v1 = b1->velocityRaw(); - Vector2 v2 = b2->velocityRaw(); + Vector2 p1 = pb1->positionRaw(); + Vector2 p2 = pb2->positionRaw(); + Vector2 v1 = pb1->velocityRaw(); + Vector2 v2 = pb2->velocityRaw(); // quick binding box check - if (p1.x - r1 > p2.x + r2 - || p1.x + r1 < p2.x - r2 - || p1.y - r1 > p2.y + r2 - || p1.y + r1 < p2.y - r2) + if (p1.m_fX - r1 > p2.m_fX + r2 + || p1.m_fX + r1 < p2.m_fX - r2 + || p1.m_fY - r1 > p2.m_fY + r2 + || p1.m_fY + r1 < p2.m_fY - r2) return false; // test if not touching if ((p1 - p2).sqrLength() >= (r1 + r2)*(r1 + r2)) return false; - // test if they are moving apart in some way if they aren't it's likely + // test if they are moving apart in some way if they are it's likely // that they collided last frame and are still overlapping if ((v1 - v2).dot(p1 - p2) >= 0) return false; - pcInfo->point = p1 - (p1 - p2) * r1 / (r1 + r2); - pcInfo->normal = p1 - p2; + pcInfo->m_vecPoint = p1 - (p1 - p2) * r1 / (r1 + r2); + pcInfo->m_vecNormal = p1 - p2; return true; } @@ -318,14 +324,14 @@ bool getInfo(const Polygon* pPoly, const Ball* pBall, CollisionInfo* pcInfo) Vector2 vecPos = pBall->positionRaw(); Vector2 vecVelo = pBall->velocityRaw(); - float fMaxX = pPoly->maxP.x; - float fMinX = pPoly->minP.x; - float fMaxY = pPoly->maxP.y; - float fMinY = pPoly->minP.y; + float fMaxX = pPoly->maxP.m_fX; + float fMinX = pPoly->minP.m_fX; + float fMaxY = pPoly->maxP.m_fY; + float fMinY = pPoly->minP.m_fY; // quick binding box check - if (vecPos.x - fRad > fMaxX || vecPos.x + fRad < fMinX || - vecPos.y - fRad > fMaxY || vecPos.y + fRad < fMinY) + if (vecPos.m_fX - fRad > fMaxX || vecPos.m_fX + fRad < fMinX || + vecPos.m_fY - fRad > fMaxY || vecPos.m_fY + fRad < fMinY) return false; @@ -339,10 +345,10 @@ bool getInfo(const Polygon* pPoly, const Ball* pBall, CollisionInfo* pcInfo) for (unsigned int i = 0; i < num; i++) { Vector2 vec = vectorToLine(vecPos, - pts[i].x, - pts[i].y, - pts[(i + 1) % num].x, - pts[(i + 1) % num].y); + pts[i].m_fX, + pts[i].m_fY, + pts[(i + 1) % num].m_fX, + pts[(i + 1) % num].m_fY); if (vec.sqrLength() <= fRad*fRad && 0 < vec.dot(vecVelo)) { @@ -356,8 +362,8 @@ bool getInfo(const Polygon* pPoly, const Ball* pBall, CollisionInfo* pcInfo) return false; - pcInfo->point = vecTotVec / iTot + vecPos; - pcInfo->normal = vecPos - pcInfo->point; + pcInfo->m_vecPoint = vecTotVec / iTot + vecPos; + pcInfo->m_vecNormal = vecPos - pcInfo->m_vecPoint; return true; }