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
00030 #include "worldElement.h"
00031 #include "matvec3D.h"
00032 #include "world.h"
00033 #include "mytools.h"
00034 #include "contact.h"
00035 #include "body.h"
00036 #include "collisionInterface.h"
00037
00038 #ifdef USE_DMALLOC
00039 #include "dmalloc.h"
00040 #endif
00041
00042
00043 #include "debug.h"
00044
00045 #include <QTextStream>
00046
00047 const double WorldElement::ONE_STEP = 1.0e6;
00048
00053 WorldElement::WorldElement(World *w,const char *name) : QObject((QObject *)w,name)
00054 {
00055 myWorld=w; IVRoot=NULL;
00056 if (!name) myName = "unnamed";
00057 else myName = name;
00058 myFilename = "unspecified";
00059 contactsChangedFlag=false;
00060 }
00061
00062
00066 WorldElement::WorldElement(const WorldElement &e) : QObject((QObject *)e.myWorld,e.name())
00067 {
00068 myWorld = e.myWorld;
00069 myName = e.myName;
00070 IVRoot = e.IVRoot;
00071 myFilename = e.myFilename;
00072 contactsChangedFlag = e.contactsChangedFlag;
00073 }
00074
00075
00080 WorldElement::~WorldElement()
00081 {
00082
00083 }
00084
00094 bool
00095 WorldElement::interpolateTo(transf lastTran, transf newTran, const CollisionReport &colReport)
00096 {
00097 vec3 nextTranslation;
00098 Quaternion nextRotation;
00099 transf nextTran;
00100 int numCols = colReport.size();
00101
00102
00103
00104
00105
00106
00107 double t = 0.0, deltat = 1.0, minDist;
00108 bool done = false;
00109
00110 while (!done && deltat > 1.0e-20 && t >= 0) {
00111 DBGP("move interpolation cycle")
00112 deltat /= 2.0;
00113
00114 nextTranslation = (1.0-t)*lastTran.translation() + t*newTran.translation();
00115 nextRotation = Quaternion::Slerp(t,lastTran.rotation(),newTran.rotation());
00116 nextTran = transf(nextRotation,nextTranslation);
00117 DBGP("moving to time : " << t);
00118 if (setTran(nextTran) == FAILURE) {
00119 deltat = 0;
00120 break;
00121 }
00122
00123 minDist = myWorld->getDist(colReport[0].first,colReport[0].second);
00124 for (int i=1; i<numCols; i++) {
00125 double dist = myWorld->getDist(colReport[i].first,colReport[i].second);
00126 minDist = MIN(minDist,dist);
00127 }
00128 DBGP("minDist: " << minDist);
00129 if (minDist > 0) {
00130 if (minDist < Contact::THRESHOLD * 0.5)
00131 break;
00132 t += deltat;
00133 }
00134 else
00135 t -= deltat;
00136
00137
00138 if ( deltat <= 1.0e-20 || t < 0) {
00139 for (int i=0; i<numCols; i++) {
00140 double dist = myWorld->getDist(colReport[i].first,colReport[i].second);
00141 DBGA(colReport[i].first->getName().latin1() << " -- " <<
00142 colReport[i].second->getName().latin1() << " is " << dist);
00143 }
00144 }
00145
00146 }
00147 if (deltat < 1.0e-20 || t < 0) {
00148 DBGP("deltat failsafe or negative t hit; interpolate failure");
00149 fprintf(stdout,"WorldElement interpolation error!\n");
00150 return false;
00151 } else {
00152 DBGP("deltat: " << deltat << "; minDist: " << minDist <<"; interpolate success.");
00153 return true;
00154 }
00155 }
00156
00162 bool WorldElement::jumpTo(transf newTran, CollisionReport *contactReport)
00163 {
00164 int i, numCols;
00165 bool success;
00166 CollisionReport colReport;
00167 transf lastTran = getTran();
00168 if ( setTran(newTran) == FAILURE) return false;
00169
00170 std::vector<Body*> interestList;
00171
00172 getBodyList(&interestList);
00173 contactReport->clear();
00174 while (1) {
00175 numCols = myWorld->getCollisionReport(&colReport, &interestList);
00176 if (!numCols) {
00177 return true;
00178 }
00179
00180 #ifdef GRASPITDBG
00181 for (i=0; i<numCols; i++) {
00182 std::cerr << colReport[i].first->getName().latin1()<<" -- "
00183 << colReport[i].second->getName().latin1() << std::endl;
00184 }
00185 DBGP("I am " << myName.latin1() );
00186 #endif
00187
00188 success = interpolateTo(lastTran, getTran(), colReport );
00189 if (!success) {
00190 return false;
00191 }
00192 contactReport->clear();
00193 for (i=0;i<numCols;i++) {
00194 if (myWorld->getDist(colReport[i].first,colReport[i].second) < Contact::THRESHOLD)
00195 contactReport->push_back(colReport[i]);
00196 }
00197 }
00198 }
00199
00212 bool
00213 WorldElement::moveTo(transf &newTran,double translStepSize, double rotStepSize)
00214 {
00215 bool moveFinished = false;
00216 transf origTran,nextTran,motion;
00217 Quaternion nextRotation;
00218 vec3 nextTranslation;
00219 double percentComplete,moveIncrement,translationLength;
00220 double angle;
00221 vec3 axis;
00222 bool success;
00223
00224 CollisionReport contactReport;
00225
00226
00227
00228 origTran = getTran();
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 translationLength = (newTran.translation() - origTran.translation()).len();
00240 nextRotation = newTran.rotation() * origTran.rotation().inverse();
00241 nextRotation.ToAngleAxis(angle,axis);
00242
00243 moveIncrement = 1.0;
00244 if (translationLength != 0.0) {
00245 if (translStepSize == ONE_STEP)
00246 moveIncrement = 1.0;
00247 else
00248 moveIncrement = MIN(moveIncrement, translStepSize / translationLength);
00249 }
00250 if (angle != 0.0) {
00251 if (rotStepSize == ONE_STEP)
00252 moveIncrement = MIN(moveIncrement, 1.0);
00253 else
00254 moveIncrement = MIN(moveIncrement, rotStepSize / angle);
00255 }
00256
00257
00258 nextTranslation = (1.0-moveIncrement)*origTran.translation() + moveIncrement*newTran.translation();
00259 nextRotation = Quaternion::Slerp(moveIncrement,origTran.rotation(), newTran.rotation());
00260 nextTran = transf(nextRotation,nextTranslation);
00261 motion = nextTran * getTran().inverse();
00262
00263 if (contactsPreventMotion(motion)) {
00264 DBGP("contacts prevent motion")
00265 return false;
00266 }
00267
00268 percentComplete = 0.0;
00269 while (!moveFinished) {
00270 percentComplete += moveIncrement;
00271 if (percentComplete >= 1.0) {
00272 percentComplete = 1.0;
00273 moveFinished = true;
00274 }
00275
00276 nextTranslation = (1.0-percentComplete)*origTran.translation() + percentComplete*newTran.translation();
00277 nextRotation = Quaternion::Slerp(percentComplete,origTran.rotation(), newTran.rotation());
00278 nextTran = transf(nextRotation,nextTranslation);
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 success = jumpTo(nextTran, &contactReport);
00289 if (!success || contactReport.size() != 0) {
00290 moveFinished = true;
00291 }
00292 }
00293
00294 if (!success) {
00295 DBGA("JumpTo error, stopping execution. Object " << myName.latin1() << " in thread "
00296 << getWorld()->getCollisionInterface()->getThreadId());
00297 } else {
00298 myWorld->findContacts(contactReport);
00299 }
00300
00301 if (contactReport.size() != 0) return false;
00302 return true;
00303 }
00304