Quark Physics  1.0
2D Rigid and Soft Body Physics Engine
qmesh.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 QMESH_H
29 #define QMESH_H
30 #include <vector>
31 #include "cmath"
32 #include "qspring.h"
33 #include "qparticle.h"
34 #include "json/json.hpp"
35 #include "fstream"
36 #include "qmath_utils.h"
37 
38 using json =nlohmann::json;
39 
40 using namespace std;
41 
42 class QBody;
47 struct QMesh
48 {
49 public:
50  enum CollisionBehaviors{
51  CIRCLES,
52  POLYGONS,
53  POLYLINE
54  };
55 protected:
56  vector<QParticle*> particles=vector<QParticle*>();
57 
58  //General Properties
59  QVector position=QVector::Zero();
60  QVector globalPosition=QVector::Zero();
61  float rotation=0.0f;
62  float globalRotation=0.0f;
63  vector<QSpring*> springs=vector<QSpring*>();
64  vector <QParticle*> polygon=vector<QParticle*>();
65  vector<vector<QParticle*>> subConvexPolygons=vector<vector<QParticle*>>();
66  float circumference=0.0f;
67  QBody *ownerBody=nullptr;
68  CollisionBehaviors collisionBehavior=CollisionBehaviors::CIRCLES;
69  vector<vector<int>> UVMaps=vector<vector<int>>();
70 
71  bool collisionBehaviorNeedsUpdate=false;
72 
73  //Helper Methods
74  void UpdateCollisionBehavior();
75 
76  //Polygon Properties
77  vector<float> lastPolygonCornerAngles;
78  float minAngleConstraintOfPolygon=M_PI*0.3;
79 
80  //Polygon Methods
81  void UpdateSubConvexPolygons();
82  void ApplyAngleConstraintsToPolygon();
83  bool CheckIsPolygonConcave(vector<QParticle*> polygonParticles);
84  static bool CheckIsReflex(QVector pA,QVector pB, QVector pC);
85  static bool CheckIsReflex(int indexA,int indexB, int indexC, vector<QParticle*> polygonParticles);
86  static void TriangulatePolygon(vector<QParticle*> &polygonParticles,vector<vector<int>> &triangles);
87  static void DecompositePolygon(vector<QParticle*> &polygonParticles,vector<vector<QParticle*>> &polygons);
88  bool subConvexPolygonsNeedsUpdate=false;
89 
90 public:
93  struct MeshData{
95  vector<QVector> particlePositions;
97  vector<float> particleRadValues;
99  vector<bool> particleInternalValues;
103  vector<pair<int,int>> springList;
108  vector<pair<int,int>> internalSpringList;
114  vector<int> polygon;
115 
116 
122  vector<vector<int>> UVMaps;
123 
125  QVector position=QVector::Zero();
126 
128  float rotation=0.0f;
129 
130  };
131 
132  friend class QWorld;
133  friend class QBody;
134  friend class QRigidBody;
135  friend class QSoftBody;
136  friend class QRaycast;
137  friend class QCollision;
138 
140  QMesh();
141  ~QMesh();
142 
143 
144  //General Get Methods
147  return position;
148  }
151  return globalPosition;
152  }
154  float GetRotation(){
155  return rotation;
156  }
159  return globalRotation;
160  }
162  float GetInitialArea(){
163  float res=0.0f;
164  for(size_t n=0;n<GetSubConvexPolygonCount();n++){
165 
166  res+=GetPolygonArea(GetSubConvexPolygonAt(n),true);
167  }
168  for(auto particle:particles){
169  if(particle->GetRadius()>0.5f){
170  res+=particle->GetRadius()*particle->GetRadius();
171  }
172  }
173  return res;
174  }
177  float res=0.0f;
178  for(size_t n=0;n<GetSubConvexPolygonCount();n++){
179  res+=GetPolygonArea(GetSubConvexPolygonAt(n),true);
180  }
181  return res;
182  }
185  float GetArea(){
186  float res=0.0f;
187  for(size_t n=0;n<GetSubConvexPolygonCount();n++){
188  res+=GetPolygonArea(GetSubConvexPolygonAt(n));
189  }
190  for(auto particle:particles){
191  if(particle->GetRadius()>0.5f){
192  res+=particle->GetRadius()*particle->GetRadius();
193  }
194  }
195  return res;
196  }
199  float res=0.0f;
200  for(size_t n=0;n<GetSubConvexPolygonCount();n++){
201  res+=GetPolygonArea(GetSubConvexPolygonAt(n));
202  }
203 
204  return res;
205  }
206 
209  float res=0.0f;
210  for(size_t n=0;n<GetSubConvexPolygonCount();n++){
211  auto polygon=GetSubConvexPolygonAt(n);
212  for(int i=0;i<polygon.size();i++){
213  QParticle *p=polygon[i];
214  QParticle *np=polygon[(i+1)%polygon.size()];
215  float length=(np->GetPosition()-p->GetPosition()).Length();
216  res+=length;
217  }
218  }
219 // for(auto spring:springs){
220 // res+=(spring.GetParticleA()->GetGlobalPosition()-spring.GetParticleB()->GetGlobalPosition()).Length();
221 // }
222  return res;
223  }
228  return ownerBody;
229  }
233  CollisionBehaviors GetCollisionBehavior(){
234  if(collisionBehaviorNeedsUpdate){
235  UpdateCollisionBehavior();
236  collisionBehaviorNeedsUpdate=false;
237  }
238  return collisionBehavior;
239  }
240 
241 
242  //General Set Methods
248  position=value;
249  return this;
250  }
256  globalPosition=value;
257  return this;
258  }
263  QMesh *SetRotation(float value){
264  rotation=value;
265  return this;
266  }
267 
268 
269 
270 
271 
272  //Particle Operations
273 
278  QMesh * AddParticle(QParticle *particle);
279 
284  QMesh * RemoveParticleAt(int index);
289  QMesh * RemoveParticle(QParticle *particle);
292  int GetParticleCount();
296  QParticle *GetParticleAt(int index);
297 
302  int GetParticleIndex(QParticle *particle){
303  for(int i=0;i<particles.size();i++){
304  if(particles[i]==particle){
305  return i;
306  }
307  }
308  return -1;
309  }
310 
311 
312 
313 
314  //Polygon Operations
315 
320  QMesh * SetPolygon(vector<QParticle *> polygonParticles);
321 
328  QMesh * AddParticleToPolygon(QParticle * particle, int position=-1);
329 
336  QMesh *RemoveParticleFromPolygon(QParticle * particle);
337 
344  QMesh * RemoveParticleFromPolygonAt(int index);
345 
350  QMesh * RemovePolygon();
351 
354  int GetPolygonParticleCount();
355 
361  QParticle *GetParticleFromPolygon(int index);
362 
363 
369  return minAngleConstraintOfPolygon;
370  }
371 
378  minAngleConstraintOfPolygon=radian;
379  return this;
380  }
381 
382 
383 
384 
385 
386 
387 
388 
389 
393  QMesh *AddClosedPolygon(vector<QParticle*> polygon);
399 
403  if (subConvexPolygonsNeedsUpdate==true){
404  UpdateSubConvexPolygons();
405  subConvexPolygonsNeedsUpdate=false;
406  }
407  return subConvexPolygons.size();
408  }
412  vector<QParticle*> &GetSubConvexPolygonAt(int index){
413  if (subConvexPolygonsNeedsUpdate==true){
414  UpdateSubConvexPolygons();
415  subConvexPolygonsNeedsUpdate=false;
416  }
417  return subConvexPolygons[index];
418  }
419 
420 
421  //Spring Operations
422 
427  QMesh *AddSpring(QSpring *spring);
432  QMesh *RemoveSpring(QSpring *spring);
437  QMesh *RemoveSpringAt(int index);
442  QMesh *RemoveMatchingSprings(QParticle *particle);
446  return springs.size();
447  }
451  QSpring *GetSpringAt(int index){
452  return springs[index];
453  }
458  int GetSpringIndex(QSpring *spring){
459  for(int i=0;i<springs.size();i++)
460  if(springs[i]==spring)
461  return i;
462  return -1;
463  }
464 
465 
466 
467  //UV Operations
468 
472  return UVMaps.size();
473  };
474 
478  vector<int> GetUVMapAt(int index){
479  return UVMaps[index];
480  };
481 
486  QMesh * AddUVMap(vector<int> map);
487 
493  QMesh * RemoveUVMapAt(int index);
494 
499  QMesh * ClearUVMaps();
500 
501 
502 
503 
508  QMesh * RemoveMatchingUVMaps(int particleIndex);
509 
510 
511 
512 
513 
514 
515 
516  //Static Methods
523  static QMesh * CreateWithCircle(float radius,QVector centerPosition=QVector::Zero());
535  static QMesh * CreateWithPolygon(float radius,int sideCount,QVector centerPosition=QVector::Zero(),int polarGrid=-1,bool enableSprings=true, bool enablePolygons=true,float particleRadius=0.5f);
536 
547  static QMesh * CreateWithRect(QVector size,QVector centerPosition=QVector::Zero(),QVector grid=QVector::Zero(),bool enableSprings=true, bool enablePolygons=true,float particleRadius=0.5f);
548 
555  static QMesh * CreateWithMeshData(QMesh::MeshData &data,bool enableSprings=true, bool enablePolygons=true);
556 
561  static vector<QMesh::MeshData> GetMeshDatasFromFile(string filePath);
562 
563 
568  static vector<QMesh::MeshData> GetMeshDatasFromJsonData(std::string &jsonBasedData);
569 
570 
571 
572 
573 
579  static float GetPolygonArea(vector<QParticle*> &polygonPoints,bool withLocalPositions=false);
580 
581 
589  static bool CheckCollisionBehaviors(QMesh *meshA,QMesh * meshB,CollisionBehaviors firstBehavior,CollisionBehaviors secondBehavior );
598  static MeshData GenerateRectangleMeshData(QVector size,QVector centerPosition=QVector::Zero(),QVector grid=QVector::Zero(),float particleRadius=0.5f);
608  static MeshData GeneratePolygonMeshData(float radius, int sideCount, QVector centerPosition=QVector::Zero(),int polarGrid=-1,float particleRadius=0.5f);
609 
614  static pair<QVector, float> GetAveragePositionAndRotation(vector<QParticle*> particleCollection);
615 
623  static vector<QVector> GetMatchingParticlePositions(vector<QParticle*> particleCollection,QVector targetPosition, float targetRotation);
624 
625 
626 
627 
628 
629 
630 
631 
632 
633 };
634 
635 #endif // QMESH_H
QBody objects are the base class for all types of bodies. Any class derived from QBody shares these m...
Definition: qbody.h:43
The QCollision class performs all collision detection operations. The relevant methods return contact...
Definition: qcollision.h:44
QParticle objects form the network structures of QMesh objects defined for all body object types....
Definition: qparticle.h:37
QVector GetPosition()
Definition: qparticle.h:71
QRaycast objects send a ray into the world and return collision results with body objects....
Definition: qraycast.h:38
QRigidBody is a type of body that is simulated with the dynamics of Rigid body. A rigid body is a typ...
Definition: qrigidbody.h:40
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
Definition: qmesh.h:93
vector< QVector > particlePositions
Definition: qmesh.h:95
vector< pair< int, int > > springList
Definition: qmesh.h:103
vector< bool > particleInternalValues
Definition: qmesh.h:99
vector< int > polygon
Definition: qmesh.h:114
vector< vector< int > > UVMaps
Definition: qmesh.h:122
vector< float > particleRadValues
Definition: qmesh.h:97
vector< pair< int, int > > internalSpringList
Definition: qmesh.h:108
Every QBody object requires meshes. In other traditional physics engines, the term 'shape' is used in...
Definition: qmesh.h:48
vector< QParticle * > & GetSubConvexPolygonAt(int index)
Definition: qmesh.h:412
QVector GetGlobalPosition()
Definition: qmesh.h:150
QSpring * GetSpringAt(int index)
Definition: qmesh.h:451
int GetSpringIndex(QSpring *spring)
Definition: qmesh.h:458
QVector GetPosition()
Definition: qmesh.h:146
float GetRotation()
Definition: qmesh.h:154
QMesh * SetGlobalPosition(QVector value)
Definition: qmesh.h:255
float GetGlobalRotation()
Definition: qmesh.h:158
int GetUVMapCount()
Definition: qmesh.h:471
float GetMinAngleConstraintOfPolygon()
Definition: qmesh.h:368
QMesh * AddClosedPolygon(vector< QParticle * > polygon)
float GetArea()
Definition: qmesh.h:185
int GetParticleIndex(QParticle *particle)
Definition: qmesh.h:302
vector< int > GetUVMapAt(int index)
Definition: qmesh.h:478
QBody * GetOwnerBody()
Definition: qmesh.h:227
float GetInitialPolygonsArea()
Definition: qmesh.h:176
QMesh * SetRotation(float value)
Definition: qmesh.h:263
int GetSpringCount()
Definition: qmesh.h:445
int GetSubConvexPolygonCount()
Definition: qmesh.h:402
QMesh * RemoveClosedPolygonAt(int index)
float GetCircumference()
Definition: qmesh.h:208
float GetInitialArea()
Definition: qmesh.h:162
QMesh * SetPosition(QVector value)
Definition: qmesh.h:247
float GetPolygonsArea()
Definition: qmesh.h:198
QMesh * SetMinAngleConstraintOfPolygon(float radian)
Definition: qmesh.h:377
CollisionBehaviors GetCollisionBehavior()
Definition: qmesh.h:233
Definition: qvector.h:44