summaryrefslogtreecommitdiff
path: root/libs/raylib/src/physac.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/raylib/src/physac.h')
-rw-r--r--libs/raylib/src/physac.h1307
1 files changed, 616 insertions, 691 deletions
diff --git a/libs/raylib/src/physac.h b/libs/raylib/src/physac.h
index d9b534b..4b419bb 100644
--- a/libs/raylib/src/physac.h
+++ b/libs/raylib/src/physac.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* Physac v1.0 - 2D Physics library for videogames
+* Physac v1.1 - 2D Physics library for videogames
*
* DESCRIPTION:
*
@@ -20,38 +20,44 @@
* The generated implementation will stay private inside implementation file and all
* internal symbols and functions will only be visible inside that file.
*
-* #define PHYSAC_NO_THREADS
-* The generated implementation won't include pthread library and user must create a secondary thread to call PhysicsThread().
-* It is so important that the thread where PhysicsThread() is called must not have v-sync or any other CPU limitation.
+* #define PHYSAC_DEBUG
+* Show debug traces log messages about physic bodies creation/destruction, physic system errors,
+* some calculations results and NULL reference exceptions
*
-* #define PHYSAC_STANDALONE
-* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
-* internally in the library and input management and drawing functions must be provided by
-* the user (check library implementation for further details).
+* #define PHYSAC_DEFINE_VECTOR2_TYPE
+* Forces library to define struct Vector2 data type (float x; float y)
*
-* #define PHYSAC_DEBUG
-* Traces log messages when creating and destroying physics bodies and detects errors in physics
-* calculations and reference exceptions; it is useful for debug purposes
+* #define PHYSAC_AVOID_TIMMING_SYSTEM
+* Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps,
+* it allows just running UpdatePhysics() automatically on a separate thread at a desired time step.
+* In case physics steps update needs to be controlled by user with a custom timming mechanism,
+* just define this flag and the internal timming mechanism will be avoided, in that case,
+* timming libraries are neither required by the module.
*
* #define PHYSAC_MALLOC()
+* #define PHYSAC_CALLOC()
* #define PHYSAC_FREE()
* You can define your own malloc/free implementation replacing stdlib.h malloc()/free() functions.
* Otherwise it will include stdlib.h and use the C standard library malloc()/free() function.
*
+* COMPILATION:
*
-* NOTE 1: Physac requires multi-threading, when InitPhysics() a second thread is created to manage physics calculations.
-* NOTE 2: Physac requires static C library linkage to avoid dependency on MinGW DLL (-static -lpthread)
-*
-* Use the following code to compile:
-* gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static -lraylib -lpthread -lopengl32 -lgdi32 -lwinmm -std=c99
+* Use the following code to compile with GCC:
+* gcc -o $(NAME_PART).exe $(FILE_NAME) -s -static -lraylib -lopengl32 -lgdi32 -lwinmm -std=c99
*
-* VERY THANKS TO:
-* Ramon Santamaria (github: @raysan5)
+* VERSIONS HISTORY:
+* 1.1 (20-Jan-2021) @raysan5: Library general revision
+* Removed threading system (up to the user)
+* Support MSVC C++ compilation using CLITERAL()
+* Review DEBUG mechanism for TRACELOG() and all TRACELOG() messages
+* Review internal variables/functions naming for consistency
+* Allow option to avoid internal timming system, to allow app manage the steps
+* 1.0 (12-Jun-2017) First release of the library
*
*
* LICENSE: zlib/libpng
*
-* Copyright (c) 2016-2018 Victor Fisac (github: @victorfisac)
+* Copyright (c) 2016-2021 Victor Fisac (@victorfisac) and Ramon Santamaria (@raysan5)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@@ -87,6 +93,9 @@
#ifndef PHYSAC_MALLOC
#define PHYSAC_MALLOC(size) malloc(size)
#endif
+#ifndef PHYSAC_CALLOC
+ #define PHYSAC_CALLOC(size, n) calloc(size, n)
+#endif
#ifndef PHYSAC_FREE
#define PHYSAC_FREE(ptr) free(ptr)
#endif
@@ -94,42 +103,95 @@
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define PHYSAC_MAX_BODIES 64
-#define PHYSAC_MAX_MANIFOLDS 4096
-#define PHYSAC_MAX_VERTICES 24
-#define PHYSAC_CIRCLE_VERTICES 24
+#define PHYSAC_MAX_BODIES 64 // Maximum number of physic bodies supported
+#define PHYSAC_MAX_MANIFOLDS 4096 // Maximum number of physic bodies interactions (64x64)
+#define PHYSAC_MAX_VERTICES 24 // Maximum number of vertex for polygons shapes
+#define PHYSAC_DEFAULT_CIRCLE_VERTICES 24 // Default number of vertices for circle shapes
#define PHYSAC_COLLISION_ITERATIONS 100
#define PHYSAC_PENETRATION_ALLOWANCE 0.05f
#define PHYSAC_PENETRATION_CORRECTION 0.4f
-#define PHYSAC_PI 3.14159265358979323846
+#define PHYSAC_PI 3.14159265358979323846f
#define PHYSAC_DEG2RAD (PHYSAC_PI/180.0f)
//----------------------------------------------------------------------------------
-// Types and Structures Definition
-// NOTE: Below types are required for PHYSAC_STANDALONE usage
+// Data Types Structure Definition
//----------------------------------------------------------------------------------
-#if defined(PHYSAC_STANDALONE)
- // Boolean type
- #if defined(__STDC__) && __STDC_VERSION__ >= 199901L
- #include <stdbool.h>
- #elif !defined(__cplusplus) && !defined(bool)
- typedef enum { false, true } bool;
- #endif
-
- // Vector2 type
- typedef struct Vector2 {
- float x;
- float y;
- } Vector2;
+#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
+ #include <stdbool.h>
#endif
-typedef enum PhysicsShapeType { PHYSICS_CIRCLE, PHYSICS_POLYGON } PhysicsShapeType;
+typedef enum PhysicsShapeType { PHYSICS_CIRCLE = 0, PHYSICS_POLYGON } PhysicsShapeType;
// Previously defined to be used in PhysicsShape struct as circular dependencies
typedef struct PhysicsBodyData *PhysicsBody;
+#if defined(PHYSAC_DEFINE_VECTOR2_TYPE)
+// Vector2 type
+typedef struct Vector2 {
+ float x;
+ float y;
+} Vector2;
+#endif
+
+// Matrix2x2 type (used for polygon shape rotation matrix)
+typedef struct Matrix2x2 {
+ float m00;
+ float m01;
+ float m10;
+ float m11;
+} Matrix2x2;
+
+typedef struct PhysicsVertexData {
+ unsigned int vertexCount; // Vertex count (positions and normals)
+ Vector2 positions[PHYSAC_MAX_VERTICES]; // Vertex positions vectors
+ Vector2 normals[PHYSAC_MAX_VERTICES]; // Vertex normals vectors
+} PhysicsVertexData;
+
+typedef struct PhysicsShape {
+ PhysicsShapeType type; // Shape type (circle or polygon)
+ PhysicsBody body; // Shape physics body data pointer
+ PhysicsVertexData vertexData; // Shape vertices data (used for polygon shapes)
+ float radius; // Shape radius (used for circle shapes)
+ Matrix2x2 transform; // Vertices transform matrix 2x2
+} PhysicsShape;
+
+typedef struct PhysicsBodyData {
+ unsigned int id; // Unique identifier
+ bool enabled; // Enabled dynamics state (collisions are calculated anyway)
+ Vector2 position; // Physics body shape pivot
+ Vector2 velocity; // Current linear velocity applied to position
+ Vector2 force; // Current linear force (reset to 0 every step)
+ float angularVelocity; // Current angular velocity applied to orient
+ float torque; // Current angular force (reset to 0 every step)
+ float orient; // Rotation in radians
+ float inertia; // Moment of inertia
+ float inverseInertia; // Inverse value of inertia
+ float mass; // Physics body mass
+ float inverseMass; // Inverse value of mass
+ float staticFriction; // Friction when the body has not movement (0 to 1)
+ float dynamicFriction; // Friction when the body has movement (0 to 1)
+ float restitution; // Restitution coefficient of the body (0 to 1)
+ bool useGravity; // Apply gravity force to dynamics
+ bool isGrounded; // Physics grounded on other body state
+ bool freezeOrient; // Physics rotation constraint
+ PhysicsShape shape; // Physics body shape information (type, radius, vertices, transform)
+} PhysicsBodyData;
+
+typedef struct PhysicsManifoldData {
+ unsigned int id; // Unique identifier
+ PhysicsBody bodyA; // Manifold first physics body reference
+ PhysicsBody bodyB; // Manifold second physics body reference
+ float penetration; // Depth of penetration from collision
+ Vector2 normal; // Normal direction vector from 'a' to 'b'
+ Vector2 contacts[2]; // Points of contact during collision
+ unsigned int contactsCount; // Current collision number of contacts
+ float restitution; // Mixed restitution during collision
+ float dynamicFriction; // Mixed dynamic friction during collision
+ float staticFriction; // Mixed static friction during collision
+} PhysicsManifoldData, *PhysicsManifold;
+
#if defined(__cplusplus)
extern "C" { // Prevents name mangling of functions
#endif
@@ -137,26 +199,32 @@ extern "C" { // Prevents name mangling of fun
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
-PHYSACDEF void InitPhysics(void); // Initializes physics values, pointers and creates physics loop thread
-PHYSACDEF void RunPhysicsStep(void); // Run physics step, to be used if PHYSICS_NO_THREADS is set in your main loop
+// Physics system management
+PHYSACDEF void InitPhysics(void); // Initializes physics system
+PHYSACDEF void UpdatePhysics(void); // Update physics system
+PHYSACDEF void ResetPhysics(void); // Reset physics system (global variables)
+PHYSACDEF void ClosePhysics(void); // Close physics system and unload used memory
PHYSACDEF void SetPhysicsTimeStep(double delta); // Sets physics fixed time step in milliseconds. 1.666666 by default
-PHYSACDEF bool IsPhysicsEnabled(void); // Returns true if physics thread is currently enabled
PHYSACDEF void SetPhysicsGravity(float x, float y); // Sets physics global gravity force
+
+// Physic body creation/destroy
PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density); // Creates a new circle physics body with generic parameters
PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density); // Creates a new rectangle physics body with generic parameters
PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density); // Creates a new polygon physics body with generic parameters
+PHYSACDEF void DestroyPhysicsBody(PhysicsBody body); // Destroy a physics body
+
+// Physic body forces
PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force); // Adds a force to a physics body
PHYSACDEF void PhysicsAddTorque(PhysicsBody body, float amount); // Adds an angular force to a physics body
PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force); // Shatters a polygon shape physics body to little physics bodies with explosion force
-PHYSACDEF int GetPhysicsBodiesCount(void); // Returns the current amount of created physics bodies
+PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians); // Sets physics body shape transform based on radians parameter
+
+// Query physics info
PHYSACDEF PhysicsBody GetPhysicsBody(int index); // Returns a physics body of the bodies pool at a specific index
+PHYSACDEF int GetPhysicsBodiesCount(void); // Returns the current amount of created physics bodies
PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position)
-PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians); // Sets physics body shape transform based on radians parameter
-PHYSACDEF void DestroyPhysicsBody(PhysicsBody body); // Unitializes and destroy a physics body
-PHYSACDEF void ResetPhysics(void); // Destroys created physics bodies and manifolds and resets global values
-PHYSACDEF void ClosePhysics(void); // Unitializes physics pointers and closes physics loop thread
#if defined(__cplusplus)
}
@@ -172,212 +240,140 @@ PHYSACDEF void ClosePhysics(void);
#if defined(PHYSAC_IMPLEMENTATION)
-#if !defined(PHYSAC_NO_THREADS)
- #include <pthread.h> // Required for: pthread_t, pthread_create()
-#endif
-
-#if defined(PHYSAC_DEBUG)
-
-#endif
-
// Support TRACELOG macros
#if defined(PHYSAC_DEBUG)
#include <stdio.h> // Required for: printf()
#define TRACELOG(...) printf(__VA_ARGS__)
#else
- #define TRACELOG(...) (void)0
+ #define TRACELOG(...) (void)0;
#endif
-#include <stdlib.h> // Required for: malloc(), free(), srand(), rand()
+#include <stdlib.h> // Required for: malloc(), calloc(), free()
#include <math.h> // Required for: cosf(), sinf(), fabs(), sqrtf()
-#if !defined(PHYSAC_STANDALONE)
- #include "raymath.h" // Required for: Vector2Add(), Vector2Subtract()
+#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
+ // Time management functionality
+ #include <time.h> // Required for: time(), clock_gettime()
+ #if defined(_WIN32)
+ // Functions required to query time on Windows
+ int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
+ int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
+ #endif
+ #if defined(__linux__) || defined(__FreeBSD__)
+ #if _POSIX_C_SOURCE < 199309L
+ #undef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
+ #endif
+ #include <sys/time.h> // Required for: timespec
+ #endif
+ #if defined(__APPLE__) // macOS also defines __MACH__
+ #include <mach/mach_time.h> // Required for: mach_absolute_time()
+ #endif
#endif
-// Time management functionality
-#include <time.h> // Required for: time(), clock_gettime()
-#if defined(_WIN32)
- // Functions required to query time on Windows
- int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
- int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
-#elif defined(__linux__)
- #if _POSIX_C_SOURCE < 199309L
- #undef _POSIX_C_SOURCE
- #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
- #endif
- #include <sys/time.h> // Required for: timespec
-#elif defined(__APPLE__) // macOS also defines __MACH__
- #include <mach/mach_time.h> // Required for: mach_absolute_time()
+// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
+// Plain structures in C++ (without constructors) can be initialized from { } initializers.
+#if defined(__cplusplus)
+ #define CLITERAL(type) type
+#else
+ #define CLITERAL(type) (type)
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define min(a,b) (((a)<(b))?(a):(b))
-#define max(a,b) (((a)>(b))?(a):(b))
-#define PHYSAC_FLT_MAX 3.402823466e+38f
-#define PHYSAC_EPSILON 0.000001f
-#define PHYSAC_K 1.0f/3.0f
-#define PHYSAC_VECTOR_ZERO (Vector2){ 0.0f, 0.0f }
-
-//----------------------------------------------------------------------------------
-// Data Types Structure Definition
-//----------------------------------------------------------------------------------
-
-// Matrix2x2 type (used for polygon shape rotation matrix)
-typedef struct Matrix2x2 {
- float m00;
- float m01;
- float m10;
- float m11;
-} Matrix2x2;
-
-typedef struct PolygonData {
- unsigned int vertexCount; // Current used vertex and normals count
- Vector2 positions[PHYSAC_MAX_VERTICES]; // Polygon vertex positions vectors
- Vector2 normals[PHYSAC_MAX_VERTICES]; // Polygon vertex normals vectors
-} PolygonData;
-
-typedef struct PhysicsShape {
- PhysicsShapeType type; // Physics shape type (circle or polygon)
- PhysicsBody body; // Shape physics body reference
- float radius; // Circle shape radius (used for circle shapes)
- Matrix2x2 transform; // Vertices transform matrix 2x2
- PolygonData vertexData; // Polygon shape vertices position and normals data (just used for polygon shapes)
-} PhysicsShape;
-
-typedef struct PhysicsBodyData {
- unsigned int id; // Reference unique identifier
- bool enabled; // Enabled dynamics state (collisions are calculated anyway)
- Vector2 position; // Physics body shape pivot
- Vector2 velocity; // Current linear velocity applied to position
- Vector2 force; // Current linear force (reset to 0 every step)
- float angularVelocity; // Current angular velocity applied to orient
- float torque; // Current angular force (reset to 0 every step)
- float orient; // Rotation in radians
- float inertia; // Moment of inertia
- float inverseInertia; // Inverse value of inertia
- float mass; // Physics body mass
- float inverseMass; // Inverse value of mass
- float staticFriction; // Friction when the body has not movement (0 to 1)
- float dynamicFriction; // Friction when the body has movement (0 to 1)
- float restitution; // Restitution coefficient of the body (0 to 1)
- bool useGravity; // Apply gravity force to dynamics
- bool isGrounded; // Physics grounded on other body state
- bool freezeOrient; // Physics rotation constraint
- PhysicsShape shape; // Physics body shape information (type, radius, vertices, normals)
-} PhysicsBodyData;
-
-typedef struct PhysicsManifoldData {
- unsigned int id; // Reference unique identifier
- PhysicsBody bodyA; // Manifold first physics body reference
- PhysicsBody bodyB; // Manifold second physics body reference
- float penetration; // Depth of penetration from collision
- Vector2 normal; // Normal direction vector from 'a' to 'b'
- Vector2 contacts[2]; // Points of contact during collision
- unsigned int contactsCount; // Current collision number of contacts
- float restitution; // Mixed restitution during collision
- float dynamicFriction; // Mixed dynamic friction during collision
- float staticFriction; // Mixed static friction during collision
-} PhysicsManifoldData, *PhysicsManifold;
+#define PHYSAC_MIN(a,b) (((a)<(b))?(a):(b))
+#define PHYSAC_MAX(a,b) (((a)>(b))?(a):(b))
+#define PHYSAC_FLT_MAX 3.402823466e+38f
+#define PHYSAC_EPSILON 0.000001f
+#define PHYSAC_K 1.0f/3.0f
+#define PHYSAC_VECTOR_ZERO CLITERAL(Vector2){ 0.0f, 0.0f }
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-#if !defined(PHYSAC_NO_THREADS)
-static pthread_t physicsThreadId; // Physics thread id
-#endif
-static unsigned int usedMemory = 0; // Total allocated dynamic memory
-static bool physicsThreadEnabled = false; // Physics thread enabled state
-static double baseTime = 0.0; // Offset time for MONOTONIC clock
+static double deltaTime = 1.0/60.0/10.0 * 1000; // Delta time in milliseconds used for physics steps
+
+#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
+// Time measure variables
+static double baseClockTicks = 0.0; // Offset clock ticks for MONOTONIC clock
+static unsigned long long int frequency = 0; // Hi-res clock frequency
static double startTime = 0.0; // Start time in milliseconds
-static double deltaTime = 1.0/60.0/10.0 * 1000; // Delta time used for physics steps, in milliseconds
static double currentTime = 0.0; // Current time in milliseconds
-static unsigned long long int frequency = 0; // Hi-res clock frequency
+#endif
-static double accumulator = 0.0; // Physics time step delta time accumulator
-static unsigned int stepsCount = 0; // Total physics steps processed
-static Vector2 gravityForce = { 0.0f, 9.81f }; // Physics world gravity force
+// Physics system configuration
static PhysicsBody bodies[PHYSAC_MAX_BODIES]; // Physics bodies pointers array
static unsigned int physicsBodiesCount = 0; // Physics world current bodies counter
static PhysicsManifold contacts[PHYSAC_MAX_MANIFOLDS]; // Physics bodies pointers array
static unsigned int physicsManifoldsCount = 0; // Physics world current manifolds counter
+static Vector2 gravityForce = { 0.0f, 9.81f }; // Physics world gravity force
+
+// Utilities variables
+static unsigned int usedMemory = 0; // Total allocated dynamic memory
+
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
+#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
+// Timming measure functions
+static void InitTimer(void); // Initializes hi-resolution MONOTONIC timer
+static unsigned long long int GetClockTicks(void); // Get hi-res MONOTONIC time measure in mseconds
+static double GetCurrentTime(void); // Get current time measure in milliseconds
+#endif
+
+static void UpdatePhysicsStep(void); // Update physics step (dynamics, collisions and position corrections)
+
static int FindAvailableBodyIndex(); // Finds a valid index for a new physics body initialization
-static PolygonData CreateRandomPolygon(float radius, int sides); // Creates a random polygon shape with max vertex distance from polygon pivot
-static PolygonData CreateRectanglePolygon(Vector2 pos, Vector2 size); // Creates a rectangle polygon shape based on a min and max positions
-static void *PhysicsLoop(void *arg); // Physics loop thread function
-static void PhysicsStep(void); // Physics steps calculations (dynamics, collisions and position corrections)
static int FindAvailableManifoldIndex(); // Finds a valid index for a new manifold initialization
+static PhysicsVertexData CreateDefaultPolygon(float radius, int sides); // Creates a random polygon shape with max vertex distance from polygon pivot
+static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size); // Creates a rectangle polygon shape based on a min and max positions
+
+static void InitializePhysicsManifolds(PhysicsManifold manifold); // Initializes physics manifolds to solve collisions
static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b); // Creates a new physics manifold to solve collision
static void DestroyPhysicsManifold(PhysicsManifold manifold); // Unitializes and destroys a physics manifold
+
static void SolvePhysicsManifold(PhysicsManifold manifold); // Solves a created physics manifold between two physics bodies
static void SolveCircleToCircle(PhysicsManifold manifold); // Solves collision between two circle shape physics bodies
static void SolveCircleToPolygon(PhysicsManifold manifold); // Solves collision between a circle to a polygon shape physics bodies
static void SolvePolygonToCircle(PhysicsManifold manifold); // Solves collision between a polygon to a circle shape physics bodies
static void SolvePolygonToPolygon(PhysicsManifold manifold); // Solves collision between two polygons shape physics bodies
static void IntegratePhysicsForces(PhysicsBody body); // Integrates physics forces into velocity
-static void InitializePhysicsManifolds(PhysicsManifold manifold); // Initializes physics manifolds to solve collisions
-static void IntegratePhysicsImpulses(PhysicsManifold manifold); // Integrates physics collisions impulses to solve collisions
static void IntegratePhysicsVelocity(PhysicsBody body); // Integrates physics velocity into position and forces
+static void IntegratePhysicsImpulses(PhysicsManifold manifold); // Integrates physics collisions impulses to solve collisions
static void CorrectPhysicsPositions(PhysicsManifold manifold); // Corrects physics bodies positions based on manifolds collision information
-static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, PhysicsShape shapeB); // Finds polygon shapes axis least penetration
static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, PhysicsShape inc, int index); // Finds two polygon shapes incident face
-static int Clip(Vector2 normal, float clip, Vector2 *faceA, Vector2 *faceB); // Calculates clipping based on a normal and two faces
-static bool BiasGreaterThan(float valueA, float valueB); // Check if values are between bias range
-static Vector2 TriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3); // Returns the barycenter of a triangle given by 3 points
-
-static void InitTimer(void); // Initializes hi-resolution MONOTONIC timer
-static unsigned long long int GetTimeCount(void); // Get hi-res MONOTONIC time measure in mseconds
-static double GetCurrentTime(void); // Get current time measure in milliseconds
-
-// Math functions
-static Vector2 MathCross(float value, Vector2 vector); // Returns the cross product of a vector and a value
-static float MathCrossVector2(Vector2 v1, Vector2 v2); // Returns the cross product of two vectors
-static float MathLenSqr(Vector2 vector); // Returns the len square root of a vector
-static float MathDot(Vector2 v1, Vector2 v2); // Returns the dot product of two vectors
-static inline float DistSqr(Vector2 v1, Vector2 v2); // Returns the square root of distance between two vectors
-static void MathNormalize(Vector2 *vector); // Returns the normalized values of a vector
-#if defined(PHYSAC_STANDALONE)
-static Vector2 Vector2Add(Vector2 v1, Vector2 v2); // Returns the sum of two given vectors
-static Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Returns the subtract of two given vectors
-#endif
+static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, PhysicsShape shapeB); // Finds polygon shapes axis least penetration
-static Matrix2x2 Mat2Radians(float radians); // Creates a matrix 2x2 from a given radians value
-static void Mat2Set(Matrix2x2 *matrix, float radians); // Set values from radians to a created matrix 2x2
-static inline Matrix2x2 Mat2Transpose(Matrix2x2 matrix); // Returns the transpose of a given matrix 2x2
-static inline Vector2 Mat2MultiplyVector2(Matrix2x2 matrix, Vector2 vector); // Multiplies a vector by a matrix 2x2
+// Math required functions
+static Vector2 MathVector2Product(Vector2 vector, float value); // Returns the product of a vector and a value
+static float MathVector2CrossProduct(Vector2 v1, Vector2 v2); // Returns the cross product of two vectors
+static float MathVector2SqrLen(Vector2 vector); // Returns the len square root of a vector
+static float MathVector2DotProduct(Vector2 v1, Vector2 v2); // Returns the dot product of two vectors
+static inline float MathVector2SqrDistance(Vector2 v1, Vector2 v2); // Returns the square root of distance between two vectors
+static void MathVector2Normalize(Vector2 *vector); // Returns the normalized values of a vector
+static Vector2 MathVector2Add(Vector2 v1, Vector2 v2); // Returns the sum of two given vectors
+static Vector2 MathVector2Subtract(Vector2 v1, Vector2 v2); // Returns the subtract of two given vectors
+static Matrix2x2 MathMatFromRadians(float radians); // Returns a matrix 2x2 from a given radians value
+static inline Matrix2x2 MathMatTranspose(Matrix2x2 matrix); // Returns the transpose of a given matrix 2x2
+static inline Vector2 MathMatVector2Product(Matrix2x2 matrix, Vector2 vector); // Returns product between matrix 2x2 and vector
+static int MathVector2Clip(Vector2 normal, Vector2 *faceA, Vector2 *faceB, float clip); // Returns clipping value based on a normal and two faces
+static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3); // Returns the barycenter of a triangle given by 3 points
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
+
// Initializes physics values, pointers and creates physics loop thread
PHYSACDEF void InitPhysics(void)
{
- #if !defined(PHYSAC_NO_THREADS)
- // NOTE: if defined, user will need to create a thread for PhysicsThread function manually
- // Create physics thread using POSIXS thread libraries
- pthread_create(&physicsThreadId, NULL, &PhysicsLoop, NULL);
- #endif
-
+#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
// Initialize high resolution timer
InitTimer();
+#endif
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] physics module initialized successfully\n");
- #endif
-
- accumulator = 0.0;
-}
-
-// Returns true if physics thread is currently enabled
-PHYSACDEF bool IsPhysicsEnabled(void)
-{
- return physicsThreadEnabled;
+ TRACELOG("[PHYSAC] Physics module initialized successfully\n");
}
// Sets physics global gravity force
@@ -390,47 +386,42 @@ PHYSACDEF void SetPhysicsGravity(float x, float y)
// Creates a new circle physics body with generic parameters
PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density)
{
- PhysicsBody newBody = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_CIRCLE_VERTICES, density);
- return newBody;
+ PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density);
+ return body;
}
// Creates a new rectangle physics body with generic parameters
PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density)
{
- PhysicsBody newBody = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
+ // NOTE: Make sure body data is initialized to 0
+ PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1);
usedMemory += sizeof(PhysicsBodyData);
- int newId = FindAvailableBodyIndex();
- if (newId != -1)
+ int id = FindAvailableBodyIndex();
+ if (id != -1)
{
// Initialize new body with generic values
- newBody->id = newId;
- newBody->enabled = true;
- newBody->position = pos;
- newBody->velocity = (Vector2){ 0.0f };
- newBody->force = (Vector2){ 0.0f };
- newBody->angularVelocity = 0.0f;
- newBody->torque = 0.0f;
- newBody->orient = 0.0f;
- newBody->shape.type = PHYSICS_POLYGON;
- newBody->shape.body = newBody;
- newBody->shape.radius = 0.0f;
- newBody->shape.transform = Mat2Radians(0.0f);
- newBody->shape.vertexData = CreateRectanglePolygon(pos, (Vector2){ width, height });
+ body->id = id;
+ body->enabled = true;
+ body->position = pos;
+ body->shape.type = PHYSICS_POLYGON;
+ body->shape.body = body;
+ body->shape.transform = MathMatFromRadians(0.0f);
+ body->shape.vertexData = CreateRectanglePolygon(pos, CLITERAL(Vector2){ width, height });
// Calculate centroid and moment of inertia
Vector2 center = { 0.0f, 0.0f };
float area = 0.0f;
float inertia = 0.0f;
- for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++)
+ for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
{
// Triangle vertices, third vertex implied as (0, 0)
- Vector2 p1 = newBody->shape.vertexData.positions[i];
- int nextIndex = (((i + 1) < newBody->shape.vertexData.vertexCount) ? (i + 1) : 0);
- Vector2 p2 = newBody->shape.vertexData.positions[nextIndex];
+ Vector2 p1 = body->shape.vertexData.positions[i];
+ unsigned int nextIndex = (((i + 1) < body->shape.vertexData.vertexCount) ? (i + 1) : 0);
+ Vector2 p2 = body->shape.vertexData.positions[nextIndex];
- float D = MathCrossVector2(p1, p2);
+ float D = MathVector2CrossProduct(p1, p2);
float triangleArea = D/2;
area += triangleArea;
@@ -449,74 +440,70 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float
// Translate vertices to centroid (make the centroid (0, 0) for the polygon in model space)
// Note: this is not really necessary
- for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++)
+ for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
{
- newBody->shape.vertexData.positions[i].x -= center.x;
- newBody->shape.vertexData.positions[i].y -= center.y;
+ body->shape.vertexData.positions[i].x -= center.x;
+ body->shape.vertexData.positions[i].y -= center.y;
}
- newBody->mass = density*area;
- newBody->inverseMass = ((newBody->mass != 0.0f) ? 1.0f/newBody->mass : 0.0f);
- newBody->inertia = density*inertia;
- newBody->inverseInertia = ((newBody->inertia != 0.0f) ? 1.0f/newBody->inertia : 0.0f);
- newBody->staticFriction = 0.4f;
- newBody->dynamicFriction = 0.2f;
- newBody->restitution = 0.0f;
- newBody->useGravity = true;
- newBody->isGrounded = false;
- newBody->freezeOrient = false;
+ body->mass = density*area;
+ body->inverseMass = ((body->mass != 0.0f) ? 1.0f/body->mass : 0.0f);
+ body->inertia = density*inertia;
+ body->inverseInertia = ((body->inertia != 0.0f) ? 1.0f/body->inertia : 0.0f);
+ body->staticFriction = 0.4f;
+ body->dynamicFriction = 0.2f;
+ body->restitution = 0.0f;
+ body->useGravity = true;
+ body->isGrounded = false;
+ body->freezeOrient = false;
// Add new body to bodies pointers array and update bodies count
- bodies[physicsBodiesCount] = newBody;
+ bodies[physicsBodiesCount] = body;
physicsBodiesCount++;
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] created polygon physics body id %i\n", newBody->id);
- #endif
+ TRACELOG("[PHYSAC] Physic body created successfully (id: %i)\n", body->id);
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] new physics body creation failed because there is any available id to use\n");
- #endif
+ else TRACELOG("[PHYSAC] Physic body could not be created, PHYSAC_MAX_BODIES reached\n");
- return newBody;
+ return body;
}
// Creates a new polygon physics body with generic parameters
PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density)
{
- PhysicsBody newBody = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
+ PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
usedMemory += sizeof(PhysicsBodyData);
- int newId = FindAvailableBodyIndex();
- if (newId != -1)
+ int id = FindAvailableBodyIndex();
+ if (id != -1)
{
// Initialize new body with generic values
- newBody->id = newId;
- newBody->enabled = true;
- newBody->position = pos;
- newBody->velocity = PHYSAC_VECTOR_ZERO;
- newBody->force = PHYSAC_VECTOR_ZERO;
- newBody->angularVelocity = 0.0f;
- newBody->torque = 0.0f;
- newBody->orient = 0.0f;
- newBody->shape.type = PHYSICS_POLYGON;
- newBody->shape.body = newBody;
- newBody->shape.transform = Mat2Radians(0.0f);
- newBody->shape.vertexData = CreateRandomPolygon(radius, sides);
+ body->id = id;
+ body->enabled = true;
+ body->position = pos;
+ body->velocity = PHYSAC_VECTOR_ZERO;
+ body->force = PHYSAC_VECTOR_ZERO;
+ body->angularVelocity = 0.0f;
+ body->torque = 0.0f;
+ body->orient = 0.0f;
+ body->shape.type = PHYSICS_POLYGON;
+ body->shape.body = body;
+ body->shape.transform = MathMatFromRadians(0.0f);
+ body->shape.vertexData = CreateDefaultPolygon(radius, sides);
// Calculate centroid and moment of inertia
Vector2 center = { 0.0f, 0.0f };
float area = 0.0f;
float inertia = 0.0f;
- for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++)
+ for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
{
// Triangle vertices, third vertex implied as (0, 0)
- Vector2 position1 = newBody->shape.vertexData.positions[i];
- int nextIndex = (((i + 1) < newBody->shape.vertexData.vertexCount) ? (i + 1) : 0);
- Vector2 position2 = newBody->shape.vertexData.positions[nextIndex];
+ Vector2 position1 = body->shape.vertexData.positions[i];
+ unsigned int nextIndex = (((i + 1) < body->shape.vertexData.vertexCount) ? (i + 1) : 0);
+ Vector2 position2 = body->shape.vertexData.positions[nextIndex];
- float cross = MathCrossVector2(position1, position2);
+ float cross = MathVector2CrossProduct(position1, position2);
float triangleArea = cross/2;
area += triangleArea;
@@ -535,42 +522,38 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si
// Translate vertices to centroid (make the centroid (0, 0) for the polygon in model space)
// Note: this is not really necessary
- for (int i = 0; i < newBody->shape.vertexData.vertexCount; i++)
+ for (unsigned int i = 0; i < body->shape.vertexData.vertexCount; i++)
{
- newBody->shape.vertexData.positions[i].x -= center.x;
- newBody->shape.vertexData.positions[i].y -= center.y;
+ body->shape.vertexData.positions[i].x -= center.x;
+ body->shape.vertexData.positions[i].y -= center.y;
}
- newBody->mass = density*area;
- newBody->inverseMass = ((newBody->mass != 0.0f) ? 1.0f/newBody->mass : 0.0f);
- newBody->inertia = density*inertia;
- newBody->inverseInertia = ((newBody->inertia != 0.0f) ? 1.0f/newBody->inertia : 0.0f);
- newBody->staticFriction = 0.4f;
- newBody->dynamicFriction = 0.2f;
- newBody->restitution = 0.0f;
- newBody->useGravity = true;
- newBody->isGrounded = false;
- newBody->freezeOrient = false;
+ body->mass = density*area;
+ body->inverseMass = ((body->mass != 0.0f) ? 1.0f/body->mass : 0.0f);
+ body->inertia = density*inertia;
+ body->inverseInertia = ((body->inertia != 0.0f) ? 1.0f/body->inertia : 0.0f);
+ body->staticFriction = 0.4f;
+ body->dynamicFriction = 0.2f;
+ body->restitution = 0.0f;
+ body->useGravity = true;
+ body->isGrounded = false;
+ body->freezeOrient = false;
// Add new body to bodies pointers array and update bodies count
- bodies[physicsBodiesCount] = newBody;
+ bodies[physicsBodiesCount] = body;
physicsBodiesCount++;
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] created polygon physics body id %i\n", newBody->id);
- #endif
+ TRACELOG("[PHYSAC] Physic body created successfully (id: %i)\n", body->id);
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] new physics body creation failed because there is any available id to use\n");
- #endif
+ else TRACELOG("[PHYSAC] Physics body could not be created, PHYSAC_MAX_BODIES reached\n");
- return newBody;
+ return body;
}
// Adds a force to a physics body
PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force)
{
- if (body != NULL) body->force = Vector2Add(body->force, force);
+ if (body != NULL) body->force = MathVector2Add(body->force, force);
}
// Adds an angular force to a physics body
@@ -586,15 +569,15 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
{
if (body->shape.type == PHYSICS_POLYGON)
{
- PolygonData vertexData = body->shape.vertexData;
+ PhysicsVertexData vertexData = body->shape.vertexData;
bool collision = false;
- for (int i = 0; i < vertexData.vertexCount; i++)
+ for (unsigned int i = 0; i < vertexData.vertexCount; i++)
{
Vector2 positionA = body->position;
- Vector2 positionB = Mat2MultiplyVector2(body->shape.transform, Vector2Add(body->position, vertexData.positions[i]));
- int nextIndex = (((i + 1) < vertexData.vertexCount) ? (i + 1) : 0);
- Vector2 positionC = Mat2MultiplyVector2(body->shape.transform, Vector2Add(body->position, vertexData.positions[nextIndex]));
+ Vector2 positionB = MathMatVector2Product(body->shape.transform, MathVector2Add(body->position, vertexData.positions[i]));
+ unsigned int nextIndex = (((i + 1) < vertexData.vertexCount) ? (i + 1) : 0);
+ Vector2 positionC = MathMatVector2Product(body->shape.transform, MathVector2Add(body->position, vertexData.positions[nextIndex]));
// Check collision between each triangle
float alpha = ((positionB.y - positionC.y)*(position.x - positionC.x) + (positionC.x - positionB.x)*(position.y - positionC.y))/
@@ -626,54 +609,54 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
for (int i = 0; i < count; i++)
{
int nextIndex = (((i + 1) < count) ? (i + 1) : 0);
- Vector2 center = TriangleBarycenter(vertices[i], vertices[nextIndex], PHYSAC_VECTOR_ZERO);
- center = Vector2Add(bodyPos, center);
- Vector2 offset = Vector2Subtract(center, bodyPos);
+ Vector2 center = MathTriangleBarycenter(vertices[i], vertices[nextIndex], PHYSAC_VECTOR_ZERO);
+ center = MathVector2Add(bodyPos, center);
+ Vector2 offset = MathVector2Subtract(center, bodyPos);
- PhysicsBody newBody = CreatePhysicsBodyPolygon(center, 10, 3, 10); // Create polygon physics body with relevant values
+ PhysicsBody body = CreatePhysicsBodyPolygon(center, 10, 3, 10); // Create polygon physics body with relevant values
- PolygonData newData = { 0 };
- newData.vertexCount = 3;
+ PhysicsVertexData vertexData = { 0 };
+ vertexData.vertexCount = 3;
- newData.positions[0] = Vector2Subtract(vertices[i], offset);
- newData.positions[1] = Vector2Subtract(vertices[nextIndex], offset);
- newData.positions[2] = Vector2Subtract(position, center);
+ vertexData.positions[0] = MathVector2Subtract(vertices[i], offset);
+ vertexData.positions[1] = MathVector2Subtract(vertices[nextIndex], offset);
+ vertexData.positions[2] = MathVector2Subtract(position, center);
// Separate vertices to avoid unnecessary physics collisions
- newData.positions[0].x *= 0.95f;
- newData.positions[0].y *= 0.95f;
- newData.positions[1].x *= 0.95f;
- newData.positions[1].y *= 0.95f;
- newData.positions[2].x *= 0.95f;
- newData.positions[2].y *= 0.95f;
+ vertexData.positions[0].x *= 0.95f;
+ vertexData.positions[0].y *= 0.95f;
+ vertexData.positions[1].x *= 0.95f;
+ vertexData.positions[1].y *= 0.95f;
+ vertexData.positions[2].x *= 0.95f;
+ vertexData.positions[2].y *= 0.95f;
// Calculate polygon faces normals
- for (int j = 0; j < newData.vertexCount; j++)
+ for (unsigned int j = 0; j < vertexData.vertexCount; j++)
{
- int nextVertex = (((j + 1) < newData.vertexCount) ? (j + 1) : 0);
- Vector2 face = Vector2Subtract(newData.positions[nextVertex], newData.positions[j]);
+ unsigned int nextVertex = (((j + 1) < vertexData.vertexCount) ? (j + 1) : 0);
+ Vector2 face = MathVector2Subtract(vertexData.positions[nextVertex], vertexData.positions[j]);
- newData.normals[j] = (Vector2){ face.y, -face.x };
- MathNormalize(&newData.normals[j]);
+ vertexData.normals[j] = CLITERAL(Vector2){ face.y, -face.x };
+ MathVector2Normalize(&vertexData.normals[j]);
}
// Apply computed vertex data to new physics body shape
- newBody->shape.vertexData = newData;
- newBody->shape.transform = trans;
+ body->shape.vertexData = vertexData;
+ body->shape.transform = trans;
// Calculate centroid and moment of inertia
center = PHYSAC_VECTOR_ZERO;
float area = 0.0f;
float inertia = 0.0f;
- for (int j = 0; j < newBody->shape.vertexData.vertexCount; j++)
+ for (unsigned int j = 0; j < body->shape.vertexData.vertexCount; j++)
{
// Triangle vertices, third vertex implied as (0, 0)
- Vector2 p1 = newBody->shape.vertexData.positions[j];
- int nextVertex = (((j + 1) < newBody->shape.vertexData.vertexCount) ? (j + 1) : 0);
- Vector2 p2 = newBody->shape.vertexData.positions[nextVertex];
+ Vector2 p1 = body->shape.vertexData.positions[j];
+ unsigned int nextVertex = (((j + 1) < body->shape.vertexData.vertexCount) ? (j + 1) : 0);
+ Vector2 p2 = body->shape.vertexData.positions[nextVertex];
- float D = MathCrossVector2(p1, p2);
+ float D = MathVector2CrossProduct(p1, p2);
float triangleArea = D/2;
area += triangleArea;
@@ -690,32 +673,30 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
center.x *= 1.0f/area;
center.y *= 1.0f/area;
- newBody->mass = area;
- newBody->inverseMass = ((newBody->mass != 0.0f) ? 1.0f/newBody->mass : 0.0f);
- newBody->inertia = inertia;
- newBody->inverseInertia = ((newBody->inertia != 0.0f) ? 1.0f/newBody->inertia : 0.0f);
+ body->mass = area;
+ body->inverseMass = ((body->mass != 0.0f) ? 1.0f/body->mass : 0.0f);
+ body->inertia = inertia;
+ body->inverseInertia = ((body->inertia != 0.0f) ? 1.0f/body->inertia : 0.0f);
// Calculate explosion force direction
- Vector2 pointA = newBody->position;
- Vector2 pointB = Vector2Subtract(newData.positions[1], newData.positions[0]);
+ Vector2 pointA = body->position;
+ Vector2 pointB = MathVector2Subtract(vertexData.positions[1], vertexData.positions[0]);
pointB.x /= 2.0f;
pointB.y /= 2.0f;
- Vector2 forceDirection = Vector2Subtract(Vector2Add(pointA, Vector2Add(newData.positions[0], pointB)), newBody->position);
- MathNormalize(&forceDirection);
+ Vector2 forceDirection = MathVector2Subtract(MathVector2Add(pointA, MathVector2Add(vertexData.positions[0], pointB)), body->position);
+ MathVector2Normalize(&forceDirection);
forceDirection.x *= force;
forceDirection.y *= force;
// Apply force to new physics body
- PhysicsAddForce(newBody, forceDirection);
+ PhysicsAddForce(body, forceDirection);
}
PHYSAC_FREE(vertices);
}
}
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] error when trying to shatter a null reference physics body");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: PhysicsShatter: NULL physic body\n");
}
// Returns the current amount of created physics bodies
@@ -729,20 +710,13 @@ PHYSACDEF PhysicsBody GetPhysicsBody(int index)
{
PhysicsBody body = NULL;
- if (index < physicsBodiesCount)
+ if (index < (int)physicsBodiesCount)
{
body = bodies[index];
- if (body == NULL)
- {
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] error when trying to get a null reference physics body");
- #endif
- }
+ if (body == NULL) TRACELOG("[PHYSAC] WARNING: GetPhysicsBody: NULL physic body\n");
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] physics body index is out of bounds");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: Physic body index is out of bounds\n");
return body;
}
@@ -752,18 +726,14 @@ PHYSACDEF int GetPhysicsShapeType(int index)
{
int result = -1;
- if (index < physicsBodiesCount)
+ if (index < (int)physicsBodiesCount)
{
PhysicsBody body = bodies[index];
if (body != NULL) result = body->shape.type;
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] error when trying to get a null reference physics body");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: GetPhysicsShapeType: NULL physic body\n");
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] physics body index is out of bounds");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: Physic body index is out of bounds\n");
return result;
}
@@ -773,7 +743,7 @@ PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
{
int result = 0;
- if (index < physicsBodiesCount)
+ if (index < (int)physicsBodiesCount)
{
PhysicsBody body = bodies[index];
@@ -781,18 +751,14 @@ PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
{
switch (body->shape.type)
{
- case PHYSICS_CIRCLE: result = PHYSAC_CIRCLE_VERTICES; break;
+ case PHYSICS_CIRCLE: result = PHYSAC_DEFAULT_CIRCLE_VERTICES; break;
case PHYSICS_POLYGON: result = body->shape.vertexData.vertexCount; break;
default: break;
}
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] error when trying to get a null reference physics body");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: GetPhysicsShapeVerticesCount: NULL physic body\n");
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] physics body index is out of bounds");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: Physic body index is out of bounds\n");
return result;
}
@@ -808,20 +774,18 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
{
case PHYSICS_CIRCLE:
{
- position.x = body->position.x + cosf(360.0f/PHYSAC_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius;
- position.y = body->position.y + sinf(360.0f/PHYSAC_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius;
+ position.x = body->position.x + cosf(360.0f/PHYSAC_DEFAULT_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius;
+ position.y = body->position.y + sinf(360.0f/PHYSAC_DEFAULT_CIRCLE_VERTICES*vertex*PHYSAC_DEG2RAD)*body->shape.radius;
} break;
case PHYSICS_POLYGON:
{
- PolygonData vertexData = body->shape.vertexData;
- position = Vector2Add(body->position, Mat2MultiplyVector2(body->shape.transform, vertexData.positions[vertex]));
+ PhysicsVertexData vertexData = body->shape.vertexData;
+ position = MathVector2Add(body->position, MathMatVector2Product(body->shape.transform, vertexData.positions[vertex]));
} break;
default: break;
}
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] error when trying to get a null reference physics body");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: GetPhysicsShapeVertex: NULL physic body\n");
return position;
}
@@ -833,7 +797,7 @@ PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians)
{
body->orient = radians;
- if (body->shape.type == PHYSICS_POLYGON) body->shape.transform = Mat2Radians(radians);
+ if (body->shape.type == PHYSICS_POLYGON) body->shape.transform = MathMatFromRadians(radians);
}
}
@@ -845,7 +809,7 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
int id = body->id;
int index = -1;
- for (int i = 0; i < physicsBodiesCount; i++)
+ for (unsigned int i = 0; i < physicsBodiesCount; i++)
{
if (bodies[i]->id == id)
{
@@ -856,9 +820,7 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
if (index == -1)
{
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] Not possible to find body id %i in pointers array\n", id);
- #endif
+ TRACELOG("[PHYSAC] WARNING: Requested body (id: %i) can not be found\n", id);
return; // Prevent access to index -1
}
@@ -868,7 +830,7 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
bodies[index] = NULL;
// Reorder physics bodies pointers array and its catched index
- for (int i = index; i < physicsBodiesCount; i++)
+ for (unsigned int i = index; i < physicsBodiesCount; i++)
{
if ((i + 1) < physicsBodiesCount) bodies[i] = bodies[i + 1];
}
@@ -876,74 +838,80 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
// Update physics bodies count
physicsBodiesCount--;
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] destroyed physics body id %i\n", id);
- #endif
+ TRACELOG("[PHYSAC] Physic body destroyed successfully (id: %i)\n", id);
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] error trying to destroy a null referenced body\n");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: DestroyPhysicsBody: NULL physic body\n");
}
// Destroys created physics bodies and manifolds and resets global values
PHYSACDEF void ResetPhysics(void)
{
- // Unitialize physics bodies dynamic memory allocations
- for (int i = physicsBodiesCount - 1; i >= 0; i--)
+ if (physicsBodiesCount > 0)
{
- PhysicsBody body = bodies[i];
-
- if (body != NULL)
+ // Unitialize physics bodies dynamic memory allocations
+ for (unsigned int i = physicsBodiesCount - 1; i >= 0; i--)
{
- PHYSAC_FREE(body);
- bodies[i] = NULL;
- usedMemory -= sizeof(PhysicsBodyData);
+ PhysicsBody body = bodies[i];
+
+ if (body != NULL)
+ {
+ PHYSAC_FREE(body);
+ bodies[i] = NULL;
+ usedMemory -= sizeof(PhysicsBodyData);
+ }
}
- }
- physicsBodiesCount = 0;
+ physicsBodiesCount = 0;
+ }
- // Unitialize physics manifolds dynamic memory allocations
- for (int i = physicsManifoldsCount - 1; i >= 0; i--)
+ if (physicsManifoldsCount > 0)
{
- PhysicsManifold manifold = contacts[i];
-
- if (manifold != NULL)
+ // Unitialize physics manifolds dynamic memory allocations
+ for (unsigned int i = physicsManifoldsCount - 1; i >= 0; i--)
{
- PHYSAC_FREE(manifold);
- contacts[i] = NULL;
- usedMemory -= sizeof(PhysicsManifoldData);
+ PhysicsManifold manifold = contacts[i];
+
+ if (manifold != NULL)
+ {
+ PHYSAC_FREE(manifold);
+ contacts[i] = NULL;
+ usedMemory -= sizeof(PhysicsManifoldData);
+ }
}
- }
- physicsManifoldsCount = 0;
+ physicsManifoldsCount = 0;
+ }
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] physics module reset successfully\n");
- #endif
+ TRACELOG("[PHYSAC] Physics module reseted successfully\n");
}
// Unitializes physics pointers and exits physics loop thread
PHYSACDEF void ClosePhysics(void)
{
- // Exit physics loop thread
- physicsThreadEnabled = false;
-
- #if !defined(PHYSAC_NO_THREADS)
- pthread_join(physicsThreadId, NULL);
- #endif
-
// Unitialize physics manifolds dynamic memory allocations
- for (int i = physicsManifoldsCount - 1; i >= 0; i--) DestroyPhysicsManifold(contacts[i]);
-
+ if (physicsManifoldsCount > 0)
+ {
+ for (unsigned int i = physicsManifoldsCount - 1; i >= 0; i--)
+ DestroyPhysicsManifold(contacts[i]);
+ }
+
// Unitialize physics bodies dynamic memory allocations
- for (int i = physicsBodiesCount - 1; i >= 0; i--) DestroyPhysicsBody(bodies[i]);
+ if (physicsBodiesCount > 0)
+ {
+ for (unsigned int i = physicsBodiesCount - 1; i >= 0; i--)
+ DestroyPhysicsBody(bodies[i]);
+ }
- #if defined(PHYSAC_DEBUG)
- if (physicsBodiesCount > 0 || usedMemory != 0) TRACELOG("[PHYSAC] physics module closed with %i still allocated bodies [MEMORY: %i bytes]\n", physicsBodiesCount, usedMemory);
- else if (physicsManifoldsCount > 0 || usedMemory != 0) TRACELOG("[PHYSAC] physics module closed with %i still allocated manifolds [MEMORY: %i bytes]\n", physicsManifoldsCount, usedMemory);
- else TRACELOG("[PHYSAC] physics module closed successfully\n");
- #endif
+ // Trace log info
+ if ((physicsBodiesCount > 0) || (usedMemory != 0))
+ {
+ TRACELOG("[PHYSAC] WARNING: Physics module closed with unallocated bodies (BODIES: %i, MEMORY: %i bytes)\n", physicsBodiesCount, usedMemory);
+ }
+ else if ((physicsManifoldsCount > 0) || (usedMemory != 0))
+ {
+ TRACELOG("[PHYSAC] WARNING: Pysics module closed with unallocated manifolds (MANIFOLDS: %i, MEMORY: %i bytes)\n", physicsManifoldsCount, usedMemory);
+ }
+ else TRACELOG("[PHYSAC] Physics module closed successfully\n");
}
//----------------------------------------------------------------------------------
@@ -958,7 +926,7 @@ static int FindAvailableBodyIndex()
int currentId = i;
// Check if current id already exist in other physics body
- for (int k = 0; k < physicsBodiesCount; k++)
+ for (unsigned int k = 0; k < physicsBodiesCount; k++)
{
if (bodies[k]->id == currentId)
{
@@ -968,9 +936,9 @@ static int FindAvailableBodyIndex()
}
// If it is not used, use it as new physics body id
- if (currentId == i)
+ if (currentId == (int)i)
{
- index = i;
+ index = (int)i;
break;
}
}
@@ -978,106 +946,82 @@ static int FindAvailableBodyIndex()
return index;
}
-// Creates a random polygon shape with max vertex distance from polygon pivot
-static PolygonData CreateRandomPolygon(float radius, int sides)
+// Creates a default polygon shape with max vertex distance from polygon pivot
+static PhysicsVertexData CreateDefaultPolygon(float radius, int sides)
{
- PolygonData data = { 0 };
+ PhysicsVertexData data = { 0 };
data.vertexCount = sides;
// Calculate polygon vertices positions
- for (int i = 0; i < data.vertexCount; i++)
+ for (unsigned int i = 0; i < data.vertexCount; i++)
{
- data.positions[i].x = cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
- data.positions[i].y = sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
+ data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
+ data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
}
// Calculate polygon faces normals
- for (int i = 0; i < data.vertexCount; i++)
+ for (int i = 0; i < (int)data.vertexCount; i++)
{
int nextIndex = (((i + 1) < sides) ? (i + 1) : 0);
- Vector2 face = Vector2Subtract(data.positions[nextIndex], data.positions[i]);
+ Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
- data.normals[i] = (Vector2){ face.y, -face.x };
- MathNormalize(&data.normals[i]);
+ data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
+ MathVector2Normalize(&data.normals[i]);
}
return data;
}
// Creates a rectangle polygon shape based on a min and max positions
-static PolygonData CreateRectanglePolygon(Vector2 pos, Vector2 size)
+static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size)
{
- PolygonData data = { 0 };
+ PhysicsVertexData data = { 0 };
data.vertexCount = 4;
// Calculate polygon vertices positions
- data.positions[0] = (Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
- data.positions[1] = (Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
- data.positions[2] = (Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
- data.positions[3] = (Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
+ data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
+ data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
+ data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
+ data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
// Calculate polygon faces normals
- for (int i = 0; i < data.vertexCount; i++)
+ for (unsigned int i = 0; i < data.vertexCount; i++)
{
int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0);
- Vector2 face = Vector2Subtract(data.positions[nextIndex], data.positions[i]);
+ Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
- data.normals[i] = (Vector2){ face.y, -face.x };
- MathNormalize(&data.normals[i]);
+ data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
+ MathVector2Normalize(&data.normals[i]);
}
return data;
}
-// Physics loop thread function
-static void *PhysicsLoop(void *arg)
-{
-#if !defined(PHYSAC_NO_THREADS)
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] physics thread created successfully\n");
- #endif
-
- // Initialize physics loop thread values
- physicsThreadEnabled = true;
-
- // Physics update loop
- while (physicsThreadEnabled)
- {
- RunPhysicsStep();
- }
-#endif
-
- return NULL;
-}
-
-// Physics steps calculations (dynamics, collisions and position corrections)
-static void PhysicsStep(void)
+// Update physics step (dynamics, collisions and position corrections)
+void UpdatePhysicsStep(void)
{
- // Update current steps count
- stepsCount++;
-
// Clear previous generated collisions information
- for (int i = physicsManifoldsCount - 1; i >= 0; i--)
+ for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--)
{
PhysicsManifold manifold = contacts[i];
if (manifold != NULL) DestroyPhysicsManifold(manifold);
}
// Reset physics bodies grounded state
- for (int i = 0; i < physicsBodiesCount; i++)
+ for (unsigned int i = 0; i < physicsBodiesCount; i++)
{
PhysicsBody body = bodies[i];
body->isGrounded = false;
}
-
+
// Generate new collision information
- for (int i = 0; i < physicsBodiesCount; i++)
+ for (unsigned int i = 0; i < physicsBodiesCount; i++)
{
PhysicsBody bodyA = bodies[i];
if (bodyA != NULL)
{
- for (int j = i + 1; j < physicsBodiesCount; j++)
+ for (unsigned int j = i + 1; j < physicsBodiesCount; j++)
{
PhysicsBody bodyB = bodies[j];
@@ -1091,15 +1035,15 @@ static void PhysicsStep(void)
if (manifold->contactsCount > 0)
{
// Create a new manifold with same information as previously solved manifold and add it to the manifolds pool last slot
- PhysicsManifold newManifold = CreatePhysicsManifold(bodyA, bodyB);
- newManifold->penetration = manifold->penetration;
- newManifold->normal = manifold->normal;
- newManifold->contacts[0] = manifold->contacts[0];
- newManifold->contacts[1] = manifold->contacts[1];
- newManifold->contactsCount = manifold->contactsCount;
- newManifold->restitution = manifold->restitution;
- newManifold->dynamicFriction = manifold->dynamicFriction;
- newManifold->staticFriction = manifold->staticFriction;
+ PhysicsManifold manifold = CreatePhysicsManifold(bodyA, bodyB);
+ manifold->penetration = manifold->penetration;
+ manifold->normal = manifold->normal;
+ manifold->contacts[0] = manifold->contacts[0];
+ manifold->contacts[1] = manifold->contacts[1];
+ manifold->contactsCount = manifold->contactsCount;
+ manifold->restitution = manifold->restitution;
+ manifold->dynamicFriction = manifold->dynamicFriction;
+ manifold->staticFriction = manifold->staticFriction;
}
}
}
@@ -1107,23 +1051,23 @@ static void PhysicsStep(void)
}
// Integrate forces to physics bodies
- for (int i = 0; i < physicsBodiesCount; i++)
+ for (unsigned int i = 0; i < physicsBodiesCount; i++)
{
PhysicsBody body = bodies[i];
if (body != NULL) IntegratePhysicsForces(body);
}
// Initialize physics manifolds to solve collisions
- for (int i = 0; i < physicsManifoldsCount; i++)
+ for (unsigned int i = 0; i < physicsManifoldsCount; i++)
{
PhysicsManifold manifold = contacts[i];
if (manifold != NULL) InitializePhysicsManifolds(manifold);
}
// Integrate physics collisions impulses to solve collisions
- for (int i = 0; i < PHYSAC_COLLISION_ITERATIONS; i++)
+ for (unsigned int i = 0; i < PHYSAC_COLLISION_ITERATIONS; i++)
{
- for (int j = 0; j < physicsManifoldsCount; j++)
+ for (unsigned int j = 0; j < physicsManifoldsCount; j++)
{
PhysicsManifold manifold = contacts[i];
if (manifold != NULL) IntegratePhysicsImpulses(manifold);
@@ -1131,21 +1075,21 @@ static void PhysicsStep(void)
}
// Integrate velocity to physics bodies
- for (int i = 0; i < physicsBodiesCount; i++)
+ for (unsigned int i = 0; i < physicsBodiesCount; i++)
{
PhysicsBody body = bodies[i];
if (body != NULL) IntegratePhysicsVelocity(body);
}
// Correct physics bodies positions based on manifolds collision information
- for (int i = 0; i < physicsManifoldsCount; i++)
+ for (unsigned int i = 0; i < physicsManifoldsCount; i++)
{
PhysicsManifold manifold = contacts[i];
if (manifold != NULL) CorrectPhysicsPositions(manifold);
}
// Clear physics bodies forces
- for (int i = 0; i < physicsBodiesCount; i++)
+ for (unsigned int i = 0; i < physicsBodiesCount; i++)
{
PhysicsBody body = bodies[i];
if (body != NULL)
@@ -1156,31 +1100,34 @@ static void PhysicsStep(void)
}
}
-// Wrapper to ensure PhysicsStep is run with at a fixed time step
-PHYSACDEF void RunPhysicsStep(void)
+// Update physics system
+// Physics steps are launched at a fixed time step if enabled
+PHYSACDEF void UpdatePhysics(void)
{
- // Calculate current time
+#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
+ static double deltaTimeAccumulator = 0.0;
+
+ // Calculate current time (ms)
currentTime = GetCurrentTime();
- // Calculate current delta time
+ // Calculate current delta time (ms)
const double delta = currentTime - startTime;
// Store the time elapsed since the last frame began
- accumulator += delta;
+ deltaTimeAccumulator += delta;
// Fixed time stepping loop
- while (accumulator >= deltaTime)
+ while (deltaTimeAccumulator >= deltaTime)
{
-#ifdef PHYSAC_DEBUG
- //TRACELOG("currentTime %f, startTime %f, accumulator-pre %f, accumulator-post %f, delta %f, deltaTime %f\n",
- // currentTime, startTime, accumulator, accumulator-deltaTime, delta, deltaTime);
-#endif
- PhysicsStep();
- accumulator -= deltaTime;
+ UpdatePhysicsStep();
+ deltaTimeAccumulator -= deltaTime;
}
// Record the starting of this frame
startTime = currentTime;
+#else
+ UpdatePhysicsStep();
+#endif
}
PHYSACDEF void SetPhysicsTimeStep(double delta)
@@ -1197,7 +1144,7 @@ static int FindAvailableManifoldIndex()
int currentId = i;
// Check if current id already exist in other physics body
- for (int k = 0; k < physicsManifoldsCount; k++)
+ for (unsigned int k = 0; k < physicsManifoldsCount; k++)
{
if (contacts[k]->id == currentId)
{
@@ -1220,34 +1167,32 @@ static int FindAvailableManifoldIndex()
// Creates a new physics manifold to solve collision
static PhysicsManifold CreatePhysicsManifold(PhysicsBody a, PhysicsBody b)
{
- PhysicsManifold newManifold = (PhysicsManifold)PHYSAC_MALLOC(sizeof(PhysicsManifoldData));
+ PhysicsManifold manifold = (PhysicsManifold)PHYSAC_MALLOC(sizeof(PhysicsManifoldData));
usedMemory += sizeof(PhysicsManifoldData);
- int newId = FindAvailableManifoldIndex();
- if (newId != -1)
+ int id = FindAvailableManifoldIndex();
+ if (id != -1)
{
// Initialize new manifold with generic values
- newManifold->id = newId;
- newManifold->bodyA = a;
- newManifold->bodyB = b;
- newManifold->penetration = 0;
- newManifold->normal = PHYSAC_VECTOR_ZERO;
- newManifold->contacts[0] = PHYSAC_VECTOR_ZERO;
- newManifold->contacts[1] = PHYSAC_VECTOR_ZERO;
- newManifold->contactsCount = 0;
- newManifold->restitution = 0.0f;
- newManifold->dynamicFriction = 0.0f;
- newManifold->staticFriction = 0.0f;
+ manifold->id = id;
+ manifold->bodyA = a;
+ manifold->bodyB = b;
+ manifold->penetration = 0;
+ manifold->normal = PHYSAC_VECTOR_ZERO;
+ manifold->contacts[0] = PHYSAC_VECTOR_ZERO;
+ manifold->contacts[1] = PHYSAC_VECTOR_ZERO;
+ manifold->contactsCount = 0;
+ manifold->restitution = 0.0f;
+ manifold->dynamicFriction = 0.0f;
+ manifold->staticFriction = 0.0f;
// Add new body to bodies pointers array and update bodies count
- contacts[physicsManifoldsCount] = newManifold;
+ contacts[physicsManifoldsCount] = manifold;
physicsManifoldsCount++;
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] new physics manifold creation failed because there is any available id to use\n");
- #endif
+ else TRACELOG("[PHYSAC] Physic manifold could not be created, PHYSAC_MAX_MANIFOLDS reached\n");
- return newManifold;
+ return manifold;
}
// Unitializes and destroys a physics manifold
@@ -1258,7 +1203,7 @@ static void DestroyPhysicsManifold(PhysicsManifold manifold)
int id = manifold->id;
int index = -1;
- for (int i = 0; i < physicsManifoldsCount; i++)
+ for (unsigned int i = 0; i < physicsManifoldsCount; i++)
{
if (contacts[i]->id == id)
{
@@ -1267,13 +1212,7 @@ static void DestroyPhysicsManifold(PhysicsManifold manifold)
}
}
- if (index == -1)
- {
- #if defined(PHYSAC_DEBUG)
- TRACELOG("[PHYSAC] Not possible to manifold id %i in pointers array\n", id);
- #endif
- return; // Prevent access to index -1
- }
+ if (index == -1) return; // Prevent access to index -1
// Free manifold allocated memory
PHYSAC_FREE(manifold);
@@ -1281,7 +1220,7 @@ static void DestroyPhysicsManifold(PhysicsManifold manifold)
contacts[index] = NULL;
// Reorder physics manifolds pointers array and its catched index
- for (int i = index; i < physicsManifoldsCount; i++)
+ for (unsigned int i = index; i < physicsManifoldsCount; i++)
{
if ((i + 1) < physicsManifoldsCount) contacts[i] = contacts[i + 1];
}
@@ -1289,9 +1228,7 @@ static void DestroyPhysicsManifold(PhysicsManifold manifold)
// Update physics manifolds count
physicsManifoldsCount--;
}
- #if defined(PHYSAC_DEBUG)
- else TRACELOG("[PHYSAC] error trying to destroy a null referenced manifold\n");
- #endif
+ else TRACELOG("[PHYSAC] WARNING: DestroyPhysicsManifold: NULL physic manifold\n");
}
// Solves a created physics manifold between two physics bodies
@@ -1333,9 +1270,9 @@ static void SolveCircleToCircle(PhysicsManifold manifold)
if ((bodyA == NULL) || (bodyB == NULL)) return;
// Calculate translational vector, which is normal
- Vector2 normal = Vector2Subtract(bodyB->position, bodyA->position);
+ Vector2 normal = MathVector2Subtract(bodyB->position, bodyA->position);
- float distSqr = MathLenSqr(normal);
+ float distSqr = MathVector2SqrLen(normal);
float radius = bodyA->shape.radius + bodyB->shape.radius;
// Check if circles are not in contact
@@ -1351,14 +1288,14 @@ static void SolveCircleToCircle(PhysicsManifold manifold)
if (distance == 0.0f)
{
manifold->penetration = bodyA->shape.radius;
- manifold->normal = (Vector2){ 1.0f, 0.0f };
+ manifold->normal = CLITERAL(Vector2){ 1.0f, 0.0f };
manifold->contacts[0] = bodyA->position;
}
else
{
manifold->penetration = radius - distance;
- manifold->normal = (Vector2){ normal.x/distance, normal.y/distance }; // Faster than using MathNormalize() due to sqrt is already performed
- manifold->contacts[0] = (Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
+ manifold->normal = CLITERAL(Vector2){ normal.x/distance, normal.y/distance }; // Faster than using MathVector2Normalize() due to sqrt is already performed
+ manifold->contacts[0] = CLITERAL(Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
}
// Update physics body grounded state if normal direction is down
@@ -1377,17 +1314,17 @@ static void SolveCircleToPolygon(PhysicsManifold manifold)
// Transform circle center to polygon transform space
Vector2 center = bodyA->position;
- center = Mat2MultiplyVector2(Mat2Transpose(bodyB->shape.transform), Vector2Subtract(center, bodyB->position));
+ center = MathMatVector2Product(MathMatTranspose(bodyB->shape.transform), MathVector2Subtract(center, bodyB->position));
// Find edge with minimum penetration
// It is the same concept as using support points in SolvePolygonToPolygon
float separation = -PHYSAC_FLT_MAX;
int faceNormal = 0;
- PolygonData vertexData = bodyB->shape.vertexData;
+ PhysicsVertexData vertexData = bodyB->shape.vertexData;
- for (int i = 0; i < vertexData.vertexCount; i++)
+ for (unsigned int i = 0; i < vertexData.vertexCount; i++)
{
- float currentSeparation = MathDot(vertexData.normals[i], Vector2Subtract(center, vertexData.positions[i]));
+ float currentSeparation = MathVector2DotProduct(vertexData.normals[i], MathVector2Subtract(center, vertexData.positions[i]));
if (currentSeparation > bodyA->shape.radius) return;
@@ -1400,60 +1337,60 @@ static void SolveCircleToPolygon(PhysicsManifold manifold)
// Grab face's vertices
Vector2 v1 = vertexData.positions[faceNormal];
- int nextIndex = (((faceNormal + 1) < vertexData.vertexCount) ? (faceNormal + 1) : 0);
+ int nextIndex = (((faceNormal + 1) < (int)vertexData.vertexCount) ? (faceNormal + 1) : 0);
Vector2 v2 = vertexData.positions[nextIndex];
// Check to see if center is within polygon
if (separation < PHYSAC_EPSILON)
{
manifold->contactsCount = 1;
- Vector2 normal = Mat2MultiplyVector2(bodyB->shape.transform, vertexData.normals[faceNormal]);
- manifold->normal = (Vector2){ -normal.x, -normal.y };
- manifold->contacts[0] = (Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
+ Vector2 normal = MathMatVector2Product(bodyB->shape.transform, vertexData.normals[faceNormal]);
+ manifold->normal = CLITERAL(Vector2){ -normal.x, -normal.y };
+ manifold->contacts[0] = CLITERAL(Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
manifold->penetration = bodyA->shape.radius;
return;
}
// Determine which voronoi region of the edge center of circle lies within
- float dot1 = MathDot(Vector2Subtract(center, v1), Vector2Subtract(v2, v1));
- float dot2 = MathDot(Vector2Subtract(center, v2), Vector2Subtract(v1, v2));
+ float dot1 = MathVector2DotProduct(MathVector2Subtract(center, v1), MathVector2Subtract(v2, v1));
+ float dot2 = MathVector2DotProduct(MathVector2Subtract(center, v2), MathVector2Subtract(v1, v2));
manifold->penetration = bodyA->shape.radius - separation;
if (dot1 <= 0.0f) // Closest to v1
{
- if (DistSqr(center, v1) > bodyA->shape.radius*bodyA->shape.radius) return;
+ if (MathVector2SqrDistance(center, v1) > bodyA->shape.radius*bodyA->shape.radius) return;
manifold->contactsCount = 1;
- Vector2 normal = Vector2Subtract(v1, center);
- normal = Mat2MultiplyVector2(bodyB->shape.transform, normal);
- MathNormalize(&normal);
+ Vector2 normal = MathVector2Subtract(v1, center);
+ normal = MathMatVector2Product(bodyB->shape.transform, normal);
+ MathVector2Normalize(&normal);
manifold->normal = normal;
- v1 = Mat2MultiplyVector2(bodyB->shape.transform, v1);
- v1 = Vector2Add(v1, bodyB->position);
+ v1 = MathMatVector2Product(bodyB->shape.transform, v1);
+ v1 = MathVector2Add(v1, bodyB->position);
manifold->contacts[0] = v1;
}
else if (dot2 <= 0.0f) // Closest to v2
{
- if (DistSqr(center, v2) > bodyA->shape.radius*bodyA->shape.radius) return;
+ if (MathVector2SqrDistance(center, v2) > bodyA->shape.radius*bodyA->shape.radius) return;
manifold->contactsCount = 1;
- Vector2 normal = Vector2Subtract(v2, center);
- v2 = Mat2MultiplyVector2(bodyB->shape.transform, v2);
- v2 = Vector2Add(v2, bodyB->position);
+ Vector2 normal = MathVector2Subtract(v2, center);
+ v2 = MathMatVector2Product(bodyB->shape.transform, v2);
+ v2 = MathVector2Add(v2, bodyB->position);
manifold->contacts[0] = v2;
- normal = Mat2MultiplyVector2(bodyB->shape.transform, normal);
- MathNormalize(&normal);
+ normal = MathMatVector2Product(bodyB->shape.transform, normal);
+ MathVector2Normalize(&normal);
manifold->normal = normal;
}
else // Closest to face
{
Vector2 normal = vertexData.normals[faceNormal];
- if (MathDot(Vector2Subtract(center, v1), normal) > bodyA->shape.radius) return;
+ if (MathVector2DotProduct(MathVector2Subtract(center, v1), normal) > bodyA->shape.radius) return;
- normal = Mat2MultiplyVector2(bodyB->shape.transform, normal);
- manifold->normal = (Vector2){ -normal.x, -normal.y };
- manifold->contacts[0] = (Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
+ normal = MathMatVector2Product(bodyB->shape.transform, normal);
+ manifold->normal = CLITERAL(Vector2){ -normal.x, -normal.y };
+ manifold->contacts[0] = CLITERAL(Vector2){ manifold->normal.x*bodyA->shape.radius + bodyA->position.x, manifold->normal.y*bodyA->shape.radius + bodyA->position.y };
manifold->contactsCount = 1;
}
}
@@ -1500,7 +1437,8 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold)
PhysicsShape incPoly; // Incident
// Determine which shape contains reference face
- if (BiasGreaterThan(penetrationA, penetrationB))
+ // Checking bias range for penetration
+ if (penetrationA >= (penetrationB*0.95f + penetrationA*0.01f))
{
refPoly = bodyA;
incPoly = bodyB;
@@ -1519,37 +1457,37 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold)
FindIncidentFace(&incidentFace[0], &incidentFace[1], refPoly, incPoly, referenceIndex);
// Setup reference face vertices
- PolygonData refData = refPoly.vertexData;
+ PhysicsVertexData refData = refPoly.vertexData;
Vector2 v1 = refData.positions[referenceIndex];
- referenceIndex = (((referenceIndex + 1) < refData.vertexCount) ? (referenceIndex + 1) : 0);
+ referenceIndex = (((referenceIndex + 1) < (int)refData.vertexCount) ? (referenceIndex + 1) : 0);
Vector2 v2 = refData.positions[referenceIndex];
// Transform vertices to world space
- v1 = Mat2MultiplyVector2(refPoly.transform, v1);
- v1 = Vector2Add(v1, refPoly.body->position);
- v2 = Mat2MultiplyVector2(refPoly.transform, v2);
- v2 = Vector2Add(v2, refPoly.body->position);
+ v1 = MathMatVector2Product(refPoly.transform, v1);
+ v1 = MathVector2Add(v1, refPoly.body->position);
+ v2 = MathMatVector2Product(refPoly.transform, v2);
+ v2 = MathVector2Add(v2, refPoly.body->position);
// Calculate reference face side normal in world space
- Vector2 sidePlaneNormal = Vector2Subtract(v2, v1);
- MathNormalize(&sidePlaneNormal);
+ Vector2 sidePlaneNormal = MathVector2Subtract(v2, v1);
+ MathVector2Normalize(&sidePlaneNormal);
// Orthogonalize
Vector2 refFaceNormal = { sidePlaneNormal.y, -sidePlaneNormal.x };
- float refC = MathDot(refFaceNormal, v1);
- float negSide = MathDot(sidePlaneNormal, v1)*-1;
- float posSide = MathDot(sidePlaneNormal, v2);
+ float refC = MathVector2DotProduct(refFaceNormal, v1);
+ float negSide = MathVector2DotProduct(sidePlaneNormal, v1)*-1;
+ float posSide = MathVector2DotProduct(sidePlaneNormal, v2);
- // Clip incident face to reference face side planes (due to floating point error, possible to not have required points
- if (Clip((Vector2){ -sidePlaneNormal.x, -sidePlaneNormal.y }, negSide, &incidentFace[0], &incidentFace[1]) < 2) return;
- if (Clip(sidePlaneNormal, posSide, &incidentFace[0], &incidentFace[1]) < 2) return;
+ // MathVector2Clip incident face to reference face side planes (due to floating point error, possible to not have required points
+ if (MathVector2Clip(CLITERAL(Vector2){ -sidePlaneNormal.x, -sidePlaneNormal.y }, &incidentFace[0], &incidentFace[1], negSide) < 2) return;
+ if (MathVector2Clip(sidePlaneNormal, &incidentFace[0], &incidentFace[1], posSide) < 2) return;
// Flip normal if required
- manifold->normal = (flip ? (Vector2){ -refFaceNormal.x, -refFaceNormal.y } : refFaceNormal);
+ manifold->normal = (flip ? CLITERAL(Vector2){ -refFaceNormal.x, -refFaceNormal.y } : refFaceNormal);
// Keep points behind reference face
- int currentPoint = 0; // Clipped points behind reference face
- float separation = MathDot(refFaceNormal, incidentFace[0]) - refC;
+ int currentPoint = 0; // MathVector2Clipped points behind reference face
+ float separation = MathVector2DotProduct(refFaceNormal, incidentFace[0]) - refC;
if (separation <= 0.0f)
{
manifold->contacts[currentPoint] = incidentFace[0];
@@ -1558,7 +1496,7 @@ static void SolvePolygonToPolygon(PhysicsManifold manifold)
}
else manifold->penetration = 0.0f;
- separation = MathDot(refFaceNormal, incidentFace[1]) - refC;
+ separation = MathVector2DotProduct(refFaceNormal, incidentFace[1]) - refC;
if (separation <= 0.0f)
{
@@ -1578,16 +1516,16 @@ static void IntegratePhysicsForces(PhysicsBody body)
{
if ((body == NULL) || (body->inverseMass == 0.0f) || !body->enabled) return;
- body->velocity.x += (body->force.x*body->inverseMass)*(deltaTime/2.0);
- body->velocity.y += (body->force.y*body->inverseMass)*(deltaTime/2.0);
+ body->velocity.x += (float)((body->force.x*body->inverseMass)*(deltaTime/2.0));
+ body->velocity.y += (float)((body->force.y*body->inverseMass)*(deltaTime/2.0));
if (body->useGravity)
{
- body->velocity.x += gravityForce.x*(deltaTime/1000/2.0);
- body->velocity.y += gravityForce.y*(deltaTime/1000/2.0);
+ body->velocity.x += (float)(gravityForce.x*(deltaTime/1000/2.0));
+ body->velocity.y += (float)(gravityForce.y*(deltaTime/1000/2.0));
}
- if (!body->freezeOrient) body->angularVelocity += body->torque*body->inverseInertia*(deltaTime/2.0);
+ if (!body->freezeOrient) body->angularVelocity += (float)(body->torque*body->inverseInertia*(deltaTime/2.0));
}
// Initializes physics manifolds to solve collisions
@@ -1603,14 +1541,14 @@ static void InitializePhysicsManifolds(PhysicsManifold manifold)
manifold->staticFriction = sqrtf(bodyA->staticFriction*bodyB->staticFriction);
manifold->dynamicFriction = sqrtf(bodyA->dynamicFriction*bodyB->dynamicFriction);
- for (int i = 0; i < manifold->contactsCount; i++)
+ for (unsigned int i = 0; i < manifold->contactsCount; i++)
{
// Caculate radius from center of mass to contact
- Vector2 radiusA = Vector2Subtract(manifold->contacts[i], bodyA->position);
- Vector2 radiusB = Vector2Subtract(manifold->contacts[i], bodyB->position);
+ Vector2 radiusA = MathVector2Subtract(manifold->contacts[i], bodyA->position);
+ Vector2 radiusB = MathVector2Subtract(manifold->contacts[i], bodyB->position);
- Vector2 crossA = MathCross(bodyA->angularVelocity, radiusA);
- Vector2 crossB = MathCross(bodyB->angularVelocity, radiusB);
+ Vector2 crossA = MathVector2Product(radiusA, bodyA->angularVelocity);
+ Vector2 crossB = MathVector2Product(radiusB, bodyB->angularVelocity);
Vector2 radiusV = { 0.0f, 0.0f };
radiusV.x = bodyB->velocity.x + crossB.x - bodyA->velocity.x - crossA.x;
@@ -1618,7 +1556,7 @@ static void InitializePhysicsManifolds(PhysicsManifold manifold)
// Determine if we should perform a resting collision or not;
// The idea is if the only thing moving this object is gravity, then the collision should be performed without any restitution
- if (MathLenSqr(radiusV) < (MathLenSqr((Vector2){ gravityForce.x*deltaTime/1000, gravityForce.y*deltaTime/1000 }) + PHYSAC_EPSILON)) manifold->restitution = 0;
+ if (MathVector2SqrLen(radiusV) < (MathVector2SqrLen(CLITERAL(Vector2){ (float)(gravityForce.x*deltaTime/1000), (float)(gravityForce.y*deltaTime/1000) }) + PHYSAC_EPSILON)) manifold->restitution = 0;
}
}
@@ -1638,25 +1576,25 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold)
return;
}
- for (int i = 0; i < manifold->contactsCount; i++)
+ for (unsigned int i = 0; i < manifold->contactsCount; i++)
{
// Calculate radius from center of mass to contact
- Vector2 radiusA = Vector2Subtract(manifold->contacts[i], bodyA->position);
- Vector2 radiusB = Vector2Subtract(manifold->contacts[i], bodyB->position);
+ Vector2 radiusA = MathVector2Subtract(manifold->contacts[i], bodyA->position);
+ Vector2 radiusB = MathVector2Subtract(manifold->contacts[i], bodyB->position);
// Calculate relative velocity
Vector2 radiusV = { 0.0f, 0.0f };
- radiusV.x = bodyB->velocity.x + MathCross(bodyB->angularVelocity, radiusB).x - bodyA->velocity.x - MathCross(bodyA->angularVelocity, radiusA).x;
- radiusV.y = bodyB->velocity.y + MathCross(bodyB->angularVelocity, radiusB).y - bodyA->velocity.y - MathCross(bodyA->angularVelocity, radiusA).y;
+ radiusV.x = bodyB->velocity.x + MathVector2Product(radiusB, bodyB->angularVelocity).x - bodyA->velocity.x - MathVector2Product(radiusA, bodyA->angularVelocity).x;
+ radiusV.y = bodyB->velocity.y + MathVector2Product(radiusB, bodyB->angularVelocity).y - bodyA->velocity.y - MathVector2Product(radiusA, bodyA->angularVelocity).y;
// Relative velocity along the normal
- float contactVelocity = MathDot(radiusV, manifold->normal);
+ float contactVelocity = MathVector2DotProduct(radiusV, manifold->normal);
// Do not resolve if velocities are separating
if (contactVelocity > 0.0f) return;
- float raCrossN = MathCrossVector2(radiusA, manifold->normal);
- float rbCrossN = MathCrossVector2(radiusB, manifold->normal);
+ float raCrossN = MathVector2CrossProduct(radiusA, manifold->normal);
+ float rbCrossN = MathVector2CrossProduct(radiusB, manifold->normal);
float inverseMassSum = bodyA->inverseMass + bodyB->inverseMass + (raCrossN*raCrossN)*bodyA->inverseInertia + (rbCrossN*rbCrossN)*bodyB->inverseInertia;
@@ -1672,37 +1610,37 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold)
{
bodyA->velocity.x += bodyA->inverseMass*(-impulseV.x);
bodyA->velocity.y += bodyA->inverseMass*(-impulseV.y);
- if (!bodyA->freezeOrient) bodyA->angularVelocity += bodyA->inverseInertia*MathCrossVector2(radiusA, (Vector2){ -impulseV.x, -impulseV.y });
+ if (!bodyA->freezeOrient) bodyA->angularVelocity += bodyA->inverseInertia*MathVector2CrossProduct(radiusA, CLITERAL(Vector2){ -impulseV.x, -impulseV.y });
}
if (bodyB->enabled)
{
bodyB->velocity.x += bodyB->inverseMass*(impulseV.x);
bodyB->velocity.y += bodyB->inverseMass*(impulseV.y);
- if (!bodyB->freezeOrient) bodyB->angularVelocity += bodyB->inverseInertia*MathCrossVector2(radiusB, impulseV);
+ if (!bodyB->freezeOrient) bodyB->angularVelocity += bodyB->inverseInertia*MathVector2CrossProduct(radiusB, impulseV);
}
// Apply friction impulse to each physics body
- radiusV.x = bodyB->velocity.x + MathCross(bodyB->angularVelocity, radiusB).x - bodyA->velocity.x - MathCross(bodyA->angularVelocity, radiusA).x;
- radiusV.y = bodyB->velocity.y + MathCross(bodyB->angularVelocity, radiusB).y - bodyA->velocity.y - MathCross(bodyA->angularVelocity, radiusA).y;
+ radiusV.x = bodyB->velocity.x + MathVector2Product(radiusB, bodyB->angularVelocity).x - bodyA->velocity.x - MathVector2Product(radiusA, bodyA->angularVelocity).x;
+ radiusV.y = bodyB->velocity.y + MathVector2Product(radiusB, bodyB->angularVelocity).y - bodyA->velocity.y - MathVector2Product(radiusA, bodyA->angularVelocity).y;
- Vector2 tangent = { radiusV.x - (manifold->normal.x*MathDot(radiusV, manifold->normal)), radiusV.y - (manifold->normal.y*MathDot(radiusV, manifold->normal)) };
- MathNormalize(&tangent);
+ Vector2 tangent = { radiusV.x - (manifold->normal.x*MathVector2DotProduct(radiusV, manifold->normal)), radiusV.y - (manifold->normal.y*MathVector2DotProduct(radiusV, manifold->normal)) };
+ MathVector2Normalize(&tangent);
// Calculate impulse tangent magnitude
- float impulseTangent = -MathDot(radiusV, tangent);
+ float impulseTangent = -MathVector2DotProduct(radiusV, tangent);
impulseTangent /= inverseMassSum;
impulseTangent /= (float)manifold->contactsCount;
- float absImpulseTangent = fabs(impulseTangent);
+ float absImpulseTangent = (float)fabs(impulseTangent);
// Don't apply tiny friction impulses
if (absImpulseTangent <= PHYSAC_EPSILON) return;
// Apply coulumb's law
Vector2 tangentImpulse = { 0.0f, 0.0f };
- if (absImpulseTangent < impulse*manifold->staticFriction) tangentImpulse = (Vector2){ tangent.x*impulseTangent, tangent.y*impulseTangent };
- else tangentImpulse = (Vector2){ tangent.x*-impulse*manifold->dynamicFriction, tangent.y*-impulse*manifold->dynamicFriction };
+ if (absImpulseTangent < impulse*manifold->staticFriction) tangentImpulse = CLITERAL(Vector2){ tangent.x*impulseTangent, tangent.y*impulseTangent };
+ else tangentImpulse = CLITERAL(Vector2){ tangent.x*-impulse*manifold->dynamicFriction, tangent.y*-impulse*manifold->dynamicFriction };
// Apply friction impulse
if (bodyA->enabled)
@@ -1710,7 +1648,7 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold)
bodyA->velocity.x += bodyA->inverseMass*(-tangentImpulse.x);
bodyA->velocity.y += bodyA->inverseMass*(-tangentImpulse.y);
- if (!bodyA->freezeOrient) bodyA->angularVelocity += bodyA->inverseInertia*MathCrossVector2(radiusA, (Vector2){ -tangentImpulse.x, -tangentImpulse.y });
+ if (!bodyA->freezeOrient) bodyA->angularVelocity += bodyA->inverseInertia*MathVector2CrossProduct(radiusA, CLITERAL(Vector2){ -tangentImpulse.x, -tangentImpulse.y });
}
if (bodyB->enabled)
@@ -1718,7 +1656,7 @@ static void IntegratePhysicsImpulses(PhysicsManifold manifold)
bodyB->velocity.x += bodyB->inverseMass*(tangentImpulse.x);
bodyB->velocity.y += bodyB->inverseMass*(tangentImpulse.y);
- if (!bodyB->freezeOrient) bodyB->angularVelocity += bodyB->inverseInertia*MathCrossVector2(radiusB, tangentImpulse);
+ if (!bodyB->freezeOrient) bodyB->angularVelocity += bodyB->inverseInertia*MathVector2CrossProduct(radiusB, tangentImpulse);
}
}
}
@@ -1728,11 +1666,11 @@ static void IntegratePhysicsVelocity(PhysicsBody body)
{
if ((body == NULL) ||!body->enabled) return;
- body->position.x += body->velocity.x*deltaTime;
- body->position.y += body->velocity.y*deltaTime;
+ body->position.x += (float)(body->velocity.x*deltaTime);
+ body->position.y += (float)(body->velocity.y*deltaTime);
- if (!body->freezeOrient) body->orient += body->angularVelocity*deltaTime;
- Mat2Set(&body->shape.transform, body->orient);
+ if (!body->freezeOrient) body->orient += (float)(body->angularVelocity*deltaTime);
+ body->shape.transform = MathMatFromRadians(body->orient);
IntegratePhysicsForces(body);
}
@@ -1746,8 +1684,8 @@ static void CorrectPhysicsPositions(PhysicsManifold manifold)
if ((bodyA == NULL) || (bodyB == NULL)) return;
Vector2 correction = { 0.0f, 0.0f };
- correction.x = (max(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.x*PHYSAC_PENETRATION_CORRECTION;
- correction.y = (max(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.y*PHYSAC_PENETRATION_CORRECTION;
+ correction.x = (PHYSAC_MAX(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.x*PHYSAC_PENETRATION_CORRECTION;
+ correction.y = (PHYSAC_MAX(manifold->penetration - PHYSAC_PENETRATION_ALLOWANCE, 0.0f)/(bodyA->inverseMass + bodyB->inverseMass))*manifold->normal.y*PHYSAC_PENETRATION_CORRECTION;
if (bodyA->enabled)
{
@@ -1767,12 +1705,12 @@ static Vector2 GetSupport(PhysicsShape shape, Vector2 dir)
{
float bestProjection = -PHYSAC_FLT_MAX;
Vector2 bestVertex = { 0.0f, 0.0f };
- PolygonData data = shape.vertexData;
+ PhysicsVertexData data = shape.vertexData;
- for (int i = 0; i < data.vertexCount; i++)
+ for (unsigned int i = 0; i < data.vertexCount; i++)
{
Vector2 vertex = data.positions[i];
- float projection = MathDot(vertex, dir);
+ float projection = MathVector2DotProduct(vertex, dir);
if (projection > bestProjection)
{
@@ -1790,31 +1728,31 @@ static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, Physi
float bestDistance = -PHYSAC_FLT_MAX;
int bestIndex = 0;
- PolygonData dataA = shapeA.vertexData;
- //PolygonData dataB = shapeB.vertexData;
+ PhysicsVertexData dataA = shapeA.vertexData;
+ //PhysicsVertexData dataB = shapeB.vertexData;
- for (int i = 0; i < dataA.vertexCount; i++)
+ for (unsigned int i = 0; i < dataA.vertexCount; i++)
{
// Retrieve a face normal from A shape
Vector2 normal = dataA.normals[i];
- Vector2 transNormal = Mat2MultiplyVector2(shapeA.transform, normal);
+ Vector2 transNormal = MathMatVector2Product(shapeA.transform, normal);
// Transform face normal into B shape's model space
- Matrix2x2 buT = Mat2Transpose(shapeB.transform);
- normal = Mat2MultiplyVector2(buT, transNormal);
+ Matrix2x2 buT = MathMatTranspose(shapeB.transform);
+ normal = MathMatVector2Product(buT, transNormal);
// Retrieve support point from B shape along -n
- Vector2 support = GetSupport(shapeB, (Vector2){ -normal.x, -normal.y });
+ Vector2 support = GetSupport(shapeB, CLITERAL(Vector2){ -normal.x, -normal.y });
// Retrieve vertex on face from A shape, transform into B shape's model space
Vector2 vertex = dataA.positions[i];
- vertex = Mat2MultiplyVector2(shapeA.transform, vertex);
- vertex = Vector2Add(vertex, shapeA.body->position);
- vertex = Vector2Subtract(vertex, shapeB.body->position);
- vertex = Mat2MultiplyVector2(buT, vertex);
+ vertex = MathMatVector2Product(shapeA.transform, vertex);
+ vertex = MathVector2Add(vertex, shapeA.body->position);
+ vertex = MathVector2Subtract(vertex, shapeB.body->position);
+ vertex = MathMatVector2Product(buT, vertex);
// Compute penetration distance in B shape's model space
- float distance = MathDot(normal, Vector2Subtract(support, vertex));
+ float distance = MathVector2DotProduct(normal, MathVector2Subtract(support, vertex));
// Store greatest distance
if (distance > bestDistance)
@@ -1831,22 +1769,22 @@ static float FindAxisLeastPenetration(int *faceIndex, PhysicsShape shapeA, Physi
// Finds two polygon shapes incident face
static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, PhysicsShape inc, int index)
{
- PolygonData refData = ref.vertexData;
- PolygonData incData = inc.vertexData;
+ PhysicsVertexData refData = ref.vertexData;
+ PhysicsVertexData incData = inc.vertexData;
Vector2 referenceNormal = refData.normals[index];
// Calculate normal in incident's frame of reference
- referenceNormal = Mat2MultiplyVector2(ref.transform, referenceNormal); // To world space
- referenceNormal = Mat2MultiplyVector2(Mat2Transpose(inc.transform), referenceNormal); // To incident's model space
+ referenceNormal = MathMatVector2Product(ref.transform, referenceNormal); // To world space
+ referenceNormal = MathMatVector2Product(MathMatTranspose(inc.transform), referenceNormal); // To incident's model space
// Find most anti-normal face on polygon
int incidentFace = 0;
float minDot = PHYSAC_FLT_MAX;
- for (int i = 0; i < incData.vertexCount; i++)
+ for (unsigned int i = 0; i < incData.vertexCount; i++)
{
- float dot = MathDot(referenceNormal, incData.normals[i]);
+ float dot = MathVector2DotProduct(referenceNormal, incData.normals[i]);
if (dot < minDot)
{
@@ -1856,22 +1794,22 @@ static void FindIncidentFace(Vector2 *v0, Vector2 *v1, PhysicsShape ref, Physics
}
// Assign face vertices for incident face
- *v0 = Mat2MultiplyVector2(inc.transform, incData.positions[incidentFace]);
- *v0 = Vector2Add(*v0, inc.body->position);
- incidentFace = (((incidentFace + 1) < incData.vertexCount) ? (incidentFace + 1) : 0);
- *v1 = Mat2MultiplyVector2(inc.transform, incData.positions[incidentFace]);
- *v1 = Vector2Add(*v1, inc.body->position);
+ *v0 = MathMatVector2Product(inc.transform, incData.positions[incidentFace]);
+ *v0 = MathVector2Add(*v0, inc.body->position);
+ incidentFace = (((incidentFace + 1) < (int)incData.vertexCount) ? (incidentFace + 1) : 0);
+ *v1 = MathMatVector2Product(inc.transform, incData.positions[incidentFace]);
+ *v1 = MathVector2Add(*v1, inc.body->position);
}
-// Calculates clipping based on a normal and two faces
-static int Clip(Vector2 normal, float clip, Vector2 *faceA, Vector2 *faceB)
+// Returns clipping value based on a normal and two faces
+static int MathVector2Clip(Vector2 normal, Vector2 *faceA, Vector2 *faceB, float clip)
{
int sp = 0;
Vector2 out[2] = { *faceA, *faceB };
// Retrieve distances from each endpoint to the line
- float distanceA = MathDot(normal, *faceA) - clip;
- float distanceB = MathDot(normal, *faceB) - clip;
+ float distanceA = MathVector2DotProduct(normal, *faceA) - clip;
+ float distanceB = MathVector2DotProduct(normal, *faceB) - clip;
// If negative (behind plane)
if (distanceA <= 0.0f) out[sp++] = *faceA;
@@ -1883,10 +1821,10 @@ static int Clip(Vector2 normal, float clip, Vector2 *faceA, Vector2 *faceB)
// Push intersection point
float alpha = distanceA/(distanceA - distanceB);
out[sp] = *faceA;
- Vector2 delta = Vector2Subtract(*faceB, *faceA);
+ Vector2 delta = MathVector2Subtract(*faceB, *faceA);
delta.x *= alpha;
delta.y *= alpha;
- out[sp] = Vector2Add(out[sp], delta);
+ out[sp] = MathVector2Add(out[sp], delta);
sp++;
}
@@ -1897,14 +1835,8 @@ static int Clip(Vector2 normal, float clip, Vector2 *faceA, Vector2 *faceB)
return sp;
}
-// Check if values are between bias range
-static bool BiasGreaterThan(float valueA, float valueB)
-{
- return (valueA >= (valueB*0.95f + valueA*0.01f));
-}
-
// Returns the barycenter of a triangle given by 3 points
-static Vector2 TriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
+static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
{
Vector2 result = { 0.0f, 0.0f };
@@ -1914,11 +1846,10 @@ static Vector2 TriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
return result;
}
+#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
// Initializes hi-resolution MONOTONIC timer
static void InitTimer(void)
{
- srand(time(NULL)); // Initialize random seed
-
#if defined(_WIN32)
QueryPerformanceFrequency((unsigned long long int *) &frequency);
#endif
@@ -1934,12 +1865,12 @@ static void InitTimer(void)
frequency = (timebase.denom*1e9)/timebase.numer;
#endif
- baseTime = GetTimeCount(); // Get MONOTONIC clock time offset
- startTime = GetCurrentTime(); // Get current time
+ baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset
+ startTime = GetCurrentTime(); // Get current time in milliseconds
}
-// Get hi-res MONOTONIC time measure in seconds
-static unsigned long long int GetTimeCount(void)
+// Get hi-res MONOTONIC time measure in clock ticks
+static unsigned long long int GetClockTicks(void)
{
unsigned long long int value = 0;
@@ -1963,42 +1894,45 @@ static unsigned long long int GetTimeCount(void)
// Get current time in milliseconds
static double GetCurrentTime(void)
{
- return (double)(GetTimeCount() - baseTime)/frequency*1000;
+ return (double)(GetClockTicks() - baseClockTicks)/frequency*1000;
}
+#endif // !PHYSAC_AVOID_TIMMING_SYSTEM
+
// Returns the cross product of a vector and a value
-static inline Vector2 MathCross(float value, Vector2 vector)
+static inline Vector2 MathVector2Product(Vector2 vector, float value)
{
- return (Vector2){ -value*vector.y, value*vector.x };
+ Vector2 result = { -value*vector.y, value*vector.x };
+ return result;
}
// Returns the cross product of two vectors
-static inline float MathCrossVector2(Vector2 v1, Vector2 v2)
+static inline float MathVector2CrossProduct(Vector2 v1, Vector2 v2)
{
return (v1.x*v2.y - v1.y*v2.x);
}
// Returns the len square root of a vector
-static inline float MathLenSqr(Vector2 vector)
+static inline float MathVector2SqrLen(Vector2 vector)
{
return (vector.x*vector.x + vector.y*vector.y);
}
// Returns the dot product of two vectors
-static inline float MathDot(Vector2 v1, Vector2 v2)
+static inline float MathVector2DotProduct(Vector2 v1, Vector2 v2)
{
return (v1.x*v2.x + v1.y*v2.y);
}
// Returns the square root of distance between two vectors
-static inline float DistSqr(Vector2 v1, Vector2 v2)
+static inline float MathVector2SqrDistance(Vector2 v1, Vector2 v2)
{
- Vector2 dir = Vector2Subtract(v1, v2);
- return MathDot(dir, dir);
+ Vector2 dir = MathVector2Subtract(v1, v2);
+ return MathVector2DotProduct(dir, dir);
}
// Returns the normalized values of a vector
-static void MathNormalize(Vector2 *vector)
+static void MathVector2Normalize(Vector2 *vector)
{
float length, ilength;
@@ -2013,51 +1947,42 @@ static void MathNormalize(Vector2 *vector)
vector->y *= ilength;
}
-#if defined(PHYSAC_STANDALONE)
// Returns the sum of two given vectors
-static inline Vector2 Vector2Add(Vector2 v1, Vector2 v2)
+static inline Vector2 MathVector2Add(Vector2 v1, Vector2 v2)
{
- return (Vector2){ v1.x + v2.x, v1.y + v2.y };
+ Vector2 result = { v1.x + v2.x, v1.y + v2.y };
+ return result;
}
// Returns the subtract of two given vectors
-static inline Vector2 Vector2Subtract(Vector2 v1, Vector2 v2)
+static inline Vector2 MathVector2Subtract(Vector2 v1, Vector2 v2)
{
- return (Vector2){ v1.x - v2.x, v1.y - v2.y };
+ Vector2 result = { v1.x - v2.x, v1.y - v2.y };
+ return result;
}
-#endif
// Creates a matrix 2x2 from a given radians value
-static Matrix2x2 Mat2Radians(float radians)
-{
- float c = cosf(radians);
- float s = sinf(radians);
-
- return (Matrix2x2){ c, -s, s, c };
-}
-
-// Set values from radians to a created matrix 2x2
-static void Mat2Set(Matrix2x2 *matrix, float radians)
+static Matrix2x2 MathMatFromRadians(float radians)
{
float cos = cosf(radians);
float sin = sinf(radians);
- matrix->m00 = cos;
- matrix->m01 = -sin;
- matrix->m10 = sin;
- matrix->m11 = cos;
+ Matrix2x2 result = { cos, -sin, sin, cos };
+ return result;
}
// Returns the transpose of a given matrix 2x2
-static inline Matrix2x2 Mat2Transpose(Matrix2x2 matrix)
+static inline Matrix2x2 MathMatTranspose(Matrix2x2 matrix)
{
- return (Matrix2x2){ matrix.m00, matrix.m10, matrix.m01, matrix.m11 };
+ Matrix2x2 result = { matrix.m00, matrix.m10, matrix.m01, matrix.m11 };
+ return result;
}
// Multiplies a vector by a matrix 2x2
-static inline Vector2 Mat2MultiplyVector2(Matrix2x2 matrix, Vector2 vector)
+static inline Vector2 MathMatVector2Product(Matrix2x2 matrix, Vector2 vector)
{
- return (Vector2){ matrix.m00*vector.x + matrix.m01*vector.y, matrix.m10*vector.x + matrix.m11*vector.y };
+ Vector2 result = { matrix.m00*vector.x + matrix.m01*vector.y, matrix.m10*vector.x + matrix.m11*vector.y };
+ return result;
}
#endif // PHYSAC_IMPLEMENTATION