diff --git a/examples/physics_demo.lua b/examples/physics_demo.lua new file mode 100644 index 0000000..47fa09f --- /dev/null +++ b/examples/physics_demo.lua @@ -0,0 +1,87 @@ +local ffi = require "ffi" + +local screenWidth = 800 +local screenHeight = 450 + +rl.SetConfigFlags(rl.FLAG_MSAA_4X_HINT) + +rl.InitWindow(screenWidth, screenHeight, "Physac [raylib-lua] - Physics demo") +local logoX = screenWidth - rl.MeasureText("Physac", 30) - 10 +local logoY = 15 + +local needsReset = false + +rl.InitPhysics() + +local floor = rl.CreatePhysicsBodyRectangle({ screenWidth/2, screenHeight }, 500, 100, 10) +floor.enabled = false + +local circle = rl.CreatePhysicsBodyCircle({ screenWidth/2, screenHeight/2 }, 45, 10) +circle.enabled = false + +rl.SetTargetFPS(60) + +while not rl.WindowShouldClose() do + rl.RunPhysicsStep() + + if needsReset then + floor = rl.CreatePhysicsBodyRectangle({ screenWidth/2, screenHeight }, 500, 100, 10) + circle = rl.CreatePhysicsBodyCircle({ screenWidth/2, screenHeight/2 }, 45, 10) + + floor.enabled = false + circle.enabled = false + + needsReset = false + end + + if rl.IsKeyPressed(string.byte("R")) then + rl.ResetPhysics() + needsReset = true + end + + if rl.IsMouseButtonPressed(rl.MOUSE_LEFT_BUTTON) then + rl.CreatePhysicsBodyPolygon(rl.GetMousePosition(), rl.GetRandomValue(20, 80), rl.GetRandomValue(3, 8), 10); + elseif rl.IsMouseButtonPressed(rl.MOUSE_RIGHT_BUTTON) then + rl.CreatePhysicsBodyCircle(rl.GetMousePosition(), rl.GetRandomValue(10, 45), 10) + end + + local bodiesCount = rl.GetPhysicsBodiesCount() + + for i=0,bodiesCount do + local body = rl.GetPhysicsBody(i) + + if body ~= nil and (body.position.y > screenHeight*2) then + print("Destroyed " .. tostring(body)) + rl.DestroyPhysicsBody(body) + end + end + + rl.BeginDrawing() + rl.ClearBackground(rl.BLACK) + + bodiesCount = rl.GetPhysicsBodiesCount() + for i=0,bodiesCount-1 do + local body = rl.GetPhysicsBody(i) + + if body ~= nil then + local vertexCount = rl.GetPhysicsShapeVerticesCount(i) + for j=0,vertexCount-1 do + local vertexA = rl.GetPhysicsShapeVertex(body, j); + + local jj = ((j + 1) < vertexCount) and (j + 1) or 0 + local vertexB = rl.GetPhysicsShapeVertex(body, jj); + + rl.DrawLineV(vertexA, vertexB, rl.GREEN) + end + end + end + + rl.DrawText("Left mouse button to create a polygon", 10, 10, 10, rl.WHITE); + rl.DrawText("Right mouse button to create a circle", 10, 25, 10, rl.WHITE); + rl.DrawText("Press 'R' to reset example", 10, 40, 10, rl.WHITE); + + rl.DrawText("Physac", logoX, logoY, 30, rl.WHITE); + rl.DrawText("Powered by", logoX + 50, logoY - 7, 10, rl.WHITE); + + rl.EndDrawing() +end \ No newline at end of file diff --git a/makefile b/makefile index 48d1284..88a9a94 100644 --- a/makefile +++ b/makefile @@ -7,6 +7,8 @@ LUA ?= luajit CFLAGS += -Iluajit/src -Iraylib/src LDFLAGS += -Lluajit/src -lluajit -Lraylib/src -lraylib +MODULES := rlgl physac + ifeq ($(OS),Windows_NT) LDFLAGS += -lopengl32 -lgdi32 -lwinmm -static endif @@ -40,7 +42,7 @@ src/autogen/boot.c: src/raylib.lua src/raylua.lua $(LUA) tools/lua2str.lua $@ raylua_boot_lua $^ src/autogen/bind.c: - $(LUA) tools/genbind.lua $@ + $(LUA) tools/genbind.lua $@ $(MODULES) src/autogen/builder.c: src/raylua_builder.lua $(LUA) tools/lua2str.lua $@ raylua_builder_lua $^ diff --git a/src/raylib.lua b/src/raylib.lua index ef6bd83..b8b09d2 100644 --- a/src/raylib.lua +++ b/src/raylib.lua @@ -594,6 +594,58 @@ ffi.cdef [[ typedef void (*TraceLogCallback)(int logType, const char *text, va_list args); ]] +-- Physac cdef +ffi.cdef [[ + typedef struct PhysicsBodyData *PhysicsBody; + typedef enum PhysicsShapeType { + PHYSICS_CIRCLE, + PHYSICS_POLYGON + } PhysicsShapeType; + + typedef struct Matrix2x2 { + float m00; + float m01; + float m10; + float m11; + } Matrix2x2; + + typedef struct PolygonData { + unsigned int vertexCount; + Vector2 positions[24]; + Vector2 normals[24]; + } PolygonData; + + typedef struct PhysicsShape { + PhysicsShapeType type; + PhysicsBody body; + float radius; + Matrix2x2 transform; + PolygonData vertexData; + } PhysicsShape; + + typedef struct PhysicsBodyData { + unsigned int id; + bool enabled; + Vector2 position; + Vector2 velocity; + Vector2 force; + float angularVelocity; + float torque; + float orient; + float inertia; + float inverseInertia; + float mass; + float inverseMass; + float staticFriction; + float dynamicFriction; + float restitution; + bool useGravity; + bool isGrounded; + bool freezeOrient; + PhysicsShape shape; + } PhysicsBodyData; +]] + -- Load bind entry ffi.cdef [[ struct raylua_bind_entry { diff --git a/src/raylua.c b/src/raylua.c index 7cb687e..dc13a24 100644 --- a/src/raylua.c +++ b/src/raylua.c @@ -19,6 +19,12 @@ #include #include +#include + +#define PHYSAC_IMPLEMENTATION +#define PHYSAC_NO_THREADS +#include + #include "autogen/bind.c" #include "autogen/boot.c" diff --git a/tools/genbind.lua b/tools/genbind.lua index 400e9ff..3cdd1a4 100644 --- a/tools/genbind.lua +++ b/tools/genbind.lua @@ -13,48 +13,80 @@ local structs = { "Material", "Model", "Transform", "BoneInfo", "ModelAnimation", "Ray", "RayHitInfo", "BoundingBox", "Wave", "Sound", "Music", "AudioStream", "VrDeviceInfo", "Camera3D", "RenderTexture2D", - "TextureCubemap", "TraceLogCallback" + "TextureCubemap", "TraceLogCallback", "PhysicsBody" } local functions = {} local proto = {} -for line in io.lines "tools/api.h" do - line = line:gsub("(%W)([%l%d]%w*)", function (before, part) - for i,keyword in ipairs(keywords) do - if part == keyword then - return before .. part +local counter = 0 + +local custom_support = { + ["rlgl"] = function (line) + return line:gsub("[%s*]+(rl%w+)", function (part) + functions[#functions + 1] = part + counter = counter + 1 + + if counter == 2 then + print("WARN: Multiple matches for: " .. line) end - end - return before - end) + return "(*)" + end) + end +} - local count = 0 +local file = io.open(arg[1], "wb") +local modules = { "api" } - line = line:gsub("%u%w+", function (part) - for i,struct in ipairs(structs) do - if part == struct then - return part - end - end - - functions[#functions + 1] = part - count = count + 1 - - if count == 2 then - print("WARN: Multiple match for: " .. line) - end - - return "(*)" - end) - - proto[#proto + 1] = line:gsub(";", "") +for i=2,#arg do + modules[i] = arg[i] end -assert(#proto == #functions, "Mismatching proto and function count.") +for _,modname in ipairs(modules) do + for line in io.lines("tools/" .. modname .. ".h") do + if custom_support[modname] then + line = custom_support[modname](line) + end + + line = line:gsub("(%W)([%l%d][%w_]*)", function (before, part) + for i,keyword in ipairs(keywords) do + if part == keyword then + return before .. part + end + end + + return before + end) + + line = line:gsub("%u%w+", function (part) + for i,struct in ipairs(structs) do + if part == struct then + return part + end + end + + functions[#functions + 1] = part + counter = counter + 1 + + if count == 2 then + print("WARN: Multiple matches for: " .. line) + end + + return "(*)" + end) + + -- Strip spaces + line = line:gsub("([(),*.]) +(%w)", function (a, b) return a .. b end) + line = line:gsub("(%w) +([(),*.])", function (a, b) return a .. b end) + + proto[#proto + 1] = line:gsub(";", "") + end +end + +assert(#proto == #functions, "Mismatching proto and function count : " .. + #proto .. " ~= " .. #functions) -local file = io.open(arg[1], "w") file:write [[ struct raylua_bind_entry { const char *name; diff --git a/tools/physac.h b/tools/physac.h new file mode 100644 index 0000000..be03018 --- /dev/null +++ b/tools/physac.h @@ -0,0 +1,20 @@ +void InitPhysics(void); +void RunPhysicsStep(void); +void SetPhysicsTimeStep(double delta); +bool IsPhysicsEnabled(void); +void SetPhysicsGravity(float x, float y); +PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density); +PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density); +PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density); +void PhysicsAddForce(PhysicsBody body, Vector2 force); +void PhysicsAddTorque(PhysicsBody body, float amount); +void PhysicsShatter(PhysicsBody body, Vector2 position, float force); +int GetPhysicsBodiesCount(void); +PhysicsBody GetPhysicsBody(int index); +int GetPhysicsShapeType(int index); +int GetPhysicsShapeVerticesCount(int index); +Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); +void SetPhysicsBodyRotation(PhysicsBody body, float radians); +void DestroyPhysicsBody(PhysicsBody body); +void ResetPhysics(void); +void ClosePhysics(void); diff --git a/tools/rlgl.h b/tools/rlgl.h new file mode 100644 index 0000000..18d463b --- /dev/null +++ b/tools/rlgl.h @@ -0,0 +1,69 @@ +void rlMatrixMode(int mode); +void rlPushMatrix(void); +void rlPopMatrix(void); +void rlLoadIdentity(void); +void rlTranslatef(float x, float y, float z); +void rlRotatef(float angleDeg, float x, float y, float z); +void rlScalef(float x, float y, float z); +void rlMultMatrixf(float *matf); +void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar); +void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar); +void rlViewport(int x, int y, int width, int height); +void rlBegin(int mode); +void rlEnd(void); +void rlVertex2i(int x, int y); +void rlVertex2f(float x, float y); +void rlVertex3f(float x, float y, float z); +void rlTexCoord2f(float x, float y); +void rlNormal3f(float x, float y, float z); +void rlColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a); +void rlColor3f(float x, float y, float z); +void rlColor4f(float x, float y, float z, float w); +void rlEnableTexture(unsigned int id); +void rlDisableTexture(void); +void rlTextureParameters(unsigned int id, int param, int value); +void rlEnableRenderTexture(unsigned int id); +void rlDisableRenderTexture(void); +void rlEnableDepthTest(void); +void rlDisableDepthTest(void); +void rlEnableBackfaceCulling(void); +void rlDisableBackfaceCulling(void); +void rlEnableScissorTest(void); +void rlDisableScissorTest(void); +void rlScissor(int x, int y, int width, int height); +void rlEnableWireMode(void); +void rlDisableWireMode(void); +void rlDeleteTextures(unsigned int id); +void rlDeleteRenderTextures(RenderTexture2D target); +void rlDeleteShader(unsigned int id); +void rlDeleteVertexArrays(unsigned int id); +void rlDeleteBuffers(unsigned int id); +void rlClearColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a); +void rlClearScreenBuffers(void); +void rlUpdateBuffer(int bufferId, void *data, int dataSize); +unsigned int rlLoadAttribBuffer(unsigned int vaoId, int shaderLoc, void *buffer, int size, bool dynamic); +void rlglInit(int width, int height); +void rlglClose(void); +void rlglDraw(void); +int rlGetVersion(void); +bool rlCheckBufferLimit(int vCount); +void rlSetDebugMarker(const char *text); +void rlLoadExtensions(void *loader); +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); +unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); +unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderBuffer); +unsigned int rlLoadTextureCubemap(void *data, int size, int format); +void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data); +void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); +void rlUnloadTexture(unsigned int id); +void rlGenerateMipmaps(Texture2D *texture); +void *rlReadTexturePixels(Texture2D texture); +unsigned char *rlReadScreenPixels(int width, int height); +RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depthBits, bool useDepthTexture); +void rlRenderTextureAttach(RenderTexture target, unsigned int id, int attachType); +bool rlRenderTextureComplete(RenderTexture target); +void rlLoadMesh(Mesh *mesh, bool dynamic); +void rlUpdateMesh(Mesh mesh, int buffer, int num); +void rlUpdateMeshAt(Mesh mesh, int buffer, int num, int index); +void rlDrawMesh(Mesh mesh, Material material, Matrix transform); +void rlUnloadMesh(Mesh mesh);