Quark Physics  1.0
2D Rigid and Soft Body Physics Engine
qworld.h
1 
2 /************************************************************************************
3  * MIT License
4  *
5  * Copyright (c) 2023 Eray Zesen
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  * https://github.com/erayzesen/QuarkPhysics
25  *
26 **************************************************************************************/
27 
28 #ifndef QWORLD_H
29 #define QWORLD_H
30 #include <iostream>
31 #include <map>
32 #include <vector>
33 #include "qbody.h"
34 #include "qjoint.h"
35 #include "qvector.h"
36 #include "qmanifold.h"
37 #include "qgizmos.h"
38 #include "qbroadphase.h"
39 #include "qcollision.h"
40 #include "qrigidbody.h"
41 #include "qsoftbody.h"
42 #include "qraycast.h"
43 #include "qjoint.h"
44 #include "qmath_utils.h"
45 
46 
47 using namespace std;
51 class QWorld{
52 
53 protected:
54 
55 
56  //Collections
57 
58 
59  vector <QJoint*> joints=vector<QJoint*>();
60 
61  vector <QSpring*> springs=vector<QSpring*>();
62 
63  vector<QRaycast*> raycasts=vector<QRaycast*>();
64 
65  vector <QGizmo*> gizmos=vector<QGizmo*>();
66 
67  vector<vector<QBody*> > sleepingIslands=vector<vector<QBody*> >();
68 
69  unordered_set<pair<QBody*, QBody*>, QBody::BodyPairHash,QBody::BodyPairEqual> collisionExceptions;
70 
71  vector<QManifold> manifolds;
72 
73  //Broadphase
74  QBroadPhase *broadPhase=nullptr;
75 
76 
77 
78  //Physics World Properties
79 
80  bool enabled=true;
81  QVector gravity=QVector(0.0f,0.2f);
82  bool enableSleeping=true;
83  bool enableBroadphase=true;
84  int iteration=4;
85  float timeScale=1.0f;
86 
87 
88  //Sleeping
89  float sleepingPositionTolerance=0.1f;
90  float sleepingRotationTolerance=M_PI/180.0f;
91 
92  //Debug Features
93  int debugAABBTestCount=0; //aabb test method call count
94  int debugCollisionTestCount=0; // any collision method call count
95 
96  void ClearGizmos();
97  void ClearBodies();
98 
99 
100  //Collisions, Dynamic Colliders Islands and Sleeping Feature
101  void CreateIslands(int bodyIndex, vector<QBody*> &bodyList, vector<QBody*> &island, vector<bool> &visitedList);
102  void GenerateIslands(vector<QBody*> &bodyList, vector<vector<QBody*>> &islandList);
103  static bool SortBodiesHorizontal(const QBody *bodyA,const QBody *bodyB);
104  static bool SortBodiesVertical(const QBody *bodyA,const QBody *bodyB);
105  void GetCollisionPairs(vector<QBody *> &bodyList,vector<pair<QBody *, QBody *> > *resList);
106 
107  void CreateIslands(QBody &body, vector<QBody*> island);
108  vector<vector<QBody>> GenerateIslands(vector<QBody> bodyList );
109  float softBodyCollisionHysteresis=0.2f;
110 
111  //Constraints
112  void UpdateConstraints();
113 
114 
115 
116 
117 public:
118 
119 
120 
121  vector<QBody*> bodies=vector<QBody*>();
122 
123  /* It's the maximum world size in pixels. It is used in some calculations that require maximum values. */
124  inline static float MAX_WORLD_SIZE=99999.0f;
125 
126  //General Get Methods
127  /* Returns the gravity force of the world.
128  */
129  QVector GetGravity(){
130  return gravity;
131  }
132 
133 
137  return enableSleeping;
138  }
142  return sleepingPositionTolerance;
143  }
147  return sleepingRotationTolerance;
148  }
152  return enableBroadphase;
153  }
154 
159  return broadPhase;
160  }
161 
162 
167  return iteration;
168  }
169 
171  float GetTimeScale(){
172  return timeScale;
173  }
174 
176  bool GetEnabled(){
177  return enabled;
178  }
182  return softBodyCollisionHysteresis;
183  }
184 
185  //General Set Methods
191  gravity=value;
192  return this;
193  }
198  enableSleeping=value;
199  return this;
200  }
205  sleepingPositionTolerance=value;
206  return this;
207  }
212  sleepingRotationTolerance=value;
213  return this;
214  }
218  enableBroadphase=value;
219  return this;
220  }
221 
226  QWorld *SetBroadphase(QBroadPhase *externalBroadphase){
227  broadPhase=externalBroadphase;
228  if (broadPhase!=nullptr){
229  broadPhase->Clear();
230  }
231  return this;
232  }
233 
234 
240  iteration=value;
241  return this;
242  }
243 
244 
248  QWorld *SetTimeScale(float value=1.0f){
249  if (timeScale!=value){
250  float velocityTimeScaleFactor=0.0f;
251  if(timeScale!=0){
252  if (value<timeScale){
253  velocityTimeScaleFactor=1/timeScale*value;
254  }else{
255  velocityTimeScaleFactor=1.0f;
256  }
257  }
258 
259 
260  for (auto body:bodies){
261  if(body->enableBodySpecificTimeScale==false){
262  //recalculate velocities
263  if (body->bodyType==QBody::BodyTypes::RIGID){
264  QVector vel=body->GetPosition()-body->GetPreviousPosition();
265  vel*=velocityTimeScaleFactor;
266  body->SetPreviousPosition(body->GetPosition()-vel);
267  float rotVel=body->GetRotation()-body->GetPreviousRotation();
268  rotVel*=velocityTimeScaleFactor;
269  body->SetPreviousRotation(body->GetRotation()-rotVel);
270  }else if(body->bodyType!=QBody::BodyTypes::AREA){
271  for(auto mesh :body->_meshes){
272  for (auto particle :mesh->particles){
273  QVector vel=particle->GetGlobalPosition()-particle->GetPreviousGlobalPosition();
274  vel*=velocityTimeScaleFactor;
275  particle->SetPreviousGlobalPosition(particle->GetGlobalPosition()-vel );
276  }
277  }
278  }
279  body->WakeUp();
280 
281 
282  }
283  }
284  timeScale=value;
285  }
286  return this;
287  }
288 
292  QWorld *SetEnabled(bool value){
293  enabled=value;
294  return this;
295  }
296 
302  softBodyCollisionHysteresis=value;
303  return this;
304  }
305 
306 
307  //Methods
310  void Update();
311 
312 
313 
320  static vector<QCollision::Contact*> GetCollisions(QBody *bodyA, QBody *bodyB,bool applyHotSolvers=true);
321 
322 
327  QWorld *AddBody(QBody *body);
332  QWorld *AddBodyGroup(const vector<QBody*> &bodyGroup);
337  QWorld *RemoveBody(QBody *body);
343  QWorld *RemoveBodyAt(int index);
347  return bodies.size();
348  }
352  QBody *GetBodyAt(int index){
353  return bodies[index];
354  }
358  int GetBodyIndex(QBody *body){
359  if(body==nullptr)
360  return -1;
361  for(int i=0;i<bodies.size();i++){
362  if(bodies[i]==body)
363  return i;
364  }
365  return -1;
366  }
373  vector<QBody*> GetBodiesHitByPoint(QVector point,int maxBodyCount=1,bool onlyRigidBodies=true,int layersBit=-1);
381  vector<QParticle*> GetParticlesCloseToPoint(QVector point,float distance,int maxParticleCount=1,bool exceptRigidBodies=true,int layersBit=-1);
385  bool CollideWithWorld(QBody *body);
386 
390  vector<QManifold> TestCollisionWithWorld(QBody *body);
391 
392  //Joint Operations
396  QWorld *AddJoint(QJoint *joint);
400  QWorld *RemoveJoint(QJoint *joint);
405  QWorld *RemoveJointAt(int index);
409  QWorld *RemoveMatchingJoints(QBody *body);
413  return joints.size();
414  }
418  QJoint *GetJointAt(int index){
419  return joints[index];
420  }
424  int GetJointIndex(QJoint *joint){
425  for(int i=0;i<joints.size();i++)
426  if(joints[i]==joint)
427  return i;
428  return -1;
429  }
430 
431  //Spring Operations
435  QWorld *AddSpring(QSpring *spring);
439  QWorld *RemoveSpring(QSpring *spring);
444  QWorld *RemoveSpringAt(int index);
448  QWorld *RemoveMatchingSprings(QBody *body);
452  QWorld *RemoveMatchingSprings(QParticle *particle);
456  return springs.size();
457  }
461  QSpring *GetSpringAt(int index){
462  return springs[index];
463  }
467  int GetSpringIndex(QSpring *spring){
468  for(int i=0;i<springs.size();i++)
469  if(springs[i]==spring)
470  return i;
471  return -1;
472  }
473 
474  //Raycast Operations
478  QWorld *AddRaycast(QRaycast * raycast);
482  QWorld *RemoveRaycast(QRaycast *raycast);
487  QWorld *RemoveRaycastAt(int index);
491  return raycasts.size();
492  }
496  QRaycast *GetRaycastAt(int index){
497  return raycasts[index];
498  }
502  int GetRaycastIndex(QRaycast *raycast){
503  for(int i=0;i<raycasts.size();i++)
504  if(raycasts[i]==raycast)
505  return i;
506  return -1;
507  }
508 
509  //Gizmos Operations
512  vector<QGizmo*> *GetGizmos(){
513  return &gizmos;
514  };
515 
516  //Collision Exceptions
521  QWorld *AddCollisionException(QBody *bodyA, QBody *bodyB);
526  QWorld *RemoveCollisionException(QBody *bodyA, QBody *bodyB);
530  QWorld *RemoveMatchingCollisionException(QBody *body);
535  bool CheckCollisionException(QBody *bodyA, QBody *bodyB);
536 
537  //
540  QWorld();
541  ~QWorld();
544  QWorld *ClearJoints();
547  QWorld *ClearSprings();
550  QWorld *ClearRaycasts();
553  QWorld *ClearWorld();
554 
555  friend class QCollision;
556  friend class QManifold;
557  friend class QSoftBody;
558  friend class QBroadPhase;
559 
560 
561 
562 };
563 
564 #endif // QWORLD_H
QBody objects are the base class for all types of bodies. Any class derived from QBody shares these m...
Definition: qbody.h:43
QVector GetPreviousPosition()
Definition: qbody.h:202
QBody * WakeUp()
Definition: qbody.h:679
float GetPreviousRotation()
Definition: qbody.h:214
float GetRotation()
Definition: qbody.h:206
QVector GetPosition()
Definition: qbody.h:198
QBody * SetPreviousRotation(float angleRadian)
Definition: qbody.h:461
QBody * SetPreviousPosition(QVector value)
Definition: qbody.h:416
Definition: qbroadphase.h:44
The QCollision class performs all collision detection operations. The relevant methods return contact...
Definition: qcollision.h:44
QJoint objects serves to apply various distance constraints between rigid bodies. Additionally,...
Definition: qjoint.h:37
QManifold retrieves collision data from collision tests between two QBody objects using QCollision me...
Definition: qmanifold.h:36
QParticle objects form the network structures of QMesh objects defined for all body object types....
Definition: qparticle.h:40
QRaycast objects send a ray into the world and return collision results with body objects....
Definition: qraycast.h:38
QSoftBody is a body type that defines deformable, soft objects in the physics world....
Definition: qsoftbody.h:35
You can apply distance constraints between 2 particles using the QSpring. The physics engine uses QSp...
Definition: qspring.h:39
A QWorld object is required to create a physics simulation. The QWorld class manages the entire physi...
Definition: qworld.h:51
bool GetEnabled()
Definition: qworld.h:176
QWorld * SetSleepingRotationTolerance(float value)
Definition: qworld.h:211
bool GetBroadphaseEnabled()
Definition: qworld.h:151
QWorld * SetSleepingPositionTolerance(float value)
Definition: qworld.h:204
QWorld * SetTimeScale(float value=1.0f)
Definition: qworld.h:248
QSpring * GetSpringAt(int index)
Definition: qworld.h:461
float GetTimeScale()
Definition: qworld.h:171
int GetBodyCount()
Definition: qworld.h:346
int GetBodyIndex(QBody *body)
Definition: qworld.h:358
int GetIterationCount()
Definition: qworld.h:166
int GetRaycastCount()
Definition: qworld.h:490
float GetSleepingPositionTolerance()
Definition: qworld.h:141
QWorld * SetSoftBodyCollisionHysteresis(float value)
Definition: qworld.h:301
int GetJointCount()
Definition: qworld.h:412
bool GetSleepingEnabled()
Definition: qworld.h:136
QJoint * GetJointAt(int index)
Definition: qworld.h:418
QBody * GetBodyAt(int index)
Definition: qworld.h:352
int GetJointIndex(QJoint *joint)
Definition: qworld.h:424
QRaycast * GetRaycastAt(int index)
Definition: qworld.h:496
QWorld * SetBroadphaseEnabled(bool value)
Definition: qworld.h:217
QWorld * SetSleepingEnabled(bool value)
Definition: qworld.h:197
int GetSpringIndex(QSpring *spring)
Definition: qworld.h:467
QWorld * SetBroadphase(QBroadPhase *externalBroadphase)
Definition: qworld.h:226
QWorld * SetIterationCount(int value)
Definition: qworld.h:239
QWorld * SetGravity(QVector value)
Definition: qworld.h:190
vector< QGizmo * > * GetGizmos()
Definition: qworld.h:512
float GetSoftBodyCollisionHysteresis()
Definition: qworld.h:181
float GetSleepingRotationTolerance()
Definition: qworld.h:146
int GetRaycastIndex(QRaycast *raycast)
Definition: qworld.h:502
QWorld * SetEnabled(bool value)
Definition: qworld.h:292
QBroadPhase * GetBroadphase()
Definition: qworld.h:158
int GetSpringCount()
Definition: qworld.h:455
Definition: qbody.h:77
Definition: qbody.h:69
Definition: qvector.h:44