MBED port of the Physacs library

Files at this revision

API Documentation at this revision

Comitter:
jstephens78
Date:
Mon Dec 05 19:27:37 2022 +0000
Parent:
0:e39efa4f4f58
Commit message:
Update README, add MBED example

Changed in this revision

README.md Show annotated file Show diff for this revision Revisions of this file
physac.h Show annotated file Show diff for this revision Revisions of this file
diff -r e39efa4f4f58 -r ebc0214989c0 README.md
--- a/README.md	Tue Nov 29 22:42:42 2022 +0000
+++ b/README.md	Mon Dec 05 19:27:37 2022 +0000
@@ -1,5 +1,171 @@
 <img src="https://github.com/victorfisac/Physac/blob/master/icon/physac_256x256.png">
 
+# Physac-MBED
+This is a port of the Physac physics library to the MBED platform.
+
+## Resource Usage
+The following outlines are based on defaults settings described under
+[##Modifications], and can be used to gauge resource demands of using Physac-MBED:
+ - Each `PhysicsBody` requires 172 bytes of memory. Unless calling PhysicsShatter,
+   these are always generated by user.
+ - Each `PhysicsManifold` requires 56 bytes. These are generated internally during
+   collisions to represent how the PhysicsBodys are interacting.
+
+## Modifications
+The original Physac library was altered in the following ways to get running and
+to reduce footprint:
+ - `PHYSAC_MAX_BODIES` was set to 16
+ - `PHYSAC_MAX_MANIFOLDS` was set to 96
+ - `PHYSAC_MAX_VERTICES` was set to 4
+ - `PHYSAC_CIRCLE_VERTICES` was set to 12
+
+Physac-MBED can represent only collision shapes which are triangles, rectangles,
+or circles in its out-of-the-box configuration.
+
+## Using Physac
+A simple demo using Physac-MBED to simulate objects and render them to a uLCD
+display:
+```c++
+#include "mbed.h"
+#include "uLCD_4DGL.h"
+
+#define PHYSAC_NO_THREADS
+#define PHYSAC_STANDALONE
+#define PHYSAC_IMPLEMENTATION
+#define _STDBOOL_H
+#include "physac.h"
+
+uLCD_4DGL uLCD(p9,p10,p30);
+
+int main(void)
+{
+    uLCD.baudrate(BAUD_3000000);
+    wait(.05);
+
+    int screenWidth = 128;
+    int screenHeight = 128;
+    PhysicsBody floor = CreatePhysicsBodyRectangle((Vector2) {
+        screenWidth/2, screenHeight - 4
+    }, screenWidth - 2, 4, 100);
+    floor->enabled = false;             // make object static
+
+    // Defines which objects to create in the demo, and their initial properties
+    //  { x, y, density, rot, v_x, v_y }
+    const size_t objs_n = 5;
+    size_t objs_rect_n = 4;
+    float objs_init[objs_n][6] = {
+        { 48,   0,   10,   PHYSAC_PI / 4,  0,     0 },
+        { 48,   64,  10,   0,              0,     0 },
+        { 92,   0,   10,   0,              0,     0 },
+        { 80,   48,  10,   PHYSAC_PI / 4,  0,     0 },
+        { 256,  0,   30,  0,              -.75,  -.5 },
+    };
+    PhysicsBody objs[objs_n];
+
+    // Create demo objects
+    for (int i = 0; i < objs_n; i++) {
+        if (i < objs_rect_n) {
+            objs[i] = CreatePhysicsBodyRectangle((Vector2) {
+                objs_init[i][0], objs_init[i][1]
+            }, 24, 24, objs_init[i][2]);
+        } else {
+            objs[i] = CreatePhysicsBodyCircle((Vector2) {
+                objs_init[i][0], objs_init[i][1]
+            }, 12, objs_init[i][2]);
+        }
+        SetPhysicsBodyRotation(objs[i], objs_init[i][3]);
+        objs[i]->velocity.x = objs_init[i][4];
+        objs[i]->velocity.y = objs_init[i][5];
+    }
+
+    // Simulation Loop
+    Timer timer;
+    timer.start();
+
+    // Time per step in ms
+    deltaTime = 2.5;
+
+    while (true) {
+        float dt = timer.read() * 1000;
+        timer.reset();
+
+        // In this demo, rendering takes orders of magnitudes longer than
+        // physics takes to compute. So we run several steps per frame.
+        for (int i = 0; i < 8; i++) {
+            PhysicsStep();
+        }
+        float phys_time = timer.read() * 1000;
+
+        // Draw physics bodies
+        uLCD.cls();
+        int bodiesCount = GetPhysicsBodiesCount();
+        for (int i = 0; i < bodiesCount; i++) {
+            PhysicsBody body = GetPhysicsBody(i);
+
+            if (body != NULL) {
+                int vertexCount = GetPhysicsShapeVerticesCount(i);
+                for (int j = 0; j < vertexCount; j++) {
+                    // Get physics bodies shape vertices to draw lines
+                    // Note: GetPhysicsShapeVertex() already calculates rotation transformations
+                    Vector2 vertexA = GetPhysicsShapeVertex(body, j);
+
+                    int jj = (((j + 1) < vertexCount) ? (j + 1) : 0);   // Get next vertex or first to close the shape
+                    Vector2 vertexB = GetPhysicsShapeVertex(body, jj);
+
+                    uLCD.line(vertexA.x, vertexA.y, vertexB.x, vertexB.y, GREEN);     // Draw a line between two vertex positions
+                }
+            }
+        }
+        float render_time = timer.read()*1000 - phys_time;
+
+        printf("[%2.2f] Phys: %4.4f Render: %4.4f\r\n",
+                  dt,
+                  phys_time,
+                  render_time);
+    }
+
+    ClosePhysics();       // Unitialize physics
+}
+```
+
+### Use in multi-file projects:
+**Note**: the `PHYSAC_IMPLEMENTATION` macro will cause the definitions of all
+the internal functions of Physac to be included. This should **only be done once,
+from .cpp file**. For example:
+```c++
+// myheader.h
+#define PHYSAC_NO_THREADS
+#define PHYSAC_STANDALONE
+#define _STDBOOL_H
+#include "physac.h"     // this includes only the declarations
+
+------
+
+// myfile.cpp
+#include "myheader.h"
+
+#define PHYSAC_IMPLEMENTATION
+#include "physac.h"     // this includes the definitions
+```
+
+## Future work
+Possible future improvements to this port:
+
+ 1. Re-work allocation scheme so users can pre-allocate arrays of bodies and
+    manifolds
+
+ 2. Implement a partial collision reporting scheme.
+ 
+    Presently in `PhysicsStep()`, all bodies are iterated, a manifold is generated
+    for every collision, and *then* manifolds are iteratively resolved. This is
+    necessary for "correct" resolution of collisions in sequence with velocity,
+    but this requires a lot of working memory.
+    
+    A possible trade-off would be to iterate bodies only until a certain number
+    of manifolds are generated, then updating those bodies. This would reduce the
+    resource demands for large scenes, at the expense of accuracy.
+
+
 # Physac
 
 Physac is a small 2D physics engine written in pure C. The engine uses a fixed time-step thread loop to simluate physics.
@@ -7,17 +173,6 @@
 
 The header file includes some tweakable define values to fit the results that the user wants with a minimal bad results. Most of those values are commented with a little explanation about their uses.
 
-_Note: The example code uses raylib programming library to create the program window and rendering framework._
-
-Installation
------
-
-Physac requires raylib. To get it, follow the next steps:
-
-    * Go to [raylib](https://www.github.com/raysan5/raylib) and clone the repository.
-    * Ensure to pull the last changes of 'master' branch.
-    * Use code inside examples header comments to compile and execute.
-
 Physac API
 -----
 
@@ -32,7 +187,7 @@
     float angularVelocity;          // Current angular velocity applied to orient
     float torque;                   // Current angular force (reset to 0 every step)
     float orient;                   // Rotation in radians
-    float staticFriction;           // Friction when the body has not movement (0 to 1)
+    float staticFriction;           // Friction when the body has no 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
@@ -41,8 +196,8 @@
     PhysicsShape shape;             // Physics body shape information (type, radius, vertices, normals)
 } *PhysicsBody;
 ```
+
 The header contains a few customizable define values. I set the values that gived me the best results.
-
 ```c
 #define     PHYSAC_MAX_BODIES               64
 #define     PHYSAC_MAX_MANIFOLDS            4096
@@ -124,8 +279,4 @@
 
    *  stdlib.h - Memory allocation [malloc(), free(), srand(), rand()].
    *  stdio.h  - Message logging (only if PHYSAC_DEBUG is defined) [printf()].
-   *  math.h   - Math operations functions [cos(), sin(), fabs(), sqrtf()].
-
-**It is independent to any graphics engine** and prepared to use any graphics API and use the vertices information (look at examples Drawing logic) to draw lines or shapes in screen. For example, this vertices information can be use in OpenGL API glVertex2f().
-
-By the way, I use [raylib](http://www.raylib.com) to create the examples. This videogames programming library is used to handle inputs, window management and graphics drawing (using OpenGL API).
+   *  math.h   - Math operations functions [cos(), sin(), fabs(), sqrtf()].
\ No newline at end of file
diff -r e39efa4f4f58 -r ebc0214989c0 physac.h
--- a/physac.h	Tue Nov 29 22:42:42 2022 +0000
+++ b/physac.h	Mon Dec 05 19:27:37 2022 +0000
@@ -98,10 +98,10 @@
 //----------------------------------------------------------------------------------
 // Defines and Macros
 //----------------------------------------------------------------------------------
-#define     PHYSAC_MAX_BODIES               64
+#define     PHYSAC_MAX_BODIES               32
 #define     PHYSAC_MAX_MANIFOLDS            256
 #define     PHYSAC_MAX_VERTICES             4
-#define     PHYSAC_CIRCLE_VERTICES          6
+#define     PHYSAC_CIRCLE_VERTICES          12
 
 #define     PHYSAC_COLLISION_ITERATIONS     100
 #define     PHYSAC_PENETRATION_ALLOWANCE    0.05f
@@ -110,8 +110,12 @@
 #define     PHYSAC_PI                       3.14159265358979323846
 #define     PHYSAC_DEG2RAD                  (PHYSAC_PI/180.0f)
 
+#ifndef     PHYSAC_MALLOC
 #define     PHYSAC_MALLOC(size)             malloc(size)
+#endif
+#ifndef     PHYSAC_FREE
 #define     PHYSAC_FREE(ptr)                free(ptr)
+#endif
 
 //----------------------------------------------------------------------------------
 // Types and Structures Definition