/* Physac.cs * * Copyright 2020 Chris Dill * * Release under zLib License. * See LICENSE for details. */ using System; using System.Numerics; using System.Runtime.InteropServices; using System.Security; using Raylib_cs; namespace Physac_cs { public enum PhysicsShapeType { PHYSICS_CIRCLE, PHYSICS_POLYGON } // Mat2 type (used for polygon shape rotation matrix) [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Mat2 { public float m00; public float m01; public float m10; public float m11; } // @TODO Custom array marshall issue https://github.com/ChrisDill/Raylib-cs/issues/9 // Hack same as raylib.cs _MaterialMap_e_FixedBuffer // No easy way to marshall arrays of custom types. no idea why? public unsafe struct _Polygon_e_FixedBuffer { public Vector2 v0; public Vector2 v1; public Vector2 v2; public Vector2 v3; public Vector2 v4; public Vector2 v5; public Vector2 v6; public Vector2 v7; public Vector2 v8; public Vector2 v9; public Vector2 v10; public Vector2 v11; public Vector2 v12; public Vector2 v13; public Vector2 v14; public Vector2 v15; public Vector2 v16; public Vector2 v17; public Vector2 v18; public Vector2 v19; public Vector2 v20; public Vector2 v21; public Vector2 v22; public Vector2 v23; public Vector2 v24; public Vector2 this[int index] { get { fixed (Vector2* e = &v0) return e[index]; } } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct PolygonData { public uint vertexCount; // Current used vertex and normals count public _Polygon_e_FixedBuffer positions; // Polygon vertex positions vectors public _Polygon_e_FixedBuffer normals; // Polygon vertex normals vectors } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct PhysicsShape { public PhysicsShapeType type; // Physics shape type (circle or polygon) public IntPtr body; // Shape physics body reference public float radius; // Circle shape radius (used for circle shapes) public Mat2 transform; // Vertices transform matrix 2x2 public PolygonData vertexData; // Polygon shape vertices position and normals data (just used for polygon shapes) } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public partial struct PhysicsBodyData { public uint id; [MarshalAs(UnmanagedType.Bool)] public bool enabled; public Vector2 position; public Vector2 velocity; public Vector2 force; public float angularVelocity; public float torque; public float orient; public float inertia; public float inverseInertia; public float mass; public float inverseMass; public float staticFriction; public float dynamicFriction; public float restitution; [MarshalAs(UnmanagedType.Bool)] public bool useGravity; [MarshalAs(UnmanagedType.Bool)] public bool isGrounded; [MarshalAs(UnmanagedType.Bool)] public bool freezeOrient; public PhysicsShape shape; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct PhysicsManifoldData { public uint id; // Reference unique identifier public IntPtr bodyA; // Manifold first physics body reference public IntPtr bodyB; // Manifold second physics body reference public float penetration; // Depth of penetration from collision public Vector2 normal; // Normal direction vector from 'a' to 'b' public Vector2 contactsA; // Points of contact during collision public Vector2 contactsB; // Points of contact during collision public uint contactsCount; // Current collision number of contacts public float restitution; // Mixed restitution during collision public float dynamicFriction; // Mixed dynamic friction during collision public float staticFriction; // Mixed static friction during collision } [SuppressUnmanagedCodeSecurity] public static class Physac { // Used by DllImport to load the native library. public const string nativeLibName = "physac"; public const int PHYSAC_MAX_BODIES = 64; public const int PHYSAC_MAX_MANIFOLDS = 4096; public const int PHYSAC_MAX_VERTICES = 24; public const int PHYSAC_CIRCLE_VERTICES = 24; public const int PHYSAC_COLLISION_ITERATIONS = 100; public const float PHYSAC_PENETRATION_ALLOWANCE = 0.05f; public const float PHYSAC_PENETRATION_CORRECTION = 0.4f; // Initializes physics values, pointers and creates physics loop thread [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void InitPhysics(); // Run physics step, to be used if PHYSICS_NO_THREADS is set in your main loop [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void RunPhysicsStep(); // Sets physics fixed time step in milliseconds. 1.666666 by default [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void SetPhysicsTimeStep(double delta); // Returns true if physics thread is currently enabled [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern bool IsPhysicsEnabled(); // Sets physics global gravity force [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void SetPhysicsGravity(float x, float y); // Creates a new circle physics body with generic parameters // IntPtr refers to a PhysicsBodyData * [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr CreatePhysicsBodyCircle(Vector2 pos, float radius, float density); // Creates a new rectangle physics body with generic parameters // IntPtr refers to a PhysicsBodyData * [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density); // Creates a new polygon physics body with generic parameters // IntPtr refers to a PhysicsBodyData * [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density); // Adds a force to a physics body [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void PhysicsAddForce(PhysicsBodyData body, Vector2 force); // Adds an angular force to a physics body [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void PhysicsAddTorque(PhysicsBodyData body, float amount); // Shatters a polygon shape physics body to little physics bodies with explosion force [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void PhysicsShatter(PhysicsBodyData body, Vector2 position, float force); // Returns the current amount of created physics bodies [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern int GetPhysicsBodiesCount(); // Returns a physics body of the bodies pool at a specific index // IntPtr refers to a PhysicsBodyData * [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr GetPhysicsBody(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON) [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern int GetPhysicsShapeType(int index); // Returns the amount of vertices of a physics body shape [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern int GetPhysicsShapeVerticesCount(int index); // Returns transformed position of a body shape (body position + vertex transformed position) [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern Vector2 GetPhysicsShapeVertex(PhysicsBodyData body, int vertex); // Sets physics body shape transform based on radians parameter [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void SetPhysicsBodyRotation(PhysicsBodyData body, float radians); // Unitializes and destroy a physics body [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void DestroyPhysicsBody(PhysicsBodyData body); // Destroys created physics bodies and manifolds and resets global values [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void ResetPhysics(); // Unitializes physics pointers and closes physics loop thread [DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] public static extern void ClosePhysics(); } }