added suport for ballxpolygon collision ... VERY hacky
authorPatrik Gornicz <Gornicz.P@gmail.com>
Wed, 21 Jan 2009 04:55:17 +0000 (23:55 -0500)
committerPatrik Gornicz <Gornicz.P@gmail.com>
Wed, 21 Jan 2009 04:55:17 +0000 (23:55 -0500)
src/Entities/Polygon.cpp
src/Entities/Polygon.h
src/collisionManager.cpp
src/entityCreator.cpp
src/mathw.cpp
src/mathw.h

index bf2fb00..cd03d85 100644 (file)
@@ -31,6 +31,7 @@ Polygon::Polygon(const vector<Vector2>& 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<points.size(); i++)
+    {
+             if(points[i].x < minP.x) minP.x = points[i].x;
+        else if(points[i].x > 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
 }
index b8c8493..82ff9d7 100644 (file)
@@ -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
index 5d2dff0..8aa2dc7 100644 (file)
 #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<Ball*>(p);
+    Vector2 minP;
+    Vector2 maxP;
 
-    if( b == NULL )
-    {
-        DPF(0, "ENTITY TYPE NOT SUPPORTED BY placeEntity()!!");
-        return;
+    { // Ball case
+        Ball* b = dynamic_cast<Ball*>(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<Polygon*>(p);
 
-    for( int x =  static_cast<int>( (xb - rad) / (screenX / xDivisions) );
-             x <= static_cast<int>( (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<int>( minP.x / (screenX / xDivisions) );
+             x <= static_cast<int>( maxP.x / (screenX / xDivisions) );
              x++ )
     {
         if(x < 0 || xDivisions <= x)
             break;
 
-        for( int y =  static_cast<int>( (yb - rad) / (screenY / yDivisions) );
-                 y <= static_cast<int>( (yb + rad) / (screenY / yDivisions) );
+        for( int y =  static_cast<int>( minP.y / (screenY / yDivisions) );
+                 y <= static_cast<int>( 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<Ball*>(p1);
-    Ball* b2 = dynamic_cast<Ball*>(p2);
+    {
+        Ball* b1 = dynamic_cast<Ball*>(p1);
+        Ball* b2 = dynamic_cast<Ball*>(p2);
+
+        if( b1 != NULL && b2 != NULL )
+        {
+            applyCollision(b1, b2);
+            return;
+        }
+    }
 
-    if( b1 != NULL && b2 != NULL )
     {
-        applyCollision(b1, b2);
-        return;
+        Polygon*    pPoly   = dynamic_cast<Polygon*>(p1);
+        Ball*       pBall   = dynamic_cast<Ball*>(p2);
+
+        if( pPoly != NULL && pBall != NULL )
+        {
+            applyCollision(pPoly, pBall);
+            return;
+        }
+    }
+
+    {
+        Polygon*    pPoly   = dynamic_cast<Polygon*>(p2);
+        Ball*       pBall   = dynamic_cast<Ball*>(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<Vector2>& 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;
+}
index 1b4b6f7..104158c 100644 (file)
@@ -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<Vector2> 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));
 }
index 830a33d..eda4781 100644 (file)
@@ -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);
index b45bfc0..312379f 100644 (file)
@@ -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);