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/SOLIDCollisionDetector>
00026 #include <gfx/Triangle3>
00027 #include <base/ref>
00028 #include <base/Quat4>
00029
00030 using physics::SOLIDCollisionDetector;
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
00042
00043
00044 void SOLIDCollisionDetectorResponse(void *client_data,
00045 DtObjectRef object1,
00046 DtObjectRef object2,
00047 const DtCollData *coll_data);
00048
00049
00050
00051
00052
00053 SOLIDCollisionDetector::SOLIDCollisionDetector()
00054 : collisionDetectionEnabled(true)
00055 {
00056 if (!SOLIDResponseFunctionRegistered) {
00057
00058 dtSetDefaultResponse(SOLIDCollisionDetectorResponse, DT_SIMPLE_RESPONSE, this);
00059
00060 SOLIDResponseFunctionRegistered = true;
00061 }
00062 else {
00063 Logln("Warning: Only one instance of SOLIDCollisionDetector will function correctly due to SOLID's C API. Sorry.");
00064 }
00065
00066 }
00067
00068
00069 SOLIDCollisionDetector::~SOLIDCollisionDetector()
00070 {
00071 SOLIDResponseFunctionRegistered=false;
00072 }
00073
00074
00075 template<typename T>
00076 inline void* cast_void_ptr(T* p)
00077 { return const_cast<void*>(static_cast<const void*>(p)); }
00078
00079
00080 SOLIDCollisionDetector::SOLIDCollisionState::SOLIDCollisionState(ref<const Solid> solid1, ref<const Solid> solid2,
00081 CollisionModel::CollisionModelType modelType)
00082 : CollisionState(solid1, solid2)
00083 {
00084 ref<const SOLIDCollisionModel> cm1 = narrow_ref<const SOLIDCollisionModel>( solid1->getShape()->getCollisionModel(modelType) );
00085 ref<const SOLIDCollisionModel> cm2 = narrow_ref<const SOLIDCollisionModel>( solid2->getShape()->getCollisionModel(modelType) );
00086
00087 dtCreateObject( cast_void_ptr(&(*solid1)), cm1->getSOLIDShapeRef() );
00088 dtCreateObject( cast_void_ptr(&(*solid2)), cm2->getSOLIDShapeRef() );
00089 }
00090
00091 SOLIDCollisionDetector::SOLIDCollisionState::~SOLIDCollisionState()
00092 {
00093 dtDeleteObject(cast_void_ptr(&(*solid1)));
00094 dtDeleteObject(cast_void_ptr(&(*solid2)));
00095 }
00096
00097
00098
00099
00100 ref<CollisionState> SOLIDCollisionDetector::newCollisionState(ref<const Solid> solid1, ref<const Solid> solid2) const
00101 {
00102 SOLIDCollisionState *sp = NewNamedObj("SOLIDCollisionState") SOLIDCollisionState(solid1, solid2, getType());
00103 return ref<SOLIDCollisionState>(sp);
00104 }
00105
00106 bool SOLIDCollisionDetector::collision(ref<const Solid> solid1, ref<const Solid> solid2, CollisionQueryType queryType)
00107 {
00108 if (!collisionDetectionEnabled) return false;
00109
00110
00111
00112
00113
00114
00115
00116 ref<SOLIDCollisionState> cs(narrow_ref<SOLIDCollisionState>(getCollisionState(solid1,solid2)));
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 dtSelectObject( cast_void_ptr(&(*solid1)) );
00130 dtLoadIdentity();
00131 Quat4 q1(solid1->getOrientation());
00132 dtRotate(q1.v.x, q1.v.y, q1.v.z, q1.w);
00133 Point3 p1(solid1->getPosition());
00134 dtTranslate(p1.x, p1.y, p1.z);
00135
00136 dtSelectObject( cast_void_ptr(&(*solid2)) );
00137 dtLoadIdentity();
00138 Quat4 q2(solid2->getOrientation());
00139 dtRotate(q2.v.x, q2.v.y, q2.v.z, q2.w);
00140 Point3 p2(solid2->getPosition());
00141 dtTranslate(p2.x, p2.y, p2.z);
00142
00143 collided=false;
00144
00145 dtTestObjects( cast_void_ptr(&(*solid1)), cast_void_ptr(&(*solid2)) );
00146
00147 if (collided) {
00148
00149
00150 if ((this->solid1 != solid1) || (this->solid2 != solid2)) {
00151 Debugln("Got unexpected collision callback from another pair of solids. Ignoring.");
00152 return false;
00153 }
00154
00155 const DtScalar* p1 = collision_data->point1;
00156 const DtScalar* p2 = collision_data->point2;
00157 const DtScalar* n = collision_data->normal;
00158 Point3 cp1(p1[0],p1[1],p1[2]);
00159 Point3 cp2(p2[0],p2[1],p2[2]);
00160 Vector3 cn(n[0],n[1],n[2]);
00161 CollisionState::Contact contact(cp1, cp2,cn);
00162
00163 cs->contacts.clear();
00164 cs->contacts.push_back(contact);
00165 Debugln("Collided!!");
00166 }
00167
00168 return collided;
00169 }
00170
00171
00172
00173 void SOLIDCollisionDetector::collisionCallback(DtObjectRef object1, DtObjectRef object2,
00174 const DtCollData* coll_data)
00175 {
00176 if (collided) {
00177 Debugln("collisionCallback() called more than once. Ignoring collision.");
00178 return;
00179 }
00180
00181 collided = true;
00182
00183 solid1 = ref<const Solid>(static_cast<const Solid*>(object1));
00184 solid2 = ref<const Solid>(static_cast<const Solid*>(object2));
00185 collision_data = coll_data;
00186 }
00187
00188
00189
00190
00191 void SOLIDCollisionDetectorResponse(
00192 void *client_data,
00193 DtObjectRef object1,
00194 DtObjectRef object2,
00195 const DtCollData *coll_data)
00196 {
00197 SOLIDCollisionDetector* cd = static_cast<SOLIDCollisionDetector*>(client_data);
00198 cd->collisionCallback(object1, object2, coll_data);
00199 }
00200
00201
00202
00203
00204 bool SOLIDCollisionDetector::SOLIDResponseFunctionRegistered = false;
00205