colmodel.cpp

Go to the documentation of this file.
00001 //#define WANT_TRACE
00002 
00003 /* MAINTAINER: Petko CURRENT EDITOR: Bernard */
00004 #include "colmodel.h"
00005 #include "globals.h"
00006 #include "log.h"
00007 
00008 const double EPSILON = 0.00001;
00009 
00010 
00011 
00012 
00013 CollisionModel::CollisionModel()
00014 {
00015         mReseted = true;
00016         mBox.zeroize();
00017         mTransBox.zeroize();
00018         mTranslation.set( 0, 0, 0 );
00019         mRotation.set( ZERO_ROTATION_VECTOR, 0 );
00020         mAvoidVector.set( 0, 0, 0);
00021 }
00022 
00023 #define SEP_TEST(box1, box2, a1, a2, b1, b2) \
00024         if ( absD((d=box1.trySepparatingAxis(box2, a1, a2, b1, b2, normal))) < absD(min)) \
00025         { \
00026                 if (absD(min = d) < EPSILON) return false; \
00027                 result = normal; \
00028         }
00029 
00030 #define SEPSELF_TEST(box1, box2, a1, a2, b1, b2) \
00031         if ( absD((d=box1.trySepparatingAxisSelf(box2, a1, a2, b1, b2, normal))) < absD(min)) \
00032         { \
00033                 if (absD(min = d) < EPSILON) return false; \
00034                 result = normal; \
00035         }
00036 
00037 #define SEPSELF_MINUSTEST(box1, box2, a1, a2, b1, b2) \
00038         if ( absD((d=box1.trySepparatingAxisSelf(box2, a1, a2, b1, b2, normal))) < absD(min)) \
00039         { \
00040                 if (absD(min = -d) < EPSILON) return false; \
00041                 result = normal; \
00042         }
00043 
00044 bool CollisionModel::computeMinimalAvoidVector(const CollisionModel & model, GLVector3d & result)
00045 {
00046         // quick check - not needed to get correct results,
00047         // but speed up the testing
00048         if (!mTransBox.quickCheckCollision(model.mTransBox)) 
00049         {
00050                 return false;
00051         }
00052         
00053         const CDBox &box1 = mTransBox;
00054         const CDBox &box2 = model.mTransBox;
00055         
00056         GLVector3d normal;
00057         double d, min = 10000;
00058         
00059         // Testing planes defined by both boxes
00060         for (int i = 0; i < 2; i++) 
00061         {
00062                 for (int j = 0; j < 2; j++)
00063                         SEP_TEST(box1, box2, i, i+1, j, j+1);
00064                 
00065                 SEP_TEST(box1, box2, i, i+1, 0,   4);
00066                 SEP_TEST(box1, box2, 0,   4, i, i+1);
00067         }
00068         SEP_TEST(box1, box2, 0, 4, 0, 4);
00069         
00070         // Testing planes defined by our box
00071         SEPSELF_TEST(box1, box2, 0, 1, 1, 2);
00072         SEPSELF_TEST(box1, box2, 1, 2, 1, 5);
00073         SEPSELF_TEST(box1, box2, 0, 1, 0, 4);
00074         
00075         // Testing planes defined by second box [note that the result mus be mutiplyed by -1]
00076         SEPSELF_MINUSTEST(box1, box2, 0, 1, 1, 2);
00077         SEPSELF_MINUSTEST(box2, box1, 0, 1, 1, 2);
00078         SEPSELF_MINUSTEST(box2, box1, 1, 2, 1, 5);
00079         SEPSELF_MINUSTEST(box2, box1, 0, 1, 0, 4);
00080         
00081         // Create avoid vector from normal of minimal separating plane
00082         result *= min;
00083                 
00084         return true;
00085 }
00086 
00087         double projectAndCompareMax(const CDBox & box1, const CDBox & box2, const GLVector3d &normal, double scale)
00088         {               
00089                 // Get min / max for first box
00090                 double min1, max1;
00091                 box1.project(normal, min1, max1);
00092                 
00093                 // Get min / max for second box
00094                 double min2, max2;
00095                 box2.project(normal, min2, max2);
00096         
00097                 // Decide the colision
00098                 if (min2 >= max1 || min1 >= max2) 
00099                 {
00100                         return 0; // No collision
00101                 }
00102                 
00103                 if (scale == 0) return 100000;
00104                 if ((max2 - min1)/scale > 0) return (max2 - min1)/scale;
00105                 return (min2 - max1)/scale;
00106         }
00107 
00108         double trySepparatingAxisMax(const CDBox &box1, const CDBox &box2, int a1, int a2,
00109                                              int b1, int b2, GLVector3d &normal, const GLVector3d &direction)
00110         {
00111                 // compute normal vector of seprarating plane
00112                 normal = box1.mVertex[a1]-box1.mVertex[a2];
00113                 normal.cross(box2.mVertex[b1]-box2.mVertex[b2]);
00114                 
00115                 if (normal.length() == 0) 
00116                 {
00117                         return 100000000;               
00118                 }
00119                 normal.normalize();
00120         
00121                 double scale = normal.dot(direction);
00122                         
00123                 return projectAndCompareMax(box1, box2, normal, scale);
00124         }
00125 
00126         double trySepparatingAxisSelfMax(const CDBox &box1, const CDBox &box2, int a1, int a2,
00127                                               int b1, int b2, GLVector3d &normal, const GLVector3d &direction)
00128         {
00129                 // compute normal vector of seprarating plane
00130                 normal = box1.mVertex[a1]-box1.mVertex[a2];
00131                 normal.cross(box1.mVertex[b1]-box1.mVertex[b2]);
00132                 
00133                 if (normal.length() == 0) 
00134                 {
00135                         return 100000000;               
00136                 }
00137                 normal.normalize();
00138         
00139                 double scale = normal.dot(direction);
00140                 
00141                 return projectAndCompareMax(box1, box2, normal, scale);
00142         }
00143 
00144 
00145 #define SEP_TESTMAX(box1, box2, a1, a2, b1, b2) \
00146         if ( (d = trySepparatingAxisMax(box1, box2, a1, a2, b1, b2, normal, direction)) <  min) \
00147         { \
00148                 if ((min = d) < EPSILON) return 0; \
00149                 if (min < 0) \
00150                  LOGE " POZOR!!!" << endl; \
00151         }
00152 
00153 #define SEPSELF_TESTMAX(box1, box2, a1, a2, b1, b2) \
00154         if ( (d = trySepparatingAxisSelfMax(box1, box2, a1, a2, b1, b2, normal, direction)) <  min) \
00155         { \
00156                 if ((min = d) < EPSILON) return 0; \
00157                 if (min < 0) \
00158                  LOGE " POZOR!!!" << endl; \
00159         }
00160 
00161 #define SEPSELF_MINUSTESTMAX(box1, box2, a1, a2, b1, b2) \
00162         if ( (d = trySepparatingAxisSelfMax(box1, box2, a1, a2, b1, b2, normal, -direction)) <  min) \
00163         { \
00164                 if ((min = d) < EPSILON) return 0; \
00165                 if (min < 0) \
00166                  LOGE " POZOR!!!" << endl; \
00167         }
00168 
00169 double CollisionModel::computeMinimalAvoidDistance( const CollisionModel & model, GLVector3d & direction)
00170 {
00171         // quick check - not needed to get correct results,
00172         // but speed up the testing
00173         if (!mTransBox.quickCheckCollision(model.mTransBox)) 
00174         {
00175                 return 0;
00176         }
00177         
00178         const CDBox &box1 = mTransBox;
00179         const CDBox &box2 = model.mTransBox;
00180         
00181         GLVector3d normal;
00182         double d, min = 10000;
00183         
00184         // Testing planes defined by both boxes
00185         for (int i = 0; i < 2; i++) 
00186         {
00187                 for (int j = 0; j < 2; j++)             
00188                         SEP_TESTMAX(box1, box2, i, i+1, j, j+1);
00189                 
00190                 SEP_TESTMAX(box1, box2, i, i+1, 0,   4);
00191                 SEP_TESTMAX(box1, box2, 0,   4, i, i+1);
00192         }
00193         SEP_TESTMAX(box1, box2, 0, 4, 0, 4);
00194         
00195         // Testing planes defined by our box
00196         SEPSELF_TESTMAX(box1, box2, 0, 1, 1, 2);
00197         SEPSELF_TESTMAX(box1, box2, 1, 2, 1, 5);
00198         SEPSELF_TESTMAX(box1, box2, 0, 1, 0, 4);
00199         
00200         // Testing planes defined by second box [note that the result mus be mutiplyed by -1]
00201         SEPSELF_MINUSTESTMAX(box1, box2, 0, 1, 1, 2);
00202         SEPSELF_MINUSTESTMAX(box2, box1, 0, 1, 1, 2);
00203         SEPSELF_MINUSTESTMAX(box2, box1, 1, 2, 1, 5);
00204         SEPSELF_MINUSTESTMAX(box2, box1, 0, 1, 0, 4);
00205         
00206         return min;
00207 
00208 }

Generated on Wed Apr 12 13:55:27 2006 for bjs by  doxygen 1.4.5