00001
00002 #ifndef DOLOG
00003
00004 #undef DOLOG
00005 #endif
00006
00007
00008 #include <algorithm>
00009 #include <iomanip>
00010 #include <sstream>
00011 #include <stdexcept>
00012
00013 #include "BilliardPhysics.h"
00014 #include "Object.h"
00015 #include "TableBorder.h"
00016 #include "Collision.h"
00017 #include "defines.h"
00018
00019
00022 BilliardPhysics::BilliardPhysics()
00023 : mObjects(),
00024 mBorders(),
00025 mCollisions(),
00026 mTime(0.0f),
00027 mLoadFile(),
00028 mInFile(),
00029 mSaveFile(),
00030 mOutFile()
00031 {
00032 mBorders[0] = new TableBorder("left", TABLE_MIN.z(), true, Vec3f(0, 0, 1));
00033 mBorders[1] = new TableBorder("top", TABLE_MAX.x(), false, Vec3f(-1, 0, 0));
00034 mBorders[2] = new TableBorder("right", TABLE_MAX.z(), true, Vec3f(0, 0, -1));
00035 mBorders[3] = new TableBorder("bottom", TABLE_MIN.x(), false, Vec3f(1, 0, 0));
00036 LOG("");
00037 LOG("physics init");
00038 LOG("------------");
00039 LOG("constants:");
00040 LOG("EPSILON = " << std::setprecision(8) << EPSILON);
00041 LOG("PHYS_EPS = " << std::setprecision(8) << PHYS_EPS);
00042 LOG("MUE_SLIDING = " << std::setprecision(8) << MUE_SLIDING);
00043 LOG("MUE_ROLLING = " << std::setprecision(8) << MUE_ROLLING);
00044 LOG("MUE_BALLS = " << std::setprecision(8) << MUE_BALLS);
00045 LOG("COLLISION_LOSS = " << std::setprecision(8) << COLLISION_LOSS);
00046 LOG("T_IMPULSE = " << std::setprecision(8) << T_IMPULSE);
00047 LOG("GRAVITY = " << std::setprecision(8) << GRAVITY);
00048 LOG("CONTACT_RADIUS = " << std::setprecision(8) << CONTACT_RADIUS);
00049 LOG("BALL_MASS = " << std::setprecision(8) << BALL_MASS);
00050 LOG("FRAME_LENGTH = " << std::setprecision(8) << FRAME_LENGTH);
00051 LOG("");
00052 }
00053
00056 BilliardPhysics::~BilliardPhysics()
00057 {
00058 for (int i=0; i<4; i++)
00059 delete mBorders[i];
00060 for (unsigned int i =0; i<mCollisions.size(); i++)
00061 delete mCollisions[i];
00062 }
00063
00066 void BilliardPhysics::remove(Object * obj)
00067 {
00068 for (std::vector<Object*>::iterator it=mObjects.begin(); it != mObjects.end(); ++it)
00069 {
00070 if ((*it) == obj)
00071 {
00072 mObjects.erase(it);
00073 break;
00074 }
00075 }
00076 }
00077
00078
00081 void BilliardPhysics::step()
00082 {
00083 LOG("physics step()");
00084
00085 if (mLoadFile != "")
00086 {
00087 LOG("Loading frame...");
00088 std::stringstream s;
00089 mInFile.read(reinterpret_cast<char *>(&mTime), sizeof(float));
00090 unsigned int tmp;
00091 mInFile.read(reinterpret_cast<char *>(&tmp), sizeof(unsigned int));
00092 if (tmp != mObjects.size())
00093 {
00094 s << "Unexpected number of objects (" << tmp << ") in file \"" << mLoadFile << "\" ";
00095 s << "should be: " << mObjects.size();
00096 throw std::logic_error(s.str());
00097 }
00098 for (unsigned int i=0; i<mObjects.size(); i++)
00099 {
00100 mObjects[i]->readDump(mInFile);
00101 }
00102 return;
00103 }
00104
00105 createCollisionList();
00106 dumpCollisions();
00107
00108
00109 int nrcollisions = 0;
00110 std::vector<Collision *> sameTime;
00111 while (mCollisions.size() > 0)
00112 {
00113 assert(mCollisions.at(0));
00114 LLOG("collecting");
00115
00116 sameTime.clear();
00117 sameTime.push_back(mCollisions[0]);
00118 unsigned int j = 1;
00119 while (j < mCollisions.size() && mCollisions[j]->time < sameTime[0]->time + EPSILON)
00120 {
00121 assert(mCollisions.at(j));
00122 sameTime.push_back(mCollisions[j]);
00123 j++;
00124 }
00125
00126 LLOG("colliding");
00127
00128 for (unsigned int i = 0; i<sameTime.size(); i++)
00129 {
00130 assert(sameTime.at(i));
00131 sameTime[i]->collide();
00132 nrcollisions++;
00133 }
00134
00135 LLOG("updating");
00136
00137 for (unsigned int i=0; i<mObjects.size(); i++)
00138 {
00139 mObjects[i]->updateProperties(sameTime[0]->time);
00140 }
00141 updateCollisionList(sameTime);
00142 }
00143 LOG("processed " << nrcollisions << " collisions");
00144
00145 LOG("update properties of " << mObjects.size() << " objects");
00146
00147 for (unsigned int i=0; i<mObjects.size(); i++)
00148 {
00149 mObjects[i]->updateProperties(mTime + FRAME_LENGTH);
00150 #ifndef DOLOG
00151 LOG(mObjects[i]->name() << " : pos = " << mObjects[i]->position()
00152 << " v = " << mObjects[i]->velocity() << " w = " << mObjects[i]->angularVelocity());
00153 #endif
00154 }
00155 mTime += FRAME_LENGTH;
00156
00157
00158 if (mSaveFile != "")
00159 {
00160 LOG("Dumping frame...");
00161 mOutFile.write(reinterpret_cast<char *>(&mTime), sizeof(float));
00162 unsigned int tmp = mObjects.size();
00163 mOutFile.write(reinterpret_cast<char *>(&tmp), sizeof(unsigned int));
00164 for (unsigned int i=0; i<mObjects.size(); i++)
00165 {
00166 mObjects[i]->writeDump(mOutFile);
00167 }
00168 mOutFile.flush();
00169 }
00170 }
00171
00172
00175 void BilliardPhysics::createCollisionList()
00176 {
00177 for (unsigned int i =0; i<mCollisions.size(); i++)
00178 delete mCollisions[i];
00179 mCollisions.clear();
00180 for (unsigned int i=0; i<mObjects.size(); i++)
00181 {
00182
00183 for (unsigned int j=i+1; j<mObjects.size(); j++)
00184 {
00185 float time = mTime;
00186 if (willCollide(time, mObjects[i], mObjects[j]))
00187 mCollisions.push_back(new BallCollision(time, mObjects[i], mObjects[j]));
00188 }
00189
00190 for (int j=0; j<4; j++)
00191 {
00192 float time = mTime;
00193 if (willHitBorder(time, mObjects[i], mBorders[j]))
00194 mCollisions.push_back(new BorderCollision(time, mObjects[i], mBorders[j]));
00195 }
00196 }
00197 std::sort(mCollisions.begin(), mCollisions.end(), Collision::compare);
00198 }
00199
00200
00204 bool BilliardPhysics::willCollide(float & time, const Object * o1, const Object * o2) const
00205 {
00206 assert(o1);
00207 assert(o2);
00208 LLOG("testing possible collision of " << o1->name() << " vs " << o2->name() << " time: " << std::setprecision(6) << time);
00209 if (!o1->applyPhysics() || !o2->applyPhysics())
00210 return false;
00211 assert(time >= -0.0f);
00212 assert(o1->time() <= time + EPSILON);
00213 assert(o2->time() <= time + EPSILON);
00214 assert(fabs(o1->time() - o2->time()) < EPSILON);
00215
00216
00217
00218
00219 if (o1 == o2 || time < mTime || mTime + FRAME_LENGTH <= time)
00220 return false;
00221
00222
00223
00224
00225
00226
00227 Vec3f dv = o1->velocity() - o2->velocity();
00228 Vec3f dp = o1->position() - o2->position();
00229 LLOG("dv : " << dv << " |dv| : " << dv.length() << " dp : " << dp << " |dp| : " << dp.length());
00230 LLOG("v1 = " << o1->velocity() << " v2 = " << o2->velocity());
00231 if (dp.length() < BALL_RADIUS*2 - EPSILON)
00232 {
00233
00234 time = o1->time() + EPSILON;
00235 return true;
00236 }
00237 float a = dv.dot(dv);
00238 float b = 2*dp.dot(dv);
00239 float c = dp.dot(dp) - 4*BALL_RADIUS*BALL_RADIUS;
00240 float D = b*b - 4*a*c;
00241
00242 if (D < 0.0f)
00243 return false;
00244 D = sqrtf(D);
00245 float t1;
00246 float t2;
00247 if (fabs(a) > EPSILON)
00248 {
00249 t1 = (- b + D)*0.5f/a;
00250 t2 = (- b - D)*0.5f/a;
00251 }
00252 else
00253 {
00254 if (fabs(b) < EPSILON)
00255 return false;
00256 t1 = -c / b;
00257 t2 = -c / b;
00258 }
00259 t1 += o1->time();
00260 t2 += o2->time();
00261
00262 LLOG("(" << mTime << " .. " << mTime + FRAME_LENGTH << ") time : " << time << " t1 : " << t1 << " t2 : " << t2);
00263
00264 float t = t1;
00265 t1 = t1 < t2 ? t1 : t2;
00266 t2 = t < t2 ? t2 : t;
00267 LLOG("(" << mTime << " .. " << mTime + FRAME_LENGTH << ") time : " << time << " t1 : " << t1 << " t2 : " << t2);
00268 if (time <= t1 && t1 <= mTime + FRAME_LENGTH)
00269 {
00270 time = t1 + EPSILON;
00271 return true;
00272 }
00273 if (time <= t2 && t2 <= mTime + FRAME_LENGTH)
00274 {
00275 time = t2 + EPSILON;
00276 return true;
00277 }
00278 return false;
00279 }
00280
00281
00285 bool BilliardPhysics::willHitBorder(float & time, const Object * obj, const TableBorder * border) const
00286 {
00287 assert(obj);
00288 assert(border);
00289 LLOG("testing possible collision of " << obj->name() << " vs " << border->name() << " border time: " << std::setprecision(6) << time);
00290 assert(time >= -0.0f);
00291 assert(obj->time() <= time + EPSILON);
00292
00293
00294
00295 if (time < mTime || mTime + FRAME_LENGTH <= time)
00296 return false;
00297 for (int i=0; i<4; i++)
00298 if (obj == mBorders[i])
00299 return false;
00300
00301
00302
00303 float t = INFINITY;
00304 if (border->xAligned())
00305 {
00306
00307 if (fabs(obj->velocity().z()) > PHYS_EPS)
00308 {
00309 t = border->dist() - obj->position().z();
00310 LLOG("t = " << t);
00311 if (t * obj->velocity().z() > 0.0f && fabs(t) < BALL_RADIUS - EPSILON)
00312 {
00313 t = time - obj->time();
00314 }
00315 else
00316 {
00317 t = t < 0.0f ? t + BALL_RADIUS : t - BALL_RADIUS;
00318 t /= obj->velocity().z();
00319 }
00320 }
00321 }
00322 else
00323 {
00324
00325 if (fabs(obj->velocity().x()) > PHYS_EPS)
00326 {
00327 t = border->dist() - obj->position().x();
00328 LLOG("t = " << t);
00329 if (t * obj->velocity().x() > 0.0f && fabs(t) < BALL_RADIUS - EPSILON)
00330 {
00331 t = time - obj->time();
00332 }
00333 else
00334 {
00335 t = t < 0.0f ? t + BALL_RADIUS : t - BALL_RADIUS;
00336 t /= obj->velocity().x();
00337 }
00338 }
00339 }
00340 t += obj->time();
00341 LLOG("(" << mTime << " .. " << mTime + FRAME_LENGTH << ") time : " << time << " t : " << t);
00342
00343
00344 if (time - EPSILON < t && t <= mTime + FRAME_LENGTH)
00345 {
00346 time = t + EPSILON;
00347 return true;
00348 }
00349 return false;
00350 }
00351
00352
00358 void BilliardPhysics::updateCollisionList(const std::vector<Collision *> & clsns)
00359 {
00360 assert(clsns.size() > 0);
00361 #ifdef DOLOG
00362 LLOG("collisions to update with:");
00363 for (unsigned int j = 0; j < clsns.size(); j++)
00364 {
00365 assert(clsns[j]);
00366 assert(clsns[j]->first);
00367 assert(clsns[j]->second);
00368 LLOG("clsn " << j << " " << clsns[j]->dump());
00369 }
00370 LLOG(" # # # ");
00371 dumpCollisions();
00372 #endif
00373
00374
00375 std::vector<Collision *> toFree(clsns);
00376 for (unsigned int i = 0; i < mCollisions.size(); )
00377 {
00378 bool notDeleted = true;
00379 for (unsigned int j = 0; j < clsns.size(); j++)
00380 {
00381 if (mCollisions[i]->isAffected(clsns[j]))
00382 {
00383
00384 toFree.push_back(mCollisions[i]);
00385 mCollisions[i] = mCollisions[mCollisions.size()-1];
00386 mCollisions.pop_back();
00387 notDeleted = false;
00388 break;
00389 }
00390 }
00391 if (notDeleted)
00392 i++;
00393 }
00394
00395 LLOG("removed invalid collisions");
00396 dumpCollisions();
00397
00398
00399 for (unsigned int i = 0; i < mObjects.size(); i++)
00400 {
00401 for (unsigned int j = 0; j < clsns.size(); j++)
00402 {
00403 LLOG("current (" << j << " / " << clsns.size() << ") collision: " << clsns.at(j)->dump());
00404
00405 float time = clsns[j]->time;
00406 Collision * cs[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
00407 if (willCollide(time, clsns[j]->first, mObjects[i])
00408 && clsns[j]->second != mObjects[i]
00409 && clsns[j]->time < time)
00410 cs[5] = new BallCollision(time, clsns[j]->first, mObjects[i]);
00411
00412 time = clsns[j]->time;
00413 if (willCollide(time, clsns[j]->second, mObjects[i])
00414 && clsns[j]->first != mObjects[i]
00415 && clsns[j]->time < time)
00416 cs[4] = new BallCollision(time, clsns[j]->second, mObjects[i]);
00417
00418
00419 for (int k=0; k<4; k++)
00420 {
00421 time = clsns[j]->time;
00422 if (willHitBorder(time, mObjects[i], mBorders[k])
00423 && (clsns[j]->first != mObjects[i] || clsns[j]->second != mBorders[k])
00424 && clsns[j]->time < time)
00425 cs[k] = new BorderCollision(time, mObjects[i], mBorders[k]);
00426 }
00427
00428
00429 for (int l=0; l<6; l++)
00430 {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 if (cs[l])
00441 mCollisions.push_back(cs[l]);
00442 }
00443 }
00444 }
00445 LLOG("unsorted");
00446 dumpCollisions();
00447
00448 std::sort(mCollisions.begin(), mCollisions.end(), Collision::ucompare);
00449 LLOG("sorted by duplicates");
00450 dumpCollisions();
00451
00452 Collision * last = NULL;
00453 for (unsigned int i = 0; i < mCollisions.size(); i++)
00454 {
00455 if (last && Collision::predicate(last, mCollisions[i]))
00456 {
00457 delete mCollisions[i];
00458 mCollisions[i] = NULL;
00459 continue;
00460 }
00461 else
00462 {
00463 last = mCollisions[i];
00464 }
00465 for (unsigned int j = 0; j < clsns.size(); j++)
00466 {
00467 if (Collision::predicate(clsns[j], mCollisions[i]))
00468 {
00469 delete mCollisions[i];
00470 mCollisions[i] = NULL;
00471 }
00472 }
00473 }
00474 mCollisions.erase(std::unique(mCollisions.begin(), mCollisions.end(), Collision::predicate), mCollisions.end());
00475 LLOG("deleted");
00476 dumpCollisions();
00477
00478
00479 std::sort(mCollisions.begin(), mCollisions.end(), Collision::compare);
00480 LLOG("sorted by time");
00481 dumpCollisions();
00482 if (mCollisions.size() > 0 && !mCollisions[0])
00483 {
00484 std::vector<Collision *>::iterator endnull = mCollisions.begin();
00485 while (mCollisions.size() > 0 && endnull != mCollisions.end() && !*endnull)
00486 ++endnull;
00487 mCollisions.erase(mCollisions.begin(), endnull);
00488 }
00489 LLOG("no nulls");
00490 dumpCollisions();
00491
00492
00493 LLOG("free memory");
00494 for (unsigned int j = 0; j < toFree.size(); j++)
00495 {
00496 LLOG(j << " / " << toFree.size() << " " << toFree[j] << " " << toFree[j]->dump());
00497 }
00498 std::sort(toFree.begin(), toFree.end());
00499 std::vector<Collision *>::iterator endit = std::unique(toFree.begin(), toFree.end());
00500 for (std::vector<Collision *>::iterator it = toFree.begin(); it != endit; ++it)
00501 delete *it;
00502
00503 LLOG("added new collisions");
00504 dumpCollisions();
00505 LLOG("\n");
00506 }
00507
00510 void BilliardPhysics::dumpCollisions() const
00511 {
00512 #ifdef DOLOG
00513 LOG("dumping " << mCollisions.size() << " collisions:");
00514 for (unsigned int i = 0; i < mCollisions.size(); i++)
00515 {
00516 if (!mCollisions[i])
00517 {
00518 LOG(std::setw(3) << i << " : NULL");
00519 }
00520 else
00521 {
00522 LOG(std::setw(3) << i << " : " << mCollisions[i]->dump());
00523 }
00524 }
00525 LOG("\n");
00526 #endif
00527 }
00528
00529
00534 void BilliardPhysics::dumpToFile(const std::string & file)
00535 {
00536 if (mOutFile)
00537 mOutFile.close();
00538 mOutFile.clear();
00539 if (file == "")
00540 return;
00541 mOutFile.open(file.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
00542 if (!mOutFile)
00543 {
00544 mSaveFile = "";
00545 throw std::logic_error("Can not open file \"" + file + "\" for physics");
00546 }
00547 mSaveFile = file;
00548
00549 int magic = 0x31796870;
00550 mOutFile.write(reinterpret_cast<const char *>(&magic), sizeof(int));
00551
00552 mOutFile.write(reinterpret_cast<const char *>(&BALL_RADIUS), sizeof(float));
00553 mOutFile.write(reinterpret_cast<const char *>(&PHYS_EPS), sizeof(float));
00554 mOutFile.write(reinterpret_cast<const char *>(&MUE_SLIDING), sizeof(float));
00555 mOutFile.write(reinterpret_cast<const char *>(&MUE_ROLLING), sizeof(float));
00556 mOutFile.write(reinterpret_cast<const char *>(&MUE_BALLS), sizeof(float));
00557 mOutFile.write(reinterpret_cast<const char *>(&COLLISION_LOSS), sizeof(float));
00558 mOutFile.write(reinterpret_cast<const char *>(&T_IMPULSE), sizeof(float));
00559 mOutFile.write(reinterpret_cast<const char *>(&GRAVITY), sizeof(float));
00560 mOutFile.write(reinterpret_cast<const char *>(&CONTACT_RADIUS), sizeof(float));
00561 mOutFile.write(reinterpret_cast<const char *>(&BALL_MASS), sizeof(float));
00562 mOutFile.write(reinterpret_cast<const char *>(&SPREAD_POW), sizeof(float));
00563 mOutFile.write(reinterpret_cast<const char *>(&SPREAD_MAX_V), sizeof(float));
00564 mOutFile.write(reinterpret_cast<const char *>(&FRAME_LENGTH), sizeof(float));
00565
00566 mOutFile.clear();
00567 mOutFile.flush();
00568 }
00569
00570
00575 void BilliardPhysics::loadFromFile(const std::string & file)
00576 {
00577 if (mInFile)
00578 mInFile.close();
00579 mInFile.clear();
00580 if (file == "")
00581 return;
00582 mInFile.open(file.c_str(), std::ios::in | std::ios::binary);
00583 if (!mInFile)
00584 {
00585 mLoadFile = "";
00586 return;
00587 }
00588
00589
00590 int magic = 0x31796870;
00591 float tmpf;
00592 std::stringstream strs;
00593 mInFile.read(reinterpret_cast<char *>(&magic), sizeof(int));
00594 if (magic != 0x31796870)
00595 {
00596 strs << "Unknown physics file format \"" << magic << "\", file: \"" << file << "\"";
00597 throw std::logic_error(strs.str());
00598 }
00599
00600 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00601 mInFile.clear();
00602 if (fabs(tmpf - BALL_RADIUS) > EPSILON)
00603 {
00604 strs << "BALL_RADIUS constant differ from built in, expected: " << std::setprecision(8) << BALL_RADIUS;
00605 strs << " got: " << std::setprecision(8) << tmpf;
00606 throw std::logic_error(strs.str());
00607 }
00608
00609 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00610 mInFile.clear();
00611 if (fabs(tmpf - PHYS_EPS) > EPSILON)
00612 {
00613 strs << "PHYS_EPS constant differ from built in, expected: " << std::setprecision(8) << PHYS_EPS;
00614 strs << " got: " << std::setprecision(8) << tmpf;
00615 throw std::logic_error(strs.str());
00616 }
00617
00618 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00619 mInFile.clear();
00620 if (fabs(tmpf - MUE_SLIDING) > EPSILON)
00621 {
00622 strs << "MUE_SLIDING constant differ from built in, expected: " << std::setprecision(8) << MUE_SLIDING;
00623 strs << " got: " << std::setprecision(8) << tmpf;
00624 throw std::logic_error(strs.str());
00625 }
00626
00627 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00628 mInFile.clear();
00629 if (fabs(tmpf - MUE_ROLLING) > EPSILON)
00630 {
00631 strs << "MUE_ROLLING constant differ from built in, expected: " << std::setprecision(8) << MUE_ROLLING;
00632 strs << " got: " << std::setprecision(8) << tmpf;
00633 throw std::logic_error(strs.str());
00634 }
00635
00636 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00637 mInFile.clear();
00638 if (fabs(tmpf - MUE_BALLS) > EPSILON)
00639 {
00640 strs << "MUE_BALLS constant differ from built in, expected: " << std::setprecision(8) << MUE_BALLS;
00641 strs << " got: " << std::setprecision(8) << tmpf;
00642 throw std::logic_error(strs.str());
00643 }
00644
00645 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00646 mInFile.clear();
00647 if (fabs(tmpf - COLLISION_LOSS) > EPSILON)
00648 {
00649 strs << "COLLISION_LOSS constant differ from built in, expected: " << std::setprecision(8) << COLLISION_LOSS;
00650 strs << " got: " << std::setprecision(8) << tmpf;
00651 throw std::logic_error(strs.str());
00652 }
00653
00654 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00655 mInFile.clear();
00656 if (fabs(tmpf - T_IMPULSE) > EPSILON)
00657 {
00658 strs << "T_IMPULSE constant differ from built in, expected: " << std::setprecision(8) << T_IMPULSE;
00659 strs << " got: " << std::setprecision(8) << tmpf;
00660 throw std::logic_error(strs.str());
00661 }
00662
00663 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00664 mInFile.clear();
00665 if (fabs(tmpf - GRAVITY) > EPSILON)
00666 {
00667 strs << "GRAVITY constant differ from built in, expected: " << std::setprecision(8) << GRAVITY;
00668 strs << " got: " << std::setprecision(8) << tmpf;
00669 throw std::logic_error(strs.str());
00670 }
00671
00672 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00673 mInFile.clear();
00674 if (fabs(tmpf - CONTACT_RADIUS) > EPSILON)
00675 {
00676 strs << "CONTACT_RADIUS constant differ from built in, expected: " << std::setprecision(8) << CONTACT_RADIUS;
00677 strs << " got: " << std::setprecision(8) << tmpf;
00678 throw std::logic_error(strs.str());
00679 }
00680
00681 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00682 mInFile.clear();
00683 if (fabs(tmpf - BALL_MASS) > EPSILON)
00684 {
00685 strs << "BALL_MASS constant differ from built in, expected: " << std::setprecision(8) << BALL_MASS;
00686 strs << " got: " << std::setprecision(8) << tmpf;
00687 throw std::logic_error(strs.str());
00688 }
00689
00690 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00691 mInFile.clear();
00692 if (fabs(tmpf - SPREAD_POW) > EPSILON)
00693 {
00694 strs << "SPREAD_POW constant differ from built in, expected: " << std::setprecision(8) << SPREAD_POW;
00695 strs << " got: " << std::setprecision(8) << tmpf;
00696 throw std::logic_error(strs.str());
00697 }
00698
00699 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00700 mInFile.clear();
00701 if (fabs(tmpf - SPREAD_MAX_V) > EPSILON)
00702 {
00703 strs << "SPREAD_MAX_V constant differ from built in, expected: " << std::setprecision(8) << SPREAD_MAX_V;
00704 strs << " got: " << std::setprecision(8) << tmpf;
00705 throw std::logic_error(strs.str());
00706 }
00707
00708 mInFile.read(reinterpret_cast<char *>(&tmpf), sizeof(float));
00709 mInFile.clear();
00710 if (fabs(tmpf - FRAME_LENGTH) > EPSILON)
00711 {
00712 strs << "FRAME_LENGTH constant differ from built in, expected: " << std::setprecision(8) << FRAME_LENGTH;
00713 strs << " got: " << std::setprecision(8) << tmpf;
00714 throw std::logic_error(strs.str());
00715 }
00716
00717 mLoadFile = file;
00718 }
00719
00720