00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <physics/GJKCollisionDetector>
00026 #include <gfx/Triangle3>
00027 #include <base/ref>
00028 #include <base/Quat4>
00029
00030 using physics::GJKCollisionDetector;
00031 using physics::CollisionState;
00032 using physics::CollisionModelProvider;
00033 using base::Vector3;
00034 using base::Matrix3;
00035 using base::transpose;
00036 using base::inverse;
00037 using base::cross;
00038 using gfx::Triangle3;
00039
00040
00041 #include <osg/Node>
00042 #include <osg/Group>
00043 #include <osg/Geode>
00044 #include <osg/Transform>
00045 #include <osg/StateSet>
00046 #include <osg/Material>
00047 #include <osg/Array>
00048 #include <osg/PolygonMode>
00049 #include <osg/Geometry>
00050
00051 using osg::Vec4;
00052 using osg::StateSet;
00053
00054
00055
00056
00057
00058
00059
00060 GJKCollisionDetector::GJKCollisionDetector()
00061 : collisionDetectionEnabled(true), node(0)
00062 {
00063 }
00064
00065
00066 GJKCollisionDetector::~GJKCollisionDetector()
00067 {
00068 }
00069
00070
00071 const Real rel_error = 1e-6;
00072 const Real abs_error = 1e-10;
00073
00074
00075
00076 GJKCollisionDetector::GJKCollisionState::GJKCollisionState(ref<const Solid> solid1, ref<const Solid> solid2,
00077 CollisionModel::CollisionModelType modelType)
00078 : CollisionState(solid1, solid2)
00079 {
00080 ref<const GJKCollisionModel> cm1 = narrow_ref<const GJKCollisionModel>( solid1->getCollisionModel(modelType) );
00081 ref<const GJKCollisionModel> cm2 = narrow_ref<const GJKCollisionModel>( solid2->getCollisionModel(modelType) );
00082
00083 }
00084
00085 GJKCollisionDetector::GJKCollisionState::~GJKCollisionState()
00086 {
00087 }
00088
00089
00090
00091
00092 ref<CollisionState> GJKCollisionDetector::newCollisionState(ref<const Solid> solid1, ref<const Solid> solid2) const
00093 {
00094 GJKCollisionState *sp = NewNamedObj("GJKCollisionState") GJKCollisionState(solid1, solid2, getType());
00095 return ref<GJKCollisionState>(sp);
00096 }
00097
00098 bool GJKCollisionDetector::collision(ref<const Solid> solid1, ref<const Solid> solid2, CollisionQueryType queryType)
00099 {
00100 if (!collisionDetectionEnabled) return false;
00101 if (queryType == PotentialCollision) return true;
00102
00103
00104
00105
00106 ref<GJKCollisionState> cs(narrow_ref<GJKCollisionState>(getCollisionState(solid1,solid2)));
00107
00108
00109
00110 ref<const GJKCollisionModel> model1
00111 = narrow_ref<const GJKCollisionModel>(solid1->getCollisionModel(getType()));
00112 ref<const GJKCollisionModel> model2
00113 = narrow_ref<const GJKCollisionModel>(solid2->getCollisionModel(getType()));
00114
00115 base::Transform t1(solid1->getPosition(), solid1->getOrientation());
00116 base::Transform t2(solid2->getPosition(), solid2->getOrientation());
00117
00118
00119 if (node!=0) {
00120 const Point3 s0(t1(cs->lastSupportPoint[0]));
00121 const Point3 s1(t2(cs->lastSupportPoint[1]));
00122 (*verts)[0].set(s0.x,s0.y,s0.z);
00123 (*verts)[1].set(s1.x,s1.y,s1.z);
00124 geom->setVertexArray(verts);
00125 }
00126
00127
00128
00129 ref<const Polyhedron::Vertex> support0(cs->lastSupport[0]);
00130 ref<const Polyhedron::Vertex> support1(cs->lastSupport[1]);
00131
00132
00133 ref<GJKCollisionModel::GJKModelState> ms1(NewObj GJKCollisionModel::GJKModelState(support0));
00134 ref<GJKCollisionModel::GJKModelState> ms2(NewObj GJKCollisionModel::GJKModelState(support1));
00135
00136 bool collided = intersect(model1, model2, t1, t2, ms1, ms2, cs);
00137
00138 cs->lastSupport[0] = ms1->lastSupport;
00139 cs->lastSupport[1] = ms2->lastSupport;
00140 cs->lastSupportPoint[0] = ms1->lastSupportPoint;
00141 cs->lastSupportPoint[1] = ms2->lastSupportPoint;
00142
00143
00144 if (collided) {
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 std::cout << "Collided.\n";
00162 }
00163 else {
00164 std::cout << "No Collision\n";
00165 }
00166
00167 return collided;
00168 }
00169
00170
00171
00172
00173 void GJKCollisionDetector::compute_det()
00174 {
00175 static Real dp[4][4];
00176
00177 for (Int i = 0, bit = 1; i < 4; ++i, bit <<=1)
00178 if (bits & bit) dp[i][last] = dp[last][i] = dot(y[i], y[last]);
00179 dp[last][last] = dot(y[last], y[last]);
00180
00181 det[last_bit][last] = 1;
00182 for (Int j = 0, sj = 1; j < 4; ++j, sj <<= 1) {
00183 if (bits & sj) {
00184 Int s2 = sj|last_bit;
00185 det[s2][j] = dp[last][last] - dp[last][j];
00186 det[s2][last] = dp[j][j] - dp[j][last];
00187 for (Int k = 0, sk = 1; k < j; ++k, sk <<= 1) {
00188 if (bits & sk) {
00189 Int s3 = sk|s2;
00190 det[s3][k] = det[s2][j] * (dp[j][j] - dp[j][k]) +
00191 det[s2][last] * (dp[last][j] - dp[last][k]);
00192 det[s3][j] = det[sk|last_bit][k] * (dp[k][k] - dp[k][j]) +
00193 det[sk|last_bit][last] * (dp[last][k] - dp[last][j]);
00194 det[s3][last] = det[sk|sj][k] * (dp[k][k] - dp[k][last]) +
00195 det[sk|sj][j] * (dp[j][k] - dp[j][last]);
00196 }
00197 }
00198 }
00199 }
00200 if (all_bits == 15) {
00201 det[15][0] = det[14][1] * (dp[1][1] - dp[1][0]) +
00202 det[14][2] * (dp[2][1] - dp[2][0]) +
00203 det[14][3] * (dp[3][1] - dp[3][0]);
00204 det[15][1] = det[13][0] * (dp[0][0] - dp[0][1]) +
00205 det[13][2] * (dp[2][0] - dp[2][1]) +
00206 det[13][3] * (dp[3][0] - dp[3][1]);
00207 det[15][2] = det[11][0] * (dp[0][0] - dp[0][2]) +
00208 det[11][1] * (dp[1][0] - dp[1][2]) +
00209 det[11][3] * (dp[3][0] - dp[3][2]);
00210 det[15][3] = det[7][0] * (dp[0][0] - dp[0][3]) +
00211 det[7][1] * (dp[1][0] - dp[1][3]) +
00212 det[7][2] * (dp[2][0] - dp[2][3]);
00213 }
00214 }
00215
00216
00217 inline bool GJKCollisionDetector::valid(Int s)
00218 {
00219 for (Int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
00220 if (all_bits & bit) {
00221 if (s & bit) { if (det[s][i] <= 0) return false; }
00222 else if (det[s|bit][i] > 0) return false;
00223 }
00224 }
00225 return true;
00226 }
00227
00228 inline void GJKCollisionDetector::compute_vector(Int bits, Vector3& v)
00229 {
00230 Real sum = 0;
00231 v.setZero();
00232 for (Int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
00233 if (bits & bit) {
00234 sum += det[bits][i];
00235 v += y[i] * det[bits][i];
00236 }
00237 }
00238 v *= 1 / sum;
00239 }
00240
00241 inline void GJKCollisionDetector::compute_points(int bits, Point3& p1, Point3& p2)
00242 {
00243 Real sum = 0;
00244 p1.setZero();
00245 p2.setZero();
00246 for (Int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
00247 if (bits & bit) {
00248 sum += det[bits][i];
00249 p1 += p[i] * det[bits][i];
00250 p2 += q[i] * det[bits][i];
00251 }
00252 }
00253 Real s = 1 / sum;
00254 p1 *= s;
00255 p2 *= s;
00256 }
00257
00258 inline bool GJKCollisionDetector::closest(Vector3& v)
00259 {
00260 compute_det();
00261 for (Int s = bits; s; --s) {
00262 if ((s & bits) == s) {
00263 if (valid(s|last_bit)) {
00264 bits = s|last_bit;
00265 compute_vector(bits, v);
00266 return true;
00267 }
00268 }
00269 }
00270 if (valid(last_bit)) {
00271 bits = last_bit;
00272 v = y[last];
00273 return true;
00274 }
00275
00276 return false;
00277 }
00278
00279
00280 bool GJKCollisionDetector::intersect(ref<const GJKCollisionModel> model1, ref<const GJKCollisionModel> model2,
00281 const base::Transform& t1, const base::Transform& t2,
00282 ref<GJKCollisionModel::GJKModelState> modelState1,
00283 ref<GJKCollisionModel::GJKModelState> modelState2,
00284 ref<GJKCollisionState> collisionState)
00285 {
00286 Vector3 w;
00287 Vector3& v(collisionState->v);
00288
00289 bits = 0;
00290 all_bits = 0;
00291
00292
00293 do {
00294 last = 0;
00295 last_bit = 1;
00296 while (bits & last_bit) { ++last; last_bit <<= 1; }
00297 w = t1(model1->support(modelState1,t1.rotate(-v)))
00298 - t2(model2->support(modelState2,t2.rotate( v)));
00299 if (dot(v, w) > 0) return false;
00300
00301 y[last] = w;
00302 all_bits = bits|last_bit;
00303 if (!closest(v)) {
00304 return false;
00305 }
00306 }
00307 while (bits < 15 && !v.equalsZero() );
00308 return true;
00309 }
00310
00311
00312
00313
00314 osg::Node* GJKCollisionDetector::createOSGVisual(Visual::Attributes visualAttributes) const
00315 {
00316 if (!(visualAttributes & ShowCollisionDetection)) return NewObj osg::Node();
00317
00318 if ((node!=0) && (attributes==visualAttributes))
00319 return &(*node);
00320
00321
00322 geom = new osg::Geometry();
00323
00324 StateSet* state = new osg::StateSet();
00325 osg::Material* mat = new osg::Material();
00326 Vec4 col( 1, 1, 0, 1);
00327 mat->setAmbient( osg::Material::FRONT_AND_BACK, col );
00328 mat->setDiffuse( osg::Material::FRONT_AND_BACK, col );
00329 state->setAttribute( mat );
00330
00331
00332 verts = new osg::Vec3Array(2);
00333 (*verts)[0].set(0,0,0);
00334 (*verts)[1].set(0,0,0);
00335 geom->setVertexArray(verts);
00336
00337 osg::Vec4Array* colors = new osg::Vec4Array(1);
00338 (*colors)[0].set(1.0f,0.0f,0.0f,1.0f);
00339 geom->setColorArray(colors);
00340 geom->setColorBinding(osg::Geometry::BIND_OVERALL);
00341
00342 osg::DrawArrays* linearray = new osg::DrawArrays(osg::PrimitiveSet::LINES,0,2);
00343 geom->addPrimitiveSet(linearray);
00344
00345 osg::Geode* geode = new osg::Geode();
00346 geode = new osg::Geode();
00347 geode->setName("Debug");
00348 geode->addDrawable(&(*geom));
00349
00350 node = geode;
00351 attributes = visualAttributes;
00352
00353 return &(*node);
00354 }
00355