diff --git a/src/api/types/world.c b/src/api/types/world.c index 69610b7f..5644ddb6 100644 --- a/src/api/types/world.c +++ b/src/api/types/world.c @@ -101,7 +101,9 @@ int l_lovrWorldCollide(lua_State* L) { World* world = luax_checktype(L, 1, World); Shape* a = luax_checktypeof(L, 2, Shape); Shape* b = luax_checktypeof(L, 3, Shape); - lua_pushboolean(L, lovrWorldCollide(world, a, b)); + float friction = luaL_optnumber(L, 4, -1); + float restitution = luaL_optnumber(L, 5, -1); + lua_pushboolean(L, lovrWorldCollide(world, a, b, friction, restitution)); return 1; } diff --git a/src/physics/physics.c b/src/physics/physics.c index 858fd2c2..1ad8accc 100644 --- a/src/physics/physics.c +++ b/src/physics/physics.c @@ -3,7 +3,7 @@ #include static void defaultNearCallback(void* data, dGeomID a, dGeomID b) { - lovrWorldCollide((World*) data, dGeomGetData(a), dGeomGetData(b)); + lovrWorldCollide((World*) data, dGeomGetData(a), dGeomGetData(b), -1, -1); } static void customNearCallback(void* data, dGeomID shapeA, dGeomID shapeB) { @@ -90,15 +90,28 @@ int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b) { return 1; } -int lovrWorldCollide(World* world, Shape* a, Shape* b) { +int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution) { if (!a || !b) { return 0; } dContact contacts[MAX_CONTACTS]; + Collider* colliderA = a->collider; + Collider* colliderB = b->collider; + + if (friction < 0) { + friction = sqrt(colliderA->friction * colliderB->friction); + } + + if (restitution < 0) { + restitution = MAX(colliderA->restitution, colliderB->restitution); + } + for (int i = 0; i < MAX_CONTACTS; i++) { contacts[i].surface.mode = 0; + contacts[i].surface.mu = friction; + contacts[i].surface.bounce = restitution; contacts[i].surface.mu = dInfinity; } @@ -106,7 +119,7 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b) { for (int i = 0; i < contactCount; i++) { dJointID joint = dJointCreateContact(world->id, world->contactGroup, &contacts[i]); - dJointAttach(joint, a->collider->body, b->collider->body); + dJointAttach(joint, colliderA->body, colliderB->body); } return contactCount; diff --git a/src/physics/physics.h b/src/physics/physics.h index 5f095857..a2fe39fe 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -33,6 +33,8 @@ typedef struct { void* userdata; vec_void_t shapes; vec_void_t joints; + float friction; + float restitution; } Collider; typedef struct { @@ -68,7 +70,7 @@ void lovrWorldDestroyData(World* world); void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata); void lovrWorldComputeOverlaps(World* world); int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b); -int lovrWorldCollide(World* world, Shape* a, Shape* b); +int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution); void lovrWorldGetGravity(World* world, float* x, float* y, float* z); void lovrWorldSetGravity(World* world, float x, float y, float z); void lovrWorldGetLinearDamping(World* world, float* damping, float* threshold);