physac.h 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988
  1. /**********************************************************************************************
  2. *
  3. * Physac v1.1 - 2D Physics library for videogames
  4. *
  5. * DESCRIPTION:
  6. *
  7. * Physac is a small 2D physics engine written in pure C. The engine uses a fixed time-step thread loop
  8. * to simluate physics. A physics step contains the following phases: get collision information,
  9. * apply dynamics, collision solving and position correction. It uses a very simple struct for physic
  10. * bodies with a position vector to be used in any 3D rendering API.
  11. *
  12. * CONFIGURATION:
  13. *
  14. * #define PHYSAC_IMPLEMENTATION
  15. * Generates the implementation of the library into the included file.
  16. * If not defined, the library is in header only mode and can be included in other headers
  17. * or source files without problems. But only ONE file should hold the implementation.
  18. *
  19. * #define PHYSAC_STATIC (defined by default)
  20. * The generated implementation will stay private inside implementation file and all
  21. * internal symbols and functions will only be visible inside that file.
  22. *
  23. * #define PHYSAC_DEBUG
  24. * Show debug traces log messages about physic bodies creation/destruction, physic system errors,
  25. * some calculations results and NULL reference exceptions
  26. *
  27. * #define PHYSAC_DEFINE_VECTOR2_TYPE
  28. * Forces library to define struct Vector2 data type (float x; float y)
  29. *
  30. * #define PHYSAC_AVOID_TIMMING_SYSTEM
  31. * Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps,
  32. * it allows just running UpdatePhysics() automatically on a separate thread at a desired time step.
  33. * In case physics steps update needs to be controlled by user with a custom timming mechanism,
  34. * just define this flag and the internal timming mechanism will be avoided, in that case,
  35. * timming libraries are neither required by the module.
  36. *
  37. * #define PHYSAC_MALLOC()
  38. * #define PHYSAC_CALLOC()
  39. * #define PHYSAC_FREE()
  40. * You can define your own malloc/free implementation replacing stdlib.h malloc()/free() functions.
  41. * Otherwise it will include stdlib.h and use the C standard library malloc()/free() function.
  42. *
  43. * COMPILATION:
  44. *
  45. * Use the following code to compile with GCC:
  46. * gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static -lraylib -lopengl32 -lgdi32 -lwinmm -std=c99
  47. *
  48. * VERSIONS HISTORY:
  49. * 1.1 (20-Jan-2021) @raysan5: Library general revision
  50. * Removed threading system (up to the user)
  51. * Support MSVC C++ compilation using CLITERAL()
  52. * Review DEBUG mechanism for TRACELOG() and all TRACELOG() messages
  53. * Review internal variables/functions naming for consistency
  54. * Allow option to avoid internal timming system, to allow app manage the steps
  55. * 1.0 (12-Jun-2017) First release of the library
  56. *
  57. *
  58. * LICENSE: zlib/libpng
  59. *
  60. * Copyright (c) 2016-2021 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5)
  61. *
  62. * This software is provided "as-is", without any express or implied warranty. In no event
  63. * will the authors be held liable for any damages arising from the use of this software.
  64. *
  65. * Permission is granted to anyone to use this software for any purpose, including commercial
  66. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  67. *
  68. * 1. The origin of this software must not be misrepresented; you must not claim that you
  69. * wrote the original software. If you use this software in a product, an acknowledgment
  70. * in the product documentation would be appreciated but is not required.
  71. *
  72. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  73. * as being the original software.
  74. *
  75. * 3. This notice may not be removed or altered from any source distribution.
  76. *
  77. **********************************************************************************************/
  78. #if !defined(PHYSAC_H)
  79. #define PHYSAC_H
  80. #if defined(PHYSAC_STATIC)
  81. #define PHYSACDEF static // Functions just visible to module including this file
  82. #else
  83. #if defined(__cplusplus)
  84. #define PHYSACDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
  85. #else
  86. #define PHYSACDEF extern // Functions visible from other files
  87. #endif
  88. #endif
  89. // Allow custom memory allocators
  90. #ifndef PHYSAC_MALLOC
  91. #define PHYSAC_MALLOC(size) malloc(size)
  92. #endif
  93. #ifndef PHYSAC_CALLOC
  94. #define PHYSAC_CALLOC(size, n) calloc(size, n)
  95. #endif
  96. #ifndef PHYSAC_FREE
  97. #define PHYSAC_FREE(ptr) free(ptr)
  98. #endif
  99. //----------------------------------------------------------------------------------
  100. // Defines and Macros
  101. //----------------------------------------------------------------------------------
  102. #define PHYSAC_MAX_BODIES 64 // Maximum number of physic bodies supported
  103. #define PHYSAC_MAX_MANIFOLDS 4096 // Maximum number of physic bodies interactions (64x64)
  104. #define PHYSAC_MAX_VERTICES 24 // Maximum number of vertex for polygons shapes
  105. #define PHYSAC_DEFAULT_CIRCLE_VERTICES 24 // Default number of vertices for circle shapes
  106. #define PHYSAC_COLLISION_ITERATIONS 100
  107. #define PHYSAC_PENETRATION_ALLOWANCE 0.05f
  108. #define PHYSAC_PENETRATION_CORRECTION 0.4f
  109. #define PHYSAC_PI 3.14159265358979323846f
  110. #define PHYSAC_DEG2RAD (PHYSAC_PI/180.0f)
  111. //----------------------------------------------------------------------------------
  112. // Data Types Structure Definition
  113. //----------------------------------------------------------------------------------
  114. #if defined(__STDC__) && __STDC_VERSION__ >= 199901L
  115. #include <stdbool.h>
  116. #endif
  117. typedef enum PhysicsShapeType { PHYSICS_CIRCLE = 0, PHYSICS_POLYGON } PhysicsShapeType;
  118. // Previously defined to be used in PhysicsShape struct as circular dependencies
  119. typedef struct PhysicsBodyData *PhysicsBody;
  120. #if defined(PHYSAC_DEFINE_VECTOR2_TYPE)
  121. // Vector2 type
  122. typedef struct Vector2 {
  123. float x;
  124. float y;
  125. } Vector2;
  126. #endif
  127. // Matrix2x2 type (used for polygon shape rotation matrix)
  128. typedef struct Matrix2x2 {
  129. float m00;
  130. float m01;
  131. float m10;
  132. float m11;
  133. } Matrix2x2;
  134. typedef struct PhysicsVertexData {
  135. unsigned int vertexCount; // Vertex count (positions and normals)
  136. Vector2 positions[PHYSAC_MAX_VERTICES]; // Vertex positions vectors
  137. Vector2 normals[PHYSAC_MAX_VERTICES]; // Vertex normals vectors
  138. } PhysicsVertexData;
  139. typedef struct PhysicsShape {
  140. PhysicsShapeType type; // Shape type (circle or polygon)
  141. PhysicsBody body; // Shape physics body data pointer
  142. PhysicsVertexData vertexData; // Shape vertices data (used for polygon shapes)
  143. float radius; // Shape radius (used for circle shapes)
  144. Matrix2x2 transform; // Vertices transform matrix 2x2
  145. } PhysicsShape;
  146. typedef struct PhysicsBodyData {
  147. unsigned int id; // Unique identifier
  148. bool enabled; // Enabled dynamics state (collisions are calculated anyway)
  149. Vector2 position; // Physics body shape pivot
  150. Vector2 velocity; // Current linear velocity applied to position
  151. Vector2 force; // Current linear force (reset to 0 every step)
  152. float angularVelocity; // Current angular velocity applied to orient
  153. float torque; // Current angular force (reset to 0 every step)
  154. float orient; // Rotation in radians
  155. float inertia; // Moment of inertia
  156. float inverseInertia; // Inverse value of inertia
  157. float mass; // Physics body mass
  158. float inverseMass; // Inverse value of mass
  159. float staticFriction; // Friction when the body has not movement (0 to 1)
  160. float dynamicFriction; // Friction when the body has movement (0 to 1)
  161. float restitution; // Restitution coefficient of the body (0 to 1)
  162. bool useGravity; // Apply gravity force to dynamics
  163. bool isGrounded; // Physics grounded on other body state
  164. bool freezeOrient; // Physics rotation constraint
  165. PhysicsShape shape; // Physics body shape information (type, radius, vertices, transform)
  166. } PhysicsBodyData;
  167. typedef struct PhysicsManifoldData {
  168. unsigned int id; // Unique identifier
  169. PhysicsBody bodyA; // Manifold first physics body reference
  170. PhysicsBody bodyB; // Manifold second physics body reference
  171. float penetration; // Depth of penetration from collision
  172. Vector2 normal; // Normal direction vector from 'a' to 'b'
  173. Vector2 contacts[2]; // Points of contact during collision
  174. unsigned int contactsCount; // Current collision number of contacts
  175. float restitution; // Mixed restitution during collision
  176. float dynamicFriction; // Mixed dynamic friction during collision
  177. float staticFriction; // Mixed static friction during collision
  178. } PhysicsManifoldData, *PhysicsManifold;
  179. #if defined(__cplusplus)
  180. extern "C" { // Prevents name mangling of functions
  181. #endif
  182. //----------------------------------------------------------------------------------
  183. // Module Functions Declaration
  184. //----------------------------------------------------------------------------------
  185. // Physics system management
  186. PHYSACDEF void InitPhysics(void); // Initializes physics system
  187. PHYSACDEF void UpdatePhysics(void); // Update physics system
  188. PHYSACDEF void ResetPhysics(void); // Reset physics system (global variables)
  189. PHYSACDEF void ClosePhysics(void); // Close physics system and unload used memory
  190. PHYSACDEF void SetPhysicsTimeStep(double delta); // Sets physics fixed time step in milliseconds. 1.666666 by default
  191. PHYSACDEF void SetPhysicsGravity(float x, float y); // Sets physics global gravity force
  192. // Physic body creation/destroy
  193. PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density); // Creates a new circle physics body with generic parameters
  194. PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density); // Creates a new rectangle physics body with generic parameters
  195. PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density); // Creates a new polygon physics body with generic parameters
  196. PHYSACDEF void DestroyPhysicsBody(PhysicsBody body); // Destroy a physics body
  197. // Physic body forces
  198. PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force); // Adds a force to a physics body
  199. PHYSACDEF void PhysicsAddTorque(PhysicsBody body, float amount); // Adds an angular force to a physics body
  200. PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force); // Shatters a polygon shape physics body to little physics bodies with explosion force
  201. PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians); // Sets physics body shape transform based on radians parameter
  202. // Query physics info
  203. PHYSACDEF PhysicsBody GetPhysicsBody(int index); // Returns a physics body of the bodies pool at a specific index
  204. PHYSACDEF int GetPhysicsBodiesCount(void); // Returns the current amount of created physics bodies
  205. PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
  206. PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape
  207. PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position)
  208. #if defined(__cplusplus)
  209. }
  210. #endif
  211. #endif // PHYSAC_H
  212. /***********************************************************************************
  213. *
  214. * PHYSAC IMPLEMENTATION
  215. *
  216. ************************************************************************************/
  217. #if defined(PHYSAC_IMPLEMENTATION)
  218. // Support TRACELOG macros
  219. #if defined(PHYSAC_DEBUG)
  220. #include <stdio.h> // Required for: printf()
  221. #define TRACELOG(...) printf(__VA_ARGS__)
  222. #else
  223. #define TRACELOG(...) (void)0;
  224. #endif
  225. #include <stdlib.h> // Required for: malloc(), calloc(), free()
  226. #include <math.h> // Required for: cosf(), sinf(), fabs(), sqrtf()
  227. #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
  228. // Time management functionality
  229. #include <time.h> // Required for: time(), clock_gettime()
  230. #if defined(_WIN32)
  231. // Functions required to query time on Windows
  232. int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
  233. int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
  234. #endif
  235. #if defined(__linux__) || defined(__FreeBSD__)
  236. #if _POSIX_C_SOURCE < 199309L
  237. #undef _POSIX_C_SOURCE
  238. #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
  239. #endif
  240. #include <sys/time.h> // Required for: timespec
  241. #endif
  242. #if defined(__APPLE__) // macOS also defines __MACH__
  243. #include <mach/mach_time.h> // Required for: mach_absolute_time()
  244. #endif
  245. #endif
  246. // NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
  247. // Plain structures in C++ (without constructors) can be initialized from { } initializers.
  248. #if defined(__cplusplus)
  249. #define CLITERAL(type) type
  250. #else
  251. #define CLITERAL(type) (type)
  252. #endif
  253. //----------------------------------------------------------------------------------
  254. // Defines and Macros
  255. //----------------------------------------------------------------------------------
  256. #define PHYSAC_MIN(a,b) (((a)<(b))?(a):(b))
  257. #define PHYSAC_MAX(a,b) (((a)>(b))?(a):(b))
  258. #define PHYSAC_FLT_MAX 3.402823466e+38f
  259. #define PHYSAC_EPSILON 0.000001f
  260. #define PHYSAC_K 1.0f/3.0f
  261. #define PHYSAC_VECTOR_ZERO CLITERAL(Vector2){ 0.0f, 0.0f }
  262. //----------------------------------------------------------------------------------
  263. // Global Variables Definition
  264. //----------------------------------------------------------------------------------
  265. static double deltaTime = 1.0/60.0/10.0 * 1000; // Delta time in milliseconds used for physics steps
  266. #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
  267. // Time measure variables
  268. static double baseClockTicks = 0.0; // Offset clock ticks for MONOTONIC clock
  269. static unsigned long long int frequency = 0; // Hi-res clock frequency
  270. static double startTime = 0.0; // Start time in milliseconds
  271. static double currentTime = 0.0; // Current time in milliseconds
  272. #endif
  273. // Physics system configuration
  274. static PhysicsBody bodies[PHYSAC_MAX_BODIES]; // Physics bodies pointers array
  275. static unsigned int physicsBodiesCount = 0; // Physics world current bodies counter
  276. static PhysicsManifold contacts[PHYSAC_MAX_MANIFOLDS]; // Physics bodies pointers array
  277. static unsigned int physicsManifoldsCount = 0; // Physics world current manifolds counter
  278. static Vector2 gravityForce = { 0.0f, 9.81f }; // Physics world gravity force
  279. // Utilities variables
  280. static unsigned int usedMemory = 0; // Total allocated dynamic memory
  281. //----------------------------------------------------------------------------------
  282. // Module Internal Functions Declaration
  283. //----------------------------------------------------------------------------------
  284. #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
  285. // Timming measure functions
  286. static void InitTimer(void); // Initializes hi-resolution MONOTONIC timer
  287. static unsigned long long int GetClockTicks(void); // Get hi-res MONOTONIC time measure in mseconds
  288. static double GetCurrentTime(void); // Get current time measure in milliseconds
  289. #endif
  290. static void UpdatePhysicsStep(void); // Update physics step (dynamics, collisions and position corrections)
  291. static int FindAvailableBodyIndex(); // Finds a valid index for a new physics body initialization
  292. static int FindAvailableManifoldIndex(); // Finds a valid index for a new manifold initialization
  293. static PhysicsVertexData CreateDefaultPolygon(float radius, int sides); // Creates a random polygon shape with max vertex distance from polygon pivot
  294. static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size); // Creates a rectangle polygon shape based on a min and max positions
  295. static void InitializePhysicsManifolds(PhysicsManifold manifold); // Initializes physics manifolds to solve collisions
  296. static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b); // Creates a new physics manifold to solve collision
  297. static void DestroyPhysicsManifold(PhysicsManifold manifold); // Unitializes and destroys a physics manifold
  298. static void SolvePhysicsManifold(PhysicsManifold manifold); // Solves a created physics manifold between two physics bodies
  299. static void SolveCircleToCircle(PhysicsManifold manifold); // Solves collision between two circle shape physics bodies
  300. static void SolveCircleToPolygon(PhysicsManifold manifold); // Solves collision between a circle to a polygon shape physics bodies
  301. static void SolvePolygonToCircle(PhysicsManifold manifold); // Solves collision between a polygon to a circle shape physics bodies
  302. static void SolvePolygonToPolygon(PhysicsManifold manifold); // Solves collision between two polygons shape physics bodies
  303. static void IntegratePhysicsForces(PhysicsBody body); // Integrates physics forces into velocity
  304. static void IntegratePhysicsVelocity(PhysicsBody body); // Integrates physics velocity into position and forces
  305. static void IntegratePhysicsImpulses(PhysicsManifold manifold); // Integrates physics collisions impulses to solve collisions
  306. static void CorrectPhysicsPositions(PhysicsManifold manifold); // Corrects physics bodies positions based on manifolds collision information
  307. static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, PhysicsShape inc, int index); // Finds two polygon shapes incident face
  308. static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, PhysicsShape shapeB); // Finds polygon shapes axis least penetration
  309. // Math required functions
  310. static Vector2 MathVector2Product(Vector2 vector, float value); // Returns the product of a vector and a value
  311. static float MathVector2CrossProduct(Vector2 v1, Vector2 v2); // Returns the cross product of two vectors
  312. static float MathVector2SqrLen(Vector2 vector); // Returns the len square root of a vector
  313. static float MathVector2DotProduct(Vector2 v1, Vector2 v2); // Returns the dot product of two vectors
  314. static inline float MathVector2SqrDistance(Vector2 v1, Vector2 v2); // Returns the square root of distance between two vectors
  315. static void MathVector2Normalize(Vector2 *vector); // Returns the normalized values of a vector
  316. static Vector2 MathVector2Add(Vector2 v1, Vector2 v2); // Returns the sum of two given vectors
  317. static Vector2 MathVector2Subtract(Vector2 v1, Vector2 v2); // Returns the subtract of two given vectors
  318. static Matrix2x2 MathMatFromRadians(float radians); // Returns a matrix 2x2 from a given radians value
  319. static inline Matrix2x2 MathMatTranspose(Matrix2x2 matrix); // Returns the transpose of a given matrix 2x2
  320. static inline Vector2 MathMatVector2Product(Matrix2x2 matrix, Vector2 vector); // Returns product between matrix 2x2 and vector
  321. static int MathVector2Clip(Vector2 normal, Vector2 *faceA, Vector2 *faceB, float clip); // Returns clipping value based on a normal and two faces
  322. static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3); // Returns the barycenter of a triangle given by 3 points
  323. //----------------------------------------------------------------------------------
  324. // Module Functions Definition
  325. //----------------------------------------------------------------------------------
  326. // Initializes physics values, pointers and creates physics loop thread
  327. PHYSACDEF void InitPhysics(void)
  328. {
  329. #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
  330. // Initialize high resolution timer
  331. InitTimer();
  332. #endif
  333. TRACELOG("[PHYSAC] Physics module initialized successfully\n");
  334. }
  335. // Sets physics global gravity force
  336. PHYSACDEF void SetPhysicsGravity(float x, float y)
  337. {
  338. gravityForce.x = x;
  339. gravityForce.y = y;
  340. }
  341. // Creates a new circle physics body with generic parameters
  342. PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density)
  343. {
  344. PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density);
  345. return body;
  346. }
  347. // Creates a new rectangle physics body with generic parameters
  348. PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density)
  349. {
  350. // NOTE: Make sure body data is initialized to 0
  351. PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1);
  352. usedMemory += sizeof(PhysicsBodyData);
  353. int id = FindAvailableBodyIndex();
  354. if (id != -1)
  355. {
  356. // Initialize new body with generic values
  357. body->id = id;
  358. body->enabled = true;
  359. body->position = pos;
  360. body->shape.type = PHYSICS_POLYGON;
  361. body->shape.body = body;
  362. body->shape.transform = MathMatFromRadians(0.0f);
  363. body->shape.vertexData = CreateRectanglePolygon(pos, CLITERAL(Vector2){ width, height });
  364. // Calculate centroid and moment of inertia
  365. Vector2 center = { 0.0f, 0.0f };
  366. float area = 0.0f;
  367. float inertia = 0.0f;
  368. for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
  369. {
  370. // Triangle vertices, third vertex implied as (0, 0)
  371. Vector2 p1 = body->shape.vertexData.positions[i];
  372. unsigned int nextIndex = (((i + 1) < body->shape.vertexData.vertexCount) ? (i + 1) : 0);
  373. Vector2 p2 = body->shape.vertexData.positions[nextIndex];
  374. float D = MathVector2CrossProduct(p1, p2);
  375. float triangleArea = D/2;
  376. area += triangleArea;
  377. // Use area to weight the centroid average, not just vertex position
  378. center.x += triangleArea*PHYSAC_K*(p1.x + p2.x);
  379. center.y += triangleArea*PHYSAC_K*(p1.y + p2.y);
  380. float intx2 = p1.x*p1.x + p2.x*p1.x + p2.x*p2.x;
  381. float inty2 = p1.y*p1.y + p2.y*p1.y + p2.y*p2.y;
  382. inertia += (0.25f*PHYSAC_K*D)*(intx2 + inty2);
  383. }
  384. center.x *= 1.0f/area;
  385. center.y *= 1.0f/area;
  386. // Translate vertices to centroid (make the centroid (0, 0) for the polygon in model space)
  387. // Note: this is not really necessary
  388. for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
  389. {
  390. body->shape.vertexData.positions[i].x -= center.x;
  391. body->shape.vertexData.positions[i].y -= center.y;
  392. }
  393. body->mass = density*area;
  394. body->inverseMass = ((body->mass != 0.0f) ? 1.0f/body->mass : 0.0f);
  395. body->inertia = density*inertia;
  396. body->inverseInertia = ((body->inertia != 0.0f) ? 1.0f/body->inertia : 0.0f);
  397. body->staticFriction = 0.4f;
  398. body->dynamicFriction = 0.2f;
  399. body->restitution = 0.0f;
  400. body->useGravity = true;
  401. body->isGrounded = false;
  402. body->freezeOrient = false;
  403. // Add new body to bodies pointers array and update bodies count
  404. bodies[physicsBodiesCount] = body;
  405. physicsBodiesCount++;
  406. TRACELOG("[PHYSAC] Physic body created successfully (id: %i)\n", body->id);
  407. }
  408. else TRACELOG("[PHYSAC] Physic body could not be created, PHYSAC_MAX_BODIES reached\n");
  409. return body;
  410. }
  411. // Creates a new polygon physics body with generic parameters
  412. PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density)
  413. {
  414. PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
  415. usedMemory += sizeof(PhysicsBodyData);
  416. int id = FindAvailableBodyIndex();
  417. if (id != -1)
  418. {
  419. // Initialize new body with generic values
  420. body->id = id;
  421. body->enabled = true;
  422. body->position = pos;
  423. body->velocity = PHYSAC_VECTOR_ZERO;
  424. body->force = PHYSAC_VECTOR_ZERO;
  425. body->angularVelocity = 0.0f;
  426. body->torque = 0.0f;
  427. body->orient = 0.0f;
  428. body->shape.type = PHYSICS_POLYGON;
  429. body->shape.body = body;
  430. body->shape.transform = MathMatFromRadians(0.0f);
  431. body->shape.vertexData = CreateDefaultPolygon(radius, sides);
  432. // Calculate centroid and moment of inertia
  433. Vector2 center = { 0.0f, 0.0f };
  434. float area = 0.0f;
  435. float inertia = 0.0f;
  436. for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
  437. {
  438. // Triangle vertices, third vertex implied as (0, 0)
  439. Vector2 position1 = body->shape.vertexData.positions[i];
  440. unsigned int nextIndex = (((i + 1) < body->shape.vertexData.vertexCount) ? (i + 1) : 0);
  441. Vector2 position2 = body->shape.vertexData.positions[nextIndex];
  442. float cross = MathVector2CrossProduct(position1, position2);
  443. float triangleArea = cross/2;
  444. area += triangleArea;
  445. // Use area to weight the centroid average, not just vertex position
  446. center.x += triangleArea*PHYSAC_K*(position1.x + position2.x);
  447. center.y += triangleArea*PHYSAC_K*(position1.y + position2.y);
  448. float intx2 = position1.x*position1.x + position2.x*position1.x + position2.x*position2.x;
  449. float inty2 = position1.y*position1.y + position2.y*position1.y + position2.y*position2.y;
  450. inertia += (0.25f*PHYSAC_K*cross)*(intx2 + inty2);
  451. }
  452. center.x *= 1.0f/area;
  453. center.y *= 1.0f/area;
  454. // Translate vertices to centroid (make the centroid (0, 0) for the polygon in model space)
  455. // Note: this is not really necessary
  456. for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
  457. {
  458. body->shape.vertexData.positions[i].x -= center.x;
  459. body->shape.vertexData.positions[i].y -= center.y;
  460. }
  461. body->mass = density*area;
  462. body->inverseMass = ((body->mass != 0.0f) ? 1.0f/body->mass : 0.0f);
  463. body->inertia = density*inertia;
  464. body->inverseInertia = ((body->inertia != 0.0f) ? 1.0f/body->inertia : 0.0f);
  465. body->staticFriction = 0.4f;
  466. body->dynamicFriction = 0.2f;
  467. body->restitution = 0.0f;
  468. body->useGravity = true;
  469. body->isGrounded = false;
  470. body->freezeOrient = false;
  471. // Add new body to bodies pointers array and update bodies count
  472. bodies[physicsBodiesCount] = body;
  473. physicsBodiesCount++;
  474. TRACELOG("[PHYSAC] Physic body created successfully (id: %i)\n", body->id);
  475. }
  476. else TRACELOG("[PHYSAC] Physics body could not be created, PHYSAC_MAX_BODIES reached\n");
  477. return body;
  478. }
  479. // Adds a force to a physics body
  480. PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force)
  481. {
  482. if (body != NULL) body->force = MathVector2Add(body->force, force);
  483. }
  484. // Adds an angular force to a physics body
  485. PHYSACDEF void PhysicsAddTorque(PhysicsBody body, float amount)
  486. {
  487. if (body != NULL) body->torque += amount;
  488. }
  489. // Shatters a polygon shape physics body to little physics bodies with explosion force
  490. PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
  491. {
  492. if (body != NULL)
  493. {
  494. if (body->shape.type == PHYSICS_POLYGON)
  495. {
  496. PhysicsVertexData vertexData = body->shape.vertexData;
  497. bool collision = false;
  498. for (unsigned int i = 0; i < vertexData.vertexCount; i++)
  499. {
  500. Vector2 positionA = body->position;
  501. Vector2 positionB = MathMatVector2Product(body->shape.transform, MathVector2Add(body->position, vertexData.positions[i]));
  502. unsigned int nextIndex = (((i + 1) < vertexData.vertexCount) ? (i + 1) : 0);
  503. Vector2 positionC = MathMatVector2Product(body->shape.transform, MathVector2Add(body->position, vertexData.positions[nextIndex]));
  504. // Check collision between each triangle
  505. float alpha = ((positionB.y - positionC.y)*(position.x - positionC.x) + (positionC.x - positionB.x)*(position.y - positionC.y))/
  506. ((positionB.y - positionC.y)*(positionA.x - positionC.x) + (positionC.x - positionB.x)*(positionA.y - positionC.y));
  507. float beta = ((positionC.y - positionA.y)*(position.x - positionC.x) + (positionA.x - positionC.x)*(position.y - positionC.y))/
  508. ((positionB.y - positionC.y)*(positionA.x - positionC.x) + (positionC.x - positionB.x)*(positionA.y - positionC.y));
  509. float gamma = 1.0f - alpha - beta;
  510. if ((alpha > 0.0f) && (beta > 0.0f) & (gamma > 0.0f))
  511. {
  512. collision = true;
  513. break;
  514. }
  515. }
  516. if (collision)
  517. {
  518. int count = vertexData.vertexCount;
  519. Vector2 bodyPos = body->position;
  520. Vector2 *vertices = (Vector2 *)PHYSAC_MALLOC(sizeof(Vector2)*count);
  521. Matrix2x2 trans = body->shape.transform;
  522. for (int i = 0; i < count; i++) vertices[i] = vertexData.positions[i];
  523. // Destroy shattered physics body
  524. DestroyPhysicsBody(body);
  525. for (int i = 0; i < count; i++)
  526. {
  527. int nextIndex = (((i + 1) < count) ? (i + 1) : 0);
  528. Vector2 center = MathTriangleBarycenter(vertices[i], vertices[nextIndex], PHYSAC_VECTOR_ZERO);
  529. center = MathVector2Add(bodyPos, center);
  530. Vector2 offset = MathVector2Subtract(center, bodyPos);
  531. PhysicsBody body = CreatePhysicsBodyPolygon(center, 10, 3, 10); // Create polygon physics body with relevant values
  532. PhysicsVertexData vertexData = { 0 };
  533. vertexData.vertexCount = 3;
  534. vertexData.positions[0] = MathVector2Subtract(vertices[i], offset);
  535. vertexData.positions[1] = MathVector2Subtract(vertices[nextIndex], offset);
  536. vertexData.positions[2] = MathVector2Subtract(position, center);
  537. // Separate vertices to avoid unnecessary physics collisions
  538. vertexData.positions[0].x *= 0.95f;
  539. vertexData.positions[0].y *= 0.95f;
  540. vertexData.positions[1].x *= 0.95f;
  541. vertexData.positions[1].y *= 0.95f;
  542. vertexData.positions[2].x *= 0.95f;
  543. vertexData.positions[2].y *= 0.95f;
  544. // Calculate polygon faces normals
  545. for (unsigned int j = 0; j < vertexData.vertexCount; j++)
  546. {
  547. unsigned int nextVertex = (((j + 1) < vertexData.vertexCount) ? (j + 1) : 0);
  548. Vector2 face = MathVector2Subtract(vertexData.positions[nextVertex], vertexData.positions[j]);
  549. vertexData.normals[j] = CLITERAL(Vector2){ face.y, -face.x };
  550. MathVector2Normalize(&vertexData.normals[j]);
  551. }
  552. // Apply computed vertex data to new physics body shape
  553. body->shape.vertexData = vertexData;
  554. body->shape.transform = trans;
  555. // Calculate centroid and moment of inertia
  556. center = PHYSAC_VECTOR_ZERO;
  557. float area = 0.0f;
  558. float inertia = 0.0f;
  559. for (unsigned int j = 0; j < body->shape.vertexData.vertexCount; j++)
  560. {
  561. // Triangle vertices, third vertex implied as (0, 0)
  562. Vector2 p1 = body->shape.vertexData.positions[j];
  563. unsigned int nextVertex = (((j + 1) < body->shape.vertexData.vertexCount) ? (j + 1) : 0);
  564. Vector2 p2 = body->shape.vertexData.positions[nextVertex];
  565. float D = MathVector2CrossProduct(p1, p2);
  566. float triangleArea = D/2;
  567. area += triangleArea;
  568. // Use area to weight the centroid average, not just vertex position
  569. center.x += triangleArea*PHYSAC_K*(p1.x + p2.x);
  570. center.y += triangleArea*PHYSAC_K*(p1.y + p2.y);
  571. float intx2 = p1.x*p1.x + p2.x*p1.x + p2.x*p2.x;
  572. float inty2 = p1.y*p1.y + p2.y*p1.y + p2.y*p2.y;
  573. inertia += (0.25f*PHYSAC_K*D)*(intx2 + inty2);
  574. }
  575. center.x *= 1.0f/area;
  576. center.y *= 1.0f/area;
  577. body->mass = area;
  578. body->inverseMass = ((body->mass != 0.0f) ? 1.0f/body->mass : 0.0f);
  579. body->inertia = inertia;
  580. body->inverseInertia = ((body->inertia != 0.0f) ? 1.0f/body->inertia : 0.0f);
  581. // Calculate explosion force direction
  582. Vector2 pointA = body->position;
  583. Vector2 pointB = MathVector2Subtract(vertexData.positions[1], vertexData.positions[0]);
  584. pointB.x /= 2.0f;
  585. pointB.y /= 2.0f;
  586. Vector2 forceDirection = MathVector2Subtract(MathVector2Add(pointA, MathVector2Add(vertexData.positions[0], pointB)), body->position);
  587. MathVector2Normalize(&forceDirection);
  588. forceDirection.x *= force;
  589. forceDirection.y *= force;
  590. // Apply force to new physics body
  591. PhysicsAddForce(body, forceDirection);
  592. }
  593. PHYSAC_FREE(vertices);
  594. }
  595. }
  596. }
  597. else TRACELOG("[PHYSAC] WARNING: PhysicsShatter: NULL physic body\n");
  598. }
  599. // Returns the current amount of created physics bodies
  600. PHYSACDEF int GetPhysicsBodiesCount(void)
  601. {
  602. return physicsBodiesCount;
  603. }
  604. // Returns a physics body of the bodies pool at a specific index
  605. PHYSACDEF PhysicsBody GetPhysicsBody(int index)
  606. {
  607. PhysicsBody body = NULL;
  608. if (index < (int)physicsBodiesCount)
  609. {
  610. body = bodies[index];
  611. if (body == NULL) TRACELOG("[PHYSAC] WARNING: GetPhysicsBody: NULL physic body\n");
  612. }
  613. else TRACELOG("[PHYSAC] WARNING: Physic body index is out of bounds\n");
  614. return body;
  615. }
  616. // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
  617. PHYSACDEF int GetPhysicsShapeType(int index)
  618. {
  619. int result = -1;
  620. if (index < (int)physicsBodiesCount)
  621. {
  622. PhysicsBody body = bodies[index];
  623. if (body != NULL) result = body->shape.type;
  624. else TRACELOG("[PHYSAC] WARNING: GetPhysicsShapeType: NULL physic body\n");
  625. }
  626. else TRACELOG("[PHYSAC] WARNING: Physic body index is out of bounds\n");
  627. return result;
  628. }
  629. // Returns the amount of vertices of a physics body shape
  630. PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
  631. {
  632. int result = 0;
  633. if (index < (int)physicsBodiesCount)
  634. {
  635. PhysicsBody body = bodies[index];
  636. if (body != NULL)
  637. {
  638. switch (body->shape.type)
  639. {
  640. case PHYSICS_CIRCLE: result = PHYSAC_DEFAULT_CIRCLE_VERTICES; break;
  641. case PHYSICS_POLYGON: result = body->shape.vertexData.vertexCount; break;
  642. default: break;
  643. }
  644. }
  645. else TRACELOG("[PHYSAC] WARNING: GetPhysicsShapeVerticesCount: NULL physic body\n");
  646. }
  647. else TRACELOG("[PHYSAC] WARNING: Physic body index is out of bounds\n");
  648. return result;
  649. }
  650. // Returns transformed position of a body shape (body position + vertex transformed position)
  651. PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
  652. {
  653. Vector2 position = { 0.0f, 0.0f };
  654. if (body != NULL)
  655. {
  656. switch (body->shape.type)
  657. {
  658. case PHYSICS_CIRCLE:
  659. {
  660. position.x = body->position.x + cosf(360.0f/PHYSAC_DEFAULT_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius;
  661. position.y = body->position.y + sinf(360.0f/PHYSAC_DEFAULT_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius;
  662. } break;
  663. case PHYSICS_POLYGON:
  664. {
  665. PhysicsVertexData vertexData = body->shape.vertexData;
  666. position = MathVector2Add(body->position, MathMatVector2Product(body->shape.transform, vertexData.positions[vertex]));
  667. } break;
  668. default: break;
  669. }
  670. }
  671. else TRACELOG("[PHYSAC] WARNING: GetPhysicsShapeVertex: NULL physic body\n");
  672. return position;
  673. }
  674. // Sets physics body shape transform based on radians parameter
  675. PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians)
  676. {
  677. if (body != NULL)
  678. {
  679. body->orient = radians;
  680. if (body->shape.type == PHYSICS_POLYGON) body->shape.transform = MathMatFromRadians(radians);
  681. }
  682. }
  683. // Unitializes and destroys a physics body
  684. PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
  685. {
  686. if (body != NULL)
  687. {
  688. int id = body->id;
  689. int index = -1;
  690. for (unsigned int i = 0; i < physicsBodiesCount; i++)
  691. {
  692. if (bodies[i]->id == id)
  693. {
  694. index = i;
  695. break;
  696. }
  697. }
  698. if (index == -1)
  699. {
  700. TRACELOG("[PHYSAC] WARNING: Requested body (id: %i) can not be found\n", id);
  701. return; // Prevent access to index -1
  702. }
  703. // Free body allocated memory
  704. PHYSAC_FREE(body);
  705. usedMemory -= sizeof(PhysicsBodyData);
  706. bodies[index] = NULL;
  707. // Reorder physics bodies pointers array and its catched index
  708. for (unsigned int i = index; i < physicsBodiesCount; i++)
  709. {
  710. if ((i + 1) < physicsBodiesCount) bodies[i] = bodies[i + 1];
  711. }
  712. // Update physics bodies count
  713. physicsBodiesCount--;
  714. TRACELOG("[PHYSAC] Physic body destroyed successfully (id: %i)\n", id);
  715. }
  716. else TRACELOG("[PHYSAC] WARNING: DestroyPhysicsBody: NULL physic body\n");
  717. }
  718. // Destroys created physics bodies and manifolds and resets global values
  719. PHYSACDEF void ResetPhysics(void)
  720. {
  721. if (physicsBodiesCount > 0)
  722. {
  723. // Unitialize physics bodies dynamic memory allocations
  724. for (unsigned int i = physicsBodiesCount - 1; i >= 0; i--)
  725. {
  726. PhysicsBody body = bodies[i];
  727. if (body != NULL)
  728. {
  729. PHYSAC_FREE(body);
  730. bodies[i] = NULL;
  731. usedMemory -= sizeof(PhysicsBodyData);
  732. }
  733. }
  734. physicsBodiesCount = 0;
  735. }
  736. if (physicsManifoldsCount > 0)
  737. {
  738. // Unitialize physics manifolds dynamic memory allocations
  739. for (unsigned int i = physicsManifoldsCount - 1; i >= 0; i--)
  740. {
  741. PhysicsManifold manifold = contacts[i];
  742. if (manifold != NULL)
  743. {
  744. PHYSAC_FREE(manifold);
  745. contacts[i] = NULL;
  746. usedMemory -= sizeof(PhysicsManifoldData);
  747. }
  748. }
  749. physicsManifoldsCount = 0;
  750. }
  751. TRACELOG("[PHYSAC] Physics module reseted successfully\n");
  752. }
  753. // Unitializes physics pointers and exits physics loop thread
  754. PHYSACDEF void ClosePhysics(void)
  755. {
  756. // Unitialize physics manifolds dynamic memory allocations
  757. if (physicsManifoldsCount > 0)
  758. {
  759. for (unsigned int i = physicsManifoldsCount - 1; i >= 0; i--)
  760. DestroyPhysicsManifold(contacts[i]);
  761. }
  762. // Unitialize physics bodies dynamic memory allocations
  763. if (physicsBodiesCount > 0)
  764. {
  765. for (unsigned int i = physicsBodiesCount - 1; i >= 0; i--)
  766. DestroyPhysicsBody(bodies[i]);
  767. }
  768. // Trace log info
  769. if ((physicsBodiesCount > 0) || (usedMemory != 0))
  770. {
  771. TRACELOG("[PHYSAC] WARNING: Physics module closed with unallocated bodies (BODIES: %i, MEMORY: %i bytes)\n", physicsBodiesCount, usedMemory);
  772. }
  773. else if ((physicsManifoldsCount > 0) || (usedMemory != 0))
  774. {
  775. TRACELOG("[PHYSAC] WARNING: Pysics module closed with unallocated manifolds (MANIFOLDS: %i, MEMORY: %i bytes)\n", physicsManifoldsCount, usedMemory);
  776. }
  777. else TRACELOG("[PHYSAC] Physics module closed successfully\n");
  778. }
  779. //----------------------------------------------------------------------------------
  780. // Module Internal Functions Definition
  781. //----------------------------------------------------------------------------------
  782. // Finds a valid index for a new physics body initialization
  783. static int FindAvailableBodyIndex()
  784. {
  785. int index = -1;
  786. for (int i = 0; i < PHYSAC_MAX_BODIES; i++)
  787. {
  788. int currentId = i;
  789. // Check if current id already exist in other physics body
  790. for (unsigned int k = 0; k < physicsBodiesCount; k++)
  791. {
  792. if (bodies[k]->id == currentId)
  793. {
  794. currentId++;
  795. break;
  796. }
  797. }
  798. // If it is not used, use it as new physics body id
  799. if (currentId == (int)i)
  800. {
  801. index = (int)i;
  802. break;
  803. }
  804. }
  805. return index;
  806. }
  807. // Creates a default polygon shape with max vertex distance from polygon pivot
  808. static PhysicsVertexData CreateDefaultPolygon(float radius, int sides)
  809. {
  810. PhysicsVertexData data = { 0 };
  811. data.vertexCount = sides;
  812. // Calculate polygon vertices positions
  813. for (unsigned int i = 0; i < data.vertexCount; i++)
  814. {
  815. data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
  816. data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
  817. }
  818. // Calculate polygon faces normals
  819. for (int i = 0; i < (int)data.vertexCount; i++)
  820. {
  821. int nextIndex = (((i + 1) < sides) ? (i + 1) : 0);
  822. Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
  823. data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
  824. MathVector2Normalize(&data.normals[i]);
  825. }
  826. return data;
  827. }
  828. // Creates a rectangle polygon shape based on a min and max positions
  829. static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size)
  830. {
  831. PhysicsVertexData data = { 0 };
  832. data.vertexCount = 4;
  833. // Calculate polygon vertices positions
  834. data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
  835. data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
  836. data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
  837. data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
  838. // Calculate polygon faces normals
  839. for (unsigned int i = 0; i < data.vertexCount; i++)
  840. {
  841. int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0);
  842. Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
  843. data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
  844. MathVector2Normalize(&data.normals[i]);
  845. }
  846. return data;
  847. }
  848. // Update physics step (dynamics, collisions and position corrections)
  849. void UpdatePhysicsStep(void)
  850. {
  851. // Clear previous generated collisions information
  852. for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--)
  853. {
  854. PhysicsManifold manifold = contacts[i];
  855. if (manifold != NULL) DestroyPhysicsManifold(manifold);
  856. }
  857. // Reset physics bodies grounded state
  858. for (unsigned int i = 0; i < physicsBodiesCount; i++)
  859. {
  860. PhysicsBody body = bodies[i];
  861. body->isGrounded = false;
  862. }
  863. // Generate new collision information
  864. for (unsigned int i = 0; i < physicsBodiesCount; i++)
  865. {
  866. PhysicsBody bodyA = bodies[i];
  867. if (bodyA != NULL)
  868. {
  869. for (unsigned int j = i + 1; j < physicsBodiesCount; j++)
  870. {
  871. PhysicsBody bodyB = bodies[j];
  872. if (bodyB != NULL)
  873. {
  874. if ((bodyA->inverseMass == 0) && (bodyB->inverseMass == 0)) continue;
  875. PhysicsManifold manifold = CreatePhysicsManifold(bodyA, bodyB);
  876. SolvePhysicsManifold(manifold);
  877. if (manifold->contactsCount > 0)
  878. {
  879. // Create a new manifold with same information as previously solved manifold and add it to the manifolds pool last slot
  880. PhysicsManifold manifold = CreatePhysicsManifold(bodyA, bodyB);
  881. manifold->penetration = manifold->penetration;
  882. manifold->normal = manifold->normal;
  883. manifold->contacts[0] = manifold->contacts[0];
  884. manifold->contacts[1] = manifold->contacts[1];
  885. manifold->contactsCount = manifold->contactsCount;
  886. manifold->restitution = manifold->restitution;
  887. manifold->dynamicFriction = manifold->dynamicFriction;
  888. manifold->staticFriction = manifold->staticFriction;
  889. }
  890. }
  891. }
  892. }
  893. }
  894. // Integrate forces to physics bodies
  895. for (unsigned int i = 0; i < physicsBodiesCount; i++)
  896. {
  897. PhysicsBody body = bodies[i];
  898. if (body != NULL) IntegratePhysicsForces(body);
  899. }
  900. // Initialize physics manifolds to solve collisions
  901. for (unsigned int i = 0; i < physicsManifoldsCount; i++)
  902. {
  903. PhysicsManifold manifold = contacts[i];
  904. if (manifold != NULL) InitializePhysicsManifolds(manifold);
  905. }
  906. // Integrate physics collisions impulses to solve collisions
  907. for (unsigned int i = 0; i < PHYSAC_COLLISION_ITERATIONS; i++)
  908. {
  909. for (unsigned int j = 0; j < physicsManifoldsCount; j++)
  910. {
  911. PhysicsManifold manifold = contacts[i];
  912. if (manifold != NULL) IntegratePhysicsImpulses(manifold);
  913. }
  914. }
  915. // Integrate velocity to physics bodies
  916. for (unsigned int i = 0; i < physicsBodiesCount; i++)
  917. {
  918. PhysicsBody body = bodies[i];
  919. if (body != NULL) IntegratePhysicsVelocity(body);
  920. }
  921. // Correct physics bodies positions based on manifolds collision information
  922. for (unsigned int i = 0; i < physicsManifoldsCount; i++)
  923. {
  924. PhysicsManifold manifold = contacts[i];
  925. if (manifold != NULL) CorrectPhysicsPositions(manifold);
  926. }
  927. // Clear physics bodies forces
  928. for (unsigned int i = 0; i < physicsBodiesCount; i++)
  929. {
  930. PhysicsBody body = bodies[i];
  931. if (body != NULL)
  932. {
  933. body->force = PHYSAC_VECTOR_ZERO;
  934. body->torque = 0.0f;
  935. }
  936. }
  937. }
  938. // Update physics system
  939. // Physics steps are launched at a fixed time step if enabled
  940. PHYSACDEF void UpdatePhysics(void)
  941. {
  942. #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
  943. static double deltaTimeAccumulator = 0.0;
  944. // Calculate current time (ms)
  945. currentTime = GetCurrentTime();
  946. // Calculate current delta time (ms)
  947. const double delta = currentTime - startTime;
  948. // Store the time elapsed since the last frame began
  949. deltaTimeAccumulator += delta;
  950. // Fixed time stepping loop
  951. while (deltaTimeAccumulator >= deltaTime)
  952. {
  953. UpdatePhysicsStep();
  954. deltaTimeAccumulator -= deltaTime;
  955. }
  956. // Record the starting of this frame
  957. startTime = currentTime;
  958. #else
  959. UpdatePhysicsStep();
  960. #endif
  961. }
  962. PHYSACDEF void SetPhysicsTimeStep(double delta)
  963. {
  964. deltaTime = delta;
  965. }
  966. // Finds a valid index for a new manifold initialization
  967. static int FindAvailableManifoldIndex()
  968. {
  969. int index = -1;
  970. for (int i = 0; i < PHYSAC_MAX_MANIFOLDS; i++)
  971. {
  972. int currentId = i;
  973. // Check if current id already exist in other physics body
  974. for (unsigned int k = 0; k < physicsManifoldsCount; k++)
  975. {
  976. if (contacts[k]->id == currentId)
  977. {
  978. currentId++;
  979. break;
  980. }
  981. }
  982. // If it is not used, use it as new physics body id
  983. if (currentId == i)
  984. {
  985. index = i;
  986. break;
  987. }
  988. }
  989. return index;
  990. }
  991. // Creates a new physics manifold to solve collision
  992. static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b)
  993. {
  994. PhysicsManifold manifold = (PhysicsManifold)PHYSAC_MALLOC(sizeof(PhysicsManifoldData));
  995. usedMemory += sizeof(PhysicsManifoldData);
  996. int id = FindAvailableManifoldIndex();
  997. if (id != -1)
  998. {
  999. // Initialize new manifold with generic values
  1000. manifold->id = id;
  1001. manifold->bodyA = a;
  1002. manifold->bodyB = b;
  1003. manifold->penetration = 0;
  1004. manifold->normal = PHYSAC_VECTOR_ZERO;
  1005. manifold->contacts[0] = PHYSAC_VECTOR_ZERO;
  1006. manifold->contacts[1] = PHYSAC_VECTOR_ZERO;
  1007. manifold->contactsCount = 0;
  1008. manifold->restitution = 0.0f;
  1009. manifold->dynamicFriction = 0.0f;
  1010. manifold->staticFriction = 0.0f;
  1011. // Add new body to bodies pointers array and update bodies count
  1012. contacts[physicsManifoldsCount] = manifold;
  1013. physicsManifoldsCount++;
  1014. }
  1015. else TRACELOG("[PHYSAC] Physic manifold could not be created, PHYSAC_MAX_MANIFOLDS reached\n");
  1016. return manifold;
  1017. }
  1018. // Unitializes and destroys a physics manifold
  1019. static void DestroyPhysicsManifold(PhysicsManifold manifold)
  1020. {
  1021. if (manifold != NULL)
  1022. {
  1023. int id = manifold->id;
  1024. int index = -1;
  1025. for (unsigned int i = 0; i < physicsManifoldsCount; i++)
  1026. {
  1027. if (contacts[i]->id == id)
  1028. {
  1029. index = i;
  1030. break;
  1031. }
  1032. }
  1033. if (index == -1) return; // Prevent access to index -1
  1034. // Free manifold allocated memory
  1035. PHYSAC_FREE(manifold);
  1036. usedMemory -= sizeof(PhysicsManifoldData);
  1037. contacts[index] = NULL;
  1038. // Reorder physics manifolds pointers array and its catched index
  1039. for (unsigned int i = index; i < physicsManifoldsCount; i++)
  1040. {
  1041. if ((i + 1) < physicsManifoldsCount) contacts[i] = contacts[i + 1];
  1042. }
  1043. // Update physics manifolds count
  1044. physicsManifoldsCount--;
  1045. }
  1046. else TRACELOG("[PHYSAC] WARNING: DestroyPhysicsManifold: NULL physic manifold\n");
  1047. }
  1048. // Solves a created physics manifold between two physics bodies
  1049. static void SolvePhysicsManifold(PhysicsManifold manifold)
  1050. {
  1051. switch (manifold->bodyA->shape.type)
  1052. {
  1053. case PHYSICS_CIRCLE:
  1054. {
  1055. switch (manifold->bodyB->shape.type)
  1056. {
  1057. case PHYSICS_CIRCLE: SolveCircleToCircle(manifold); break;
  1058. case PHYSICS_POLYGON: SolveCircleToPolygon(manifold); break;
  1059. default: break;
  1060. }
  1061. } break;
  1062. case PHYSICS_POLYGON:
  1063. {
  1064. switch (manifold->bodyB->shape.type)
  1065. {
  1066. case PHYSICS_CIRCLE: SolvePolygonToCircle(manifold); break;
  1067. case PHYSICS_POLYGON: SolvePolygonToPolygon(manifold); break;
  1068. default: break;
  1069. }
  1070. } break;
  1071. default: break;
  1072. }
  1073. // Update physics body grounded state if normal direction is down and grounded state is not set yet in previous manifolds
  1074. if (!manifold->bodyB->isGrounded) manifold->bodyB->isGrounded = (manifold->normal.y < 0);
  1075. }
  1076. // Solves collision between two circle shape physics bodies
  1077. static void SolveCircleToCircle(PhysicsManifold manifold)
  1078. {
  1079. PhysicsBody bodyA = manifold->bodyA;
  1080. PhysicsBody bodyB = manifold->bodyB;
  1081. if ((bodyA == NULL) || (bodyB == NULL)) return;
  1082. // Calculate translational vector, which is normal
  1083. Vector2 normal = MathVector2Subtract(bodyB->position, bodyA->position);
  1084. float distSqr = MathVector2SqrLen(normal);
  1085. float radius = bodyA->shape.radius + bodyB->shape.radius;
  1086. // Check if circles are not in contact
  1087. if (distSqr >= radius*radius)
  1088. {
  1089. manifold->contactsCount = 0;
  1090. return;
  1091. }
  1092. float distance = sqrtf(distSqr);
  1093. manifold->contactsCount = 1;
  1094. if (distance == 0.0f)
  1095. {
  1096. manifold->penetration = bodyA->shape.radius;
  1097. manifold->normal = CLITERAL(Vector2){ 1.0f, 0.0f };
  1098. manifold->contacts[0] = bodyA->position;
  1099. }
  1100. else
  1101. {
  1102. manifold->penetration = radius - distance;
  1103. manifold->normal = CLITERAL(Vector2){ normal.x/distance, normal.y/distance }; // Faster than using MathVector2Normalize() due to sqrt is already performed
  1104. manifold->contacts[0] = CLITERAL(Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
  1105. }
  1106. // Update physics body grounded state if normal direction is down
  1107. if (!bodyA->isGrounded) bodyA->isGrounded = (manifold->normal.y < 0);
  1108. }
  1109. // Solves collision between a circle to a polygon shape physics bodies
  1110. static void SolveCircleToPolygon(PhysicsManifold manifold)
  1111. {
  1112. PhysicsBody bodyA = manifold->bodyA;
  1113. PhysicsBody bodyB = manifold->bodyB;
  1114. if ((bodyA == NULL) || (bodyB == NULL)) return;
  1115. manifold->contactsCount = 0;
  1116. // Transform circle center to polygon transform space
  1117. Vector2 center = bodyA->position;
  1118. center = MathMatVector2Product(MathMatTranspose(bodyB->shape.transform), MathVector2Subtract(center, bodyB->position));
  1119. // Find edge with minimum penetration
  1120. // It is the same concept as using support points in SolvePolygonToPolygon
  1121. float separation = -PHYSAC_FLT_MAX;
  1122. int faceNormal = 0;
  1123. PhysicsVertexData vertexData = bodyB->shape.vertexData;
  1124. for (unsigned int i = 0; i < vertexData.vertexCount; i++)
  1125. {
  1126. float currentSeparation = MathVector2DotProduct(vertexData.normals[i], MathVector2Subtract(center, vertexData.positions[i]));
  1127. if (currentSeparation > bodyA->shape.radius) return;
  1128. if (currentSeparation > separation)
  1129. {
  1130. separation = currentSeparation;
  1131. faceNormal = i;
  1132. }
  1133. }
  1134. // Grab face's vertices
  1135. Vector2 v1 = vertexData.positions[faceNormal];
  1136. int nextIndex = (((faceNormal + 1) < (int)vertexData.vertexCount) ? (faceNormal + 1) : 0);
  1137. Vector2 v2 = vertexData.positions[nextIndex];
  1138. // Check to see if center is within polygon
  1139. if (separation < PHYSAC_EPSILON)
  1140. {
  1141. manifold->contactsCount = 1;
  1142. Vector2 normal = MathMatVector2Product(bodyB->shape.transform, vertexData.normals[faceNormal]);
  1143. manifold->normal = CLITERAL(Vector2){ -normal.x, -normal.y };
  1144. manifold->contacts[0] = CLITERAL(Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
  1145. manifold->penetration = bodyA->shape.radius;
  1146. return;
  1147. }
  1148. // Determine which voronoi region of the edge center of circle lies within
  1149. float dot1 = MathVector2DotProduct(MathVector2Subtract(center, v1), MathVector2Subtract(v2, v1));
  1150. float dot2 = MathVector2DotProduct(MathVector2Subtract(center, v2), MathVector2Subtract(v1, v2));
  1151. manifold->penetration = bodyA->shape.radius - separation;
  1152. if (dot1 <= 0.0f) // Closest to v1
  1153. {
  1154. if (MathVector2SqrDistance(center, v1) > bodyA->shape.radius*bodyA->shape.radius) return;
  1155. manifold->contactsCount = 1;
  1156. Vector2 normal = MathVector2Subtract(v1, center);
  1157. normal = MathMatVector2Product(bodyB->shape.transform, normal);
  1158. MathVector2Normalize(&normal);
  1159. manifold->normal = normal;
  1160. v1 = MathMatVector2Product(bodyB->shape.transform, v1);
  1161. v1 = MathVector2Add(v1, bodyB->position);
  1162. manifold->contacts[0] = v1;
  1163. }
  1164. else if (dot2 <= 0.0f) // Closest to v2
  1165. {
  1166. if (MathVector2SqrDistance(center, v2) > bodyA->shape.radius*bodyA->shape.radius) return;
  1167. manifold->contactsCount = 1;
  1168. Vector2 normal = MathVector2Subtract(v2, center);
  1169. v2 = MathMatVector2Product(bodyB->shape.transform, v2);
  1170. v2 = MathVector2Add(v2, bodyB->position);
  1171. manifold->contacts[0] = v2;
  1172. normal = MathMatVector2Product(bodyB->shape.transform, normal);
  1173. MathVector2Normalize(&normal);
  1174. manifold->normal = normal;
  1175. }
  1176. else // Closest to face
  1177. {
  1178. Vector2 normal = vertexData.normals[faceNormal];
  1179. if (MathVector2DotProduct(MathVector2Subtract(center, v1), normal) > bodyA->shape.radius) return;
  1180. normal = MathMatVector2Product(bodyB->shape.transform, normal);
  1181. manifold->normal = CLITERAL(Vector2){ -normal.x, -normal.y };
  1182. manifold->contacts[0] = CLITERAL(Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
  1183. manifold->contactsCount = 1;
  1184. }
  1185. }
  1186. // Solves collision between a polygon to a circle shape physics bodies
  1187. static void SolvePolygonToCircle(PhysicsManifold manifold)
  1188. {
  1189. PhysicsBody bodyA = manifold->bodyA;
  1190. PhysicsBody bodyB = manifold->bodyB;
  1191. if ((bodyA == NULL) || (bodyB == NULL)) return;
  1192. manifold->bodyA = bodyB;
  1193. manifold->bodyB = bodyA;
  1194. SolveCircleToPolygon(manifold);
  1195. manifold->normal.x *= -1.0f;
  1196. manifold->normal.y *= -1.0f;
  1197. }
  1198. // Solves collision between two polygons shape physics bodies
  1199. static void SolvePolygonToPolygon(PhysicsManifold manifold)
  1200. {
  1201. if ((manifold->bodyA == NULL) || (manifold->bodyB == NULL)) return;
  1202. PhysicsShape bodyA = manifold->bodyA->shape;
  1203. PhysicsShape bodyB = manifold->bodyB->shape;
  1204. manifold->contactsCount = 0;
  1205. // Check for separating axis with A shape's face planes
  1206. int faceA = 0;
  1207. float penetrationA = FindAxisLeastPenetration(&faceA, bodyA, bodyB);
  1208. if (penetrationA >= 0.0f) return;
  1209. // Check for separating axis with B shape's face planes
  1210. int faceB = 0;
  1211. float penetrationB = FindAxisLeastPenetration(&faceB, bodyB, bodyA);
  1212. if (penetrationB >= 0.0f) return;
  1213. int referenceIndex = 0;
  1214. bool flip = false; // Always point from A shape to B shape
  1215. PhysicsShape refPoly; // Reference
  1216. PhysicsShape incPoly; // Incident
  1217. // Determine which shape contains reference face
  1218. // Checking bias range for penetration
  1219. if (penetrationA >= (penetrationB*0.95f + penetrationA*0.01f))
  1220. {
  1221. refPoly = bodyA;
  1222. incPoly = bodyB;
  1223. referenceIndex = faceA;
  1224. }
  1225. else
  1226. {
  1227. refPoly = bodyB;
  1228. incPoly = bodyA;
  1229. referenceIndex = faceB;
  1230. flip = true;
  1231. }
  1232. // World space incident face
  1233. Vector2 incidentFace[2];
  1234. FindIncidentFace(&incidentFace[0], &incidentFace[1], refPoly, incPoly, referenceIndex);
  1235. // Setup reference face vertices
  1236. PhysicsVertexData refData = refPoly.vertexData;
  1237. Vector2 v1 = refData.positions[referenceIndex];
  1238. referenceIndex = (((referenceIndex + 1) < (int)refData.vertexCount) ? (referenceIndex + 1) : 0);
  1239. Vector2 v2 = refData.positions[referenceIndex];
  1240. // Transform vertices to world space
  1241. v1 = MathMatVector2Product(refPoly.transform, v1);
  1242. v1 = MathVector2Add(v1, refPoly.body->position);
  1243. v2 = MathMatVector2Product(refPoly.transform, v2);
  1244. v2 = MathVector2Add(v2, refPoly.body->position);
  1245. // Calculate reference face side normal in world space
  1246. Vector2 sidePlaneNormal = MathVector2Subtract(v2, v1);
  1247. MathVector2Normalize(&sidePlaneNormal);
  1248. // Orthogonalize
  1249. Vector2 refFaceNormal = { sidePlaneNormal.y, -sidePlaneNormal.x };
  1250. float refC = MathVector2DotProduct(refFaceNormal, v1);
  1251. float negSide = MathVector2DotProduct(sidePlaneNormal, v1)*-1;
  1252. float posSide = MathVector2DotProduct(sidePlaneNormal, v2);
  1253. // MathVector2Clip incident face to reference face side planes (due to floating point error, possible to not have required points
  1254. if (MathVector2Clip(CLITERAL(Vector2){ -sidePlaneNormal.x, -sidePlaneNormal.y }, &incidentFace[0], &incidentFace[1], negSide) < 2) return;
  1255. if (MathVector2Clip(sidePlaneNormal, &incidentFace[0], &incidentFace[1], posSide) < 2) return;
  1256. // Flip normal if required
  1257. manifold->normal = (flip ? CLITERAL(Vector2){ -refFaceNormal.x, -refFaceNormal.y } : refFaceNormal);
  1258. // Keep points behind reference face
  1259. int currentPoint = 0; // MathVector2Clipped points behind reference face
  1260. float separation = MathVector2DotProduct(refFaceNormal, incidentFace[0]) - refC;
  1261. if (separation <= 0.0f)
  1262. {
  1263. manifold->contacts[currentPoint] = incidentFace[0];
  1264. manifold->penetration = -separation;
  1265. currentPoint++;
  1266. }
  1267. else manifold->penetration = 0.0f;
  1268. separation = MathVector2DotProduct(refFaceNormal, incidentFace[1]) - refC;
  1269. if (separation <= 0.0f)
  1270. {
  1271. manifold->contacts[currentPoint] = incidentFace[1];
  1272. manifold->penetration += -separation;
  1273. currentPoint++;
  1274. // Calculate total penetration average
  1275. manifold->penetration /= currentPoint;
  1276. }
  1277. manifold->contactsCount = currentPoint;
  1278. }
  1279. // Integrates physics forces into velocity
  1280. static void IntegratePhysicsForces(PhysicsBody body)
  1281. {
  1282. if ((body == NULL) || (body->inverseMass == 0.0f) || !body->enabled) return;
  1283. body->velocity.x += (float)((body->force.x*body->inverseMass)*(deltaTime/2.0));
  1284. body->velocity.y += (float)((body->force.y*body->inverseMass)*(deltaTime/2.0));
  1285. if (body->useGravity)
  1286. {
  1287. body->velocity.x += (float)(gravityForce.x*(deltaTime/1000/2.0));
  1288. body->velocity.y += (float)(gravityForce.y*(deltaTime/1000/2.0));
  1289. }
  1290. if (!body->freezeOrient) body->angularVelocity += (float)(body->torque*body->inverseInertia*(deltaTime/2.0));
  1291. }
  1292. // Initializes physics manifolds to solve collisions
  1293. static void InitializePhysicsManifolds(PhysicsManifold manifold)
  1294. {
  1295. PhysicsBody bodyA = manifold->bodyA;
  1296. PhysicsBody bodyB = manifold->bodyB;
  1297. if ((bodyA == NULL) || (bodyB == NULL)) return;
  1298. // Calculate average restitution, static and dynamic friction
  1299. manifold->restitution = sqrtf(bodyA->restitution*bodyB->restitution);
  1300. manifold->staticFriction = sqrtf(bodyA->staticFriction*bodyB->staticFriction);
  1301. manifold->dynamicFriction = sqrtf(bodyA->dynamicFriction*bodyB->dynamicFriction);
  1302. for (unsigned int i = 0; i < manifold->contactsCount; i++)
  1303. {
  1304. // Caculate radius from center of mass to contact
  1305. Vector2 radiusA = MathVector2Subtract(manifold->contacts[i], bodyA->position);
  1306. Vector2 radiusB = MathVector2Subtract(manifold->contacts[i], bodyB->position);
  1307. Vector2 crossA = MathVector2Product(radiusA, bodyA->angularVelocity);
  1308. Vector2 crossB = MathVector2Product(radiusB, bodyB->angularVelocity);
  1309. Vector2 radiusV = { 0.0f, 0.0f };
  1310. radiusV.x = bodyB->velocity.x + crossB.x - bodyA->velocity.x - crossA.x;
  1311. radiusV.y = bodyB->velocity.y + crossB.y - bodyA->velocity.y - crossA.y;
  1312. // Determine if we should perform a resting collision or not;
  1313. // The idea is if the only thing moving this object is gravity, then the collision should be performed without any restitution
  1314. if (MathVector2SqrLen(radiusV) < (MathVector2SqrLen(CLITERAL(Vector2){ (float)(gravityForce.x*deltaTime/1000), (float)(gravityForce.y*deltaTime/1000) }) + PHYSAC_EPSILON)) manifold->restitution = 0;
  1315. }
  1316. }
  1317. // Integrates physics collisions impulses to solve collisions
  1318. static void IntegratePhysicsImpulses(PhysicsManifold manifold)
  1319. {
  1320. PhysicsBody bodyA = manifold->bodyA;
  1321. PhysicsBody bodyB = manifold->bodyB;
  1322. if ((bodyA == NULL) || (bodyB == NULL)) return;
  1323. // Early out and positional correct if both objects have infinite mass
  1324. if (fabs(bodyA->inverseMass + bodyB->inverseMass) <= PHYSAC_EPSILON)
  1325. {
  1326. bodyA->velocity = PHYSAC_VECTOR_ZERO;
  1327. bodyB->velocity = PHYSAC_VECTOR_ZERO;
  1328. return;
  1329. }
  1330. for (unsigned int i = 0; i < manifold->contactsCount; i++)
  1331. {
  1332. // Calculate radius from center of mass to contact
  1333. Vector2 radiusA = MathVector2Subtract(manifold->contacts[i], bodyA->position);
  1334. Vector2 radiusB = MathVector2Subtract(manifold->contacts[i], bodyB->position);
  1335. // Calculate relative velocity
  1336. Vector2 radiusV = { 0.0f, 0.0f };
  1337. radiusV.x = bodyB->velocity.x + MathVector2Product(radiusB, bodyB->angularVelocity).x - bodyA->velocity.x - MathVector2Product(radiusA, bodyA->angularVelocity).x;
  1338. radiusV.y = bodyB->velocity.y + MathVector2Product(radiusB, bodyB->angularVelocity).y - bodyA->velocity.y - MathVector2Product(radiusA, bodyA->angularVelocity).y;
  1339. // Relative velocity along the normal
  1340. float contactVelocity = MathVector2DotProduct(radiusV, manifold->normal);
  1341. // Do not resolve if velocities are separating
  1342. if (contactVelocity > 0.0f) return;
  1343. float raCrossN = MathVector2CrossProduct(radiusA, manifold->normal);
  1344. float rbCrossN = MathVector2CrossProduct(radiusB, manifold->normal);
  1345. float inverseMassSum = bodyA->inverseMass + bodyB->inverseMass + (raCrossN*raCrossN)*bodyA->inverseInertia + (rbCrossN*rbCrossN)*bodyB->inverseInertia;
  1346. // Calculate impulse scalar value
  1347. float impulse = -(1.0f + manifold->restitution)*contactVelocity;
  1348. impulse /= inverseMassSum;
  1349. impulse /= (float)manifold->contactsCount;
  1350. // Apply impulse to each physics body
  1351. Vector2 impulseV = { manifold->normal.x*impulse, manifold->normal.y*impulse };
  1352. if (bodyA->enabled)
  1353. {
  1354. bodyA->velocity.x += bodyA->inverseMass*(-impulseV.x);
  1355. bodyA->velocity.y += bodyA->inverseMass*(-impulseV.y);
  1356. if (!bodyA->freezeOrient) bodyA->angularVelocity += bodyA->inverseInertia*MathVector2CrossProduct(radiusA, CLITERAL(Vector2){ -impulseV.x, -impulseV.y });
  1357. }
  1358. if (bodyB->enabled)
  1359. {
  1360. bodyB->velocity.x += bodyB->inverseMass*(impulseV.x);
  1361. bodyB->velocity.y += bodyB->inverseMass*(impulseV.y);
  1362. if (!bodyB->freezeOrient) bodyB->angularVelocity += bodyB->inverseInertia*MathVector2CrossProduct(radiusB, impulseV);
  1363. }
  1364. // Apply friction impulse to each physics body
  1365. radiusV.x = bodyB->velocity.x + MathVector2Product(radiusB, bodyB->angularVelocity).x - bodyA->velocity.x - MathVector2Product(radiusA, bodyA->angularVelocity).x;
  1366. radiusV.y = bodyB->velocity.y + MathVector2Product(radiusB, bodyB->angularVelocity).y - bodyA->velocity.y - MathVector2Product(radiusA, bodyA->angularVelocity).y;
  1367. Vector2 tangent = { radiusV.x - (manifold->normal.x*MathVector2DotProduct(radiusV, manifold->normal)), radiusV.y - (manifold->normal.y*MathVector2DotProduct(radiusV, manifold->normal)) };
  1368. MathVector2Normalize(&tangent);
  1369. // Calculate impulse tangent magnitude
  1370. float impulseTangent = -MathVector2DotProduct(radiusV, tangent);
  1371. impulseTangent /= inverseMassSum;
  1372. impulseTangent /= (float)manifold->contactsCount;
  1373. float absImpulseTangent = (float)fabs(impulseTangent);
  1374. // Don't apply tiny friction impulses
  1375. if (absImpulseTangent <= PHYSAC_EPSILON) return;
  1376. // Apply coulumb's law
  1377. Vector2 tangentImpulse = { 0.0f, 0.0f };
  1378. if (absImpulseTangent < impulse*manifold->staticFriction) tangentImpulse = CLITERAL(Vector2){ tangent.x*impulseTangent, tangent.y*impulseTangent };
  1379. else tangentImpulse = CLITERAL(Vector2){ tangent.x*-impulse*manifold->dynamicFriction, tangent.y*-impulse*manifold->dynamicFriction };
  1380. // Apply friction impulse
  1381. if (bodyA->enabled)
  1382. {
  1383. bodyA->velocity.x += bodyA->inverseMass*(-tangentImpulse.x);
  1384. bodyA->velocity.y += bodyA->inverseMass*(-tangentImpulse.y);
  1385. if (!bodyA->freezeOrient) bodyA->angularVelocity += bodyA->inverseInertia*MathVector2CrossProduct(radiusA, CLITERAL(Vector2){ -tangentImpulse.x, -tangentImpulse.y });
  1386. }
  1387. if (bodyB->enabled)
  1388. {
  1389. bodyB->velocity.x += bodyB->inverseMass*(tangentImpulse.x);
  1390. bodyB->velocity.y += bodyB->inverseMass*(tangentImpulse.y);
  1391. if (!bodyB->freezeOrient) bodyB->angularVelocity += bodyB->inverseInertia*MathVector2CrossProduct(radiusB, tangentImpulse);
  1392. }
  1393. }
  1394. }
  1395. // Integrates physics velocity into position and forces
  1396. static void IntegratePhysicsVelocity(PhysicsBody body)
  1397. {
  1398. if ((body == NULL) ||!body->enabled) return;
  1399. body->position.x += (float)(body->velocity.x*deltaTime);
  1400. body->position.y += (float)(body->velocity.y*deltaTime);
  1401. if (!body->freezeOrient) body->orient += (float)(body->angularVelocity*deltaTime);
  1402. body->shape.transform = MathMatFromRadians(body->orient);
  1403. IntegratePhysicsForces(body);
  1404. }
  1405. // Corrects physics bodies positions based on manifolds collision information
  1406. static void CorrectPhysicsPositions(PhysicsManifold manifold)
  1407. {
  1408. PhysicsBody bodyA = manifold->bodyA;
  1409. PhysicsBody bodyB = manifold->bodyB;
  1410. if ((bodyA == NULL) || (bodyB == NULL)) return;
  1411. Vector2 correction = { 0.0f, 0.0f };
  1412. correction.x = (PHYSAC_MAX(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.x*PHYSAC_PENETRATION_CORRECTION;
  1413. correction.y = (PHYSAC_MAX(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.y*PHYSAC_PENETRATION_CORRECTION;
  1414. if (bodyA->enabled)
  1415. {
  1416. bodyA->position.x -= correction.x*bodyA->inverseMass;
  1417. bodyA->position.y -= correction.y*bodyA->inverseMass;
  1418. }
  1419. if (bodyB->enabled)
  1420. {
  1421. bodyB->position.x += correction.x*bodyB->inverseMass;
  1422. bodyB->position.y += correction.y*bodyB->inverseMass;
  1423. }
  1424. }
  1425. // Returns the extreme point along a direction within a polygon
  1426. static Vector2 GetSupport(PhysicsShape shape, Vector2 dir)
  1427. {
  1428. float bestProjection = -PHYSAC_FLT_MAX;
  1429. Vector2 bestVertex = { 0.0f, 0.0f };
  1430. PhysicsVertexData data = shape.vertexData;
  1431. for (unsigned int i = 0; i < data.vertexCount; i++)
  1432. {
  1433. Vector2 vertex = data.positions[i];
  1434. float projection = MathVector2DotProduct(vertex, dir);
  1435. if (projection > bestProjection)
  1436. {
  1437. bestVertex = vertex;
  1438. bestProjection = projection;
  1439. }
  1440. }
  1441. return bestVertex;
  1442. }
  1443. // Finds polygon shapes axis least penetration
  1444. static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, PhysicsShape shapeB)
  1445. {
  1446. float bestDistance = -PHYSAC_FLT_MAX;
  1447. int bestIndex = 0;
  1448. PhysicsVertexData dataA = shapeA.vertexData;
  1449. //PhysicsVertexData dataB = shapeB.vertexData;
  1450. for (unsigned int i = 0; i < dataA.vertexCount; i++)
  1451. {
  1452. // Retrieve a face normal from A shape
  1453. Vector2 normal = dataA.normals[i];
  1454. Vector2 transNormal = MathMatVector2Product(shapeA.transform, normal);
  1455. // Transform face normal into B shape's model space
  1456. Matrix2x2 buT = MathMatTranspose(shapeB.transform);
  1457. normal = MathMatVector2Product(buT, transNormal);
  1458. // Retrieve support point from B shape along -n
  1459. Vector2 support = GetSupport(shapeB, CLITERAL(Vector2){ -normal.x, -normal.y });
  1460. // Retrieve vertex on face from A shape, transform into B shape's model space
  1461. Vector2 vertex = dataA.positions[i];
  1462. vertex = MathMatVector2Product(shapeA.transform, vertex);
  1463. vertex = MathVector2Add(vertex, shapeA.body->position);
  1464. vertex = MathVector2Subtract(vertex, shapeB.body->position);
  1465. vertex = MathMatVector2Product(buT, vertex);
  1466. // Compute penetration distance in B shape's model space
  1467. float distance = MathVector2DotProduct(normal, MathVector2Subtract(support, vertex));
  1468. // Store greatest distance
  1469. if (distance > bestDistance)
  1470. {
  1471. bestDistance = distance;
  1472. bestIndex = i;
  1473. }
  1474. }
  1475. *faceIndex = bestIndex;
  1476. return bestDistance;
  1477. }
  1478. // Finds two polygon shapes incident face
  1479. static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, PhysicsShape inc, int index)
  1480. {
  1481. PhysicsVertexData refData = ref.vertexData;
  1482. PhysicsVertexData incData = inc.vertexData;
  1483. Vector2 referenceNormal = refData.normals[index];
  1484. // Calculate normal in incident's frame of reference
  1485. referenceNormal = MathMatVector2Product(ref.transform, referenceNormal); // To world space
  1486. referenceNormal = MathMatVector2Product(MathMatTranspose(inc.transform), referenceNormal); // To incident's model space
  1487. // Find most anti-normal face on polygon
  1488. int incidentFace = 0;
  1489. float minDot = PHYSAC_FLT_MAX;
  1490. for (unsigned int i = 0; i < incData.vertexCount; i++)
  1491. {
  1492. float dot = MathVector2DotProduct(referenceNormal, incData.normals[i]);
  1493. if (dot < minDot)
  1494. {
  1495. minDot = dot;
  1496. incidentFace = i;
  1497. }
  1498. }
  1499. // Assign face vertices for incident face
  1500. *v0 = MathMatVector2Product(inc.transform, incData.positions[incidentFace]);
  1501. *v0 = MathVector2Add(*v0, inc.body->position);
  1502. incidentFace = (((incidentFace + 1) < (int)incData.vertexCount) ? (incidentFace + 1) : 0);
  1503. *v1 = MathMatVector2Product(inc.transform, incData.positions[incidentFace]);
  1504. *v1 = MathVector2Add(*v1, inc.body->position);
  1505. }
  1506. // Returns clipping value based on a normal and two faces
  1507. static int MathVector2Clip(Vector2 normal, Vector2 *faceA, Vector2 *faceB, float clip)
  1508. {
  1509. int sp = 0;
  1510. Vector2 out[2] = { *faceA, *faceB };
  1511. // Retrieve distances from each endpoint to the line
  1512. float distanceA = MathVector2DotProduct(normal, *faceA) - clip;
  1513. float distanceB = MathVector2DotProduct(normal, *faceB) - clip;
  1514. // If negative (behind plane)
  1515. if (distanceA <= 0.0f) out[sp++] = *faceA;
  1516. if (distanceB <= 0.0f) out[sp++] = *faceB;
  1517. // If the points are on different sides of the plane
  1518. if ((distanceA*distanceB) < 0.0f)
  1519. {
  1520. // Push intersection point
  1521. float alpha = distanceA/(distanceA - distanceB);
  1522. out[sp] = *faceA;
  1523. Vector2 delta = MathVector2Subtract(*faceB, *faceA);
  1524. delta.x *= alpha;
  1525. delta.y *= alpha;
  1526. out[sp] = MathVector2Add(out[sp], delta);
  1527. sp++;
  1528. }
  1529. // Assign the new converted values
  1530. *faceA = out[0];
  1531. *faceB = out[1];
  1532. return sp;
  1533. }
  1534. // Returns the barycenter of a triangle given by 3 points
  1535. static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
  1536. {
  1537. Vector2 result = { 0.0f, 0.0f };
  1538. result.x = (v1.x + v2.x + v3.x)/3;
  1539. result.y = (v1.y + v2.y + v3.y)/3;
  1540. return result;
  1541. }
  1542. #if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
  1543. // Initializes hi-resolution MONOTONIC timer
  1544. static void InitTimer(void)
  1545. {
  1546. #if defined(_WIN32)
  1547. QueryPerformanceFrequency((unsigned long long int *) &frequency);
  1548. #endif
  1549. #if defined(__EMSCRIPTEN__) || defined(__linux__)
  1550. struct timespec now;
  1551. if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000;
  1552. #endif
  1553. #if defined(__APPLE__)
  1554. mach_timebase_info_data_t timebase;
  1555. mach_timebase_info(&timebase);
  1556. frequency = (timebase.denom*1e9)/timebase.numer;
  1557. #endif
  1558. baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset
  1559. startTime = GetCurrentTime(); // Get current time in milliseconds
  1560. }
  1561. // Get hi-res MONOTONIC time measure in clock ticks
  1562. static unsigned long long int GetClockTicks(void)
  1563. {
  1564. unsigned long long int value = 0;
  1565. #if defined(_WIN32)
  1566. QueryPerformanceCounter((unsigned long long int *) &value);
  1567. #endif
  1568. #if defined(__linux__)
  1569. struct timespec now;
  1570. clock_gettime(CLOCK_MONOTONIC, &now);
  1571. value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec;
  1572. #endif
  1573. #if defined(__APPLE__)
  1574. value = mach_absolute_time();
  1575. #endif
  1576. return value;
  1577. }
  1578. // Get current time in milliseconds
  1579. static double GetCurrentTime(void)
  1580. {
  1581. return (double)(GetClockTicks() - baseClockTicks)/frequency*1000;
  1582. }
  1583. #endif // !PHYSAC_AVOID_TIMMING_SYSTEM
  1584. // Returns the cross product of a vector and a value
  1585. static inline Vector2 MathVector2Product(Vector2 vector, float value)
  1586. {
  1587. Vector2 result = { -value*vector.y, value*vector.x };
  1588. return result;
  1589. }
  1590. // Returns the cross product of two vectors
  1591. static inline float MathVector2CrossProduct(Vector2 v1, Vector2 v2)
  1592. {
  1593. return (v1.x*v2.y - v1.y*v2.x);
  1594. }
  1595. // Returns the len square root of a vector
  1596. static inline float MathVector2SqrLen(Vector2 vector)
  1597. {
  1598. return (vector.x*vector.x + vector.y*vector.y);
  1599. }
  1600. // Returns the dot product of two vectors
  1601. static inline float MathVector2DotProduct(Vector2 v1, Vector2 v2)
  1602. {
  1603. return (v1.x*v2.x + v1.y*v2.y);
  1604. }
  1605. // Returns the square root of distance between two vectors
  1606. static inline float MathVector2SqrDistance(Vector2 v1, Vector2 v2)
  1607. {
  1608. Vector2 dir = MathVector2Subtract(v1, v2);
  1609. return MathVector2DotProduct(dir, dir);
  1610. }
  1611. // Returns the normalized values of a vector
  1612. static void MathVector2Normalize(Vector2 *vector)
  1613. {
  1614. float length, ilength;
  1615. Vector2 aux = *vector;
  1616. length = sqrtf(aux.x*aux.x + aux.y*aux.y);
  1617. if (length == 0) length = 1.0f;
  1618. ilength = 1.0f/length;
  1619. vector->x *= ilength;
  1620. vector->y *= ilength;
  1621. }
  1622. // Returns the sum of two given vectors
  1623. static inline Vector2 MathVector2Add(Vector2 v1, Vector2 v2)
  1624. {
  1625. Vector2 result = { v1.x + v2.x, v1.y + v2.y };
  1626. return result;
  1627. }
  1628. // Returns the subtract of two given vectors
  1629. static inline Vector2 MathVector2Subtract(Vector2 v1, Vector2 v2)
  1630. {
  1631. Vector2 result = { v1.x - v2.x, v1.y - v2.y };
  1632. return result;
  1633. }
  1634. // Creates a matrix 2x2 from a given radians value
  1635. static Matrix2x2 MathMatFromRadians(float radians)
  1636. {
  1637. float cos = cosf(radians);
  1638. float sin = sinf(radians);
  1639. Matrix2x2 result = { cos, -sin, sin, cos };
  1640. return result;
  1641. }
  1642. // Returns the transpose of a given matrix 2x2
  1643. static inline Matrix2x2 MathMatTranspose(Matrix2x2 matrix)
  1644. {
  1645. Matrix2x2 result = { matrix.m00, matrix.m10, matrix.m01, matrix.m11 };
  1646. return result;
  1647. }
  1648. // Multiplies a vector by a matrix 2x2
  1649. static inline Vector2 MathMatVector2Product(Matrix2x2 matrix, Vector2 vector)
  1650. {
  1651. Vector2 result = { matrix.m00*vector.x + matrix.m01*vector.y, matrix.m10*vector.x + matrix.m11*vector.y };
  1652. return result;
  1653. }
  1654. #endif // PHYSAC_IMPLEMENTATION