mirror of
https://github.com/bjornbytes/lovr.git
synced 2024-07-08 15:13:35 +00:00
Add contact callback and Contact object;
This commit is contained in:
parent
bee947a1d0
commit
979dd044d8
|
@ -559,6 +559,7 @@ if(LOVR_ENABLE_PHYSICS)
|
|||
target_sources(lovr PRIVATE
|
||||
src/api/l_physics.c
|
||||
src/api/l_physics_collider.c
|
||||
src/api/l_physics_contact.c
|
||||
src/api/l_physics_joints.c
|
||||
src/api/l_physics_shapes.c
|
||||
src/api/l_physics_world.c
|
||||
|
|
2
deps/jolt-physics-sharp
vendored
2
deps/jolt-physics-sharp
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 5b9a9d94fb178bf5b45875f30321da624b19ffdc
|
||||
Subproject commit 54a8f950dd55809979dc670097fa25de14723f5d
|
|
@ -307,6 +307,7 @@ static const luaL_Reg lovrPhysics[] = {
|
|||
|
||||
extern const luaL_Reg lovrWorld[];
|
||||
extern const luaL_Reg lovrCollider[];
|
||||
extern const luaL_Reg lovrContact[];
|
||||
extern const luaL_Reg lovrBoxShape[];
|
||||
extern const luaL_Reg lovrSphereShape[];
|
||||
extern const luaL_Reg lovrCapsuleShape[];
|
||||
|
@ -327,6 +328,7 @@ int luaopen_lovr_physics(lua_State* L) {
|
|||
luax_register(L, lovrPhysics);
|
||||
luax_registertype(L, World);
|
||||
luax_registertype(L, Collider);
|
||||
luax_registertype(L, Contact);
|
||||
luax_registertype(L, BoxShape);
|
||||
luax_registertype(L, SphereShape);
|
||||
luax_registertype(L, CapsuleShape);
|
||||
|
|
128
src/api/l_physics_contact.c
Normal file
128
src/api/l_physics_contact.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include "api.h"
|
||||
#include "physics/physics.h"
|
||||
#include "util.h"
|
||||
|
||||
static int l_lovrContactGetColliders(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
Collider* a = lovrContactGetColliderA(contact);
|
||||
Collider* b = lovrContactGetColliderB(contact);
|
||||
luax_pushtype(L, Collider, a);
|
||||
luax_pushtype(L, Collider, b);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetShapes(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
Shape* a = lovrContactGetShapeA(contact);
|
||||
Shape* b = lovrContactGetShapeB(contact);
|
||||
luax_pushshape(L, a);
|
||||
luax_pushshape(L, b);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetNormal(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float normal[3];
|
||||
lovrContactGetNormal(contact, normal);
|
||||
lua_pushnumber(L, normal[0]);
|
||||
lua_pushnumber(L, normal[1]);
|
||||
lua_pushnumber(L, normal[2]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetPenetration(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float penetration = lovrContactGetPenetration(contact);
|
||||
lua_pushnumber(L, penetration);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetPoints(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
uint32_t count = lovrContactGetPointCount(contact);
|
||||
lua_checkstack(L, count * 3);
|
||||
float point[3];
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
lovrContactGetPoint(contact, i, point);
|
||||
lua_pushnumber(L, point[0]);
|
||||
lua_pushnumber(L, point[1]);
|
||||
lua_pushnumber(L, point[2]);
|
||||
}
|
||||
return count * 3;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetFriction(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float friction = lovrContactGetFriction(contact);
|
||||
lua_pushnumber(L, friction);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrContactSetFriction(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float friction = luax_checkfloat(L, 2);
|
||||
lovrContactSetFriction(contact, friction);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetRestitution(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float restitution = lovrContactGetRestitution(contact);
|
||||
lua_pushnumber(L, restitution);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrContactSetRestitution(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float restitution = luax_checkfloat(L, 2);
|
||||
lovrContactSetRestitution(contact, restitution);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrContactIsEnabled(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
bool enabled = lovrContactIsEnabled(contact);
|
||||
lua_pushboolean(L, enabled);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrContactSetEnabled(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
lovrContactSetEnabled(contact, lua_toboolean(L, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrContactGetSurfaceVelocity(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float velocity[3];
|
||||
lovrContactGetSurfaceVelocity(contact, velocity);
|
||||
lua_pushnumber(L, velocity[0]);
|
||||
lua_pushnumber(L, velocity[1]);
|
||||
lua_pushnumber(L, velocity[2]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int l_lovrContactSetSurfaceVelocity(lua_State* L) {
|
||||
Contact* contact = luax_checktype(L, 1, Contact);
|
||||
float velocity[3];
|
||||
luax_readvec3(L, 2, velocity, NULL);
|
||||
lovrContactSetSurfaceVelocity(contact, velocity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrContact[] = {
|
||||
{ "getColliders", l_lovrContactGetColliders },
|
||||
{ "getShapes", l_lovrContactGetShapes },
|
||||
{ "getNormal", l_lovrContactGetNormal },
|
||||
{ "getPenetration", l_lovrContactGetPenetration },
|
||||
{ "getPoints", l_lovrContactGetPoints },
|
||||
{ "getFriction", l_lovrContactGetFriction },
|
||||
{ "setFriction", l_lovrContactSetFriction },
|
||||
{ "getRestitution", l_lovrContactGetRestitution },
|
||||
{ "setRestitution", l_lovrContactSetRestitution },
|
||||
{ "isEnabled", l_lovrContactIsEnabled },
|
||||
{ "setEnabled", l_lovrContactSetEnabled },
|
||||
{ "getSurfaceVelocity", l_lovrContactGetSurfaceVelocity },
|
||||
{ "setSurfaceVelocity", l_lovrContactSetSurfaceVelocity },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -72,6 +72,64 @@ static void queryNoCallback(void* userdata, Collider* collider) {
|
|||
*((Collider**) userdata) = collider;
|
||||
}
|
||||
|
||||
static bool filterCallback(void* userdata, World* world, Collider* a, Collider* b) {
|
||||
lua_State* L = userdata;
|
||||
luax_pushstash(L, "lovr.world.filter");
|
||||
luax_pushtype(L, World, world);
|
||||
lua_rawget(L, -2);
|
||||
lua_remove(L, -2);
|
||||
luax_pushtype(L, Collider, a);
|
||||
luax_pushtype(L, Collider, b);
|
||||
if (lua_pcall(L, 2, 1, 0)) {
|
||||
lua_settop(L, 3); // Only keep first error
|
||||
} else {
|
||||
bool accept = lua_type(L, -1) != LUA_TBOOLEAN || lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return accept;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void enterCallback(void* userdata, World* world, Collider* a, Collider* b) {
|
||||
lua_State* L = userdata;
|
||||
luax_pushstash(L, "lovr.world.enter");
|
||||
luax_pushtype(L, World, world);
|
||||
lua_rawget(L, -2);
|
||||
lua_remove(L, -2);
|
||||
luax_pushtype(L, Collider, a);
|
||||
luax_pushtype(L, Collider, b);
|
||||
if (lua_pcall(L, 2, 0, 0)) {
|
||||
lua_settop(L, 3); // Only keep first error
|
||||
}
|
||||
}
|
||||
|
||||
static void exitCallback(void* userdata, World* world, Collider* a, Collider* b) {
|
||||
lua_State* L = userdata;
|
||||
luax_pushstash(L, "lovr.world.exit");
|
||||
luax_pushtype(L, World, world);
|
||||
lua_rawget(L, -2);
|
||||
lua_remove(L, -2);
|
||||
luax_pushtype(L, Collider, a);
|
||||
luax_pushtype(L, Collider, b);
|
||||
if (lua_pcall(L, 2, 0, 0)) {
|
||||
lua_settop(L, 3); // Only keep first error
|
||||
}
|
||||
}
|
||||
|
||||
static void contactCallback(void* userdata, World* world, Collider* a, Collider* b, Contact* contact) {
|
||||
lua_State* L = userdata;
|
||||
luax_pushstash(L, "lovr.world.contact");
|
||||
luax_pushtype(L, World, world);
|
||||
lua_rawget(L, -2);
|
||||
lua_remove(L, -2);
|
||||
luax_pushtype(L, Collider, a);
|
||||
luax_pushtype(L, Collider, b);
|
||||
luax_pushtype(L, Contact, contact);
|
||||
if (lua_pcall(L, 3, 0, 0)) {
|
||||
lua_settop(L, 3); // Only keep first error
|
||||
}
|
||||
}
|
||||
|
||||
static int l_lovrWorldNewCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
float position[3];
|
||||
|
@ -242,7 +300,11 @@ static int l_lovrWorldSetGravity(lua_State* L) {
|
|||
static int l_lovrWorldUpdate(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
float dt = luax_checkfloat(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lovrWorldUpdate(world, dt);
|
||||
if (lua_type(L, 3) == LUA_TSTRING) {
|
||||
lua_error(L);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -473,6 +535,86 @@ static int l_lovrWorldSetSleepingAllowed(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrWorldGetCallbacks(lua_State* L) {
|
||||
luax_checktype(L, 1, World);
|
||||
lua_settop(L, 1);
|
||||
lua_createtable(L, 0, 3);
|
||||
|
||||
luax_pushstash(L, "lovr.world.filter");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawget(L, -2);
|
||||
lua_setfield(L, 2, "filter");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_pushstash(L, "lovr.world.enter");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawget(L, -2);
|
||||
lua_setfield(L, 2, "enter");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_pushstash(L, "lovr.world.exit");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawget(L, -2);
|
||||
lua_setfield(L, 2, "exit");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_pushstash(L, "lovr.world.contact");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_rawget(L, -2);
|
||||
lua_setfield(L, 2, "exit");
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrWorldSetCallbacks(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
lovrWorldSetCallbacks(world, &(WorldCallbacks) { 0 });
|
||||
return 0;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
|
||||
luax_pushstash(L, "lovr.world.filter");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_getfield(L, 2, "filter");
|
||||
bool filter = lua_type(L, -1) == LUA_TFUNCTION;
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_pushstash(L, "lovr.world.enter");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_getfield(L, 2, "enter");
|
||||
bool enter = lua_type(L, -1) == LUA_TFUNCTION;
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_pushstash(L, "lovr.world.exit");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_getfield(L, 2, "exit");
|
||||
bool exit = lua_type(L, -1) == LUA_TFUNCTION;
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
|
||||
luax_pushstash(L, "lovr.world.contact");
|
||||
lua_pushvalue(L, 1);
|
||||
lua_getfield(L, 2, "contact");
|
||||
bool contact = lua_type(L, -1) == LUA_TFUNCTION;
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lovrWorldSetCallbacks(world, &(WorldCallbacks) {
|
||||
.filter = filter ? filterCallback : NULL,
|
||||
.enter = enter ? enterCallback : NULL,
|
||||
.exit = exit ? exitCallback : NULL,
|
||||
.contact = contact ? contactCallback : NULL,
|
||||
.userdata = L
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrWorldGetStepCount(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
int iterations = lovrWorldGetStepCount(world);
|
||||
|
@ -513,6 +655,8 @@ const luaL_Reg lovrWorld[] = {
|
|||
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
|
||||
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
|
||||
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
|
||||
{ "getCallbacks", l_lovrWorldGetCallbacks },
|
||||
{ "setCallbacks", l_lovrWorldSetCallbacks },
|
||||
|
||||
// Deprecated
|
||||
{ "getTightness", l_lovrWorldGetTightness },
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
typedef struct World World;
|
||||
typedef struct Collider Collider;
|
||||
typedef struct Contact Contact;
|
||||
typedef struct Shape Shape;
|
||||
typedef struct Joint Joint;
|
||||
|
||||
|
@ -34,6 +35,14 @@ void lovrPhysicsDestroy(void);
|
|||
|
||||
// World
|
||||
|
||||
typedef struct {
|
||||
bool (*filter)(void* userdata, World* world, Collider* a, Collider* b);
|
||||
void (*enter)(void* userdata, World* world, Collider* a, Collider* b);
|
||||
void (*exit)(void* userdata, World* world, Collider* a, Collider* b);
|
||||
void (*contact)(void* userdata, World* world, Collider* a, Collider* b, Contact* contact);
|
||||
void* userdata;
|
||||
} WorldCallbacks;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tickRate;
|
||||
uint32_t tickLimit;
|
||||
|
@ -85,6 +94,7 @@ bool lovrWorldQuerySphere(World* world, float position[3], float radius, uint32_
|
|||
void lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||
void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||
bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag2);
|
||||
void lovrWorldSetCallbacks(World* world, WorldCallbacks* callbacks);
|
||||
|
||||
// Deprecated
|
||||
int lovrWorldGetStepCount(World* world);
|
||||
|
@ -167,6 +177,26 @@ void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float point
|
|||
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float point[3], float velocity[3]);
|
||||
void lovrColliderGetAABB(Collider* collider, float aabb[6]);
|
||||
|
||||
// Contact
|
||||
|
||||
Collider* lovrContactGetColliderA(Contact* contact);
|
||||
Collider* lovrContactGetColliderB(Contact* contact);
|
||||
Shape* lovrContactGetShapeA(Contact* contact);
|
||||
Shape* lovrContactGetShapeB(Contact* contact);
|
||||
void lovrContactGetNormal(Contact* contact, float normal[3]);
|
||||
float lovrContactGetPenetration(Contact* contact);
|
||||
uint32_t lovrContactGetPointCount(Contact* contact);
|
||||
void lovrContactGetPoint(Contact* contact, uint32_t index, float point[3]);
|
||||
float lovrContactGetFriction(Contact* contact);
|
||||
void lovrContactSetFriction(Contact* contact, float friction);
|
||||
float lovrContactGetRestitution(Contact* contact);
|
||||
void lovrContactSetRestitution(Contact* contact, float restitution);
|
||||
bool lovrContactIsEnabled(Contact* contact);
|
||||
void lovrContactSetEnabled(Contact* contact, bool enable);
|
||||
void lovrContactGetSurfaceVelocity(Contact* contact, float velocity[3]);
|
||||
void lovrContactSetSurfaceVelocity(Contact* contact, float velocity[3]);
|
||||
void lovrContactDestroy(void* ref);
|
||||
|
||||
// Shapes
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -5,17 +5,27 @@
|
|||
#include <threads.h>
|
||||
#include <joltc.h>
|
||||
|
||||
struct Contact {
|
||||
Collider* colliderA;
|
||||
Collider* colliderB;
|
||||
const JPH_ContactManifold* manifold;
|
||||
JPH_ContactSettings* settings;
|
||||
};
|
||||
|
||||
struct World {
|
||||
uint32_t ref;
|
||||
JPH_PhysicsSystem* system;
|
||||
JPH_BodyInterface* bodies;
|
||||
JPH_BodyActivationListener* activationListener;
|
||||
JPH_ObjectLayerPairFilter* objectLayerPairFilter;
|
||||
JPH_ContactListener* listener;
|
||||
Contact contact;
|
||||
Collider* colliders;
|
||||
Collider** activeColliders;
|
||||
uint32_t activeColliderCount;
|
||||
Joint* joints;
|
||||
uint32_t jointCount;
|
||||
WorldCallbacks callbacks;
|
||||
float defaultLinearDamping;
|
||||
float defaultAngularDamping;
|
||||
bool defaultIsSleepingAllowed;
|
||||
|
@ -156,6 +166,63 @@ static void onSleep(void* arg, JPH_BodyID id, uint64_t userData) {
|
|||
mtx_unlock(&world->lock);
|
||||
}
|
||||
|
||||
static JPH_ValidateResult onContactValidate(void* userdata, const JPH_Body* body1, const JPH_Body* body2, const JPH_RVec3* offset, const JPH_CollideShapeResult* result) {
|
||||
World* world = userdata;
|
||||
Collider* a = (Collider*) (uintptr_t) JPH_Body_GetUserData((JPH_Body*) body1);
|
||||
Collider* b = (Collider*) (uintptr_t) JPH_Body_GetUserData((JPH_Body*) body2);
|
||||
bool accept = world->callbacks.filter(world->callbacks.userdata, world, a, b);
|
||||
return accept ?
|
||||
JPH_ValidateResult_AcceptAllContactsForThisBodyPair :
|
||||
JPH_ValidateResult_RejectAllContactsForThisBodyPair;
|
||||
}
|
||||
|
||||
static void onContactPersisted(void* userdata, const JPH_Body* body1, const JPH_Body* body2, const JPH_ContactManifold* manifold, JPH_ContactSettings* settings) {
|
||||
World* world = userdata;
|
||||
JPH_BodyID id1 = JPH_Body_GetID(body1);
|
||||
JPH_BodyID id2 = JPH_Body_GetID(body2);
|
||||
if (world->callbacks.contact) {
|
||||
Collider* a = (Collider*) (uintptr_t) JPH_Body_GetUserData((JPH_Body*) body1);
|
||||
Collider* b = (Collider*) (uintptr_t) JPH_Body_GetUserData((JPH_Body*) body2);
|
||||
mtx_lock(&world->lock);
|
||||
world->contact.colliderA = a;
|
||||
world->contact.colliderB = b;
|
||||
world->contact.manifold = manifold;
|
||||
world->contact.settings = settings;
|
||||
world->callbacks.contact(world->callbacks.userdata, world, a, b, &world->contact);
|
||||
mtx_unlock(&world->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void onContactAdded(void* userdata, const JPH_Body* body1, const JPH_Body* body2, const JPH_ContactManifold* manifold, JPH_ContactSettings* settings) {
|
||||
World* world = userdata;
|
||||
JPH_BodyID id1 = JPH_Body_GetID(body1);
|
||||
JPH_BodyID id2 = JPH_Body_GetID(body2);
|
||||
|
||||
if (world->callbacks.enter && !JPH_PhysicsSystem_WereBodiesInContact(world->system, id1, id2)) {
|
||||
Collider* a = (Collider*) (uintptr_t) JPH_Body_GetUserData((JPH_Body*) body1);
|
||||
Collider* b = (Collider*) (uintptr_t) JPH_Body_GetUserData((JPH_Body*) body2);
|
||||
mtx_lock(&world->lock);
|
||||
world->callbacks.enter(world->callbacks.userdata, world, a, b);
|
||||
mtx_unlock(&world->lock);
|
||||
}
|
||||
|
||||
onContactPersisted(userdata, body1, body2, manifold, settings);
|
||||
}
|
||||
|
||||
static void onContactRemoved(void* userdata, const JPH_SubShapeIDPair* pair) {
|
||||
World* world = userdata;
|
||||
if (!JPH_PhysicsSystem_WereBodiesInContact(world->system, pair->Body1ID, pair->Body2ID)) {
|
||||
JPH_BodyInterface* bodies = JPH_PhysicsSystem_GetBodyInterfaceNoLock(world->system);
|
||||
Collider* a = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(bodies, pair->Body1ID);
|
||||
Collider* b = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(bodies, pair->Body2ID);
|
||||
if (a && b) {
|
||||
mtx_lock(&world->lock);
|
||||
world->callbacks.exit(world->callbacks.userdata, world, a, b);
|
||||
mtx_unlock(&world->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool lovrPhysicsInit(void) {
|
||||
if (state.initialized) return false;
|
||||
JPH_Init(32 * 1024 * 1024);
|
||||
|
@ -273,6 +340,7 @@ void lovrWorldDestroyData(World* world) {
|
|||
lovrColliderDestroyData(collider);
|
||||
world->colliders = next;
|
||||
}
|
||||
if (world->listener) JPH_ContactListener_Destroy(world->listener);
|
||||
JPH_PhysicsSystem_Destroy(world->system);
|
||||
JPH_BodyActivationListener_Destroy(world->activationListener);
|
||||
}
|
||||
|
@ -574,6 +642,26 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
|
|||
return JPH_ObjectLayerPairFilterTable_ShouldCollide(world->objectLayerPairFilter, i, j);
|
||||
}
|
||||
|
||||
void lovrWorldSetCallbacks(World* world, WorldCallbacks* callbacks) {
|
||||
if (!callbacks || (!callbacks->filter && !callbacks->enter && !callbacks->exit && !callbacks->contact)) {
|
||||
JPH_PhysicsSystem_SetContactListener(world->system, NULL);
|
||||
} else {
|
||||
if (!world->listener) {
|
||||
world->listener = JPH_ContactListener_Create();
|
||||
}
|
||||
|
||||
JPH_ContactListener_SetProcs(world->listener, (JPH_ContactListener_Procs) {
|
||||
.OnContactValidate = callbacks->filter ? onContactValidate : NULL,
|
||||
.OnContactAdded = (callbacks->enter || callbacks->contact) ? onContactAdded : NULL,
|
||||
.OnContactPersisted = callbacks->contact ? onContactPersisted : NULL,
|
||||
.OnContactRemoved = callbacks->exit ? onContactRemoved : NULL
|
||||
}, world);
|
||||
|
||||
world->callbacks = *callbacks;
|
||||
JPH_PhysicsSystem_SetContactListener(world->system, world->listener);
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
int lovrWorldGetStepCount(World* world) { return world->collisionSteps; }
|
||||
void lovrWorldSetStepCount(World* world, int iterations) { world->collisionSteps = iterations;}
|
||||
|
@ -1151,6 +1239,82 @@ void lovrColliderGetAABB(Collider* collider, float aabb[6]) {
|
|||
aabb[5] = box.max.z;
|
||||
}
|
||||
|
||||
// Contact
|
||||
|
||||
Collider* lovrContactGetColliderA(Contact* contact) {
|
||||
return contact->colliderA;
|
||||
}
|
||||
|
||||
Collider* lovrContactGetColliderB(Contact* contact) {
|
||||
return contact->colliderB;
|
||||
}
|
||||
|
||||
Shape* lovrContactGetShapeA(Contact* contact) {
|
||||
return subshapeToShape(contact->colliderA, JPH_ContactManifold_GetSubShapeID1(contact->manifold));
|
||||
}
|
||||
|
||||
Shape* lovrContactGetShapeB(Contact* contact) {
|
||||
return subshapeToShape(contact->colliderB, JPH_ContactManifold_GetSubShapeID2(contact->manifold));
|
||||
}
|
||||
|
||||
void lovrContactGetNormal(Contact* contact, float normal[3]) {
|
||||
JPH_Vec3 n;
|
||||
JPH_ContactManifold_GetWorldSpaceNormal(contact->manifold, &n);
|
||||
vec3_fromJolt(normal, &n);
|
||||
}
|
||||
|
||||
float lovrContactGetPenetration(Contact* contact) {
|
||||
return JPH_ContactManifold_GetPenetrationDepth(contact->manifold);
|
||||
}
|
||||
|
||||
uint32_t lovrContactGetPointCount(Contact* contact) {
|
||||
return JPH_ContactManifold_GetPointCount(contact->manifold);
|
||||
}
|
||||
|
||||
void lovrContactGetPoint(Contact* contact, uint32_t index, float point[3]) {
|
||||
JPH_Vec3 p;
|
||||
JPH_ContactManifold_GetWorldSpaceContactPointOn2(contact->manifold, index, &p);
|
||||
vec3_fromJolt(point, &p);
|
||||
}
|
||||
|
||||
float lovrContactGetFriction(Contact* contact) {
|
||||
return JPH_ContactSettings_GetFriction(contact->settings);
|
||||
}
|
||||
|
||||
void lovrContactSetFriction(Contact* contact, float friction) {
|
||||
return JPH_ContactSettings_SetFriction(contact->settings, friction);
|
||||
}
|
||||
|
||||
float lovrContactGetRestitution(Contact* contact) {
|
||||
return JPH_ContactSettings_GetRestitution(contact->settings);
|
||||
}
|
||||
|
||||
void lovrContactSetRestitution(Contact* contact, float restitution) {
|
||||
return JPH_ContactSettings_SetRestitution(contact->settings, restitution);
|
||||
}
|
||||
|
||||
bool lovrContactIsEnabled(Contact* contact) {
|
||||
return JPH_ContactSettings_GetIsSensor(contact->settings);
|
||||
}
|
||||
|
||||
void lovrContactSetEnabled(Contact* contact, bool enable) {
|
||||
JPH_ContactSettings_SetIsSensor(contact->settings, !enable);
|
||||
}
|
||||
|
||||
void lovrContactGetSurfaceVelocity(Contact* contact, float velocity[3]) {
|
||||
JPH_Vec3 v;
|
||||
JPH_ContactSettings_GetRelativeLinearSurfaceVelocity(contact->settings, &v);
|
||||
vec3_fromJolt(velocity, &v);
|
||||
}
|
||||
|
||||
void lovrContactSetSurfaceVelocity(Contact* contact, float velocity[3]) {
|
||||
JPH_ContactSettings_SetRelativeLinearSurfaceVelocity(contact->settings, vec3_toJolt(velocity));
|
||||
}
|
||||
|
||||
void lovrContactDestroy(void* ref) {
|
||||
// Contact is a temporary object owned by a World
|
||||
}
|
||||
|
||||
// Shapes
|
||||
|
||||
void lovrShapeDestroy(void* ref) {
|
||||
|
|
|
@ -423,6 +423,10 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
|
|||
return (world->masks[i] & (1 << j)) && (world->masks[j] & (1 << i));
|
||||
}
|
||||
|
||||
void lovrWorldSetCallbacks(World* world, WorldCallbacks* callbacks) {
|
||||
//
|
||||
}
|
||||
|
||||
Collider* lovrColliderCreate(World* world, float position[3], Shape* shape) {
|
||||
Collider* collider = lovrCalloc(sizeof(Collider));
|
||||
collider->ref = 1;
|
||||
|
@ -828,6 +832,74 @@ void lovrColliderGetAABB(Collider* collider, float aabb[6]) {
|
|||
}
|
||||
}
|
||||
|
||||
Collider* lovrContactGetColliderA(Contact* contact) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Collider* lovrContactGetColliderB(Contact* contact) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Shape* lovrContactGetShapeA(Contact* contact) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Shape* lovrContactGetShapeB(Contact* contact) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lovrContactGetNormal(Contact* contact, float normal[3]) {
|
||||
//
|
||||
}
|
||||
|
||||
float lovrContactGetPenetration(Contact* contact) {
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
uint32_t lovrContactGetPointCount(Contact* contact) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lovrContactGetPoint(Contact* contact, uint32_t index, float point[3]) {
|
||||
//
|
||||
}
|
||||
|
||||
float lovrContactGetFriction(Contact* contact) {
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
void lovrContactSetFriction(Contact* contact, float friction) {
|
||||
//
|
||||
}
|
||||
|
||||
float lovrContactGetRestitution(Contact* contact) {
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
void lovrContactSetRestitution(Contact* contact, float restitution) {
|
||||
//
|
||||
}
|
||||
|
||||
bool lovrContactIsEnabled(Contact* contact) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void lovrContactSetEnabled(Contact* contact, bool enable) {
|
||||
//
|
||||
}
|
||||
|
||||
void lovrContactGetSurfaceVelocity(Contact* contact, float velocity[3]) {
|
||||
//
|
||||
}
|
||||
|
||||
void lovrContactSetSurfaceVelocity(Contact* contact, float velocity[3]) {
|
||||
//
|
||||
}
|
||||
|
||||
void lovrContactDestroy(void* ref) {
|
||||
//
|
||||
}
|
||||
|
||||
void lovrShapeDestroy(void* ref) {
|
||||
Shape* shape = ref;
|
||||
if (shape->type == SHAPE_MESH) {
|
||||
|
|
Loading…
Reference in a new issue