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
00026 #include "collisionAlgorithms.h"
00027 #include "collisionModel.h"
00028
00029
00030 #include "debug.h"
00031
00032
00033
00034 #include "collisionAlgorithms_inl.h"
00035
00036 namespace Collision {
00037
00039
00041
00042 void recursion(const Node *n1, const Node *n2, RecursionCallback *rc)
00043 {
00044 PROF_START_TIMER(COLLISION_RECURSION);
00045
00046
00047
00048 const Node* s;
00049 const Branch *r;
00050
00051
00052
00053 bool nodeSwap = false;
00054 if ( n1->isLeaf() ){
00055 if ( !n2 || n2->isLeaf() ) {
00056
00057 rc->leafTest(static_cast<const Leaf*>(n1), static_cast<const Leaf*>(n2));
00058 PROF_STOP_TIMER(COLLISION_RECURSION);
00059 return;
00060 } else {
00061
00062 s = n1;
00063 r = static_cast<const Branch*>(n2);
00064 nodeSwap = true;
00065 }
00066 } else {
00067 if (!n2 || n2->isLeaf()) {
00068
00069 s = n2;
00070 r = static_cast<const Branch*>(n1);
00071 } else {
00072
00073
00074 if ( n1->getBoxVolume() > n2->getBoxVolume() ) {
00075 r = static_cast<const Branch*>(n1); s = n2;
00076 } else {
00077 r = static_cast<const Branch*>(n2); s = n1;
00078 nodeSwap = true;
00079 }
00080 }
00081 }
00082
00083 const Node* c1 = r->child1();
00084 const Node* c2 = r->child2();
00085
00086
00087
00088
00089
00090 double d1,d2;
00091 if (!nodeSwap) {
00092 d1 = rc->quickTest(c1, s);
00093 d2 = rc->quickTest(c2, s);
00094 } else {
00095 d1 = rc->quickTest(s, c1);
00096 d2 = rc->quickTest(s, c2);
00097 }
00098 if (d2 < d1) {
00099 std::swap(c1,c2);
00100 std::swap(d1,d2);
00101 }
00102
00103
00104 if ( rc->distanceTest(d1) ) {
00105 DBGST( c1->mark(true) );
00106 DBGST( if (s) s->mark(true) );
00107 PROF_STOP_TIMER(COLLISION_RECURSION);
00108
00109 if (!nodeSwap) {
00110 recursion(c1,s,rc);
00111 } else {
00112 recursion(s,c1,rc);
00113 }
00114 PROF_START_TIMER(COLLISION_RECURSION);
00115 }
00116
00117 if ( rc->distanceTest(d2) ) {
00118 DBGST( c2->mark(true) );
00119 DBGST( if (s) s->mark(true) );
00120 PROF_STOP_TIMER(COLLISION_RECURSION);
00121
00122 if (!nodeSwap) {
00123 recursion(c2,s,rc);
00124 } else {
00125 recursion(s,c2,rc);
00126 }
00127 PROF_START_TIMER(COLLISION_RECURSION);
00128 }
00129 PROF_STOP_TIMER(COLLISION_RECURSION);
00130 }
00131
00132 void startRecursion(const CollisionModel *model1, const CollisionModel *model2, RecursionCallback *rc)
00133 {
00134 const Node *node1 = model1->getRoot(), *node2 = NULL;
00135 if (model2) node2 = model2->getRoot();
00136
00137 DBGST( node1->markRecurse(false) );
00138 DBGST( if (node2) node2->markRecurse(false) );
00139
00140 double d = rc->quickTest( node1, node2 );
00141 if (rc->distanceTest(d)) {
00142 DBGST( node1->mark(true) );
00143 DBGST( if (node2) node2->mark(true) );
00144
00145 recursion( node1, node2, rc);
00146 }
00147 }
00148
00149 RecursionCallback::RecursionCallback(const CollisionModel *m1, const CollisionModel *m2) :
00150 mModel1(m1), mModel2(m2)
00151 {
00152 if (mModel2) {
00153 mTran2To1 = mModel2->getTran() * mModel1->getTran().inverse();
00154 mTran1To2 = mModel1->getTran() * mModel2->getTran().inverse();
00155 }
00156 }
00157
00158 void RecursionCallback::printStatistics()
00159 {
00160 DBGA(" Quick tests: " << mNumQuickTests );
00161 DBGA(" Leaf tests: " << mNumLeafTests );
00162 DBGA("Triangle tests: " << mNumTriangleTests);
00163 }
00164
00165 void CollisionCallback::printStatistics() {
00166 DBGA("Collision callback");
00167 RecursionCallback::printStatistics();
00168 DBGA(" Collision: " << mCollision << "\n" );
00169 }
00170
00172 void
00173 ContactCallback::insertContactNoDuplicates(const position &p1, const position &p2,
00174 const vec3 &n1, const vec3 &n2,
00175 double distSq, double thresh)
00176 {
00177 bool insert = true;
00178 ContactReport::iterator cit = mReport.begin();
00179 while(cit!=mReport.end() && insert) {
00180 bool remove = false;
00181 if ( (cit->b1_pos - p1).len_sq() < thresh * thresh ) {
00182 if ( (cit->b2_pos - p2).len_sq() < thresh * thresh ) {
00183
00184 insert = false;
00185 } else {
00186 if (cit->distSq < distSq) {
00187 insert = false;
00188 } else {
00189 remove = true;
00190 }
00191 }
00192 } else if ( (cit->b2_pos - p2).len_sq() < thresh * thresh ) {
00193 if (cit->distSq < distSq) {
00194 insert = false;
00195 } else {
00196 remove = true;
00197 }
00198 }
00199 if (remove) {
00200 cit = mReport.erase(cit);
00201 } else {
00202 cit++;
00203 }
00204 }
00205 if (insert) {
00206 mReport.push_back( ContactData(p1, p2, n1, n2, distSq) );
00207 }
00208 }
00209
00210 void ContactCallback::printStatistics() {
00211 DBGA("Contact callback");
00212 RecursionCallback::printStatistics();
00213 DBGA(" Contacts: " << mReport.size() << "\n" );
00214 }
00215
00216
00217 void DistanceCallback::printStatistics() {
00218 DBGA("Distance callback");
00219 RecursionCallback::printStatistics();
00220 DBGA(" Min dist: " << getMin() << "\n" );
00221 }
00222
00223 void ClosestPtCallback::printStatistics() {
00224 DBGA("Closest pt callback");
00225 RecursionCallback::printStatistics();
00226 DBGA(" Min dist: " << getMin());
00227 DBGA(" Closest point: " << mClosestPt << "\n");
00228 }
00229
00230 void
00231 RegionCallback::printStatistics() {
00232 DBGA("Region Callback");
00233 RecursionCallback::printStatistics();
00234 DBGA(" Pts in region: " << mNeighborhood.size() << "\n");
00235 }
00236
00237 void
00238 RegionCallback::insertPoint(const position &point)
00239 {
00240 Neighborhood::iterator it;
00241 for (it=mNeighborhood.begin(); it!=mNeighborhood.end(); it++) {
00242 if ( *it == point ) break;
00243 }
00244 if (it == mNeighborhood.end()) {
00245 mNeighborhood.push_back(point);
00246 }
00247 }
00248
00249 }