00001 #ifndef Impala_Application_Videolympics_PhysicsEngine_h
00002 #define Impala_Application_Videolympics_PhysicsEngine_h
00003
00004 #include "OglGui/View.h"
00005
00006 namespace Impala {
00007 namespace Application {
00008 namespace Videolympics {
00009
00010 using namespace OglGui;
00011 class PhysicsPart
00012 {
00013 public:
00014 PhysicsPart(OGLVIEW3D *view, int identifier)
00015 {
00016 mView = view;
00017 mNr = identifier;
00018 view3DSys.GetDimensions(mView, &tX, &tY, &tZ, NULL, NULL, NULL);
00019 mDestroying = false;
00020 tfX = tfY = tfZ = fX = fY = fZ = 0.0f;
00021 }
00022 void
00023 DoPhysics()
00024 {
00025 if (!IsAtTarget()) {
00026 CalcForces();
00027 float aX, aY, aZ;
00028 view3DSys.GetDimensions(mView, &aX, &aY, &aZ, NULL, NULL, NULL);
00029
00030 aX += fX;
00031 aY += fY;
00032 aZ += fZ;
00033 view3DSys.SetDimensions(mView, aX, aY, aZ, FRETAIN, FRETAIN, FRETAIN);
00034 }
00035 }
00036
00037 void
00038 CalcForces()
00039 {
00040 float sFactor = 0.005f;
00041
00042 float aX, aY, aZ;
00043 view3DSys.GetDimensions(mView, &aX, &aY, &aZ, NULL, NULL, NULL);
00044
00045 tfX = (tX - aX);
00046 tfY = (tY - aY);
00047 tfZ = (tZ - aZ);
00048
00049
00050
00051
00052 fX = (tX - aX) * 0.05;
00053 fY = (tY - aY) * 0.05;
00054 fZ = (tZ - aZ) * 0.05;
00055
00056 fX = Limit(fX, 0.2f);
00057 fY = Limit(fY, 0.2f);
00058 fZ = Limit(fZ, 0.2f);
00059 }
00060
00061 float
00062 Limit(float f, float max)
00063 {
00064 if (f > max)
00065 return max;
00066 if (f < -max)
00067 return -max;
00068 return f;
00069 }
00070
00071 void
00072 AddToStack(int stackno)
00073 {
00074 int mStackNo = stackno;
00075 }
00076
00077 void
00078 MoveTo(float x, float y, float z)
00079 {
00080 tX = x; tY = y; tZ = z;
00081 }
00082
00083 void
00084 MoveRelative(float x, float y, float z)
00085 {
00086 tX += x; tY += y; tZ += z;
00087 }
00088
00089
00090
00091
00092 void
00093 DoDestroyPart()
00094 {
00095 mDestroying = true;
00096 }
00097
00098 bool
00099 IsDestroying()
00100 {
00101 return mDestroying;
00102 }
00103
00104 bool
00105 ShouldDestroy()
00106 {
00107 if (mDestroying)
00108 return true;
00109
00110
00111
00112
00113
00114
00115
00116
00117 return false;
00118 }
00119
00120
00121 inline bool
00122 IsAlmost(float a, float r)
00123 {
00124 if (a==r) return true;
00125 if ( (a>r && a - r < 0.01) || (r>a && r - a < 0.01))
00126 return true;
00127 return false;
00128 }
00129
00130 bool
00131 IsAtTarget()
00132 {
00133 float aX, aY, aZ;
00134 view3DSys.GetDimensions(mView, &aX, &aY, &aZ, NULL, NULL, NULL);
00135 if (IsAlmost(aX,tX) && IsAlmost(aY,tY) && IsAlmost(aZ, tZ))
00136 {
00137 return true;
00138 }
00139 return false;
00140 }
00141
00142 private:
00143 bool mRequestDestroy;
00144 bool mDestroying;
00145 float tX, tY, tZ;
00146 float fX, fY, fZ;
00147 float tfX, tfY, tfZ;
00148 OGLVIEW3D *mView;
00149 int mNr;
00150
00151 int mStackNo;
00152
00153 ILOG_VAR_DEC;
00154 };
00155
00156 ILOG_VAR_INIT(PhysicsPart, Visualization.Application.Videolympics);
00157
00158
00159
00160
00161
00162 class PhysicsEngine
00163 {
00164 public:
00165
00166 PhysicsEngine()
00167 {
00168 mParts = std::vector<PhysicsPart*>();
00169 mStacks = std::map<int, std::vector<PhysicsPart*>* >();
00170 mIsFlushing = false;
00171 mFlushCounter = 0;
00172 Impala::CmdOptions& options = Impala::CmdOptions::GetInstance();
00173 mMaxImagesOnRow = options.GetInt("maxImagesOnRow");
00174 ILOG_DEBUG("Max images on row: " << mMaxImagesOnRow);
00175 }
00176
00177 void
00178 RegisterPart(PhysicsPart *p, int stackno)
00179 {
00180 if (mIsFlushing)
00181 {
00182 ILOG_DEBUG("RegisterPart: still flushing, ignored.");
00183 return;
00184 }
00185
00186 if (p == NULL) {
00187 ILOG_ERROR("Trying to register an empty PhysicsPart.");
00188 return;
00189 }
00190 mParts.push_back(p);
00191 std::vector <PhysicsPart*>* s = GetStack(stackno);
00192 s->push_back(p);
00193 MoveStackUp(stackno);
00194 ILOG_DEBUG("Added shot to stack " << stackno << " now " << s->size() << " shots in stack.");
00195 }
00196
00197 void
00198 UnregisterPart(PhysicsPart *p)
00199 {
00200
00201
00202
00203
00204
00205
00206
00207
00208 }
00209
00210 std::vector <PhysicsPart*>*
00211 GetStack(int stackno)
00212 {
00213 if(mStacks.find(stackno) == mStacks.end())
00214 {
00215 mStacks[stackno] = new std::vector<PhysicsPart*>();
00216 }
00217 return mStacks[stackno];
00218 }
00219
00220 void
00221 MoveStackUp(int stackno)
00222 {
00223 if (mIsFlushing)
00224 {
00225 ILOG_DEBUG("MoveStackUp: still flushing, ignored.");
00226 return;
00227 }
00228
00229 std::vector <PhysicsPart*>* s = GetStack(stackno);
00230 ILOG_DEBUG("MoveStackUp: " << stackno << " contains " << s->size() << " shots.");
00231 for (int i = 0; i < s->size(); i++) {
00232 PhysicsPart *p = (*s)[i];
00233 if (p == NULL)
00234 continue;
00235 p->MoveRelative(0.0f, 1.0f, 0.0f);
00236 }
00237
00238 int mMaxStackSize = mMaxImagesOnRow;
00239 if (s->size() > mMaxStackSize)
00240 {
00241 int toRemove = s->size() - mMaxStackSize;
00242 ILOG_DEBUG("Removing " << toRemove << " shots...");
00243 std::vector<PhysicsPart*>::iterator here = s->begin();
00244 while (toRemove > 0)
00245 {
00246 PhysicsPart *p = *here;
00247 if (p == NULL)
00248 continue;
00249 p->DoDestroyPart();
00250 here++;
00251 toRemove--;
00252 }
00253 here--;
00254 s->erase(s->begin(), here);
00255 }
00256 }
00257
00258 void
00259 FlushStacks()
00260 {
00261 if (mIsFlushing)
00262 return;
00263
00264 ILOG_DEBUG("Flushing stacks...");
00265
00266 std::map<int, std::vector<PhysicsPart*>* >::iterator stackiter = mStacks.begin();
00267 for (stackiter = mStacks.begin(); stackiter != mStacks.end(); stackiter++)
00268 {
00269 int stackno = stackiter->first;
00270 ILOG_DEBUG("Cleaning stack " << stackno);
00271 std::vector <PhysicsPart*>* s = GetStack(stackno);
00272 s->clear();
00273 }
00274
00275
00276 for (int i = 0; i < mParts.size(); i++) {
00277 PhysicsPart *p = mParts[i];
00278 if (p == NULL) {
00279 ILOG_ERROR("DoPhysics - PhysicsPart " << i << " = NULL.");
00280 continue;
00281 }
00282
00283 if (p->IsDestroying())
00284 continue;
00285
00286 p->MoveRelative(0.0f, +10.0f, 0.0f);
00287 }
00288
00289 mIsFlushing = true;
00290 mFlushCounter = 100;
00291 }
00292
00293 bool
00294 IsFlushing()
00295 {
00296 return mIsFlushing;
00297 }
00298
00299 void
00300 DoPhysics()
00301 {
00302 int before = mParts.size();
00303 for (int i = 0; i < mParts.size(); i++) {
00304 PhysicsPart *p = mParts[i];
00305 if (p == NULL) {
00306 ILOG_ERROR("DoPhysics - PhysicsPart " << i << " = NULL.");
00307 continue;
00308 }
00309
00310 if (p->IsDestroying())
00311 {
00312 mParts.erase(mParts.begin() + i, mParts.begin() + i + 1);
00313 i--;
00314 continue;
00315 }
00316 p->DoPhysics();
00317 }
00318
00319
00320
00321
00322
00323
00324 if (mIsFlushing)
00325 {
00326 if (mFlushCounter <= 0)
00327 {
00328 ILOG_DEBUG("Flush counter reached zero. Destroying everything in sight.");
00329
00330
00331 for (int i = 0; i < mParts.size(); i++) {
00332 PhysicsPart *p = mParts[i];
00333 if (p == NULL) {
00334 ILOG_ERROR("DoPhysics - PhysicsPart " << i << " = NULL.");
00335 continue;
00336 }
00337
00338 p->DoDestroyPart();
00339 }
00340
00341 mParts.clear();
00342
00343 mIsFlushing = false;
00344 mFlushCounter = 0;
00345 }
00346 mFlushCounter--;
00347 }
00348 }
00349
00350 std::vector<PhysicsPart*> mParts;
00351
00352 std::map<int, std::vector<PhysicsPart*>* > mStacks;
00353
00354 bool mIsFlushing;
00355 int mFlushCounter;
00356 int mMaxImagesOnRow;
00357
00358 ILOG_VAR_DEC;
00359
00360 };
00361
00362 ILOG_VAR_INIT(PhysicsEngine, Visualization.Application.Videolympics);
00363
00364
00365
00366 }
00367 }
00368 }
00369
00370 #endif