1 /************************************************************************* 2 * * 3 * Tokamak Physics Engine, Copyright (C) 2002-2007 David Lam. * 4 * All rights reserved. Email: david@tokamakphysics.com * 5 * Web: www.tokamakphysics.com * 6 * * 7 * This library is distributed in the hope that it will be useful, * 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * 10 * LICENSE.TXT for more details. * 11 * * 12 *************************************************************************/ 13 14 #ifndef SIMULATOR_H 15 #define SIMULATOR_H 16 17 #define DEFAULT_CONSTRAINT_EPSILON 0.001f 18 19 #define DEFAULT_CONSTRAINT_ITERATION 4 20 21 //#define _DEBUG_REGION 22 23 24 /////////////////////////////////////////////////////////////////// 25 // 26 // Simulator 27 // 28 // 29 /////////////////////////////////////////////////////////////////// 30 /* 31 class neGravityController: public neController 32 { 33 public: 34 neV3 gravity; 35 36 void ControllerUpdate(neRigidBody & rb) 37 { 38 neV3 gforce = gravity; 39 40 gforce *= rb.GetMass(); 41 42 rb.ApplyForceCOG(gforce); 43 } 44 }; 45 */ 46 47 class neFastImpulse 48 { 49 public: 50 neRigidBody_ * bodyA; 51 neRigidBody_ * bodyB; 52 neV3 contactA; 53 neV3 contactB; 54 neM3 k; 55 neM3 kInv; 56 neV3 initRelVel; 57 neM3 collisionFrame; 58 neM3 w2c; 59 f32 relativeSpeedSq; 60 61 public: 62 void Init(); 63 void Update(); 64 void Apply(f32 scale); 65 }; 66 67 68 struct nePhysicsMaterial 69 { 70 f32 friction; 71 f32 resititution; 72 f32 density; 73 }; 74 75 76 /**************************************************************************** 77 * 78 * NE Physics Engine 79 * 80 * Class: neRegion 81 * 82 * Desc: 83 * 84 ****************************************************************************/ 85 class neRegion; 86 87 class neCoordList 88 { 89 public: 90 neDLinkList<CCoordListEntry> coordList; 91 92 void Add(neRigidBodyBase * bb, neRigidBodyBase * hint, s32 hintCoord); 93 94 bool Reserve(s32 size, neAllocatorAbstract * all = NULL) 95 { 96 return coordList.Reserve(size, all); 97 } 98 99 void Sort(bool sortOnly); 100 101 #ifdef _DEBUG 102 103 void OuputDebug(); 104 105 #endif 106 107 s32 dim; 108 109 neByte dimPower2; 110 111 neRegion * region; 112 }; 113 114 typedef struct neOverlappedPair neOverlappedPair; 115 116 struct neOverlappedPair 117 { 118 PLACEMENT_MAGIC 119 neRigidBodyBase * bodyA; 120 neRigidBodyBase * bodyB; 121 }; 122 123 typedef struct neOverlapped neOverlapped; 124 125 struct neOverlapped 126 { 127 neByte status; 128 neOverlappedPair * pairItem; 129 }; 130 131 struct neAddBodyInfo 132 { 133 neRigidBodyBase * body; 134 135 neRigidBodyBase * hint; 136 }; 137 138 class neRegion 139 { 140 public: neRegion()141 neRegion() {} 142 143 // enum { 144 // MAX_OVERLAPPED = 100000, 145 // }; 146 enum { 147 SORT_DIMENSION_X = 1, 148 SORT_DIMENSION_Y = 2, 149 SORT_DIMENSION_Z = 4, 150 }; 151 void Initialise(neFixedTimeStepSimulator * s, neByte sortD = (SORT_DIMENSION_X | SORT_DIMENSION_Y)); 152 153 bool AddBody(neRigidBodyBase * bb, neRigidBodyBase * hint); 154 155 void InsertCoordList(neRigidBodyBase * bb, neRigidBodyBase * hint); 156 157 void RemoveBody(neRigidBodyBase * bb); 158 159 void Update(); 160 161 void Rebuild(); 162 163 neOverlapped * GetOverlappedStatus(neRigidBodyBase * a, neRigidBodyBase * b); 164 165 void ToggleOverlapStatus(neRigidBodyBase * a, neRigidBodyBase * b, neByte dimp2); 166 167 void ResetOverlapStatus(neRigidBodyBase * a, neRigidBodyBase * b); 168 169 void MakeTerrain(neTriangleMesh * tris); 170 171 void FreeTerrain(); 172 GetTriangleTree()173 neTriangleTree & GetTriangleTree() {return terrainTree;} 174 175 ~neRegion(); 176 177 public: 178 neByte sortDimension; 179 180 neFixedTimeStepSimulator * sim; 181 182 s32 maxRigidBodies; 183 184 s32 maxAnimBodies; 185 186 s32 totalBodies; 187 188 s32 maxParticle; 189 190 // neArray<neOverlapped> rb2rb; 191 192 // neArray<neOverlapped> rb2ab; 193 194 neArray<neOverlapped> b2b; 195 196 neArray<neOverlapped> b2p; 197 198 neSimpleArray<neAddBodyInfo> newBodies; 199 200 neDLinkList<neRigidBodyBase *> bodies; 201 202 neDLinkList<neOverlappedPair> overlappedPairs; 203 204 neCoordList coordLists[3]; 205 206 neTriangleTree terrainTree; 207 208 #ifdef _DEBUG_REGION 209 bool debugOn; 210 #endif 211 }; 212 213 214 /**************************************************************************** 215 * 216 * NE Physics Engine 217 * 218 * Class: neCollisionTable_ 219 * 220 * Desc: 221 * 222 ****************************************************************************/ 223 224 class neCollisionTable_ 225 { 226 public: 227 enum 228 { 229 NE_COLLISION_TABLE_MAX = neCollisionTable::NE_COLLISION_TABLE_MAX, 230 }; 231 232 neCollisionTable_(); 233 234 ~neCollisionTable_(); 235 236 void Set(s32 collisionID1, s32 collisionID2, neCollisionTable::neReponseBitFlag flag); 237 238 neCollisionTable::neReponseBitFlag Get(s32 collisionID1, s32 collisionID2); 239 GetMaxCollisionID()240 s32 GetMaxCollisionID() { 241 return NE_COLLISION_TABLE_MAX; 242 }; 243 244 public: 245 neCollisionTable::neReponseBitFlag table[NE_COLLISION_TABLE_MAX][NE_COLLISION_TABLE_MAX]; 246 247 neCollisionTable::neReponseBitFlag terrainTable[NE_COLLISION_TABLE_MAX]; 248 }; 249 250 class nePerformanceData 251 { 252 public: 253 static nePerformanceData * Create(); 254 nePerformanceData()255 nePerformanceData() 256 { 257 Reset(); 258 } Reset()259 void Reset() 260 { 261 dynamic = 0.0f; 262 position = 0.0f; 263 constrain_1 = 0.0f; 264 constrain_2 = 0.0f; 265 cd = 0.0f; 266 cdCulling = 0.0f; 267 terrain = 0.0f; 268 terrainCulling = 0.0f; 269 controllerCallback = 0.0f; 270 } 271 void Start(); 272 void Init(); 273 f32 GetCount(); GetTotalTime()274 f32 GetTotalTime() 275 { 276 return dynamic + 277 position + 278 constrain_1 + 279 constrain_2 + 280 cd + 281 cdCulling + 282 terrain + 283 terrainCulling + 284 controllerCallback; 285 }; 286 287 void UpdateDynamic(); 288 void UpdatePosition(); 289 void UpdateConstrain1(); 290 void UpdateConstrain2(); 291 void UpdateCD(); 292 void UpdateCDCulling(); 293 void UpdateTerrain(); 294 void UpdateTerrainCulling(); 295 void UpdateControllerCallback(); 296 297 f32 dynamic; 298 299 f32 position; 300 301 f32 controllerCallback; 302 303 f32 constrain_1; 304 305 f32 constrain_2; 306 307 f32 cdCulling; 308 309 f32 cd; 310 311 f32 terrain; 312 313 f32 terrainCulling; 314 315 s32 perfFreqAdjust; // in case Freq is too big 316 317 s32 overheadTicks; // overhead in calling timer 318 }; 319 320 class neFixedTimeStepSimulator 321 { 322 public: 323 friend class neRegion; 324 325 enum {MAX_MATERIAL = 256,}; 326 327 neFixedTimeStepSimulator(const neSimulatorSizeInfo & _sizeInfo, neAllocatorAbstract * alloc = NULL, const neV3 * grav = NULL); 328 329 ~neFixedTimeStepSimulator(); 330 331 void Initialise(const neV3& gravity); 332 333 neRigidBody_* CreateRigidBody(neBool isParticle = false); 334 335 neRigidBody_ * CreateRigidBodyFromConvex(TConvex * convex, neRigidBodyBase * originalBody); 336 337 neCollisionBody_* CreateCollisionBody(); 338 339 void Free(neRigidBodyBase * bb); 340 341 void Advance(f32 time, u32 nStep, nePerformanceReport * _perfReport = NULL); 342 343 void Advance(f32 time, f32 minTimeStep, f32 maxTimeStep, nePerformanceReport * _perfReport = NULL); 344 345 void Advance(nePerformanceReport * _perfReport = NULL); 346 347 bool SetMaterial(s32 index, f32 friction, f32 restitution, f32 density); 348 349 bool GetMaterial(s32 index, f32& friction, f32& restitution, f32& density); 350 351 f32 HandleCollision(neRigidBodyBase * bodyA, neRigidBodyBase * bodyB, neCollisionResult & cresult, neImpulseType impulseType, f32 scale = 0.0f); 352 353 void CollisionRigidParticle(neRigidBody_ * ba, neRigidBody_ * bb, neCollisionResult & cresult); 354 355 void SimpleShift(const neCollisionResult & cresult); 356 357 void RegisterPenetration(neRigidBodyBase * bodyA, neRigidBodyBase * bodyB, neCollisionResult & cresult); 358 359 void SetTerrainMesh(neTriangleMesh * tris); 360 361 void FreeTerrainMesh(); 362 363 void CreatePoint2PointConstraint(neRigidBodyBase * bodyA, const neV3 & pointA, neRigidBodyBase * bodyB, const neV3 & pointB); 364 365 neStackHeader * NewStackHeader(neStackInfo *); 366 367 neConstraintHeader * NewConstraintHeader(); 368 369 void CheckStackHeader(); 370 371 neLogOutputCallback * SetLogOutputCallback(neLogOutputCallback * fn); 372 373 neCollisionCallback * SetCollisionCallback(neCollisionCallback * fn); 374 375 void LogOutput(neSimulator::LOG_OUTPUT_LEVEL); 376 377 void SetLogOutputLevel(neSimulator::LOG_OUTPUT_LEVEL lvl); 378 379 void UpdateConstraintControllers(); 380 381 void FreeAllBodies(); 382 383 void GetMemoryAllocated(s32 & memoryAllocated); 384 385 neBool CheckBreakage(neRigidBodyBase * originalBody, TConvex * convex, const neV3 & contactPoint, neV3 & impulse); 386 387 void ResetTotalForce(); 388 389 void AdvanceDynamicRigidBodies(); 390 391 void AdvanceDynamicParticles(); 392 393 void AdvancePositionRigidBodies(); 394 395 void AdvancePositionParticles(); 396 397 void ApplyJointDamping(); 398 399 void ClearCollisionBodySensors(); 400 401 void UpdateAABB(); 402 403 //f32 SolveDynamicLocal(neCollisionResult * cr); 404 405 f32 SolveLocal(neCollisionResult * cr); 406 407 void AddContactConstraint(f32 & epsilon, s32 & iteration); 408 409 void SetGravity(const neV3 & g); 410 411 neV3 CalcNormalImpulse(neCollisionResult & cresult, neBool isContact); 412 413 void ResetStackHeaderFlag(); 414 415 void AddCollisionResult(neCollisionResult & cresult); 416 GetTerrainBody()417 neCollisionBody_ * GetTerrainBody() 418 { 419 return &fakeCollisionBody; 420 } 421 422 public: 423 neSimulatorSizeInfo sizeInfo; 424 425 nePerformanceReport * perfReport; 426 427 nePerformanceData * perf; 428 429 neV3 gravity; 430 431 neV3 gravityVector; 432 433 f32 gravityMag; 434 435 f32 restingSpeed; 436 437 s32 stepSoFar; 438 439 f32 _currentTimeStep; 440 441 f32 oneOnCurrentTimeStep; 442 443 f32 highEnergy; 444 445 // neConstraintSolver solver; 446 447 neDLinkList<neConstraintHeader> constraintHeaders; 448 449 neDLinkList<_neConstraint> constraintHeap; 450 451 // neDLinkList<neMiniConstraint> miniConstraintHeap; 452 453 neDLinkList<neController> controllerHeap; 454 455 neStackInfoHeap stackInfoHeap; 456 457 neStackHeaderHeap stackHeaderHeap; 458 459 neStackHeader stackHeaderX; 460 461 neDLinkList<neSensor_> sensorHeap; 462 463 neDLinkList<TConvex> geometryHeap; 464 465 neSimpleArray<neByte *> pointerBuffer1; 466 467 neSimpleArray<neByte *> pointerBuffer2; 468 469 neSimulator::LOG_OUTPUT_LEVEL logLevel; 470 471 s32 solverStage; 472 473 bool solverLastIteration; 474 475 static char logBuffer[256]; 476 477 neSimpleArray<neCollisionResult> cresultHeap; 478 479 neSimpleArray<neCollisionResult> cresultHeap2; 480 481 neConstraintHeader contactConstraintHeader; 482 483 f32 magicNumber; 484 485 s32 currentRecord; 486 487 f32 timeFromLastFrame; 488 489 f32 lastTimeStep; 490 491 protected: 492 void CheckCollision(); 493 494 void CheckTerrainCollision(); 495 496 void SolveAllConstrain(); 497 498 void SolveOneConstrainChain(f32 epsilon, s32 iteration); 499 500 void ResolvePenetration(); 501 502 void SolveContactConstrain(); 503 504 void CheckIfStationary(); 505 506 nePhysicsMaterial materials[MAX_MATERIAL]; 507 508 public: 509 510 neAllocatorAbstract * allocator; 511 512 neAllocatorDefault allocDef; 513 514 //data 515 516 u32 maxRigidBodies; 517 518 u32 maxAnimBodies; 519 520 u32 maxParticles; 521 522 neDLinkList<neRigidBody_> rigidBodyHeap; 523 524 neDLinkList<neCollisionBody_> collisionBodyHeap; 525 526 neDLinkList<neRigidBody_> rigidParticleHeap; 527 528 neList<neRigidBody_> activeRB; 529 530 neList<neRigidBody_> inactiveRB; 531 532 neList<neCollisionBody_> activeCB; 533 534 neList<neCollisionBody_> inactiveCB; 535 536 neList<neRigidBody_> activeRP; 537 538 neList<neRigidBody_> inactiveRP; 539 540 neList<neCollisionResult> colResults; 541 542 neRegion region; 543 544 neCollisionTable_ colTable; 545 546 neSimpleArray<neTreeNode*> treeNodes; 547 548 neSimpleArray<s32> triangleIndex; 549 550 neCollisionBody_ fakeCollisionBody; 551 552 //state 553 bool buildCoordList; 554 555 //others 556 neCollisionCallback * collisionCallback; 557 558 neLogOutputCallback * logCallback; 559 560 neBreakageCallback * breakageCallback; 561 562 neTerrainTriangleQueryCallback * terrainQueryCallback; 563 564 neCustomCDRB2RBCallback * customCDRB2RBCallback; 565 566 neCustomCDRB2ABCallback * customCDRB2ABCallback; 567 568 s32 idleBodyCount; 569 }; 570 571 #endif 572