00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <physics/ODECollisionDetector>
00023
00024 #include <physics/ODECollidableBody>
00025
00026 using physics::ODECollisionDetector;
00027
00028 using base::Vector3;
00029 using physics::CollisionState;
00030 using physics::CollidableBody;
00031 using physics::ODECollidableBody;
00032
00033
00034 #include <physics/SolidConnectedCollidableBody>
00035 using physics::SolidConnectedCollidableBody;
00036
00037
00038
00039 ODECollisionDetector::ODECollisionDetector()
00040 {
00041 }
00042
00043
00044 ODECollisionDetector::~ODECollisionDetector()
00045 {
00046 }
00047
00048
00049 ref<CollidableBody> ODECollisionDetector::createCollidableBody(ref<Shape> shape)
00050 {
00051 return ref<CollidableBody>(NewNamedObj("ODECollidableBody") ODECollidableBody(shape));
00052 }
00053
00054
00055 ODECollisionDetector::ODECollisionState::ODECollisionState(ref<const CollidableBody> collidable1, ref<const CollidableBody> collidable2)
00056 : CollisionState(collidable1, collidable2)
00057 {
00058 }
00059
00060
00061 ODECollisionDetector::ODECollisionState::~ODECollisionState()
00062 {
00063 }
00064
00065
00066
00067
00068 ref<CollisionState> ODECollisionDetector::newCollisionState(ref<const CollidableBody> collidable1, ref<const CollidableBody> collidable2) const
00069 {
00070 if (&(*collidable1) > &(*collidable2))
00071 base::swap(collidable1,collidable2);
00072
00073 return ref<ODECollisionState>(NewNamedObj("ODECollisionState") ODECollisionState(collidable1, collidable2) );
00074 }
00075
00076
00077
00078 void ODECollisionDetector::collide(ref<const Collidable> collidable1, ref<const Collidable> collidable2)
00079 {
00080 if (!isCollisionEnabled()) return;
00081
00082 Assertm( &(*collidable1) != &(*collidable2), "collidable1 is not collidable2");
00083
00084 if (!instanceof(*collidable1, const ODECollidableBody) || !instanceof(*collidable2, const ODECollidableBody))
00085 throw new std::runtime_error(Exception("can only collide() Collidables of type CollidableBody (specifically ODECollidableBody"));
00086
00087 ref<const ODECollidableBody> collidableBody1(narrow_ref<const ODECollidableBody>(collidable1));
00088 ref<const ODECollidableBody> collidableBody2(narrow_ref<const ODECollidableBody>(collidable2));
00089
00090 if (&(*collidableBody1) > &(*collidableBody2))
00091 base::swap(collidableBody1,collidableBody2);
00092
00093
00094 ref<CollisionState> cstate(getCollisionState(collidableBody1,collidableBody2));
00095
00096
00097
00098
00099
00100 dGeomID geomID1 = collidableBody1->getGeomID();
00101 dGeomID geomID2 = collidableBody2->getGeomID();
00102 Assert( !dGeomIsSpace(geomID1) );
00103 Assert( !dGeomIsSpace(geomID2) );
00104
00105
00106 dContactGeom contacts[4];
00107 Int numContacts = dCollide(geomID1, geomID2, 4, contacts, sizeof(dContactGeom));
00108 bool collided = (numContacts != 0);
00109
00110
00111 if (collided) {
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 cstate->contacts.clear();
00122 for (Int c=0; c<numContacts; c++) {
00123 dContactGeom* odeContact(&contacts[c]);
00124
00125 Point3 gcpos(odeContact->pos[0], odeContact->pos[1], odeContact->pos[2]);
00126 Point3 cpos1( inverse(collidableBody1->getConfiguration()) * gcpos );
00127 Point3 cpos2( inverse(collidableBody2->getConfiguration()) * gcpos );
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 Vector3 gnormal( odeContact->normal[0], odeContact->normal[1], odeContact->normal[2] );
00140 Orient inverseRot( collidableBody1->getOrientation() ); inverseRot.invert();
00141 Vector3 normal1 = inverseRot.rotate(gnormal);
00142
00143
00144
00145 CollisionState::Contact contact(cpos1, cpos2, normal1, Real(odeContact->depth) );
00146 cstate->contacts.push_back(contact);
00147 }
00148
00149 notifyListeners(collidable1, collidable2);
00150
00151 }
00152
00153 }
00154