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