00001
00002 #ifndef _COLMODEL_H
00003 #define _COLMODEL_H
00004
00005 #include "GLVector.h"
00006 #include "GLQuaternion.h"
00007
00008
00009 inline double absD(double d)
00010 {
00011 return (d >=0)? d : -d;
00012 }
00013
00014
00015
00017
00018 const int BOTTOM_FRONT_LEFT = 0;
00019 const int BOTTOM_FRONT_RIGHT= 1;
00020 const int BOTTOM_BACK_RIGHT = 2;
00021 const int BOTTOM_BACK_LEFT = 3;
00022 const int TOP_FRONT_LEFT = 4;
00023 const int TOP_FRONT_RIGHT = 5;
00024 const int TOP_BACK_RIGHT = 6;
00025 const int TOP_BACK_LEFT = 7;
00026
00027
00031 class CDBox
00032 {
00033 public:
00034 CDBox(){};
00035 virtual ~CDBox(){};
00036
00043 GLVector3d mVertex[8];
00044
00048 void zeroize()
00049 {
00050 for (int i = 0; i < 8; i++ ) mVertex[i].set( 0, 0, 0 );
00051 }
00052
00058 void translate( const GLVector3d translation )
00059 {
00060 for (int i = 0; i < 8; i++ ) mVertex[i]+= translation;
00061 }
00062
00066 void rotate( GLQuaterniond rotation )
00067 {
00068 for (int i = 0; i < 8; i++ ) mVertex[i] = rotation.rotateVector( mVertex[i] );
00069 }
00070
00071
00078 double getMin(int cordinate) const
00079 {
00080 double min = mVertex[0].val[cordinate];
00081 for (int i = 1; i < 8; i++) if (mVertex[i].val[cordinate] < min) min = mVertex[i].val[cordinate];
00082 return min;
00083 }
00084
00091 double getMax(int cordinate) const
00092 {
00093 double max = mVertex[0].val[cordinate];
00094 for (int i = 1; i < 8; i++) if (mVertex[i].val[cordinate] > max) max = mVertex[i].val[cordinate];
00095 return max;
00096 }
00097
00105 bool quickCheckCollision( const CDBox & box ) const
00106 {
00107 for (int i = 0; i < 3; i++)
00108 {
00109 if (getMax(i) <= box.getMin(i) ||
00110 getMin(i) >= box.getMax(i)) return false;
00111 }
00112 return true;
00113 }
00114
00125 void project(const GLVector3d &normal, double &min, double &max) const
00126 {
00127 min = max = normal.dot(mVertex[0]);
00128 for (int i = 1; i < 8; i++)
00129 {
00130 double d = normal.dot(mVertex[i]);
00131 if (d < min) min = d;
00132 if (d > max) max = d;
00133 }
00134 }
00135
00149 double trySepparatingAxis(const CDBox & box, int a1, int a2, int b1, int b2, GLVector3d &normal) const
00150 {
00151
00152 normal = mVertex[a1]-mVertex[a2];
00153 normal.cross(box.mVertex[b1]-box.mVertex[b2]);
00154
00155
00156
00157
00158
00159
00160 if (normal.length() == 0)
00161 {
00162 return 100000000;
00163 }
00164 normal.normalize();
00165
00166 return projectAndCompare(*this, box, normal);
00167 }
00168
00183 double trySepparatingAxisSelf(const CDBox & box, int a1, int a2, int b1, int b2, GLVector3d &normal) const
00184 {
00185
00186 normal = mVertex[a1]-mVertex[a2];
00187 normal.cross(mVertex[b1]-mVertex[b2]);
00188
00189
00190
00191
00192
00193
00194 if (normal.length() == 0)
00195 {
00196 return 100000000;
00197 }
00198 normal.normalize();
00199
00200 return projectAndCompare(*this, box, normal);
00201 }
00202
00212 static double projectAndCompare(const CDBox & box1, const CDBox & box2, const GLVector3d &normal)
00213 {
00214
00215 double min1, max1;
00216 box1.project(normal, min1, max1);
00217
00218
00219 double min2, max2;
00220 box2.project(normal, min2, max2);
00221
00222
00223 if (min2 >= max1 || min1 >= max2)
00224 {
00225 return 0;
00226 }
00227
00228 if ( max1 - min2 > max2 - min1 ) return max2 - min1;
00229 return min2 - max1;
00230 }
00231
00232 };
00233
00234
00241 class CollisionModel
00242 {
00243 public:
00244 CollisionModel();
00245 virtual ~CollisionModel(){};
00246
00254 bool checkCollision( const CollisionModel & model )
00255 {
00256 return computeMinimalAvoidVector(model, mAvoidVector);
00257 }
00258
00265 const GLVector3d & getAvoidVector()
00266 {
00267 return mAvoidVector;
00268 }
00269
00280 bool computeMinimalAvoidVector( const CollisionModel & model, GLVector3d & result );
00281
00290 double computeMinimalAvoidDistance( const CollisionModel & model, GLVector3d & direction);
00291
00297 void setTranslation( const GLVector3d &translation )
00298 {
00299 mTranslation = translation;
00300 }
00301
00308 void addTranslation( const GLVector3d &translation )
00309 {
00310 mTranslation += translation;
00311 }
00312
00318 void setRotation( const GLQuaterniond &rotation )
00319 {
00320 mRotation = rotation;
00321 }
00322
00328 void addRotation( const GLQuaterniond &rotation )
00329 {
00330 mRotation *= rotation;
00331 }
00332
00338 void finishTransformations()
00339 {
00340 mTransBox = mBox;
00341 mTransBox.rotate( mRotation );
00342 mTransBox.translate( mTranslation );
00343 mReseted = false;
00344 }
00345
00349 void resetTransformations()
00350 {
00351 mTranslation.set( 0, 0, 0 );
00352 mRotation.set( 0, 0, 0, 0 );
00353 mTransBox.zeroize();
00354 mReseted = true;
00355 }
00356
00360 bool isReseted() const
00361 {
00362 return mReseted;
00363 }
00364
00371 CDBox& getModel()
00372 {
00373 return mBox;
00374 }
00375
00380 CDBox& getTransModel()
00381 {
00382 return mTransBox;
00383 }
00384
00389 void setModel( const CDBox & model )
00390 {
00391 mBox = model;
00392 }
00393
00394 private:
00395
00396 CDBox mBox;
00397
00398 CDBox mTransBox;
00399
00400 bool mReseted;
00401
00402 GLVector3d mTranslation;
00403
00404 GLQuaterniond mRotation;
00405
00406 GLVector3d mAvoidVector;
00407 };
00408
00410 #endif