Untitled Game engine no.5  1.0
Physics.hpp
1 //
2 // Created by jibbo on 4/3/21.
3 //
4 
5 #ifndef ENGINE_PROJ_PHYSICS_HPP
6 #define ENGINE_PROJ_PHYSICS_HPP
7 
8 #include "Components.hpp"
9 #include "Debug.hpp"
10 #include <pch.hpp>
11 #include "ECS.hpp"
12 #include "Time.hpp"
13 #include "PhysicsParam.hpp"
14 
15 namespace Engine {
19  struct Physics {
20 
25  D2, D3
26  };
27 
28 
29  //<editor-fold desc="Raycasting">
39  static std::vector<CollisionPoint> Raycast(const Scene& scene, glm::vec3 pos, glm::vec3 dir, float maxDistance = FLT_MAX) {
40 
41  std::vector<CollisionPoint> points;
42 // ECS ecs = scene.GetECS();
43 // Shape shape = {glm::mat4{1}, CreateRef<VertexCollider>(std::vector<glm::vec3>{pos, pos + dir * maxDistance})};
44 //
45 // for (auto id : ecs.GetEntitiesWith(ecs.GetArchetype<Transform, Collider>())) {
46 // Ref<Transform> tf = ecs.GetComponent<Transform>(id);
47 // Ref<Collider> c = ecs.GetComponent<Collider>(id);
48 // CollisionPoint cp = GJK_EPA(shape, Shape{tf->GetMatrix(), c});
49 //
50 // if (cp.HasCollision) {
51 // points.emplace_back(cp);
52 // }
53 // }
54 
55  return points;
56  }
57 
67  static CollisionPoint RaycastClosest(const Scene& scene, glm::vec3 pos, glm::vec3 dir, float maxDistance = FLT_MAX) {
68 
69  std::vector<CollisionPoint> points = Raycast(scene, pos, dir, maxDistance);
70  CollisionPoint collisionPoint = {{}, {}, 0, false};
71  float penetration = 0;
72  for (const auto& point : points) {
73  if (point.PenetrationDepth > penetration) {
74  collisionPoint = point;
75  penetration = point.PenetrationDepth;
76  }
77  }
78  return collisionPoint;
79  }
80  //</editor-fold>
81 
82  //<editor-fold desc="GJK & EPA Methods">
83 
88  static CollisionPoint GJK_EPA(const Shape &colliderA, const Shape &colliderB, CollisionType type = D3) {
89  Simplex simplex;
90  if (GJK(colliderA, colliderB, simplex, type)) {
91  if (type == D2) {
92  return CollisionPoint{{}, {}, 0, true};
93  }
94  return EPA2(simplex, colliderA, colliderB);
95  }
96  return CollisionPoint{{}, {}, 0, false};
97  }
98 
99 
111  static CollisionPoint EPA2(Simplex &simplex, const Shape &shapeA, const Shape &shapeB) {
112  Support current{}; // storage for new simplex points
113  Support temp{}; // storage for swapping simplex points
114  Support current_edge[2]; // storage for the current edge used to remove other edges
115  Support l_edges[EPA_MAX_NUM_LOOSE_EDGES][2]; // keep track of edges we need to fix after removing faces
116  FacePoint faces[EPA_MAX_NUM_FACES]; // Array of faces, each with 3 verts and a normal
117 
118  int num_faces = 4; // current number of faces
119  int c_idx; // index of the current closest face
120  int num_loose_edges; // number of current loose edges to delete
121 
122  glm::vec3 search_dir; // current smallest face normal vector. (normal vector that minimizes the simplex point)
123  float u, v, w; // barycentric face coordinates
124  float n_dist; // normal distance, distance to a face along its normal
125  bool found_edge; // edge flag
126  float min_dist; // minimum normal face distance of the epa
127 
128  //Init faces simplex with GJK values
129  faces[0] = {simplex[0], simplex[1], simplex[2]};
130  faces[0].normal = normalize(cross(simplex[1] - simplex[0], simplex[2] - simplex[0])); //ABC
131  faces[1] = {simplex[0], simplex[2], simplex[3]};
132  faces[1].normal = normalize(cross(simplex[2] - simplex[0], simplex[3] - simplex[0])); //ACD
133  faces[2] = {simplex[0], simplex[3], simplex[1]};
134  faces[2].normal = normalize(cross(simplex[3] - simplex[0], simplex[1] - simplex[0])); //ADB
135  faces[3] = {simplex[1], simplex[3], simplex[2]};
136  faces[3].normal = normalize(cross(simplex[3] - simplex[1], simplex[2] - simplex[1])); //BDC
137 
138 
139  for (int iterations = 0; iterations < EPA_MAX_NUM_ITERATIONS; iterations++) {
140  // pre load the minimum distance to the first value and index
141  min_dist = dot(faces[0][0], faces[0].normal);
142  c_idx = 0;
143 
144  // find face that's closest to origin and the distance to it
145  for (int i = 1; i < num_faces; i++) {
146  n_dist = dot(faces[i][0], faces[i].normal);
147  if (n_dist < min_dist) {
148  min_dist = n_dist;
149  c_idx = i;
150  }
151  }
152 
153  search_dir = faces[c_idx].normal; // normal of the closest face
154  furthestDiff(shapeA, shapeB, search_dir, current); // use the closest normal to calculate a new support point
155  n_dist = dot(current, search_dir); // calculate the new normal distance.
156 
157  // Convergence (new point is not significantly further from origin)
158  if (n_dist - min_dist < EPA_TOLERANCE) {
159  // convert barycentric coordinates to world coordinates
160  Barycentric({0, 0, 0}, faces[c_idx][0], faces[c_idx][1], faces[c_idx][2], u, v, w);
161  glm::vec3 v1 = u * faces[c_idx][0].supportA + v * faces[c_idx][1].supportA + w * faces[c_idx][2].supportA;
162  glm::vec3 v2 = u * faces[c_idx][0].supportB + v * faces[c_idx][1].supportB + w * faces[c_idx][2].supportB;
163 
164  return {search_dir, {v1, v2}, n_dist, true};
165  }
166 
167  num_loose_edges = 0; // reset loose edge count
168 
169  // Find all triangles that are facing the current face and remove them
170  for (int i = 0; i < num_faces; i++) {
171  if (dot(faces[i].normal, current - faces[i][0]) > 0) {
172  // triangle i faces p and falls before it on the normal, remove it
173 
174  // Add removed triangle's edges to loose edge list.
175  // If it's already there, remove it (both edges it belonged to are gone)
176  for (int j = 0; j < FACE_VERTS; j++) {
177  current_edge[0] = faces[i][j]; // obtain an edge from a face
178  current_edge[1] = faces[i][(j + 1) % 3]; // mod with size for looping effect
179  found_edge = false;
180 
181  // Check if current edge is already in list
182  for (int k = 0; k < num_loose_edges; k++) {
183  if (l_edges[k][1] == current_edge[0] && l_edges[k][0] == current_edge[1]) {
184  //Edge is already in the list, remove it
185  //THIS ASSUMES EDGE CAN ONLY BE SHARED BY 2 TRIANGLES (which should be true)
186  //THIS ALSO ASSUMES SHARED EDGE WILL BE REVERSED IN THE TRIANGLES (which
187  //should be true provided every triangle is wound CCW)
188  l_edges[k][0] = l_edges[num_loose_edges - 1][0]; // Overwrite current edge
189  l_edges[k][1] = l_edges[num_loose_edges - 1][1]; // with last edge in list
190  num_loose_edges--;
191  found_edge = true;
192  k = num_loose_edges; // exit loop because edge can only be shared once
193  }
194  }
195 
196  // add current edge to list
197  if (!found_edge) {
198 
199  // assert(num_loose_edges<EPA_MAX_NUM_LOOSE_EDGES);
200  if (num_loose_edges >= EPA_MAX_NUM_LOOSE_EDGES) break;
201 
202  l_edges[num_loose_edges][0] = current_edge[0];
203  l_edges[num_loose_edges][1] = current_edge[1];
204  num_loose_edges++;
205  }
206  }
207 
208  // remove triangle i from list
209  faces[i] = faces[num_faces - 1];
210  num_faces--;
211  i--;
212  }
213  }
214 
215  // Reconstruct polytope with p added
216  // Make triangles out of all the loose edges of the polytope connecting all of them to the new point (current)
217  // making a cone with the point being (current) and the loose edges making up the base.
218  for (int i = 0; i < num_loose_edges; i++) {
219 
220  // assert(num_faces<EPA_MAX_NUM_FACES);
221  if (num_faces >= EPA_MAX_NUM_FACES) break;
222 
223  // make a new face with the added point
224  faces[num_faces][0] = l_edges[i][0];
225  faces[num_faces][1] = l_edges[i][1];
226  faces[num_faces][2] = current;
227  faces[num_faces].normal = normalize(cross(l_edges[i][0] - l_edges[i][1], l_edges[i][0] - current));
228 
229  // Check for inverse normal direction to maintain CCW winding,
230  // with a small bias for faces containing the origin
231  if (dot(faces[num_faces][0], faces[num_faces].normal) + EPA_BIAS < 0) {
232  temp = faces[num_faces][0];
233  faces[num_faces][0] = faces[num_faces][1];
234  faces[num_faces][1] = temp;
235  faces[num_faces].normal = -faces[num_faces].normal;
236  }
237  num_faces++;
238  }
239  }
240 
241  // use closest point
242  printf("EPA did not converge\n");
243 
244  search_dir = faces[c_idx].normal;
245  n_dist = dot(faces[c_idx][0], search_dir);
246 
247  Barycentric({0, 0, 0}, faces[c_idx][0], faces[c_idx][1], faces[c_idx][2], u, v, w);
248  glm::vec3 v1 = u * faces[c_idx][0].supportA + v * faces[c_idx][1].supportA + w * faces[c_idx][2].supportA;
249  glm::vec3 v2 = u * faces[c_idx][0].supportB + v * faces[c_idx][1].supportB + w * faces[c_idx][2].supportB;
250 
251  return {search_dir, {v1, v2}, n_dist, true};
252  }
253 
263  static bool GJK(const Shape &colliderA, const Shape &colliderB, Simplex &simplex, CollisionType type) {
264  // get the the first support point in an arbitrary direction
265  Support support = furthestDiff(colliderA, colliderB, glm::vec3{0.f, 0.f, 1.f}, support);
266  glm::vec3 direction = -support; // set the new direction to its inverse
267  simplex += support; // add the first point to the simplex
268  // search for new points
269  for (int iterations = 0; iterations < GJK_MAX_NUM_ITERATIONS; iterations++) {
270  // find new support point
271  furthestDiff(colliderA, colliderB, direction, support);
272 
273  // check if the support point is behind the origin, because this is a convex polygon the shapes do not collide
274  if (dot(support, direction) <= 0) {
275  return type == D2 && simplex.index == 3;
276  }
277 
278  // add the point to the beginning of the list
279  simplex.push(support);
280 
281  // Switch on the next simplex
282  if (NextSimplex(simplex, direction, type)) {
283  return true;
284  }
285  }
286 // printf("GJK did not converge\n");
287  return false;
288  }
289 
290  static bool NextSimplex(Simplex &simplex, glm::vec3 &direction, CollisionType type) {
291  switch (simplex.index) {
292  case 2: return Line(simplex, direction);
293  case 3: return Triangle(simplex, direction);
294  case 4: return type == D2 || Tetrahedron(simplex, direction);
295  }
296 
297  // never should be here
298  return false;
299  }
300 
301  static bool Line(Simplex &simplex, glm::vec3 &direction) {
302  Support& a = simplex[0];
303  Support& b = simplex[1];
304 
305  glm::vec3 ab = b - a;
306  glm::vec3 ao = -a;
307 
308  // if the line is facing the origin,
309  // set the new direction as a perpendicular vector to this and the line to the origin
310  if (dot(ab, ao) > 0) {
311  direction = cross(cross(ab, ao), ab);
312  } else {
313  // otherwise the line is moving further away from the origin and isn't useful to us so remove it
314  simplex = {a};
315  direction = ao;
316  }
317 
318  return false;
319  }
320 
321  static bool Triangle(Simplex &simplex, glm::vec3 &direction) {
322  Support& a = simplex[0];
323  Support& b = simplex[1];
324  Support& c = simplex[2];
325 
326  glm::vec3 ab = b - a;
327  glm::vec3 ac = c - a;
328  glm::vec3 ao = -a;
329 
330  glm::vec3 abc = cross(ab, ac);
331 
332  // compare a new ab to the value of a to the origin
333  if (dot(cross(abc, ac), ao) > 0) {
334  // does ac move toward the origin within the triangle of abc
335  if (dot(ac, ao) > 0) {
336  simplex = {a, c}; // remove point b
337  // search the new direction generated from the triangle with a, c and the origin
338  direction = cross(cross(ac, ao), ac);
339  } else {
340  // otherwise remove point c and maintain the direction
341  return Line(simplex = {a, b}, direction);
342  }
343  } else {
344  // is the triangle made from a new ac closer to the origin, i.e. is the inverse ac pointing towards the origin
345  if (dot(cross(ab, abc), ao) > 0) {
346  // remove the old c and maintain the direction
347  return Line(simplex = {a, b}, direction);
348  } else {
349  // otherwise check if the triangle normal is pointing towards the origin so make it the new direction
350  if (dot(abc, ao) > 0) {
351  direction = abc;
352  } else {
353  // otherwise modify the triangle normal direction by reordering the vertices
354  // keep searching in the opposite of the triangle normal direction
355  simplex = {a, c, b};
356  direction = -abc;
357  }
358  }
359  }
360 
361  return false;
362  }
363 
364  static bool Tetrahedron(Simplex &simplex, glm::vec3 &direction) {
365  Support& a = simplex[0];
366  Support& b = simplex[1];
367  Support& c = simplex[2];
368  Support& d = simplex[3];
369 
370  glm::vec3 ab = b - a;
371  glm::vec3 ac = c - a;
372  glm::vec3 ad = d - a;
373  glm::vec3 ao = -a;
374 
375  glm::vec3 abc = cross(ab, ac);
376  glm::vec3 acd = cross(ac, ad);
377  glm::vec3 adb = cross(ad, ab);
378 
379  // find the tetrahedron face pointing toward the origin and re-evaluate it
380  if (dot(abc, ao) > 0) {
381  return Triangle(simplex = {a, b, c}, direction);
382  }
383 
384  if (dot(acd, ao) > 0) {
385  return Triangle(simplex = {a, c, d}, direction);
386  }
387 
388  if (dot(adb, ao) > 0) {
389  return Triangle(simplex = {a, d, b}, direction);
390  }
391 
392  return true;
393  }
394  //</editor-fold>
395 
396  //<editor-fold desc="XPBD">
401  static void Update(Scene& scene) {
402  if (Debug::getDebug("simulate") == 1) {
403  simulateSystem(scene, (float) Time::dt);
404  }
405 
406  std::vector<Ref<PhysicsEntity>> elements = Collect2DElements(scene);
407  processCollisions(elements, (float) Time::dt, D2);
408  }
409 
422  static void simulateSystem(Scene& scene, float dt) {
423  int numPosIterations = 1;
424  int numSubsteps = 10;
425 
426  float h = dt / (float) numSubsteps; // get minimum time step;
427 
428  std::vector<Ref<PhysicsEntity>> elements = CollectBodiesAndParticles(scene);
429  std::vector<Ref<Joint>> joints = CollectJoints(scene);
430 
431  for (auto &elem : elements) {
432  elem->x = elem->tf->position; // obtain position
433  elem->q = elem->tf->rotation; // obtain rotation
434  elem->v = elem->rb->velocity; // obtain velocity
435  elem->w = elem->rb->w;
436  }
437 
438  for (int sStep = 0; sStep < numSubsteps; sStep++) {
439  for (auto &elem : elements) {
440  // obtain angular velocity
441  if (!elem->rb->kinematic)
442  continue;
443 
444  elem->xPrev = elem->x; // set the previous x (for calculating dx later)
445  elem->qPrev = elem->q; // save the previous rotation
446 
447  // get acceleration from force and then multiply by time to get delta v
448  elem->v += h * elem->rb->force * elem->rb->iMass;
449  elem->x += h * elem->v; // move by total v
450 
451  glm::mat3 t1 = elem->rb->invMoment;
452  glm::mat3 t2 = elem->rb->moment;
453 
454  // increase the angular momentum by the torque
455  elem->w += h * t1 * (elem->rb->t - glm::cross(elem->w, (t2 * elem->w)));
456 
457  // increase the rotation by 1/2 t (probably due to the derivative of a^2)
458  elem->q = elem->q + (h * 0.5f) * glm::qua<float>{0, elem->w.x, elem->w.y, elem->w.z} * elem->q;
459  elem->q = glm::normalize(elem->q);
460 
461  elem->clearMat();
462  }
463 
464  for (int _ = 0; _ < numPosIterations; _++) {
465  processCollisions(elements, h);
466  processJoints(joints, h);
467  }
468 
469  for (auto &elem : elements) {
470  // calculate velocity from position change
471  elem->v = (elem->x - elem->xPrev) / h;
472  // calculate change in rotation
473  elem->dQ = elem->q * glm::inverse(elem->qPrev);
474  // convert from angular change to angular velocity
475  elem->w = (2.0f / h) * glm::vec3(elem->dQ.x, elem->dQ.y, elem->dQ.z);
476  // rotate in the correct direction
477  elem->w = elem->dQ.w >= 0 ? elem->w : -elem->w;
478 
479  elem->v -= elem->v * glm::min(1.0f, h * elem->rb->airDrag);
480  elem->w -= elem->w * glm::min(1.0f, h * elem->rb->angularDrag);
481  }
482  }
483 
484  for (auto &elem : elements) {
485  // apply changes
486  elem->tf->position = elem->x;
487  elem->tf->rotation = elem->q;
488  if (!elem->rb->kinematic)
489  continue;
490  elem->rb->velocity = elem->v;
491  elem->rb->w = elem->w;
492  }
493  }
494 
504  const Ref<PhysicsEntity> &pe1,
505  const Ref<PhysicsEntity> &pe2) {
506  glm::vec3 p1 = pe1->x + pe1->q * joint->positionA;
507  glm::vec3 p2;
508  if (pe2 == nullptr) {
509  p2 = joint->positionB;
510  } else {
511  p2 = pe2->x + pe2->q * joint->positionB;
512  }
513 
514 
515  glm::vec3 normal = p2 - p1;
516  float sqrDist = glm::length2(normal);
517  if (sqrDist > joint->maxLength * joint->maxLength) {
518  float invDepth = glm::inversesqrt(sqrDist);
519  return CollisionPoint{normal * invDepth, {p1, p2}, joint->maxLength - (1.0f/invDepth), true};
520  } else if (sqrDist < joint->minLength * joint->minLength) {
521 
522  float invDepth = glm::inversesqrt(sqrDist);
523  return CollisionPoint{normal * -invDepth, {p1, p2}, (1.0f/invDepth) - joint->minLength, true};
524  } else {
525 
526  return CollisionPoint{{}, {}, 0, false};
527  }
528  }
529 
536  static void processJoints(const std::vector<Ref<Joint>> &joints, float h) {
537  for (const auto& joint : joints) {
538  Ref<PhysicsEntity> pe1 = joint->rigidBody->physicsEntity;
539  Ref<PhysicsEntity> pe2 = joint->connectedRigidBody->physicsEntity;
540 
541  CollisionPoint cp = processJoint(joint, pe1, pe2);
542  if (cp.HasCollision) {
543  applyManifold(cp, pe1, pe2, h);
544  }
545  }
546  }
547 
557  static void processCollisions(std::vector<Ref<PhysicsEntity>> &elements, float h, CollisionType type = D3) {
558  for (int i = 0; i < elements.size(); ++i) {
559  Ref<PhysicsEntity> pe1 = elements[i];
560  if (pe1->c == nullptr) continue;
561 
562  for (int j = i + 1; j < elements.size(); ++j) {
563  Ref<PhysicsEntity> pe2 = elements[j];
564  if (pe2->c == nullptr) continue;
565  CollisionPoint cp = GJK_EPA(Shape{pe1},Shape{pe2}, type);
566  if (cp.HasCollision) {
567  pe1->c->processCollision(pe2);
568  pe2->c->processCollision(pe1);
569  if (!pe1->c->trigger && !pe2->c->trigger && type != D2) {
570  applyManifold(cp, pe1, pe2, h);
571  }
572  }
573  }
574  }
575  }
576 
577 
587  float a = 0;
588  float lambda = 0;
589 
590  bool e1Static = (e1 == nullptr) || !e1->rb->kinematic;
591  bool e2Static = (e2 == nullptr) || !e2->rb->kinematic;
592 
593  if (e1Static && e2Static) {
594  return;
595  }
596 
597  glm::vec3 r1 = e1Static ? cp.contacts[0] : cp.contacts[0] - e1->x;
598  glm::vec3 r2 = e2Static ? cp.contacts[1] : cp.contacts[1] - e2->x;
599 
600  float w1 = 0;
601  if (!e1Static) {
602  // convert the normal vector to model space
603  glm::vec3 prod1 = glm::cross(r1, cp.Normal);
604  // calculate the mass impulse or mass amount of resistance in the direction (0 is non moving)
605  w1 = e1->rb->iMass + glm::dot(prod1, e1->rb->invMoment * prod1);
606  }
607 
608  float w2 = 0;
609  if (!e2Static) {
610  // same for e2
611  glm::vec3 prod2 = glm::cross(r2, cp.Normal);
612  w2 = e2->rb->iMass + glm::dot(prod2, e2->rb->invMoment * prod2);
613  }
614 
615  // calculate the stiffness of the interaction (0 is completely stiff)
616  float aTilde = a / (h * h);
617 
618  // compute the lagrangian multiplier
619  // note that whenever there is an interaction there should be a non-zero
620  // w1 + w2 + atilde
621  // we need to check that if both bodies have a imass of 0 this calculation is not preformed.
622  float dLambda = (-cp.PenetrationDepth - (aTilde * lambda)) / (w1 + w2 + aTilde);
623  glm::vec3 p = dLambda * cp.Normal; // calculate the positional impulse
624 
625  // move by the positional impulse multiplied by the inverse mass
626  // this will translate the impulse back to a change in position
627  // calculate the change in rotation
628  // convert normal to object space and invert the rotational inerta (not 100% sure about this)
629  if (!e1Static) {
630  e1->x += p * e1->rb->iMass;
631  e1->q += 0.5f * glm::qua<float>{0.f, e1->rb->invMoment * glm::cross(r1, p)} * e1->q;
632  e1->clearMat();
633  }
634  if (!e2Static) {
635  e2->x -= p * e2->rb->iMass;
636  e2->q -= 0.5f * glm::qua<float>{0.f, e2->rb->invMoment * glm::cross(r2, p)} * e2->q;
637  e2->clearMat();
638  }
639 
640 
641  }
642 
649  static std::vector<Ref<Joint>> CollectJoints(const Scene& scene) {
650  ECS ecs = scene.GetECS();
651  auto out = std::vector<Ref<Joint>>();
652 
653  auto s_rb = CreateRef<RigidBody>();
654  s_rb->setMomentCube(0, 0, 0, 0);
655 
656  for (auto id : ecs.GetEntitiesWith(ecs.GetArchetype<Joint, RigidBody>())) {
657  Ref<Joint> joint = ecs.GetComponent<Joint>(id);
658  Ref<RigidBody> rb = ecs.GetComponent<RigidBody>(id);
659  joint->rigidBody = rb;
660 
661  if (joint->connectedRigidBody == nullptr) {
662  joint->connectedRigidBody = s_rb;
663  }
664 
665  out.emplace_back(joint);
666  }
667 
668  return out;
669  }
670 
677  static std::vector<Ref<PhysicsEntity>> CollectBodiesAndParticles(Scene& scene) {
678  auto out = std::vector<Ref<PhysicsEntity>>();
679  auto s_rb = CreateRef<RigidBody>();
680  s_rb->setMomentCube(0, 0, 0, 0);
681  s_rb->kinematic = false;
682 
683  ECS ecs = scene.GetECS();
684  for (auto id : ecs.GetEntitiesWith(ecs.GetArchetype<Transform,Collider>())) {
685  Ref<Transform> tf = ecs.GetComponent<Transform>(id);
686  Ref<Collider> cl = ecs.GetComponent<Collider>(id);
687  Ref<RigidBody> rb = ecs.GetComponent<RigidBody>(id);
688 
689  if (rb == nullptr) {
690  rb = s_rb;
691  }
692 
693  Ref<Entity> e = CreateRef<Entity>(id, &scene);
694  Ref<PhysicsEntity> physicsEntity = CreateRef<PhysicsEntity>(e, tf, cl, rb);
695  rb->physicsEntity = physicsEntity;
696 
697  out.emplace_back(physicsEntity);
698  }
699 
700  return out;
701  };
702 
708  static std::vector<Ref<PhysicsEntity>> Collect2DElements(Scene& scene) {
709  auto out = std::vector<Ref<PhysicsEntity>>();
710  auto s_rb = CreateRef<RigidBody>();
711  s_rb->setMomentCube(0, 0, 0, 0);
712  s_rb->kinematic = false;
713 
714  ECS ecs = scene.GetECS();
715  for (auto id : ecs.GetEntitiesWith(ecs.GetArchetype<Transform, Collider2D>())) {
716  Ref<Transform> tf = ecs.GetComponent<Transform>(id);
717  Ref<Collider> cl = ecs.GetComponent<Collider2D>(id);
718  Ref<RigidBody> rb = ecs.GetComponent<RigidBody>(id);
719 
720  if (rb == nullptr) {
721  rb = s_rb;
722  }
723 
724  Ref<Entity> e = CreateRef<Entity>(id, &scene);
725  Ref<PhysicsEntity> physicsEntity = CreateRef<PhysicsEntity>(e, tf, cl, rb);
726 
727  rb->physicsEntity = physicsEntity;
728  physicsEntity->x = physicsEntity->tf->position; // obtain position
729  physicsEntity->q = physicsEntity->tf->rotation; // obtain rotation
730  out.emplace_back(physicsEntity);
731  }
732 
733  return out;
734  };
735  //</editor-fold>
736 
737  //<editor-fold desc="Vector-Math Functions">
746  static Support furthestDiff(const Shape &shapeA, const Shape &shapeB, const glm::vec3 &norm, Support &support) {
747  support.supportA = shapeA.furthestInDir(norm);
748  support.supportB = shapeB.furthestInDir(-norm);
749  return support = support.supportA - support.supportB;
750  }
751 
768  static void Barycentric(const glm::vec3 &p, const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c,
769  float &u, float &v, float &w) {
770  glm::vec3 v0 = b - a, v1 = c - a, v2 = p - a;
771  float d00 = dot(v0, v0);
772  float d01 = dot(v0, v1);
773  float d11 = dot(v1, v1);
774  float d20 = dot(v2, v0);
775  float d21 = dot(v2, v1);
776  float invDenom = 1.0f / (d00 * d11 - d01 * d01);
777  v = (d11 * d20 - d01 * d21) * invDenom;
778  w = (d00 * d21 - d01 * d20) * invDenom;
779  u = 1.0f - v - w;
780  }
781  //</editor-fold>
782  };
783 }
784 
785 #endif //ENGINE_PROJ_PHYSICS_HPP
Engine::Physics::furthestDiff
static Support furthestDiff(const Shape &shapeA, const Shape &shapeB, const glm::vec3 &norm, Support &support)
Definition: Physics.hpp:746
Engine::Collider
Generic type storage for a GJK enabled collider.
Definition: Components.hpp:32
Engine::Physics::Collect2DElements
static std::vector< Ref< PhysicsEntity > > Collect2DElements(Scene &scene)
Definition: Physics.hpp:708
Engine::Physics::simulateSystem
static void simulateSystem(Scene &scene, float dt)
Simulate the scene elements by a delta t Partially Implements Extended Position Based Dynamics.
Definition: Physics.hpp:422
Engine::ECS
Entity Component System.
Definition: ECS.hpp:19
Engine::Collider2D
Wrapper for 2D collisions. Tells the physics system that you want to process a 2D collision and not a...
Definition: Components.hpp:496
Engine::CollisionPoint::PenetrationDepth
float PenetrationDepth
delta x of the contact
Definition: Components.hpp:166
Engine::Scene
A container for entities currently in the Scene.
Definition: Scene.hpp:9
Engine::Simplex
Storage wrapper for support points.
Definition: Components.hpp:177
Engine::Transform
Location, orientation, and scale of an entity.
Definition: Components.hpp:312
Engine::Physics::applyManifold
static void applyManifold(CollisionPoint cp, Ref< PhysicsEntity > &e1, Ref< PhysicsEntity > &e2, float h)
Definition: Physics.hpp:586
Engine::Physics::processCollisions
static void processCollisions(std::vector< Ref< PhysicsEntity >> &elements, float h, CollisionType type=D3)
Generate collision data and solve it.
Definition: Physics.hpp:557
Engine::Physics::EPA2
static CollisionPoint EPA2(Simplex &simplex, const Shape &shapeA, const Shape &shapeB)
Expanding Polytope Algorithm Implementation Calculates the separation normal from a colliding GJK sim...
Definition: Physics.hpp:111
Engine::Shape
Definition: Components.hpp:122
Engine::Physics::CollectJoints
static std::vector< Ref< Joint > > CollectJoints(const Scene &scene)
Definition: Physics.hpp:649
Engine::Simplex::index
size_t index
support point list (max 4)
Definition: Components.hpp:179
Engine::Ref
std::shared_ptr< T > Ref
Has stuff for making references a lot more easily shared smart pointer.
Definition: Base.hpp:21
Engine::Physics::RaycastClosest
static CollisionPoint RaycastClosest(const Scene &scene, glm::vec3 pos, glm::vec3 dir, float maxDistance=FLT_MAX)
Definition: Physics.hpp:67
Engine::ECS::GetEntitiesWith
std::vector< EntityID > GetEntitiesWith()
Definition: ECS.hpp:188
Engine::Physics::GJK_EPA
static CollisionPoint GJK_EPA(const Shape &colliderA, const Shape &colliderB, CollisionType type=D3)
Combination Gilbert-Johnson-Keerthi Expanding-Polytope-Algorithm TODO: (not fully memory optimized)
Definition: Physics.hpp:88
Engine::Support
GJK support point structure. stores the resulting support point and the components that made it up....
Definition: Components.hpp:136
Engine::CollisionPoint::HasCollision
bool HasCollision
does the point actually represent a collision
Definition: Components.hpp:168
Engine::Physics::GJK
static bool GJK(const Shape &colliderA, const Shape &colliderB, Simplex &simplex, CollisionType type)
Gilbert-Johnson-Keerthi collision detection algorithm https://blog.winter.dev/2020/gjk-algorithm/ imp...
Definition: Physics.hpp:263
Engine::ECS::GetArchetype
Archetype GetArchetype(EntityID id)
Definition: ECS.hpp:73
Engine::FacePoint
Storage for the expanding polytope algorithm.
Definition: Components.hpp:240
Engine::Physics::CollectBodiesAndParticles
static std::vector< Ref< PhysicsEntity > > CollectBodiesAndParticles(Scene &scene)
Definition: Physics.hpp:677
Engine::Physics::CollisionType
CollisionType
Definition: Physics.hpp:24
Engine::CollisionPoint::contacts
std::vector< glm::vec3 > contacts
contact points in global space
Definition: Components.hpp:164
Engine::ECS::GetComponent
Ref< C > GetComponent(const EntityID &id)
Definition: ECS.hpp:80
Engine::CollisionPoint::Normal
glm::vec3 Normal
normal vector
Definition: Components.hpp:162
Engine::Physics::Barycentric
static void Barycentric(const glm::vec3 &p, const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c, float &u, float &v, float &w)
Definition: Physics.hpp:768
Engine
Definition: Animation.hpp:14
Engine::Joint
Physics Component that represents a joint between rigidbodies. Intended to be connected to a Entity a...
Definition: Components.hpp:270
Engine::Physics::Raycast
static std::vector< CollisionPoint > Raycast(const Scene &scene, glm::vec3 pos, glm::vec3 dir, float maxDistance=FLT_MAX)
Definition: Physics.hpp:39
Engine::Debug::getDebug
static float & getDebug(const std::string &key)
Definition: Debug.cpp:18
Engine::Time::dt
static double dt
time since last update
Definition: Time.hpp:12
Engine::Physics
Definition: Physics.hpp:19
Engine::Physics::Update
static void Update(Scene &scene)
Definition: Physics.hpp:401
Engine::Physics::processJoint
static CollisionPoint processJoint(const Ref< Joint > &joint, const Ref< PhysicsEntity > &pe1, const Ref< PhysicsEntity > &pe2)
Definition: Physics.hpp:503
Engine::RigidBody
Physics rigidbody component. Stores the physical parameters of an object. Such as moment of inertia,...
Definition: Components.hpp:376
Engine::Physics::processJoints
static void processJoints(const std::vector< Ref< Joint >> &joints, float h)
Definition: Physics.hpp:536
Engine::CollisionPoint
Definition: Components.hpp:160