From aa2791cf43a9ddd3a288e504db08e11d03439653 Mon Sep 17 00:00:00 2001 From: Patrik Gornicz Date: Tue, 20 Jan 2009 23:55:17 -0500 Subject: [PATCH] added suport for ballxpolygon collision ... VERY hacky --- src/Entities/Polygon.cpp | 18 +++++ src/Entities/Polygon.h | 3 +- src/collisionManager.cpp | 169 +++++++++++++++++++++++++++++++++++++++++------ src/entityCreator.cpp | 7 +- src/mathw.cpp | 29 ++++++++ src/mathw.h | 10 ++- 6 files changed, 212 insertions(+), 24 deletions(-) diff --git a/src/Entities/Polygon.cpp b/src/Entities/Polygon.cpp index bf2fb00..cd03d85 100644 --- a/src/Entities/Polygon.cpp +++ b/src/Entities/Polygon.cpp @@ -31,6 +31,7 @@ Polygon::Polygon(const vector& points) DASSERT(0 < points.size()); createBindingBox(); + centerPosition(); } Polygon::~Polygon() { @@ -47,5 +48,22 @@ void Polygon::draw() const /// ***** Private Class Methods ***** void Polygon::createBindingBox() { + DASSERT(0 < points.size()); + + maxP = points.at(0); + minP = points.at(0); + + for(unsigned int i=1; i maxP.x) maxP.x = points[i].x; + + if(points[i].y < minP.y) minP.y = points[i].y; + else if(points[i].y > maxP.y) maxP.y = points[i].y; + } +} + +void Polygon::centerPosition() +{ // TODO } diff --git a/src/Entities/Polygon.h b/src/Entities/Polygon.h index b8c8493..82ff9d7 100644 --- a/src/Entities/Polygon.h +++ b/src/Entities/Polygon.h @@ -35,7 +35,7 @@ class Polygon: public PhysicsEntity virtual void draw() const; - protected: + //protected: Vector2 maxP; // stores the max bounding box point Vector2 minP; // stores the min bounding box point @@ -44,6 +44,7 @@ class Polygon: public PhysicsEntity // color; private: void createBindingBox(); + void centerPosition(); }; #endif // POLYGON_H diff --git a/src/collisionManager.cpp b/src/collisionManager.cpp index 5d2dff0..8aa2dc7 100644 --- a/src/collisionManager.cpp +++ b/src/collisionManager.cpp @@ -21,10 +21,13 @@ #include "Vector2.h" #include "Entities/Ball.h" +#include "Entities/Polygon.h" #include "Entities/PhysicsEntity.h" #include "CollisionInfo.h" +#include "mathw.h" + /// ***** Private Class Header ***** /// ***** Private Method Headers ***** @@ -35,8 +38,10 @@ void updateEntities(); void applyCollision(PhysicsEntity* p1, PhysicsEntity* p2); void applyCollision(Ball* b1, Ball* b2); +void applyCollision(Polygon* pPoly, Ball* pBall); -bool getInfo(Ball* b1, Ball* b2, CollisionInfo* cInfo); +bool getInfo(const Ball* b1, const Ball* b2, CollisionInfo* cInfo); +bool getInfo(const Polygon* pPoly, const Ball* pBall, CollisionInfo* cInfo); /// ***** Private Variables ***** @@ -93,27 +98,52 @@ void clearEntities() void placeEntity(PhysicsEntity* p) { - Ball* b = dynamic_cast(p); + Vector2 minP; + Vector2 maxP; - if( b == NULL ) - { - DPF(0, "ENTITY TYPE NOT SUPPORTED BY placeEntity()!!"); - return; + { // Ball case + Ball* b = dynamic_cast(p); + + if( b != NULL ) + { + const float& xb = b->positionRaw().x; + const float& yb = b->positionRaw().y; + const float& rad = b->radius; + + minP.x = xb - rad; + minP.y = yb - rad; + maxP.x = xb + rad; + maxP.y = yb + rad; + + goto start; + } } - const float& xb = b->positionRaw().x; - const float& yb = b->positionRaw().y; - const float& rad = b->radius; + { // Polygon case + Polygon* pPoly = dynamic_cast(p); - for( int x = static_cast( (xb - rad) / (screenX / xDivisions) ); - x <= static_cast( (xb + rad) / (screenX / xDivisions) ); + if( pPoly != NULL ) + { + minP = pPoly->minP; + maxP = pPoly->maxP; + + goto start; + } + } + + DPF(0, "ENTITY TYPE NOT SUPPORTED BY placeEntity()!!"); + return; + +start: + for( int x = static_cast( minP.x / (screenX / xDivisions) ); + x <= static_cast( maxP.x / (screenX / xDivisions) ); x++ ) { if(x < 0 || xDivisions <= x) break; - for( int y = static_cast( (yb - rad) / (screenY / yDivisions) ); - y <= static_cast( (yb + rad) / (screenY / yDivisions) ); + for( int y = static_cast( minP.y / (screenY / yDivisions) ); + y <= static_cast( maxP.y / (screenY / yDivisions) ); y++ ) { if(y < 0 || yDivisions <= y) @@ -154,13 +184,37 @@ void updateEntities() void applyCollision(PhysicsEntity* p1, PhysicsEntity* p2) { - Ball* b1 = dynamic_cast(p1); - Ball* b2 = dynamic_cast(p2); + { + Ball* b1 = dynamic_cast(p1); + Ball* b2 = dynamic_cast(p2); + + if( b1 != NULL && b2 != NULL ) + { + applyCollision(b1, b2); + return; + } + } - if( b1 != NULL && b2 != NULL ) { - applyCollision(b1, b2); - return; + Polygon* pPoly = dynamic_cast(p1); + Ball* pBall = dynamic_cast(p2); + + if( pPoly != NULL && pBall != NULL ) + { + applyCollision(pPoly, pBall); + return; + } + } + + { + Polygon* pPoly = dynamic_cast(p2); + Ball* pBall = dynamic_cast(p1); + + if( pPoly != NULL && pBall != NULL ) + { + applyCollision(pPoly, pBall); + return; + } } DPF(0, "ENTITY TYPE NOT SUPPORTED BY applyCollision()!!"); @@ -197,7 +251,33 @@ void applyCollision(Ball* b1, Ball* b2) b2->applyImpulse(-impulse / m2 * normal, point); } -bool getInfo(Ball* b1, Ball* b2, CollisionInfo* pcInfo) +void applyCollision(Polygon* pPoly, Ball* pBall) +{ + CollisionInfo cInfo; + + if(!getInfo(pPoly, pBall, &cInfo)) + return; + + float fCoR = pBall->CoR; + Vector2 vecNorm = cInfo.normal; + + Vector2 vecVelo = pBall->velocityRaw(); + + // impulse divided by mass + float idm = (-(fCoR + 1) * vecVelo.dot(vecNorm)) + / (vecNorm.dot(vecNorm)); + + pBall->applyImpulse(idm * vecNorm); + + // HACK + // CoR penetration fix, adds the jitters + + // from center to point + //Vector2 CollP = normal / normal.Length * Ball.Radius; + //Ball.Position = Info.Point + CollP; +} + +bool getInfo(const Ball* b1, const Ball* b2, CollisionInfo* pcInfo) { // a few values to simplify the equations float r1 = b1->radius; @@ -230,3 +310,54 @@ bool getInfo(Ball* b1, Ball* b2, CollisionInfo* pcInfo) return true; } + +bool getInfo(const Polygon* pPoly, const Ball* pBall, CollisionInfo* pcInfo) +{ + // a few values to simplify the equations + float fRad = pBall->radius; + 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; + + // quick binding box check + if (vecPos.x - fRad > fMaxX || vecPos.x + fRad < fMinX || + vecPos.y - fRad > fMaxY || vecPos.y + fRad < fMinY) + return false; + + + Vector2 vecTotVec; + int iTot = 0; + + { + const vector& pts = pPoly->points; + unsigned int num = pts.size(); + + 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); + + if (vec.sqrLength() <= fRad*fRad && 0 < vec.dot(vecVelo)) + { + vecTotVec += vec; + iTot += 1; + } + } + } + + if (iTot <= 0) + return false; + + + pcInfo->point = vecTotVec / iTot + vecPos; + pcInfo->normal = vecPos - pcInfo->point; + + return true; +} diff --git a/src/entityCreator.cpp b/src/entityCreator.cpp index 1b4b6f7..104158c 100644 --- a/src/entityCreator.cpp +++ b/src/entityCreator.cpp @@ -80,11 +80,12 @@ void creator::init() addBall(Vector2(200+i*2, 200+i*2), 10, cCyan); } + // HACK // add a polygon into the mix (currently not cleaned up) vector points; - points.push_back(Vector2(50,50)); - points.push_back(Vector2(50,100)); - points.push_back(Vector2(100,50)); + points.push_back(Vector2(500,500)); + points.push_back(Vector2(300,500)); + points.push_back(Vector2(500,300)); manager::add(new Polygon(points)); } diff --git a/src/mathw.cpp b/src/mathw.cpp index 830a33d..eda4781 100644 --- a/src/mathw.cpp +++ b/src/mathw.cpp @@ -27,6 +27,35 @@ int mod(int x, int y) // Vector2 Math +Vector2 vectorToLine +( + const Vector2& vec, + float x1, + float y1, + float x2, + float y2 +) +{ + float lineSize = (float) sqrt((x1 - x2) * (x1 - x2) + + (y1 - y2) * (y1 - y2)); + if (lineSize == 0) + return Vector2(x1 - vec.x, y1 - vec.y); + + float u = ((vec.x - x1) * (x2 - x1) + + (vec.y - y1) * (y2 - y1)) / (lineSize * lineSize); + + if (u < 0) + return Vector2(x1 - vec.x, y1 - vec.y); + else if (u > 1) + return Vector2(x2 - vec.x, y2 - vec.y); + else + { + float ix = x1 + u * (x2 - x1); + float iy = y1 + u * (y2 - y1); + return Vector2(ix - vec.x, iy - vec.y); + } +} + Vector2 perp(const Vector2& vec) { return Vector2(-vec.y, vec.x); diff --git a/src/mathw.h b/src/mathw.h index b45bfc0..312379f 100644 --- a/src/mathw.h +++ b/src/mathw.h @@ -32,7 +32,15 @@ int mod(int,int); /// Vector2 Math -//Vector2 vectorToLine(float, float, float, float) const; +Vector2 vectorToLine +( + const Vector2& vec, + float x1, + float y1, + float x2, + float y2 +); + //Vector2 lineIntersection(Vector2&, Vector2&, Vector2&, Vector2&) const; //void Rotate(float rads); -- 2.10.2