physics.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. #include "physics.h"
  2. PhysicsObject createBall(glm::vec3 pos, float r)
  3. {
  4. PhysicsObject ret;
  5. ret.type = TYPE_CIRCLE;
  6. ret.position = pos;
  7. ret.shape.x = r;
  8. ret.mass = 4.f * 3.141592 * r * r * r / 3.f;
  9. return ret;
  10. }
  11. PhysicsObject createBox(glm::vec3 pos, glm::vec3 size)
  12. {
  13. PhysicsObject ret;
  14. ret.type = TYPE_BOX;
  15. ret.position = pos;
  16. ret.shape = size;
  17. ret.mass = size.x * size.y * size.z;
  18. return ret;
  19. }
  20. PhysicsObject createCilindru(glm::vec3 pos, float r, float h)
  21. {
  22. PhysicsObject ret;
  23. ret.type = TYPE_CILINDRU;
  24. ret.position = pos;
  25. ret.shape.x = r;
  26. ret.shape.y = h;
  27. ret.mass = 3.14159 * r * r * h;
  28. return ret;
  29. }
  30. void applyDrag(PhysicsObject &object)
  31. {
  32. glm::vec3 dragForce = 0.1f * -object.velocity * glm::abs(object.velocity) / 2.f;
  33. float length = glm::length(dragForce);
  34. if (length)
  35. {
  36. if (length > MAX_AIR_DRAG)
  37. {
  38. dragForce /= length;
  39. dragForce *= MAX_AIR_DRAG;
  40. }
  41. object.acceleration += dragForce;
  42. }
  43. }
  44. void Simulator::updateForces(PhysicsObject &object, float deltaTime)
  45. {
  46. if (object.mass >= INFINITY || object.mass <= 0)
  47. {
  48. object.velocity = {};
  49. object.acceleration = {};
  50. return;
  51. }
  52. object.acceleration = glm::clamp(object.acceleration,
  53. glm::vec3(-MAX_ACCELERATION), glm::vec3(MAX_ACCELERATION));
  54. //Symplectic Euler
  55. object.velocity += object.acceleration * deltaTime * 0.5f;
  56. object.velocity = glm::clamp(object.velocity, glm::vec3(-MAX_VELOCITY), glm::vec3(MAX_VELOCITY));
  57. object.position += object.velocity * deltaTime;
  58. object.velocity += object.acceleration * deltaTime * 0.5f;
  59. object.velocity = glm::clamp(object.velocity, glm::vec3(-MAX_VELOCITY), glm::vec3(MAX_VELOCITY));
  60. if (std::fabs(object.velocity.x) < 0.00001) { object.velocity.x = 0; }
  61. if (std::fabs(object.velocity.y) < 0.00001) { object.velocity.y = 0; }
  62. object.acceleration = {};
  63. }
  64. void normalizeSafe(glm::vec3 &v)
  65. {
  66. float l = glm::length(v);
  67. if (l <= 0.00000001)
  68. {
  69. v = {1,0,0};
  70. }
  71. else
  72. {
  73. v /= l;
  74. }
  75. }
  76. bool AABBvsAABB(PhysicsObject &a, PhysicsObject &b, float &penetration, glm::vec3 &normal)
  77. {
  78. // Vector from A to B
  79. glm::vec3 n = b.position - a.position;
  80. auto aMax = a.getMax();
  81. auto aMin = a.getMin();
  82. auto bMax = b.getMax();
  83. auto bMin = b.getMin();
  84. // Calculate half extents along each axis for each object
  85. float a_extent_x = (aMax.x - aMin.x) / 2.0f;
  86. float b_extent_x = (bMax.x - bMin.x) / 2.0f;
  87. float a_extent_y = (aMax.y - aMin.y) / 2.0f;
  88. float b_extent_y = (bMax.y - bMin.y) / 2.0f;
  89. float a_extent_z = (aMax.z - aMin.z) / 2.0f;
  90. float b_extent_z = (bMax.z - bMin.z) / 2.0f;
  91. // Calculate overlaps on each axis
  92. float x_overlap = a_extent_x + b_extent_x - abs(n.x);
  93. float y_overlap = a_extent_y + b_extent_y - abs(n.y);
  94. float z_overlap = a_extent_z + b_extent_z - abs(n.z);
  95. // SAT test on x, y, and z axes
  96. if (x_overlap > 0 && y_overlap > 0 && z_overlap > 0)
  97. {
  98. if (x_overlap < y_overlap && x_overlap < z_overlap)
  99. {
  100. normal = (n.x < 0) ? glm::vec3(-1, 0, 0) : glm::vec3(1, 0, 0);
  101. penetration = x_overlap;
  102. // Side collision on X axis
  103. a.collidesSide = true;
  104. b.collidesSide = true;
  105. a.collisionVector = -normal;
  106. b.collisionVector = normal;
  107. }
  108. else if (y_overlap < z_overlap)
  109. {
  110. normal = (n.y < 0) ? glm::vec3(0, -1, 0) : glm::vec3(0, 1, 0);
  111. penetration = y_overlap;
  112. if (normal.y > 0)
  113. {
  114. // 'b' hit 'a' on its bottom
  115. b.collidesBottom = true;
  116. a.collidesSide = true;
  117. }
  118. else
  119. {
  120. // 'a' hit 'b' on its bottom
  121. a.collidesBottom = true;
  122. b.collidesSide = true;
  123. }
  124. // No collisionVector for bottom/top
  125. }
  126. else
  127. {
  128. normal = (n.z < 0) ? glm::vec3(0, 0, -1) : glm::vec3(0, 0, 1);
  129. penetration = z_overlap;
  130. // Side collision on Z axis
  131. a.collidesSide = true;
  132. b.collidesSide = true;
  133. a.collisionVector = -normal;
  134. b.collisionVector = normal;
  135. }
  136. return true;
  137. }
  138. return false;
  139. }
  140. bool CirclevsCircle(PhysicsObject &a, PhysicsObject &b,
  141. float &penetration,
  142. glm::vec3 &normal
  143. )
  144. {
  145. float r = a.shape.r + b.shape.r;
  146. float rSquared = r * r;
  147. float distanceSquared = ((a.position.x - b.position.x) * (a.position.x - b.position.x)
  148. + (a.position.y - b.position.y) * (a.position.y - b.position.y)
  149. + (a.position.z - b.position.z) * (a.position.z - b.position.z));
  150. bool rez = rSquared > distanceSquared;
  151. if (rez)
  152. {
  153. normal = b.position - a.position;
  154. normalizeSafe(normal);
  155. penetration = r - sqrt(distanceSquared);
  156. }
  157. return rez;
  158. }
  159. void positionalCorrection(PhysicsObject &A, PhysicsObject &B, glm::vec3 n,
  160. float penetrationDepth, float aInverseMass, float bInverseMass)
  161. {
  162. const float percent = 0.2; // usually 20% to 80%
  163. const float slop = 0.01; // usually 0.01 to 0.1
  164. glm::vec3 correction = (glm::max(penetrationDepth - slop, 0.0f) / (aInverseMass + bInverseMass)) * percent * n;
  165. if(aInverseMass) A.position -= aInverseMass * correction;
  166. if(bInverseMass) B.position += bInverseMass * correction;
  167. };
  168. float pythagoreanSolve(float fA, float fB)
  169. {
  170. return std::sqrt(fA * fA + fB * fB);
  171. }
  172. void applyFriction(PhysicsObject &A, PhysicsObject &B, glm::vec3 tangent, glm::vec3 rv,
  173. float aInverseMass, float bInverseMass, float j)
  174. {
  175. // Solve for magnitude to apply along the friction vector
  176. float jt = -glm::dot(rv, tangent);
  177. jt = jt / (aInverseMass + bInverseMass);
  178. // PythagoreanSolve = A^2 + B^2 = C^2, solving for C given A and B
  179. // Use to approximate mu given friction coefficients of each body
  180. float mu = pythagoreanSolve(A.staticFriction, B.staticFriction);
  181. // Clamp magnitude of friction and create impulse vector
  182. //(Coulomb's Law) Ff<=Fn
  183. glm::vec3 frictionImpulse = {};
  184. if (abs(jt) < j * mu)
  185. {
  186. frictionImpulse = jt * tangent;
  187. }
  188. else
  189. {
  190. float dynamicFriction = pythagoreanSolve(A.dynamicFriction, B.dynamicFriction);
  191. frictionImpulse = -j * tangent * dynamicFriction;
  192. }
  193. // Apply
  194. if(aInverseMass) A.velocity -= (aInverseMass)*frictionImpulse;
  195. if(bInverseMass) B.velocity += (bInverseMass)*frictionImpulse;
  196. };
  197. void impulseResolution(PhysicsObject &A, PhysicsObject &B, glm::vec3 normal,
  198. float velAlongNormal, float penetrationDepth)
  199. {
  200. //calculate elasticity
  201. float e = std::min(A.bouncyness, B.bouncyness);
  202. //float e = 0.9;
  203. float massInverseA = 1.f / A.mass;
  204. float massInverseB = 1.f / B.mass;
  205. if (A.mass == 0 || A.mass == INFINITY) { massInverseA = 0; }
  206. if (B.mass == 0 || B.mass == INFINITY) { massInverseB = 0; }
  207. // Calculate impulse scalar
  208. float j = -(1.f + e) * velAlongNormal;
  209. j /= massInverseA + massInverseB;
  210. // Apply impulse
  211. glm::vec3 impulse = j * normal;
  212. if(massInverseA) A.velocity -= massInverseA * impulse;
  213. if(massInverseB) B.velocity += massInverseB * impulse;
  214. positionalCorrection(A, B, normal, penetrationDepth, massInverseA, massInverseB);
  215. {
  216. // Re-calculate relative velocity after normal impulse
  217. // is applied (impulse from first article, this code comes
  218. // directly thereafter in the same resolve function)
  219. glm::vec3 rv = B.velocity - A.velocity;
  220. // Solve for the tangent vector
  221. glm::vec3 tangent = rv - glm::dot(rv, normal) * normal;
  222. normalizeSafe(tangent);
  223. applyFriction(A, B, tangent, rv, massInverseA, massInverseB, j);
  224. }
  225. };
  226. bool AABBvsSphere(PhysicsObject abox, PhysicsObject bsphere, float &penetration, glm::vec3 &normal)
  227. {
  228. // Vector from A to B
  229. glm::vec3 n = bsphere.position - abox.position;
  230. // Closest point on A to center of B
  231. glm::vec3 closest = n;
  232. // Calculate half extents along each axis for the AABB
  233. float x_extent = (abox.getMax().x - abox.getMin().x) / 2.0f;
  234. float y_extent = (abox.getMax().y - abox.getMin().y) / 2.0f;
  235. float z_extent = (abox.getMax().z - abox.getMin().z) / 2.0f;
  236. // Clamp point to edges of the AABB
  237. closest.x = glm::clamp(closest.x, -x_extent, x_extent);
  238. closest.y = glm::clamp(closest.y, -y_extent, y_extent);
  239. closest.z = glm::clamp(closest.z, -z_extent, z_extent);
  240. bool inside = false;
  241. // Check if sphere center is inside the AABB
  242. if (n == closest)
  243. {
  244. inside = true;
  245. // Clamp to closest extent along the axis with the largest component
  246. if (abs(n.x) > abs(n.y) && abs(n.x) > abs(n.z))
  247. {
  248. closest.x = (closest.x > 0) ? x_extent : -x_extent;
  249. }
  250. else if (abs(n.y) > abs(n.z))
  251. {
  252. closest.y = (closest.y > 0) ? y_extent : -y_extent;
  253. }
  254. else
  255. {
  256. closest.z = (closest.z > 0) ? z_extent : -z_extent;
  257. }
  258. }
  259. // Calculate the vector from the closest point on A to the center of B
  260. glm::vec3 normal3D = n - closest;
  261. float d = glm::dot(normal3D, normal3D);
  262. float r = bsphere.shape.r;
  263. // Early out if the distance to the closest point is greater than the sphere's radius and the sphere is not inside the AABB
  264. if (d > r * r && !inside)
  265. {
  266. return false;
  267. }
  268. // Calculate the actual distance if needed
  269. d = sqrt(d);
  270. // Set the collision normal and penetration depth
  271. if (inside)
  272. {
  273. normal = -glm::normalize(normal3D);
  274. penetration = r - d;
  275. }
  276. else
  277. {
  278. normal = glm::normalize(normal3D);
  279. penetration = r - d;
  280. }
  281. return true;
  282. }
  283. bool CylindervsCylinder(PhysicsObject a, PhysicsObject b, float &penetration, glm::vec3 &normal)
  284. {
  285. // Vector from A to B
  286. glm::vec3 n = b.position - a.position;
  287. auto aMax = a.getMax();
  288. auto aMin = a.getMin();
  289. auto bMax = b.getMax();
  290. auto bMin = b.getMin();
  291. // Calculate half extents along each axis for each object
  292. float a_extent_x = (aMax.x - aMin.x) / 2.0f;
  293. float b_extent_x = (bMax.x - bMin.x) / 2.0f;
  294. float a_extent_y = (aMax.y - aMin.y) / 2.0f;
  295. float b_extent_y = (bMax.y - bMin.y) / 2.0f;
  296. float a_extent_z = (aMax.z - aMin.z) / 2.0f;
  297. float b_extent_z = (bMax.z - bMin.z) / 2.0f;
  298. // Calculate overlaps on each axis
  299. float x_overlap = a_extent_x + b_extent_x - abs(n.x);
  300. float y_overlap = a_extent_y + b_extent_y - abs(n.y);
  301. float z_overlap = a_extent_z + b_extent_z - abs(n.z);
  302. glm::vec2 distantaXZ(n.x, n.z);
  303. float r = a.shape.r + b.shape.r;
  304. float rSquared = r * r;
  305. float distanceSquared = ((a.position.x - b.position.x) * (a.position.x - b.position.x)
  306. + (a.position.z - b.position.z) * (a.position.z - b.position.z));
  307. bool overlapXZ = rSquared > distanceSquared;
  308. // SAT test on x, y, and z axes
  309. if (y_overlap > 0 && overlapXZ)
  310. {
  311. float XZdist = std::sqrt(distanceSquared);
  312. float xzOverlap = r - XZdist;
  313. // Determine the axis of least penetration
  314. if (y_overlap < xzOverlap)
  315. {
  316. normal = (n.y < 0) ? glm::vec3(0, -1, 0) : glm::vec3(0, 1, 0);
  317. penetration = y_overlap;
  318. }
  319. else
  320. {
  321. if (distantaXZ.x == 0 && distantaXZ.y == 0)
  322. {
  323. normal = glm::vec3(-1, 0, 0);
  324. penetration = r;
  325. }
  326. else
  327. {
  328. distantaXZ /= XZdist; //normalize
  329. normal.x = distantaXZ.x;
  330. normal.y = 0;
  331. normal.z = distantaXZ.y;
  332. penetration = xzOverlap;
  333. }
  334. }
  335. return true;
  336. }
  337. return false;
  338. }
  339. //a is cube
  340. //b is cylinder
  341. bool AABBvsCylinder(PhysicsObject a, PhysicsObject b, float &penetration, glm::vec3 &normal)
  342. {
  343. // Vector from A to B
  344. glm::vec3 n = b.position - a.position;
  345. auto aMax = a.getMax();
  346. auto aMin = a.getMin();
  347. auto bMax = b.getMax();
  348. auto bMin = b.getMin();
  349. // Calculate half extents along each axis for each object
  350. float a_extent_x = (aMax.x - aMin.x) / 2.0f;
  351. float b_extent_x = (bMax.x - bMin.x) / 2.0f;
  352. float a_extent_y = (aMax.y - aMin.y) / 2.0f;
  353. float b_extent_y = (bMax.y - bMin.y) / 2.0f;
  354. float a_extent_z = (aMax.z - aMin.z) / 2.0f;
  355. float b_extent_z = (bMax.z - bMin.z) / 2.0f;
  356. // Calculate overlaps on each axis
  357. float x_overlap = a_extent_x + b_extent_x - abs(n.x);
  358. float y_overlap = a_extent_y + b_extent_y - abs(n.y);
  359. float z_overlap = a_extent_z + b_extent_z - abs(n.z);
  360. // Closest point on A to center of B
  361. glm::vec3 closest = n;
  362. // Calculate half extents along each axis for the AABB
  363. float x_extent = (aMax.x - aMin.x) / 2.0f;
  364. float y_extent = (aMax.y - aMin.y) / 2.0f;
  365. float z_extent = (aMax.z - aMin.z) / 2.0f;
  366. // Clamp point to edges of the AABB
  367. closest.x = glm::clamp(closest.x, -x_extent, x_extent);
  368. closest.y = glm::clamp(closest.y, -y_extent, y_extent);
  369. closest.z = glm::clamp(closest.z, -z_extent, z_extent);
  370. bool inside = false;
  371. // Check if sphere center is inside the AABB
  372. if (n == closest)
  373. {
  374. inside = true;
  375. // Clamp to closest extent along the axis with the largest component
  376. if (abs(n.x) > abs(n.y) && abs(n.x) > abs(n.z))
  377. {
  378. closest.x = (closest.x > 0) ? x_extent : -x_extent;
  379. }
  380. else if (abs(n.y) > abs(n.z))
  381. {
  382. closest.y = (closest.y > 0) ? y_extent : -y_extent;
  383. }
  384. else
  385. {
  386. closest.z = (closest.z > 0) ? z_extent : -z_extent;
  387. }
  388. }
  389. glm::vec3 closestWorldPos = closest + a.position;
  390. float distantaClosestPoint = glm::distance(glm::vec3{closestWorldPos.x, 0.f, closestWorldPos.z}, {b.position.x, 0.f, b.position.z});
  391. float overlapXZ = b.shape.x - distantaClosestPoint;
  392. // SAT test on x, y, and z axes
  393. if (inside || (y_overlap > 0 && overlapXZ > 0))
  394. {
  395. // Determine the axis of least penetration
  396. if (y_overlap < overlapXZ)
  397. {
  398. normal = (n.y < 0) ? glm::vec3(0, -1, 0) : glm::vec3(0, 1, 0);
  399. penetration = y_overlap;
  400. }
  401. else
  402. {
  403. //cerc patrat
  404. // Calculate the vector from the closest point on A to the center of B
  405. glm::vec3 normal3D = n - closest; normal3D.y = 0;
  406. float d = glm::dot(normal3D, normal3D);
  407. float r = b.shape.r;
  408. if (normal3D.x == 0 && normal3D.z == 0)
  409. {
  410. normal = -glm::vec3({1,0,0});
  411. penetration = r;
  412. return true;
  413. }
  414. d = sqrt(d);
  415. // Set the collision normal and penetration depth
  416. if (inside)
  417. {
  418. normal = -glm::normalize(normal3D);
  419. penetration = r - d;
  420. }
  421. else
  422. {
  423. normal = glm::normalize(normal3D);
  424. penetration = r - d;
  425. }
  426. }
  427. return true;
  428. }
  429. return false;
  430. }
  431. //a is sphere
  432. //b is cylinder
  433. bool SpherevsCylinder(PhysicsObject a, PhysicsObject b, float &penetration, glm::vec3 &normal)
  434. {
  435. // Vector from A to B
  436. glm::vec3 n = b.position - a.position;
  437. auto aMax = a.getMax();
  438. auto aMin = a.getMin();
  439. auto bMax = b.getMax();
  440. auto bMin = b.getMin();
  441. // Calculate half extents along each axis for each object
  442. float a_extent_x = (aMax.x - aMin.x) / 2.0f;
  443. float b_extent_x = (bMax.x - bMin.x) / 2.0f;
  444. float a_extent_y = (aMax.y - aMin.y) / 2.0f;
  445. float b_extent_y = (bMax.y - bMin.y) / 2.0f;
  446. float a_extent_z = (aMax.z - aMin.z) / 2.0f;
  447. float b_extent_z = (bMax.z - bMin.z) / 2.0f;
  448. // Calculate overlaps on each axis
  449. //float x_overlap = a_extent_x + b_extent_x - abs(n.x);
  450. //float y_overlap = a_extent_y + b_extent_y - abs(n.y);
  451. //float z_overlap = a_extent_z + b_extent_z - abs(n.z);
  452. float y_overlap = 0;
  453. bool inside = false;
  454. // Closest point on B to center of A sphere
  455. glm::vec3 closest = -n;
  456. {
  457. // Calculate half extents along each axis for the AABB
  458. float x_extent = (bMax.x - bMin.x) / 2.0f;
  459. float y_extent = (bMax.y - bMin.y) / 2.0f;
  460. float z_extent = (bMax.z - bMin.z) / 2.0f;
  461. // Clamp point to edges of the AABB
  462. closest.x = glm::clamp(closest.x, -x_extent, x_extent);
  463. closest.y = glm::clamp(closest.y, -y_extent, y_extent);
  464. closest.z = glm::clamp(closest.z, -z_extent, z_extent);
  465. // Check if sphere center is inside the AABB
  466. if (n == closest)
  467. {
  468. inside = true;
  469. // Clamp to closest extent along the axis with the largest component
  470. if (abs(n.x) > abs(n.y) && abs(n.x) > abs(n.z))
  471. {
  472. closest.x = (closest.x > 0) ? x_extent : -x_extent;
  473. }
  474. else if (abs(n.y) > abs(n.z))
  475. {
  476. closest.y = (closest.y > 0) ? y_extent : -y_extent;
  477. }
  478. else
  479. {
  480. closest.z = (closest.z > 0) ? z_extent : -z_extent;
  481. }
  482. }
  483. glm::vec3 closestWorldPos = closest + b.position;
  484. y_overlap = a.shape.x - std::abs(a.position.y - closestWorldPos.y);
  485. }
  486. float overlapXZ = 0;
  487. float r = a.shape.r + b.shape.r;
  488. float distanceSquared = 0;
  489. {
  490. glm::vec2 distantaXZ(n.x, n.z);
  491. float rSquared = r * r;
  492. float distanceSquared = ((a.position.x - b.position.x) * (a.position.x - b.position.x)
  493. + (a.position.z - b.position.z) * (a.position.z - b.position.z));
  494. float XZdist = std::sqrt(distanceSquared);
  495. overlapXZ = r - XZdist;
  496. }
  497. // SAT test on x, y, and z axes
  498. if (inside || (y_overlap > 0 && overlapXZ > 0))
  499. {
  500. // Determine the axis of least penetration
  501. if (y_overlap < overlapXZ)
  502. {
  503. normal = (n.y < 0) ? glm::vec3(0, -1, 0) : glm::vec3(0, 1, 0);
  504. penetration = y_overlap;
  505. //cerc patrat
  506. //// Calculate the vector from the closest point on A to the center of B
  507. //glm::vec3 normal3D = a.position - (b.position + closest);
  508. //float d = glm::dot(normal3D, normal3D);
  509. //float r = a.shape.r;
  510. //
  511. //if (normal3D.x == 0 && normal3D.z == 0)
  512. //{
  513. // normal = -glm::vec3({1,0,0});
  514. // penetration = r;
  515. // return true;
  516. //}
  517. //
  518. //d = sqrt(d);
  519. //
  520. //// Set the collision normal and penetration depth
  521. //if (inside)
  522. //{
  523. // normal = -glm::normalize(normal3D);
  524. // penetration = r - d;
  525. //}
  526. //else
  527. //{
  528. // normal = glm::normalize(normal3D);
  529. // penetration = r - d;
  530. //}
  531. }
  532. else
  533. {
  534. //cerc cerc pe XZ
  535. normal = b.position - a.position;
  536. normal.y = 0;
  537. normalizeSafe(normal);
  538. penetration = overlapXZ;
  539. }
  540. return true;
  541. }
  542. return false;
  543. }
  544. void Simulator::update(float deltaTime)
  545. {
  546. size_t bodiesSize = bodies.size();
  547. for (auto &body: bodies)
  548. {
  549. auto &b = body.second;
  550. //gravity
  551. b.acceleration += glm::vec3{0, -9.81, 0};
  552. b.collidesBottom = 0;
  553. b.collidesSide = 0;
  554. b.collisionVector = {};
  555. if(b.mass != 0 && b.mass != INFINITY)
  556. applyDrag(b);
  557. //detect colisions
  558. for (auto &body2 : bodies)
  559. {
  560. if (body.first == body2.first) { continue; }
  561. auto &A = b;
  562. auto &B = body2.second;
  563. if (A.type == TYPE_CIRCLE &&
  564. B.type == TYPE_CIRCLE
  565. )
  566. {
  567. glm::vec3 normal = {};
  568. float penetration = 0;
  569. if (CirclevsCircle(
  570. A, B,
  571. penetration, normal))
  572. {
  573. glm::vec3 relativeVelocity = B.velocity - A.velocity;
  574. float velAlongNormal = glm::dot(relativeVelocity, normal);
  575. // Do not resolve if velocities are separating
  576. if (velAlongNormal > 0)
  577. {
  578. }
  579. else
  580. {
  581. impulseResolution(A, B, normal, velAlongNormal, penetration);
  582. }
  583. }
  584. }
  585. else
  586. if (A.type == TYPE_BOX &&
  587. B.type == TYPE_BOX
  588. )
  589. {
  590. glm::vec3 normal = {};
  591. float penetration = 0;
  592. if (AABBvsAABB(
  593. A, B,
  594. penetration, normal))
  595. {
  596. glm::vec3 relativeVelocity = B.velocity - A.velocity;
  597. float velAlongNormal = glm::dot(relativeVelocity, normal);
  598. // Do not resolve if velocities are separating
  599. if (velAlongNormal > 0)
  600. {
  601. }
  602. else
  603. {
  604. impulseResolution(A, B, normal, velAlongNormal, penetration);
  605. }
  606. }
  607. }
  608. else
  609. if (A.type == TYPE_BOX &&
  610. B.type == TYPE_CIRCLE
  611. )
  612. {
  613. glm::vec3 normal = {};
  614. float penetration = 0;
  615. if (AABBvsSphere(
  616. A, B,
  617. penetration, normal))
  618. {
  619. glm::vec3 relativeVelocity = B.velocity - A.velocity;
  620. float velAlongNormal = glm::dot(relativeVelocity, normal);
  621. // Do not resolve if velocities are separating
  622. if (velAlongNormal > 0)
  623. {
  624. }
  625. else
  626. {
  627. impulseResolution(A, B, normal, velAlongNormal, penetration);
  628. }
  629. }
  630. }
  631. else
  632. if (A.type == TYPE_CILINDRU &&
  633. B.type == TYPE_CILINDRU
  634. )
  635. {
  636. glm::vec3 normal = {};
  637. float penetration = 0;
  638. if (CylindervsCylinder(
  639. A, B,
  640. penetration, normal))
  641. {
  642. glm::vec3 relativeVelocity = B.velocity - A.velocity;
  643. float velAlongNormal = glm::dot(relativeVelocity, normal);
  644. // Do not resolve if velocities are separating
  645. if (velAlongNormal > 0)
  646. {
  647. }
  648. else
  649. {
  650. impulseResolution(A, B, normal, velAlongNormal, penetration);
  651. }
  652. }
  653. }
  654. else if (A.type == TYPE_BOX && B.type == TYPE_CILINDRU)
  655. {
  656. glm::vec3 normal = {};
  657. float penetration = 0;
  658. if (AABBvsCylinder(
  659. A, B,
  660. penetration, normal))
  661. {
  662. glm::vec3 relativeVelocity = B.velocity - A.velocity;
  663. float velAlongNormal = glm::dot(relativeVelocity, normal);
  664. // Do not resolve if velocities are separating
  665. if (velAlongNormal > 0)
  666. {
  667. }
  668. else
  669. {
  670. impulseResolution(A, B, normal, velAlongNormal, penetration);
  671. }
  672. }
  673. }
  674. else if (A.type == TYPE_CIRCLE && B.type == TYPE_CILINDRU)
  675. {
  676. glm::vec3 normal = {};
  677. float penetration = 0;
  678. if (SpherevsCylinder(
  679. A, B,
  680. penetration, normal))
  681. {
  682. glm::vec3 relativeVelocity = B.velocity - A.velocity;
  683. float velAlongNormal = glm::dot(relativeVelocity, normal);
  684. // Do not resolve if velocities are separating
  685. if (velAlongNormal > 0)
  686. {
  687. }
  688. else
  689. {
  690. impulseResolution(A, B, normal, velAlongNormal, penetration);
  691. }
  692. }
  693. }
  694. }
  695. updateForces(b, deltaTime);
  696. #pragma region hit walls
  697. auto minPos = b.getMin();
  698. auto maxPos = b.getMax();
  699. float boxDown = -boxDimensions.y / 2;
  700. if (minPos.y < boxDown)
  701. {
  702. float extra = boxDown - minPos.y;
  703. b.position.y += extra;
  704. b.velocity.y *= -1;
  705. }
  706. if (maxPos.y > boxDimensions.y / 2)
  707. {
  708. float extra = maxPos.y - boxDimensions.y / 2;
  709. b.position.y -= extra;
  710. b.velocity.y *= -1;
  711. }
  712. if (minPos.x < -boxDimensions.x / 2)
  713. {
  714. float extra = -boxDimensions.x / 2 - minPos.x;
  715. b.position.x += extra;
  716. b.velocity.x *= -1;
  717. }
  718. if (minPos.z < -boxDimensions.z / 2)
  719. {
  720. float extra = -boxDimensions.z / 2 - minPos.z;
  721. b.position.z += extra;
  722. b.velocity.z *= -1;
  723. }
  724. if (maxPos.x > boxDimensions.x / 2)
  725. {
  726. float extra = maxPos.x - boxDimensions.x / 2;
  727. b.position.x -= extra;
  728. b.velocity.x *= -1;
  729. }
  730. if (maxPos.z > boxDimensions.z / 2)
  731. {
  732. float extra = maxPos.z - boxDimensions.z / 2;
  733. b.position.z -= extra;
  734. b.velocity.z *= -1;
  735. }
  736. #pragma endregion
  737. }
  738. }