tinyphysicsengine.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #ifndef TINYPHYSICSENGINE_H
  2. #define TINYPHYSICSENGINE_H
  3. /*
  4. author: Miloslav Ciz
  5. license: CC0 1.0 (public domain)
  6. found at https://creativecommons.org/publicdomain/zero/1.0/
  7. + additional waiver of all IP
  8. version: 0.1d
  9. CONVENTIONS:
  10. - No floating point is used, we instead use integers (effectively a fixed
  11. point). TPE_FRACTIONS_PER_UNIT is an equivalent to 1.0 in floating point and
  12. all numbers are normalized by this constant.
  13. - Units: for any measure only an abstract mathematical unit is used. This unit
  14. always has TPE_FRACTIONS_PER_UNIT parts. You can see assign any
  15. correcpondence with real life units to these units. E.g. 1 spatial unit
  16. (which you can see as e.g. 1 meter) is equal to TPE_FRACTIONS_PER_UNIT.
  17. Same with temporatl (e.g. 1 second) and mass (e.g. 1 kilogram) units, and
  18. also any derived units, e.g. a unit of velocity (e.g. 1 m/s) is also equal
  19. to 1 TPE_FRACTIONS_PER_UNIT. A full angle is also split into
  20. TPE_FRACTIONS_PER_UNIT parts (instead of 2 * PI or degrees).
  21. */
  22. #include <stdint.h>
  23. typedef int32_t TPE_Unit;
  24. /** How many fractions a unit is split into. This is NOT SUPPOSED TO BE
  25. REDEFINED, so rather don't do it (otherwise things may overflow etc.). */
  26. #define TPE_FRACTIONS_PER_UNIT 512
  27. #define TPE_INFINITY 2147483647
  28. #define TPE_SHAPE_POINT 0 ///< single point in space
  29. #define TPE_SHAPE_SPHERE 1 ///< sphere, params.: radius
  30. #define TPE_SHAPE_CUBOID 2 ///< cuboid, params.: width, height, depth
  31. #define TPE_SHAPE_PLANE 3 ///< plane, params.: width, depth
  32. #define TPE_SHAPE_CYLINDER 4 ///< cylinder, params.: radius, height
  33. #define TPE_SHAPE_TRIMESH 5 /**< triangle mesh, params.:
  34. vertex count,
  35. triangle count
  36. vertices (int32_t pointer),
  37. indices (uint16_t pointer) */
  38. #define TPE_MAX_SHAPE_PARAMS 3
  39. #define TPE_MAX_SHAPE_PARAMPOINTERS 2
  40. #define TPE_BODY_FLAG_DISABLED 0x00 ///< won't take part in simul. at all
  41. #define TPE_BODY_FLAG_NONCOLLIDING 0x01 ///< simulated but won't collide
  42. typedef TPE_Unit TPE_Vec3[3];
  43. typedef struct
  44. {
  45. uint8_t shape;
  46. TPE_Unit shapeParams[TPE_MAX_SHAPE_PARAMS]; ///< parameters of the body type
  47. void *shapeParamPointers[TPE_MAX_SHAPE_PARAMPOINTERS]; ///< pointer parameters
  48. uint8_t flags;
  49. TPE_Unit position[3]; ///< position of the body's center of mass
  50. TPE_Unit mass; /**< body mass, setting this to TPE_INFINITY will
  51. make the object static (not moving at all)
  52. which may help performance */
  53. TPE_Unit velocity[0];
  54. TPE_Unit orientation[4]; ///< orientation as a quaternion
  55. TPE_Vec3 rotationAxis; /**< normalized axis of rotation, direction of
  56. rotation is given by the right hand rule */
  57. TPE_Unit rotationSpeed; /**< non-negative rotation speed around the
  58. rotationAxis, TPE_FRACTIONS_PER_UNIT mean one
  59. rotation per one temporal unit (mathematically
  60. this could be represented as the length of
  61. the rotationAxis vector, but for computational
  62. reasons it's better to have it this way) */
  63. } TPE_Body;
  64. #define TPE_PRINTF_VEC3(v) printf("[%d %d %d]",v[0],v[1],v[2]);
  65. typedef struct
  66. {
  67. uint16_t bodyCount;
  68. TPE_Body *bodies;
  69. } TPE_PhysicsWorld;
  70. //------------------------------------------------------------------------------
  71. static inline TPE_Unit TPE_nonZero(TPE_Unit x)
  72. {
  73. return x + (x == 0);
  74. }
  75. void TPE_vec3Add(const TPE_Vec3 a, const TPE_Vec3 b, TPE_Vec3 result)
  76. {
  77. result[0] = a[0] + b[0];
  78. result[1] = a[1] + b[1];
  79. result[2] = a[2] + b[2];
  80. }
  81. TPE_Unit TPE_vec3Len(TPE_Vec3 v)
  82. {
  83. return TPE_sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  84. }
  85. static inline TPE_Unit TPE_vec3DotProduct(const TPE_Vec3 v1, const TPE_Vec3 v2)
  86. {
  87. return
  88. (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / TPE_FRACTIONS_PER_UNIT;
  89. }
  90. void TPE_vec3Normalize(TPE_Vec3 v)
  91. {
  92. TPE_Unit l = TPE_vec3Len(v);
  93. if (l == 0)
  94. {
  95. v[0] = TPE_FRACTIONS_PER_UNIT;
  96. return;
  97. }
  98. v[0] = (v[0] * TPE_FRACTIONS_PER_UNIT) / l;
  99. v[1] = (v[1] * TPE_FRACTIONS_PER_UNIT) / l;
  100. v[2] = (v[2] * TPE_FRACTIONS_PER_UNIT) / l;
  101. }
  102. void TPE_vec3Project(const TPE_Vec3 v, const TPE_Vec3 base, TPE_Vec3 result)
  103. {
  104. TPE_Unit p = TPE_vec3DotProduct(v,base);
  105. printf("%d\n",p);
  106. result[0] = (p * base[0]) / TPE_FRACTIONS_PER_UNIT;
  107. result[1] = (p * base[1]) / TPE_FRACTIONS_PER_UNIT;
  108. result[2] = (p * base[2]) / TPE_FRACTIONS_PER_UNIT;
  109. }
  110. TPE_Unit TPE_sqrt(TPE_Unit value)
  111. {
  112. int8_t sign = 1;
  113. if (value < 0)
  114. {
  115. sign = -1;
  116. value *= -1;
  117. }
  118. uint32_t result = 0;
  119. uint32_t a = value;
  120. uint32_t b = 1u << 30;
  121. while (b > a)
  122. b >>= 2;
  123. while (b != 0)
  124. {
  125. if (a >= result + b)
  126. {
  127. a -= result + b;
  128. result = result + 2 * b;
  129. }
  130. b >>= 2;
  131. result >>= 1;
  132. }
  133. return result * sign;
  134. }
  135. void TPE_resolvePointCollision(
  136. const TPE_Vec3 collisionPoint,
  137. const TPE_Vec3 collisionNormal,
  138. TPE_Vec3 linVelocity1,
  139. TPE_Vec3 rotVelocity1,
  140. TPE_Unit m1,
  141. TPE_Vec3 linVelocity2,
  142. TPE_Vec3 rotVelocity2,
  143. TPE_Unit m2)
  144. {
  145. TPE_Vec3 v1, v2;
  146. TPE_vec3Add(linVelocity1,rotVelocity1,v1);
  147. TPE_vec3Add(linVelocity2,rotVelocity2,v2);
  148. // TODO
  149. }
  150. void TPE_getVelocitiesAfterCollision(
  151. TPE_Unit *v1,
  152. TPE_Unit *v2,
  153. TPE_Unit m1,
  154. TPE_Unit m2,
  155. TPE_Unit elasticity
  156. )
  157. {
  158. /* in the following a lot of TPE_FRACTIONS_PER_UNIT cancel out, feel free to
  159. check if confused */
  160. #define ANTI_OVERFLOW 30000
  161. #define ANTI_OVERFLOW_SCALE 128
  162. uint8_t overflowDanger = m1 > ANTI_OVERFLOW || *v1 > ANTI_OVERFLOW ||
  163. m2 > ANTI_OVERFLOW || *v2 > ANTI_OVERFLOW;
  164. if (overflowDanger)
  165. {
  166. m1 = (m1 != 0) ? TPE_nonZero(m1 / ANTI_OVERFLOW_SCALE) : 0;
  167. m2 = (m2 != 0) ? TPE_nonZero(m2 / ANTI_OVERFLOW_SCALE) : 0;
  168. *v1 = (*v1 != 0) ? TPE_nonZero(*v1 / ANTI_OVERFLOW_SCALE) : 0;
  169. *v2 = (*v2 != 0) ? TPE_nonZero(*v2 / ANTI_OVERFLOW_SCALE) : 0;
  170. }
  171. TPE_Unit m1Pm2 = m1 + m2;
  172. TPE_Unit v2Mv1 = *v2 - *v1;
  173. TPE_Unit m1v1Pm2v2 = ((m1 * *v1) + (m2 * *v2));
  174. *v1 = (((elasticity * m2 / TPE_FRACTIONS_PER_UNIT) * v2Mv1)
  175. + m1v1Pm2v2) / m1Pm2;
  176. *v2 = (((elasticity * m1 / TPE_FRACTIONS_PER_UNIT) * -1 * v2Mv1)
  177. + m1v1Pm2v2) / m1Pm2;
  178. if (overflowDanger)
  179. {
  180. *v1 *= ANTI_OVERFLOW_SCALE;
  181. *v2 *= ANTI_OVERFLOW_SCALE;
  182. }
  183. #undef ANTI_OVERFLOW
  184. #undef ANTI_OVERFLOW_SCALE
  185. }
  186. #endif // guard