From 9b6f58ac1ea8b8b0049caeed5ae0e048636c8a02 Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 11:29:16 -0700 Subject: [PATCH 01/26] Update Jolt; --- deps/jolt-physics-sharp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/jolt-physics-sharp b/deps/jolt-physics-sharp index 29fe07e8..2cda386d 160000 --- a/deps/jolt-physics-sharp +++ b/deps/jolt-physics-sharp @@ -1 +1 @@ -Subproject commit 29fe07e8088279c47d7108107856ec3c826d1817 +Subproject commit 2cda386d71174bec355888539679f7a4f7be1c2a From ce58619094cab9ffe2feaba48e264fd95ec4cbe0 Mon Sep 17 00:00:00 2001 From: bjorn Date: Wed, 3 Apr 2024 14:18:28 -0700 Subject: [PATCH 02/26] Colliders can only have 1 shape; rm shape pose; --- src/api/l_physics_collider.c | 43 ++++++------ src/api/l_physics_shapes.c | 81 ---------------------- src/api/l_physics_world.c | 16 ++--- src/modules/physics/physics.h | 6 +- src/modules/physics/physics_jolt.c | 106 +++++++++-------------------- 5 files changed, 61 insertions(+), 191 deletions(-) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index 52cd93e4..d9ba26fd 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -24,32 +24,28 @@ static int l_lovrColliderGetWorld(lua_State* L) { return 1; } -static int l_lovrColliderAddShape(lua_State* L) { +static int l_lovrColliderGetShape(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - Shape* shape = luax_checkshape(L, 2); - lovrColliderAddShape(collider, shape); - return 0; -} - -static int l_lovrColliderRemoveShape(lua_State* L) { - Collider* collider = luax_checktype(L, 1, Collider); - Shape* shape = luax_checkshape(L, 2); - lovrColliderRemoveShape(collider, shape); - return 0; -} - -static int l_lovrColliderGetShapes(lua_State* L) { - Collider* collider = luax_checktype(L, 1, Collider); - size_t count; - Shape** shapes = lovrColliderGetShapes(collider, &count); - lua_createtable(L, (int) count, 0); - for (size_t i = 0; i < count; i++) { - luax_pushshape(L, shapes[i]); - lua_rawseti(L, -2, (int) i + 1); + Shape* shape = lovrColliderGetShape(collider); + if (shape) { + luax_pushshape(L, shape); + } else { + lua_pushnil(L); } return 1; } +static int l_lovrColliderSetShape(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + if (lua_isnoneornil(L, 2)) { + lovrColliderSetShape(collider, NULL); + } else { + Shape* shape = luax_checkshape(L, 2); + lovrColliderSetShape(collider, shape); + } + return 0; +} + static int l_lovrColliderGetJoints(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); size_t count; @@ -563,9 +559,8 @@ const luaL_Reg lovrCollider[] = { { "destroy", l_lovrColliderDestroy }, { "isDestroyed", l_lovrColliderIsDestroyed }, { "getWorld", l_lovrColliderGetWorld }, - { "addShape", l_lovrColliderAddShape }, - { "removeShape", l_lovrColliderRemoveShape }, - { "getShapes", l_lovrColliderGetShapes }, + { "getShape", l_lovrColliderGetShape }, + { "setShape", l_lovrColliderSetShape }, { "getJoints", l_lovrColliderGetJoints }, { "getUserData", l_lovrColliderGetUserData }, { "setUserData", l_lovrColliderSetUserData }, diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index c5f6970e..0614509d 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -147,12 +147,6 @@ static int l_lovrShapeGetType(lua_State* L) { return 1; } -static int l_lovrShapeGetCollider(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - luax_pushtype(L, Collider, lovrShapeGetCollider(shape)); - return 1; -} - static int l_lovrShapeIsEnabled(lua_State* L) { Shape* shape = luax_checkshape(L, 1); lua_pushboolean(L, lovrShapeIsEnabled(shape)); @@ -214,74 +208,6 @@ static int l_lovrShapeSetUserData(lua_State* L) { return 0; } -static int l_lovrShapeGetPosition(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - float x, y, z; - lovrShapeGetPosition(shape, &x, &y, &z); - lua_pushnumber(L, x); - lua_pushnumber(L, y); - lua_pushnumber(L, z); - return 3; -} - -static int l_lovrShapeSetPosition(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - lovrCheck(lovrShapeGetCollider(shape) != NULL, "Shape must be attached to collider"); - float position[3]; - luax_readvec3(L, 2, position, NULL); - lovrShapeSetPosition(shape, position[0], position[1], position[2]); - return 0; -} - -static int l_lovrShapeGetOrientation(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - float angle, x, y, z, orientation[4]; - lovrShapeGetOrientation(shape, orientation); - quat_getAngleAxis(orientation, &angle, &x, &y, &z); - lua_pushnumber(L, angle); - lua_pushnumber(L, x); - lua_pushnumber(L, y); - lua_pushnumber(L, z); - return 4; -} - -static int l_lovrShapeSetOrientation(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - lovrCheck(lovrShapeGetCollider(shape) != NULL, "Shape must be attached to collider"); - float orientation[4]; - luax_readquat(L, 2, orientation, NULL); - lovrShapeSetOrientation(shape, orientation); - return 0; -} - -static int l_lovrShapeGetPose(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - float x, y, z; - lovrShapeGetPosition(shape, &x, &y, &z); - float angle, ax, ay, az, orientation[4]; - lovrShapeGetOrientation(shape, orientation); - quat_getAngleAxis(orientation, &angle, &ax, &ay, &az); - lua_pushnumber(L, x); - lua_pushnumber(L, y); - lua_pushnumber(L, z); - lua_pushnumber(L, angle); - lua_pushnumber(L, ax); - lua_pushnumber(L, ay); - lua_pushnumber(L, az); - return 7; -} - -static int l_lovrShapeSetPose(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - lovrCheck(lovrShapeGetCollider(shape) != NULL, "Shape must be attached to collider"); - float position[3], orientation[4]; - int index = luax_readvec3(L, 2, position, NULL); - luax_readquat(L, index, orientation, NULL); - lovrShapeSetPosition(shape, position[0], position[1], position[2]); - lovrShapeSetOrientation(shape, orientation); - return 0; -} - static int l_lovrShapeGetMass(lua_State* L) { Shape* shape = luax_checkshape(L, 1); float density = luax_checkfloat(L, 2); @@ -313,19 +239,12 @@ static int l_lovrShapeGetAABB(lua_State* L) { #define lovrShape \ { "destroy", l_lovrShapeDestroy }, \ { "getType", l_lovrShapeGetType }, \ - { "getCollider", l_lovrShapeGetCollider }, \ { "isEnabled", l_lovrShapeIsEnabled }, \ { "setEnabled", l_lovrShapeSetEnabled }, \ { "isSensor", l_lovrShapeIsSensor }, \ { "setSensor", l_lovrShapeSetSensor }, \ { "getUserData", l_lovrShapeGetUserData }, \ { "setUserData", l_lovrShapeSetUserData }, \ - { "getPosition", l_lovrShapeGetPosition }, \ - { "setPosition", l_lovrShapeSetPosition }, \ - { "getOrientation", l_lovrShapeGetOrientation }, \ - { "setOrientation", l_lovrShapeSetOrientation }, \ - { "getPose", l_lovrShapeGetPose }, \ - { "setPose", l_lovrShapeSetPose }, \ { "getMass", l_lovrShapeGetMass }, \ { "getAABB", l_lovrShapeGetAABB } diff --git a/src/api/l_physics_world.c b/src/api/l_physics_world.c index bf1a708b..e530e668 100644 --- a/src/api/l_physics_world.c +++ b/src/api/l_physics_world.c @@ -55,7 +55,7 @@ typedef struct { static bool raycastAnyCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) { RaycastData* data = userdata; if (data->tag) { - const char* tag = lovrColliderGetTag(lovrShapeGetCollider(shape)); + const char* tag = NULL; // TODO if (!tag || strcmp(tag, data->tag)) { return false; } @@ -70,7 +70,7 @@ static bool raycastAnyCallback(Shape* shape, float x, float y, float z, float nx static bool raycastClosestCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) { RaycastData* data = userdata; if (data->tag) { - const char* tag = lovrColliderGetTag(lovrShapeGetCollider(shape)); + const char* tag = NULL; // TODO if (!tag || strcmp(tag, data->tag)) { return false; } @@ -113,7 +113,7 @@ static int l_lovrWorldNewBoxCollider(lua_State* L) { int index = luax_readvec3(L, 2, position, NULL); Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); BoxShape* shape = luax_newboxshape(L, index); - lovrColliderAddShape(collider, shape); + lovrColliderSetShape(collider, shape); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -127,7 +127,7 @@ static int l_lovrWorldNewCapsuleCollider(lua_State* L) { int index = luax_readvec3(L, 2, position, NULL); Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); CapsuleShape* shape = luax_newcapsuleshape(L, index); - lovrColliderAddShape(collider, shape); + lovrColliderSetShape(collider, shape); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -141,7 +141,7 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) { int index = luax_readvec3(L, 2, position, NULL); Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); CylinderShape* shape = luax_newcylindershape(L, index); - lovrColliderAddShape(collider, shape); + lovrColliderSetShape(collider, shape); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -155,7 +155,7 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) { int index = luax_readvec3(L, 2, position, NULL); Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); SphereShape* shape = luax_newsphereshape(L, index); - lovrColliderAddShape(collider, shape); + lovrColliderSetShape(collider, shape); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -167,7 +167,7 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f); MeshShape* shape = luax_newmeshshape(L, 2); - lovrColliderAddShape(collider, shape); + lovrColliderSetShape(collider, shape); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -179,7 +179,7 @@ static int l_lovrWorldNewTerrainCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f); TerrainShape* shape = luax_newterrainshape(L, 2); - lovrColliderAddShape(collider, shape); + lovrColliderSetShape(collider, shape); lovrColliderSetKinematic(collider, true); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 0a756f75..827ed898 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -92,9 +92,8 @@ bool lovrColliderIsDestroyed(Collider* collider); void lovrColliderInitInertia(Collider* collider, Shape* shape); World* lovrColliderGetWorld(Collider* collider); Collider* lovrColliderGetNext(Collider* collider); -void lovrColliderAddShape(Collider* collider, Shape* shape); -void lovrColliderRemoveShape(Collider* collider, Shape* shape); -Shape** lovrColliderGetShapes(Collider* collider, size_t* count); +Shape* lovrColliderGetShape(Collider* collider); +void lovrColliderSetShape(Collider* collider, Shape* shape); Joint** lovrColliderGetJoints(Collider* collider, size_t* count); const char* lovrColliderGetTag(Collider* collider); bool lovrColliderSetTag(Collider* collider, const char* tag); @@ -157,7 +156,6 @@ typedef enum { void lovrShapeDestroy(void* ref); void lovrShapeDestroyData(Shape* shape); ShapeType lovrShapeGetType(Shape* shape); -Collider* lovrShapeGetCollider(Shape* shape); bool lovrShapeIsEnabled(Shape* shape); void lovrShapeSetEnabled(Shape* shape, bool enabled); bool lovrShapeIsSensor(Shape* shape); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 290b5d88..23ab7849 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -22,9 +22,9 @@ struct Collider { JPH_BodyID id; JPH_Body* body; World* world; + Shape* shape; Collider* prev; Collider* next; - arr_t(Shape*) shapes; arr_t(Joint*) joints; uint32_t tag; }; @@ -32,7 +32,6 @@ struct Collider { struct Shape { uint32_t ref; ShapeType type; - Collider* collider; JPH_Shape* shape; }; @@ -184,13 +183,13 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa world->bodies, hit_array[i].bodyID); size_t count; - Shape** shape = lovrColliderGetShapes(collider, &count); + Shape* shape = lovrColliderGetShape(collider); const JPH_RVec3 position = { x, y, z }; JPH_Vec3 normal; JPH_Body_GetWorldSpaceSurfaceNormal(collider->body, hit_array[i].subShapeID2, &position, &normal); bool shouldStop = callback( - shape[0], // assumes one shape per collider; todo: compound shapes + shape, // assumes one shape per collider; todo: compound shapes x, y, z, normal.x, normal.y, normal.z, userdata); @@ -222,8 +221,8 @@ static bool lovrWorldQueryShape(World* world, JPH_Shape* shape, float position[3 world->bodies, id); size_t count; - Shape** shape = lovrColliderGetShapes(collider, &count); - bool shouldStop = callback(shape[0], userdata); + Shape* shape = lovrColliderGetShape(collider); + bool shouldStop = callback(shape, userdata); if (shouldStop) { break; } @@ -341,7 +340,6 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) { lovrColliderSetAngularDamping(collider, world->defaultAngularDamping, 0.f); lovrColliderSetSleepingAllowed(collider, world->defaultIsSleepingAllowed); - arr_init(&collider->shapes); arr_init(&collider->joints); // Adjust the world's collider list @@ -361,7 +359,6 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) { void lovrColliderDestroy(void* ref) { Collider* collider = ref; lovrColliderDestroyData(collider); - arr_free(&collider->shapes); arr_free(&collider->joints); lovrFree(collider); } @@ -371,13 +368,9 @@ void lovrColliderDestroyData(Collider* collider) { return; } + lovrRelease(collider->shape, lovrShapeDestroy); + size_t count; - - Shape** shapes = lovrColliderGetShapes(collider, &count); - for (size_t i = 0; i < count; i++) { - lovrColliderRemoveShape(collider, shapes[i]); - } - Joint** joints = lovrColliderGetJoints(collider, &count); for (size_t i = 0; i < count; i++) { lovrRelease(joints[i], lovrJointDestroy); @@ -411,29 +404,24 @@ Collider* lovrColliderGetNext(Collider* collider) { return collider->next; } -void lovrColliderAddShape(Collider* collider, Shape* shape) { - lovrRetain(shape); - shape->collider = collider; - arr_push(&collider->shapes, shape); - bool isMeshOrTerrain = (shape->type == SHAPE_TERRAIN) || (shape->type == SHAPE_MESH); - bool shouldUpdateMass = !isMeshOrTerrain; - if (isMeshOrTerrain) { - lovrColliderSetKinematic(shape->collider, true); - } - JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, shouldUpdateMass, JPH_Activation_Activate); +Shape* lovrColliderGetShape(Collider* collider) { + return collider->shape; } -void lovrColliderRemoveShape(Collider* collider, Shape* shape) { - if (shape->collider == collider) { - // todo: actions necessary for compound shapes - shape->collider = NULL; - lovrRelease(shape, lovrShapeDestroy); - } -} +void lovrColliderSetShape(Collider* collider, Shape* shape) { + if (shape != collider->shape) { + lovrRelease(collider->shape, lovrShapeDestroy); + collider->shape = shape; + lovrRetain(shape); -Shape** lovrColliderGetShapes(Collider* collider, size_t* count) { - *count = collider->shapes.length; - return collider->shapes.data; + bool updateMass = true; + if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) { + lovrColliderSetKinematic(collider, true); + updateMass = false; + } + + JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate); + } } Joint** lovrColliderGetJoints(Collider* collider, size_t* count) { @@ -538,17 +526,15 @@ void lovrColliderSetAwake(Collider* collider, bool awake) { } float lovrColliderGetMass(Collider* collider) { - if (collider->shapes.length > 0) { - JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body); - return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties); - } - return 0.f; + if (!collider->shape) return 0.f; + JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body); + return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties); } void lovrColliderSetMass(Collider* collider, float mass) { - if (collider->shapes.length > 0) { + if (collider->shape) { JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body); - Shape* shape = collider->shapes.data[0]; + Shape* shape = collider->shape; JPH_MassProperties* massProperties; JPH_Shape_GetMassProperties(shape->shape, massProperties); JPH_MassProperties_ScaleToMass(massProperties, mass); @@ -782,10 +768,6 @@ ShapeType lovrShapeGetType(Shape* shape) { return shape->type; } -Collider* lovrShapeGetCollider(Shape* shape) { - return shape->collider; -} - bool lovrShapeIsEnabled(Shape* shape) { return true; } @@ -797,43 +779,19 @@ void lovrShapeSetEnabled(Shape* shape, bool enabled) { } bool lovrShapeIsSensor(Shape* shape) { - lovrLog(LOG_WARN, "PHY", "Jolt sensor property fetched from collider, not shape"); - return JPH_Body_IsSensor(shape->collider->body); + lovrThrow("NYI"); } void lovrShapeSetSensor(Shape* shape, bool sensor) { - lovrLog(LOG_WARN, "PHY", "Jolt sensor property is applied to collider, not shape"); - JPH_Body_SetIsSensor(shape->collider->body, sensor); + lovrThrow("NYI"); } -void lovrShapeGetPosition(Shape* shape, float* x, float* y, float* z) { - // todo: compound shapes - *x = 0.f; - *y = 0.f; - *z = 0.f; +void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) { + // } -void lovrShapeSetPosition(Shape* shape, float x, float y, float z) { - // todo: compound shapes -} - -void lovrShapeGetOrientation(Shape* shape, float* orientation) { - // todo: compound shapes - orientation[0] = 0.f; - orientation[1] = 0.f; - orientation[2] = 0.f; - orientation[3] = 1.f; -} - -void lovrShapeSetOrientation(Shape* shape, float* orientation) { - // todo: compound shapes -} - -void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {} - void lovrShapeGetAABB(Shape* shape, float aabb[6]) { - // todo: with compound shapes this is no longer correct - lovrColliderGetAABB(shape->collider, aabb); + // TODO } SphereShape* lovrSphereShapeCreate(float radius) { From 6f0b6391df807fcc02ae9f63aa9b481877849a38 Mon Sep 17 00:00:00 2001 From: bjorn Date: Wed, 3 Apr 2024 15:03:46 -0700 Subject: [PATCH 03/26] Start CompoundShape; --- src/api/api.h | 1 + src/api/l_physics.c | 11 +++++++++++ src/api/l_physics_shapes.c | 21 ++++++++++++++++++++- src/modules/physics/physics.h | 8 +++++++- src/modules/physics/physics_jolt.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/api/api.h b/src/api/api.h index 527f4a6d..5593edf2 100644 --- a/src/api/api.h +++ b/src/api/api.h @@ -203,4 +203,5 @@ struct Shape* luax_newcapsuleshape(lua_State* L, int index); struct Shape* luax_newcylindershape(lua_State* L, int index); struct Shape* luax_newmeshshape(lua_State* L, int index); struct Shape* luax_newterrainshape(lua_State* L, int index); +struct Shape* luax_newcompoundshape(lua_State* L, int index); #endif diff --git a/src/api/l_physics.c b/src/api/l_physics.c index 4f484984..206bcf90 100644 --- a/src/api/l_physics.c +++ b/src/api/l_physics.c @@ -9,6 +9,7 @@ StringEntry lovrShapeType[] = { [SHAPE_CYLINDER] = ENTRY("cylinder"), [SHAPE_MESH] = ENTRY("mesh"), [SHAPE_TERRAIN] = ENTRY("terrain"), + [SHAPE_COMPOUND] = ENTRY("compound"), { 0 } }; @@ -178,6 +179,13 @@ static int l_lovrPhysicsNewTerrainShape(lua_State* L) { return 1; } +static int l_lovrPhysicsNewCompoundShape(lua_State* L) { + CompoundShape* shape = luax_newcompoundshape(L, 1); + luax_pushtype(L, CompoundShape, shape); + lovrRelease(shape, lovrShapeDestroy); + return 1; +} + static const luaL_Reg lovrPhysics[] = { { "newWorld", l_lovrPhysicsNewWorld }, { "newBallJoint", l_lovrPhysicsNewBallJoint }, @@ -190,6 +198,7 @@ static const luaL_Reg lovrPhysics[] = { { "newSliderJoint", l_lovrPhysicsNewSliderJoint }, { "newSphereShape", l_lovrPhysicsNewSphereShape }, { "newTerrainShape", l_lovrPhysicsNewTerrainShape }, + { "newCompoundShape", l_lovrPhysicsNewCompoundShape }, { NULL, NULL } }; @@ -205,6 +214,7 @@ extern const luaL_Reg lovrCapsuleShape[]; extern const luaL_Reg lovrCylinderShape[]; extern const luaL_Reg lovrMeshShape[]; extern const luaL_Reg lovrTerrainShape[]; +extern const luaL_Reg lovrCompoundShape[]; int luaopen_lovr_physics(lua_State* L) { lua_newtable(L); @@ -221,6 +231,7 @@ int luaopen_lovr_physics(lua_State* L) { luax_registertype(L, CylinderShape); luax_registertype(L, MeshShape); luax_registertype(L, TerrainShape); + luax_registertype(L, CompoundShape); lovrPhysicsInit(); luax_atexit(L, lovrPhysicsDestroy); return 1; diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 0614509d..497f45a9 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -14,6 +14,7 @@ void luax_pushshape(lua_State* L, Shape* shape) { case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, shape); break; case SHAPE_MESH: luax_pushtype(L, MeshShape, shape); break; case SHAPE_TERRAIN: luax_pushtype(L, TerrainShape, shape); break; + case SHAPE_COMPOUND: luax_pushtype(L, CompoundShape, shape); break; default: lovrUnreachable(); } } @@ -28,7 +29,8 @@ Shape* luax_checkshape(lua_State* L, int index) { hash64("CapsuleShape", strlen("CapsuleShape")), hash64("CylinderShape", strlen("CylinderShape")), hash64("MeshShape", strlen("MeshShape")), - hash64("TerrainShape", strlen("TerrainShape")) + hash64("TerrainShape", strlen("TerrainShape")), + hash64("CompoundShape", strlen("CompoundShape")) }; for (size_t i = 0; i < COUNTOF(hashes); i++) { @@ -135,6 +137,10 @@ Shape* luax_newterrainshape(lua_State* L, int index) { } } +Shape* luax_newcompoundshape(lua_State* L, int index) { + return NULL; // TODO +} + static int l_lovrShapeDestroy(lua_State* L) { Shape* shape = luax_checkshape(L, 1); lovrShapeDestroyData(shape); @@ -372,3 +378,16 @@ const luaL_Reg lovrTerrainShape[] = { lovrShape, { NULL, NULL } }; + +static int l_lovrCompoundShapeGetShapeCount(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + uint32_t count = lovrCompoundShapeGetShapeCount(shape); + lua_pushinteger(L, count); + return 1; +} + +const luaL_Reg lovrCompoundShape[] = { + lovrShape, + { "getShapeCount", l_lovrCompoundShapeGetShapeCount }, + { NULL, NULL } +}; diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 827ed898..2d0f59ce 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -19,6 +19,7 @@ typedef Shape CapsuleShape; typedef Shape CylinderShape; typedef Shape MeshShape; typedef Shape TerrainShape; +typedef Shape CompoundShape; typedef Joint BallJoint; typedef Joint DistanceJoint; @@ -150,7 +151,8 @@ typedef enum { SHAPE_CAPSULE, SHAPE_CYLINDER, SHAPE_MESH, - SHAPE_TERRAIN + SHAPE_TERRAIN, + SHAPE_COMPOUND } ShapeType; void lovrShapeDestroy(void* ref); @@ -191,6 +193,9 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY); +CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count); +uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape); + // These tokens need to exist for Lua bindings #define lovrSphereShapeDestroy lovrShapeDestroy #define lovrBoxShapeDestroy lovrShapeDestroy @@ -198,6 +203,7 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, #define lovrCylinderShapeDestroy lovrShapeDestroy #define lovrMeshShapeDestroy lovrShapeDestroy #define lovrTerrainShapeDestroy lovrShapeDestroy +#define lovrCompoundShapeDestroy lovrShapeDestroy // Joints diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 23ab7849..aad06eae 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -751,6 +751,8 @@ void lovrColliderGetAABB(Collider* collider, float aabb[6]) { aabb[5] = box.max.z; } +// Shapes + void lovrShapeDestroy(void* ref) { Shape* shape = ref; lovrShapeDestroyData(shape); @@ -938,6 +940,34 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, return terrain; } +CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count) { + CompoundShape* parent = lovrCalloc(sizeof(CompoundShape)); + parent->ref = 1; + parent->type = SHAPE_COMPOUND; + + JPH_MutableCompoundShapeSettings* settings = JPH_MutableCompoundShapeSettings_Create(); + JPH_CompoundShapeSettings* settingsSuper = (JPH_CompoundShapeSettings*) settings; + + for (uint32_t i = 0; i < count; i++) { + JPH_Vec3 position; + JPH_Quat rotation; + vec3_init(&position.x, positions + 3 * i); + quat_init(&rotation.x, orientations + 3 * i); + JPH_CompoundShapeSettings_AddShape2(settingsSuper, &position, &rotation, shapes[i]->shape, 0); + lovrRetain(shapes[i]); + } + + parent->shape = (JPH_Shape*) JPH_MutableCompoundShape_Create(settings); + JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) settings); + return parent; +} + +uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { + return JPH_CompoundShape_GetNumSubShapes((JPH_CompoundShape*) shape->shape); +} + +// Joints + void lovrJointGetAnchors(Joint* joint, float anchor1[3], float anchor2[3]) { JPH_Body* body1 = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*) joint->constraint); JPH_Body* body2 = JPH_TwoBodyConstraint_GetBody2((JPH_TwoBodyConstraint*) joint->constraint); From b3e9e55b8a7f60f1815edc68c43dcabfb48cdc69 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 12:34:49 -0700 Subject: [PATCH 04/26] CompoundShape API; --- src/api/l_physics_shapes.c | 172 ++++++++++++++++++++++++++++- src/modules/physics/physics.h | 9 +- src/modules/physics/physics_jolt.c | 66 ++++++++++- 3 files changed, 241 insertions(+), 6 deletions(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 497f45a9..8fea2311 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -138,7 +138,82 @@ Shape* luax_newterrainshape(lua_State* L, int index) { } Shape* luax_newcompoundshape(lua_State* L, int index) { - return NULL; // TODO + if (lua_isnoneornil(L, index)) { + return lovrCompoundShapeCreate(NULL, NULL, NULL, 0, false); + } + + luaL_checktype(L, index, LUA_TTABLE); + int length = luax_len(L, index); + + uint32_t defer = lovrDeferPush(); + Shape** shapes = lovrMalloc(length * sizeof(Shape*)); + float* positions = lovrMalloc(length * 3 * sizeof(float)); + float* orientations = lovrMalloc(length * 4 * sizeof(float)); + lovrDefer(lovrFree, shapes); + lovrDefer(lovrFree, positions); + lovrDefer(lovrFree, orientations); + + for (int i = 0; i < length; i++) { + lua_rawgeti(L, index, i + 1); + lovrCheck(lua_istable(L, -1), "Expected table of tables for compound shape"); + + lua_rawgeti(L, -1, 1); + shapes[i] = luax_totype(L, -1, Shape); + lovrCheck(shapes[i], "Expected a Shape for CompoundShape entry #%d", i + 1); + lua_pop(L, 1); + + int index = 2; + lua_rawgeti(L, -1, index); + switch (lua_type(L, -1)) { + case LUA_TNIL: + vec3_set(&positions[3 * i], 0.f, 0.f, 0.f); + lua_pop(L, 1); + break; + case LUA_TNUMBER: + lua_rawgeti(L, -2, index++); + lua_rawgeti(L, -3, index++); + vec3_set(&positions[3 * i], luax_tofloat(L, -3), luax_tofloat(L, -2), luax_tofloat(L, -1)); + lua_pop(L, 3); + break; + default: { + float* v = luax_checkvector(L, -1, V_VEC3, "nil, number, or vec3"); + vec3_init(&positions[3 * i], v); + lua_pop(L, 1); + break; + } + } + + lua_rawgeti(L, -1, index); + switch (lua_type(L, -1)) { + case LUA_TNIL: + quat_identity(&orientations[4 * i]); + lua_pop(L, 1); + break; + case LUA_TNUMBER: + lua_rawgeti(L, -2, index++); + lua_rawgeti(L, -3, index++); + lua_rawgeti(L, -4, index++); + quat_set(&orientations[4 * i], luax_tofloat(L, -4), luax_tofloat(L, -3), luax_tofloat(L, -2), luax_tofloat(L, -1)); + lua_pop(L, 4); + break; + default: { + float* q = luax_checkvector(L, -1, V_QUAT, "nil, number, or quat"); + quat_init(&positions[4 * i], q); + lua_pop(L, 1); + break; + } + } + + lua_pop(L, 1); + } + + lua_getfield(L, index, "freeze"); + bool freeze = lua_toboolean(L, -1); + lua_pop(L, 1); + + CompoundShape* shape = lovrCompoundShapeCreate(shapes, positions, orientations, length, freeze); + lovrDeferPop(defer); + return shape; } static int l_lovrShapeDestroy(lua_State* L) { @@ -379,6 +454,63 @@ const luaL_Reg lovrTerrainShape[] = { { NULL, NULL } }; +static int l_lovrCompoundShapeIsFrozen(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + bool frozen = lovrCompoundShapeIsFrozen(shape); + lua_pushboolean(L, frozen); + return 1; +} + +static int l_lovrCompoundShapeAddShape(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + Shape* child = luax_checkshape(L, 2); + float position[3], orientation[4]; + int index = 3; + index = luax_readvec3(L, index, position, NULL); + index = luax_readquat(L, index, orientation, NULL); + lovrCompoundShapeAddShape(shape, child, position, orientation); + return 0; +} + +static int l_lovrCompoundShapeReplaceShape(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + uint32_t index = luax_checku32(L, 2); + Shape* child = luax_checkshape(L, 3); + float position[3], orientation[4]; + int i = 4; + i = luax_readvec3(L, i, position, NULL); + i = luax_readquat(L, i, orientation, NULL); + lovrCompoundShapeReplaceShape(shape, index, child, position, orientation); + return 0; +} + +static int l_lovrCompoundShapeRemoveShape(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + uint32_t index = luax_checku32(L, 2); + lovrCompoundShapeRemoveShape(shape, index); + return 0; +} + +static int l_lovrCompoundShapeGetShape(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + uint32_t index = luax_checku32(L, 2); + Shape* child = lovrCompoundShapeGetShape(shape, index); + luax_pushshape(L, child); + return 1; +} + +static int l_lovrCompoundShapeGetShapes(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + int count = (int) lovrCompoundShapeGetShapeCount(shape); + lua_createtable(L, count, 0); + for (int i = 0; i < count; i++) { + Shape* shape = lovrCompoundShapeGetShape(shape, (uint32_t) i); + luax_pushshape(L, shape); + lua_rawseti(L, -2, i + 1); + } + return 1; +} + static int l_lovrCompoundShapeGetShapeCount(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); uint32_t count = lovrCompoundShapeGetShapeCount(shape); @@ -386,8 +518,44 @@ static int l_lovrCompoundShapeGetShapeCount(lua_State* L) { return 1; } +static int l_lovrCompoundShapeGetShapeOffset(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + uint32_t index = luax_checku32(L, 2); + float position[3], orientation[4], angle, ax, ay, az; + lovrCompoundShapeGetShapeOffset(shape, index, position, orientation); + quat_getAngleAxis(orientation, &angle, &ax, &ay, &az); + lua_pushnumber(L, position[0]); + lua_pushnumber(L, position[1]); + lua_pushnumber(L, position[2]); + lua_pushnumber(L, angle); + lua_pushnumber(L, ax); + lua_pushnumber(L, ay); + lua_pushnumber(L, az); + return 7; +} + +static int l_lovrCompoundShapeSetShapeOffset(lua_State* L) { + CompoundShape* shape = luax_checktype(L, 1, CompoundShape); + uint32_t index = luax_checku32(L, 2); + float position[3], orientation[4]; + int i = 3; + i = luax_readvec3(L, i, position, NULL); + i = luax_readquat(L, i, orientation, NULL); + lovrCompoundShapeSetShapeOffset(shape, index, position, orientation); + return 0; +} + const luaL_Reg lovrCompoundShape[] = { lovrShape, - { "getShapeCount", l_lovrCompoundShapeGetShapeCount }, + { "isFrozen", l_lovrCompoundShapeIsFrozen }, + { "addShape", l_lovrCompoundShapeAddShape }, + { "replaceShape", l_lovrCompoundShapeReplaceShape }, + { "removeShape", l_lovrCompoundShapeRemoveShape }, + { "getShape", l_lovrCompoundShapeGetShape }, + { "getShapes", l_lovrCompoundShapeGetShapes }, + { "getShapeCount", l_lovrCompoundShapeGetShapes }, + { "getShapeOffset", l_lovrCompoundShapeGetShapeOffset }, + { "setShapeOffset", l_lovrCompoundShapeSetShapeOffset }, + { "__len", l_lovrCompoundShapeGetShapeCount }, // :) { NULL, NULL } }; diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 2d0f59ce..ac64b8bf 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -193,8 +193,15 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY); -CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count); +CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze); +bool lovrCompoundShapeIsFrozen(CompoundShape* shape); +void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation); +void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation); +void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index); +Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index); uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape); +void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation); +void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation); // These tokens need to exist for Lua bindings #define lovrSphereShapeDestroy lovrShapeDestroy diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index aad06eae..bf7c21d3 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -761,6 +761,14 @@ void lovrShapeDestroy(void* ref) { void lovrShapeDestroyData(Shape* shape) { if (shape->shape) { + if (shape->type == SHAPE_COMPOUND) { + uint32_t count = lovrCompoundShapeGetShapeCount(shape); + for (uint32_t i = 0; i < count; i++) { + Shape* child = lovrCompoundShapeGetShape(shape, i); + lovrRelease(child, lovrShapeDestroy); + } + } + JPH_Shape_Destroy(shape->shape); shape->shape = NULL; } @@ -940,20 +948,20 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, return terrain; } -CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count) { +CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count, bool freeze) { CompoundShape* parent = lovrCalloc(sizeof(CompoundShape)); parent->ref = 1; parent->type = SHAPE_COMPOUND; JPH_MutableCompoundShapeSettings* settings = JPH_MutableCompoundShapeSettings_Create(); - JPH_CompoundShapeSettings* settingsSuper = (JPH_CompoundShapeSettings*) settings; + JPH_CompoundShapeSettings* superSettings = (JPH_CompoundShapeSettings*) settings; for (uint32_t i = 0; i < count; i++) { JPH_Vec3 position; JPH_Quat rotation; vec3_init(&position.x, positions + 3 * i); quat_init(&rotation.x, orientations + 3 * i); - JPH_CompoundShapeSettings_AddShape2(settingsSuper, &position, &rotation, shapes[i]->shape, 0); + JPH_CompoundShapeSettings_AddShape2(superSettings, &position, &rotation, shapes[i]->shape, 0); lovrRetain(shapes[i]); } @@ -962,10 +970,62 @@ CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orie return parent; } +bool lovrCompoundShapeIsFrozen(CompoundShape* shape) { + return JPH_Shape_GetSubType(shape->shape) == JPH_ShapeSubType_StaticCompound; +} + +void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) { + lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); + lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); + JPH_Vec3 pos = { position[0], position[1], position[2] }; + JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; + JPH_MutableCompoundShape_AddShape((JPH_MutableCompoundShape*) shape->shape, &pos, &rot, child->shape, 0); + lovrRetain(child); +} + +void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { + lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); + lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); + JPH_Vec3 pos = { position[0], position[1], position[2] }; + JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; + JPH_MutableCompoundShape_ModifyShape2((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot, child->shape); + lovrRetain(child); +} + +void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) { + lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); + Shape* child = lovrCompoundShapeGetShape(shape, index); + JPH_MutableCompoundShape_RemoveShape((JPH_MutableCompoundShape*) shape->shape, index); + lovrRelease(child, lovrShapeDestroy); +} + +Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) { + const JPH_Shape* child; + JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, NULL, NULL, NULL); + return (Shape*) (uintptr_t) JPH_Shape_GetUserData(child); +} + uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { return JPH_CompoundShape_GetNumSubShapes((JPH_CompoundShape*) shape->shape); } +void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { + const JPH_Shape* child; + JPH_Vec3 pos; + JPH_Quat rot; + uint32_t userData; + JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, &pos, &rot, &userData); + vec3_init(position, &pos.x); + quat_init(orientation, &rot.x); +} + +void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { + lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); + JPH_Vec3 pos = { position[0], position[1], position[2] }; + JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; + JPH_MutableCompoundShape_ModifyShape((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot); +} + // Joints void lovrJointGetAnchors(Joint* joint, float anchor1[3], float anchor2[3]) { From c27694fd8e1308a9b495a713d2a78c108ce09251 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 13:18:15 -0700 Subject: [PATCH 05/26] Shapes set their userdata; --- src/modules/physics/physics_jolt.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index bf7c21d3..cb15d79e 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -810,6 +810,7 @@ SphereShape* lovrSphereShapeCreate(float radius) { sphere->ref = 1; sphere->type = SHAPE_SPHERE; sphere->shape = (JPH_Shape*) JPH_SphereShape_Create(radius); + JPH_Shape_SetUserData(sphere->shape, (uint64_t) (uintptr_t) sphere); return sphere; } @@ -828,6 +829,7 @@ BoxShape* lovrBoxShapeCreate(float w, float h, float d) { box->type = SHAPE_BOX; const JPH_Vec3 halfExtent = { w / 2.f, h / 2.f, d / 2.f }; box->shape = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f); + JPH_Shape_SetUserData(box->shape, (uint64_t) (uintptr_t) box); return box; } @@ -850,6 +852,7 @@ CapsuleShape* lovrCapsuleShapeCreate(float radius, float length) { capsule->ref = 1; capsule->type = SHAPE_CAPSULE; capsule->shape = (JPH_Shape*) JPH_CapsuleShape_Create(length / 2, radius); + JPH_Shape_SetUserData(capsule->shape, (uint64_t) (uintptr_t) capsule); return capsule; } @@ -873,24 +876,25 @@ void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length) { CylinderShape* lovrCylinderShapeCreate(float radius, float length) { lovrCheck(radius > 0.f && length > 0.f, "CylinderShape dimensions must be positive"); - CylinderShape* Cylinder = lovrCalloc(sizeof(CylinderShape)); - Cylinder->ref = 1; - Cylinder->type = SHAPE_CYLINDER; - Cylinder->shape = (JPH_Shape*) JPH_CylinderShape_Create(length / 2.f, radius); - return Cylinder; + CylinderShape* cylinder = lovrCalloc(sizeof(CylinderShape)); + cylinder->ref = 1; + cylinder->type = SHAPE_CYLINDER; + cylinder->shape = (JPH_Shape*) JPH_CylinderShape_Create(length / 2.f, radius); + JPH_Shape_SetUserData(cylinder->shape, (uint64_t) (uintptr_t) cylinder); + return cylinder; } -float lovrCylinderShapeGetRadius(CylinderShape* Cylinder) { - return JPH_CylinderShape_GetRadius((JPH_CylinderShape*) Cylinder->shape); +float lovrCylinderShapeGetRadius(CylinderShape* cylinder) { + return JPH_CylinderShape_GetRadius((JPH_CylinderShape*) cylinder->shape); } -void lovrCylinderShapeSetRadius(CylinderShape* Cylinder, float radius) { +void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius) { lovrLog(LOG_WARN, "PHY", "Jolt CylinderShape radius is read-only"); // todo: no setter available, but the shape could be removed and re-added } -float lovrCylinderShapeGetLength(CylinderShape* Cylinder) { - return JPH_CylinderShape_GetHalfHeight((JPH_CylinderShape*) Cylinder->shape) * 2.f; +float lovrCylinderShapeGetLength(CylinderShape* cylinder) { + return JPH_CylinderShape_GetHalfHeight((JPH_CylinderShape*) cylinder->shape) * 2.f; } void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) { From a7bf4ca2a4cae285f447f403b96fa67f240560a0 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 13:38:41 -0700 Subject: [PATCH 06/26] CompoundShape fixes; --- src/api/l_physics_shapes.c | 27 +++++++++++---------- src/modules/physics/physics_jolt.c | 39 +++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 8fea2311..62cc375e 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -158,7 +158,7 @@ Shape* luax_newcompoundshape(lua_State* L, int index) { lovrCheck(lua_istable(L, -1), "Expected table of tables for compound shape"); lua_rawgeti(L, -1, 1); - shapes[i] = luax_totype(L, -1, Shape); + shapes[i] = luax_checkshape(L, -1); lovrCheck(shapes[i], "Expected a Shape for CompoundShape entry #%d", i + 1); lua_pop(L, 1); @@ -170,10 +170,11 @@ Shape* luax_newcompoundshape(lua_State* L, int index) { lua_pop(L, 1); break; case LUA_TNUMBER: - lua_rawgeti(L, -2, index++); - lua_rawgeti(L, -3, index++); + lua_rawgeti(L, -2, index + 1); + lua_rawgeti(L, -3, index + 2); vec3_set(&positions[3 * i], luax_tofloat(L, -3), luax_tofloat(L, -2), luax_tofloat(L, -1)); lua_pop(L, 3); + index += 3; break; default: { float* v = luax_checkvector(L, -1, V_VEC3, "nil, number, or vec3"); @@ -190,9 +191,9 @@ Shape* luax_newcompoundshape(lua_State* L, int index) { lua_pop(L, 1); break; case LUA_TNUMBER: - lua_rawgeti(L, -2, index++); - lua_rawgeti(L, -3, index++); - lua_rawgeti(L, -4, index++); + lua_rawgeti(L, -2, index); + lua_rawgeti(L, -3, index); + lua_rawgeti(L, -4, index); quat_set(&orientations[4 * i], luax_tofloat(L, -4), luax_tofloat(L, -3), luax_tofloat(L, -2), luax_tofloat(L, -1)); lua_pop(L, 4); break; @@ -486,14 +487,14 @@ static int l_lovrCompoundShapeReplaceShape(lua_State* L) { static int l_lovrCompoundShapeRemoveShape(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - uint32_t index = luax_checku32(L, 2); + uint32_t index = luax_checku32(L, 2) - 1; lovrCompoundShapeRemoveShape(shape, index); return 0; } static int l_lovrCompoundShapeGetShape(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - uint32_t index = luax_checku32(L, 2); + uint32_t index = luax_checku32(L, 2) - 1; Shape* child = lovrCompoundShapeGetShape(shape, index); luax_pushshape(L, child); return 1; @@ -504,8 +505,8 @@ static int l_lovrCompoundShapeGetShapes(lua_State* L) { int count = (int) lovrCompoundShapeGetShapeCount(shape); lua_createtable(L, count, 0); for (int i = 0; i < count; i++) { - Shape* shape = lovrCompoundShapeGetShape(shape, (uint32_t) i); - luax_pushshape(L, shape); + Shape* child = lovrCompoundShapeGetShape(shape, (uint32_t) i); + luax_pushshape(L, child); lua_rawseti(L, -2, i + 1); } return 1; @@ -520,7 +521,7 @@ static int l_lovrCompoundShapeGetShapeCount(lua_State* L) { static int l_lovrCompoundShapeGetShapeOffset(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - uint32_t index = luax_checku32(L, 2); + uint32_t index = luax_checku32(L, 2) - 1; float position[3], orientation[4], angle, ax, ay, az; lovrCompoundShapeGetShapeOffset(shape, index, position, orientation); quat_getAngleAxis(orientation, &angle, &ax, &ay, &az); @@ -536,7 +537,7 @@ static int l_lovrCompoundShapeGetShapeOffset(lua_State* L) { static int l_lovrCompoundShapeSetShapeOffset(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - uint32_t index = luax_checku32(L, 2); + uint32_t index = luax_checku32(L, 2) - 1; float position[3], orientation[4]; int i = 3; i = luax_readvec3(L, i, position, NULL); @@ -553,7 +554,7 @@ const luaL_Reg lovrCompoundShape[] = { { "removeShape", l_lovrCompoundShapeRemoveShape }, { "getShape", l_lovrCompoundShapeGetShape }, { "getShapes", l_lovrCompoundShapeGetShapes }, - { "getShapeCount", l_lovrCompoundShapeGetShapes }, + { "getShapeCount", l_lovrCompoundShapeGetShapeCount }, { "getShapeOffset", l_lovrCompoundShapeGetShapeOffset }, { "setShapeOffset", l_lovrCompoundShapeSetShapeOffset }, { "__len", l_lovrCompoundShapeGetShapeCount }, // :) diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index cb15d79e..36b6bc89 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -953,23 +953,30 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, } CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count, bool freeze) { + lovrCheck(!freeze || count > 0, "A frozen CompoundShape must contain at least one shape"); + CompoundShape* parent = lovrCalloc(sizeof(CompoundShape)); parent->ref = 1; parent->type = SHAPE_COMPOUND; - JPH_MutableCompoundShapeSettings* settings = JPH_MutableCompoundShapeSettings_Create(); - JPH_CompoundShapeSettings* superSettings = (JPH_CompoundShapeSettings*) settings; + JPH_CompoundShapeSettings* settings = freeze ? + (JPH_CompoundShapeSettings*) JPH_StaticCompoundShapeSettings_Create() : + (JPH_CompoundShapeSettings*) JPH_MutableCompoundShapeSettings_Create(); for (uint32_t i = 0; i < count; i++) { - JPH_Vec3 position; - JPH_Quat rotation; - vec3_init(&position.x, positions + 3 * i); - quat_init(&rotation.x, orientations + 3 * i); - JPH_CompoundShapeSettings_AddShape2(superSettings, &position, &rotation, shapes[i]->shape, 0); + lovrCheck(shapes[i]->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); + JPH_Vec3 position = { positions[3 * i + 0], positions[3 * i + 1], positions[3 * i + 2] }; + JPH_Quat rotation = { orientations[4 * i + 0], orientations[4 * i + 1], orientations[4 * i + 2], orientations[4 * i + 3] }; + JPH_CompoundShapeSettings_AddShape2(settings, &position, &rotation, shapes[i]->shape, 0); lovrRetain(shapes[i]); } - parent->shape = (JPH_Shape*) JPH_MutableCompoundShape_Create(settings); + if (freeze) { + parent->shape = (JPH_Shape*) JPH_StaticCompoundShape_Create((JPH_StaticCompoundShapeSettings*) settings); + } else { + parent->shape = (JPH_Shape*) JPH_MutableCompoundShape_Create((JPH_MutableCompoundShapeSettings*) settings); + } + JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) settings); return parent; } @@ -981,6 +988,7 @@ bool lovrCompoundShapeIsFrozen(CompoundShape* shape) { void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); + lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol"); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; JPH_MutableCompoundShape_AddShape((JPH_MutableCompoundShape*) shape->shape, &pos, &rot, child->shape, 0); @@ -990,6 +998,8 @@ void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* positi void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); + lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); + lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol"); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; JPH_MutableCompoundShape_ModifyShape2((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot, child->shape); @@ -998,15 +1008,20 @@ void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); + lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); Shape* child = lovrCompoundShapeGetShape(shape, index); JPH_MutableCompoundShape_RemoveShape((JPH_MutableCompoundShape*) shape->shape, index); lovrRelease(child, lovrShapeDestroy); } Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) { - const JPH_Shape* child; - JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, NULL, NULL, NULL); - return (Shape*) (uintptr_t) JPH_Shape_GetUserData(child); + if (index < lovrCompoundShapeGetShapeCount(shape)) { + const JPH_Shape* child; + JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, NULL, NULL, NULL); + return (Shape*) (uintptr_t) JPH_Shape_GetUserData(child); + } else { + return NULL; + } } uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { @@ -1014,6 +1029,7 @@ uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { } void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { + lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); const JPH_Shape* child; JPH_Vec3 pos; JPH_Quat rot; @@ -1025,6 +1041,7 @@ void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); + lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; JPH_MutableCompoundShape_ModifyShape((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot); From 10f965d69eabdffcc54bd8ad2f68dc5b3762a38c Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 14:37:48 -0700 Subject: [PATCH 07/26] rm Shape setters; Jolt doesn't support this and requires you to recreate the shape. Since the shape -> collider relationship is 1:N, we can't really create a new shape because we'd have to figure out which colliders/compoundshapes to assign it to, which isn't feasible. --- src/api/l_physics_shapes.c | 49 ------------------------------ src/modules/physics/physics.h | 6 ---- src/modules/physics/physics_jolt.c | 30 ------------------ 3 files changed, 85 deletions(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 62cc375e..b3125238 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -336,17 +336,9 @@ static int l_lovrSphereShapeGetRadius(lua_State* L) { return 1; } -static int l_lovrSphereShapeSetRadius(lua_State* L) { - SphereShape* sphere = luax_checktype(L, 1, SphereShape); - float radius = luax_checkfloat(L, 2); - lovrSphereShapeSetRadius(sphere, radius); - return 0; -} - const luaL_Reg lovrSphereShape[] = { lovrShape, { "getRadius", l_lovrSphereShapeGetRadius }, - { "setRadius", l_lovrSphereShapeSetRadius }, { NULL, NULL } }; @@ -360,18 +352,9 @@ static int l_lovrBoxShapeGetDimensions(lua_State* L) { return 3; } -static int l_lovrBoxShapeSetDimensions(lua_State* L) { - BoxShape* box = luax_checktype(L, 1, BoxShape); - float size[3]; - luax_readscale(L, 2, size, 3, NULL); - lovrBoxShapeSetDimensions(box, size[0], size[1], size[2]); - return 0; -} - const luaL_Reg lovrBoxShape[] = { lovrShape, { "getDimensions", l_lovrBoxShapeGetDimensions }, - { "setDimensions", l_lovrBoxShapeSetDimensions }, { NULL, NULL } }; @@ -381,32 +364,16 @@ static int l_lovrCapsuleShapeGetRadius(lua_State* L) { return 1; } -static int l_lovrCapsuleShapeSetRadius(lua_State* L) { - CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape); - float radius = luax_checkfloat(L, 2); - lovrCapsuleShapeSetRadius(capsule, radius); - return 0; -} - static int l_lovrCapsuleShapeGetLength(lua_State* L) { CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape); lua_pushnumber(L, lovrCapsuleShapeGetLength(capsule)); return 1; } -static int l_lovrCapsuleShapeSetLength(lua_State* L) { - CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape); - float length = luax_checkfloat(L, 2); - lovrCapsuleShapeSetLength(capsule, length); - return 0; -} - const luaL_Reg lovrCapsuleShape[] = { lovrShape, { "getRadius", l_lovrCapsuleShapeGetRadius }, - { "setRadius", l_lovrCapsuleShapeSetRadius }, { "getLength", l_lovrCapsuleShapeGetLength }, - { "setLength", l_lovrCapsuleShapeSetLength }, { NULL, NULL } }; @@ -416,32 +383,16 @@ static int l_lovrCylinderShapeGetRadius(lua_State* L) { return 1; } -static int l_lovrCylinderShapeSetRadius(lua_State* L) { - CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape); - float radius = luax_checkfloat(L, 2); - lovrCylinderShapeSetRadius(cylinder, radius); - return 0; -} - static int l_lovrCylinderShapeGetLength(lua_State* L) { CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape); lua_pushnumber(L, lovrCylinderShapeGetLength(cylinder)); return 1; } -static int l_lovrCylinderShapeSetLength(lua_State* L) { - CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape); - float length = luax_checkfloat(L, 2); - lovrCylinderShapeSetLength(cylinder, length); - return 0; -} - const luaL_Reg lovrCylinderShape[] = { lovrShape, { "getRadius", l_lovrCylinderShapeGetRadius }, - { "setRadius", l_lovrCylinderShapeSetRadius }, { "getLength", l_lovrCylinderShapeGetLength }, - { "setLength", l_lovrCylinderShapeSetLength }, { NULL, NULL } }; diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index ac64b8bf..fd5ae7a2 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -171,23 +171,17 @@ void lovrShapeGetAABB(Shape* shape, float aabb[6]); SphereShape* lovrSphereShapeCreate(float radius); float lovrSphereShapeGetRadius(SphereShape* sphere); -void lovrSphereShapeSetRadius(SphereShape* sphere, float radius); BoxShape* lovrBoxShapeCreate(float w, float h, float d); void lovrBoxShapeGetDimensions(BoxShape* box, float* w, float* h, float* d); -void lovrBoxShapeSetDimensions(BoxShape* box, float w, float h, float d); CapsuleShape* lovrCapsuleShapeCreate(float radius, float length); float lovrCapsuleShapeGetRadius(CapsuleShape* capsule); -void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius); float lovrCapsuleShapeGetLength(CapsuleShape* capsule); -void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length); CylinderShape* lovrCylinderShapeCreate(float radius, float length); float lovrCylinderShapeGetRadius(CylinderShape* cylinder); -void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius); float lovrCylinderShapeGetLength(CylinderShape* cylinder); -void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length); MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 36b6bc89..dc451a85 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -818,11 +818,6 @@ float lovrSphereShapeGetRadius(SphereShape* sphere) { return JPH_SphereShape_GetRadius((JPH_SphereShape*) sphere->shape); } -void lovrSphereShapeSetRadius(SphereShape* sphere, float radius) { - lovrLog(LOG_WARN, "PHY", "Jolt SphereShape radius is read-only"); - // todo: no setter available, but the shape could be removed and re-added -} - BoxShape* lovrBoxShapeCreate(float w, float h, float d) { BoxShape* box = lovrCalloc(sizeof(BoxShape)); box->ref = 1; @@ -841,11 +836,6 @@ void lovrBoxShapeGetDimensions(BoxShape* box, float* w, float* h, float* d) { *d = halfExtent.z * 2.f; } -void lovrBoxShapeSetDimensions(BoxShape* box, float w, float h, float d) { - lovrLog(LOG_WARN, "PHY", "Jolt BoxShape dimensions are read-only"); - // todo: no setter available, but the shape could be removed and re-added -} - CapsuleShape* lovrCapsuleShapeCreate(float radius, float length) { lovrCheck(radius > 0.f && length > 0.f, "CapsuleShape dimensions must be positive"); CapsuleShape* capsule = lovrCalloc(sizeof(CapsuleShape)); @@ -860,20 +850,10 @@ float lovrCapsuleShapeGetRadius(CapsuleShape* capsule) { return JPH_CapsuleShape_GetRadius((JPH_CapsuleShape*) capsule->shape); } -void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius) { - lovrLog(LOG_WARN, "PHY", "Jolt CapsuleShape radius is read-only"); - // todo: no setter available, but the shape could be removed and re-added -} - float lovrCapsuleShapeGetLength(CapsuleShape* capsule) { return 2.f * JPH_CapsuleShape_GetHalfHeightOfCylinder((JPH_CapsuleShape*) capsule->shape); } -void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length) { - lovrLog(LOG_WARN, "PHY", "Jolt CapsuleShape length is read-only"); - // todo: no setter available, but the shape could be removed and re-added -} - CylinderShape* lovrCylinderShapeCreate(float radius, float length) { lovrCheck(radius > 0.f && length > 0.f, "CylinderShape dimensions must be positive"); CylinderShape* cylinder = lovrCalloc(sizeof(CylinderShape)); @@ -888,20 +868,10 @@ float lovrCylinderShapeGetRadius(CylinderShape* cylinder) { return JPH_CylinderShape_GetRadius((JPH_CylinderShape*) cylinder->shape); } -void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius) { - lovrLog(LOG_WARN, "PHY", "Jolt CylinderShape radius is read-only"); - // todo: no setter available, but the shape could be removed and re-added -} - float lovrCylinderShapeGetLength(CylinderShape* cylinder) { return JPH_CylinderShape_GetHalfHeight((JPH_CylinderShape*) cylinder->shape) * 2.f; } -void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) { - lovrLog(LOG_WARN, "PHY", "Jolt CylinderShape length is read-only"); - // todo: no setter available, but the shape could be removed and re-added -} - MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]) { MeshShape* mesh = lovrCalloc(sizeof(MeshShape)); mesh->ref = 1; From 8cbdda00f3e7d23f77208abcb120c83448d15bfc Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 16:23:20 -0700 Subject: [PATCH 08/26] Require frozen CompoundShapes to have at least 2 children; If you create a StaticCompoundShape with 1 child, Jolt creates a RotatedTranslatedShape. It would be a pain to have to branch on that, so let's just require 2 children. --- src/modules/physics/physics_jolt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index dc451a85..385acc76 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -923,7 +923,7 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, } CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count, bool freeze) { - lovrCheck(!freeze || count > 0, "A frozen CompoundShape must contain at least one shape"); + lovrCheck(!freeze || count >= 2, "A frozen CompoundShape must contain at least two shapes"); CompoundShape* parent = lovrCalloc(sizeof(CompoundShape)); parent->ref = 1; From 4f261825956f042e935b663c9fb69f2d2df95d0c Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 16:50:44 -0700 Subject: [PATCH 09/26] World queries return collider/shapeindex instead of Shape; --- src/api/l_physics_world.c | 59 +++++++++++++------------ src/modules/physics/physics.h | 4 +- src/modules/physics/physics_jolt.c | 69 +++++++++++++++--------------- 3 files changed, 69 insertions(+), 63 deletions(-) diff --git a/src/api/l_physics_world.c b/src/api/l_physics_world.c index e530e668..a2d47b94 100644 --- a/src/api/l_physics_world.c +++ b/src/api/l_physics_world.c @@ -27,17 +27,18 @@ static int nextOverlap(lua_State* L) { } } -static bool raycastCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) { +static bool raycastCallback(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata) { lua_State* L = userdata; lua_pushvalue(L, -1); - luax_pushshape(L, shape); - lua_pushnumber(L, x); - lua_pushnumber(L, y); - lua_pushnumber(L, z); - lua_pushnumber(L, nx); - lua_pushnumber(L, ny); - lua_pushnumber(L, nz); - lua_call(L, 7, 1); + luax_pushtype(L, Collider, collider); + lua_pushinteger(L, shape); + lua_pushnumber(L, position[0]); + lua_pushnumber(L, position[1]); + lua_pushnumber(L, position[2]); + lua_pushnumber(L, normal[0]); + lua_pushnumber(L, normal[1]); + lua_pushnumber(L, normal[2]); + lua_call(L, 8, 1); bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1); lua_pop(L, 1); return shouldStop; @@ -45,53 +46,55 @@ static bool raycastCallback(Shape* shape, float x, float y, float z, float nx, f typedef struct { const char* tag; - Shape* shape; + Collider* collider; + uint32_t shape; float distance; float origin[3]; float position[3]; float normal[3]; } RaycastData; -static bool raycastAnyCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) { +static bool raycastAnyCallback(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata) { RaycastData* data = userdata; if (data->tag) { - const char* tag = NULL; // TODO + const char* tag = lovrColliderGetTag(collider); if (!tag || strcmp(tag, data->tag)) { return false; } } + data->collider = collider; data->shape = shape; - vec3_set(data->position, x, y, z); - vec3_set(data->normal, nx, ny, nz); + vec3_init(data->position, position); + vec3_init(data->normal, normal); data->distance = vec3_distance(data->origin, data->position); return true; } -static bool raycastClosestCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) { +static bool raycastClosestCallback(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata) { RaycastData* data = userdata; if (data->tag) { - const char* tag = NULL; // TODO + const char* tag = lovrColliderGetTag(collider); if (!tag || strcmp(tag, data->tag)) { return false; } } - float position[3]; - vec3_set(position, x, y, z); float distance = vec3_distance(data->origin, position); if (distance < data->distance) { vec3_init(data->position, position); - vec3_set(data->normal, nx, ny, nz); + vec3_init(data->normal, normal); data->distance = distance; + data->collider = collider; data->shape = shape; } return false; } -static bool queryCallback(Shape* shape, void* userdata) { +static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) { lua_State* L = userdata; lua_pushvalue(L, -1); - luax_pushshape(L, shape); - lua_call(L, 1, 1); + luax_pushtype(L, Collider, collider); + lua_pushinteger(L, shape); + lua_call(L, 2, 1); bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1); lua_pop(L, 1); return shouldStop; @@ -309,15 +312,16 @@ static int l_lovrWorldRaycastAny(lua_State* L) { RaycastData data = { 0 }; data.tag = lua_tostring(L, index); lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastAnyCallback, &data); - if (data.shape) { - luax_pushshape(L, data.shape); + if (data.collider) { + luax_pushtype(L, Collider, data.collider); + lua_pushinteger(L, data.shape); lua_pushnumber(L, data.position[0]); lua_pushnumber(L, data.position[1]); lua_pushnumber(L, data.position[2]); lua_pushnumber(L, data.normal[0]); lua_pushnumber(L, data.normal[1]); lua_pushnumber(L, data.normal[2]); - return 7; + return 8; } else { lua_pushnil(L); return 1; @@ -334,14 +338,15 @@ static int l_lovrWorldRaycastClosest(lua_State* L) { data.tag = lua_tostring(L, index); lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastClosestCallback, &data); if (data.shape) { - luax_pushshape(L, data.shape); + luax_pushtype(L, Collider, data.collider); + lua_pushinteger(L, data.shape); lua_pushnumber(L, data.position[0]); lua_pushnumber(L, data.position[1]); lua_pushnumber(L, data.position[2]); lua_pushnumber(L, data.normal[0]); lua_pushnumber(L, data.normal[1]); lua_pushnumber(L, data.normal[2]); - return 7; + return 8; } else { lua_pushnil(L); return 1; diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index fd5ae7a2..c40b8b9d 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -27,8 +27,8 @@ typedef Joint HingeJoint; typedef Joint SliderJoint; typedef void (*CollisionResolver)(World* world, void* userdata); -typedef bool (*RaycastCallback)(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata); -typedef bool (*QueryCallback)(Shape* shape, void* userdata); +typedef bool (*RaycastCallback)(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata); +typedef bool (*QueryCallback)(Collider* collider, uint32_t shape, void* userdata); bool lovrPhysicsInit(void); void lovrPhysicsDestroy(void); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 385acc76..8e1b9c75 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -172,32 +172,34 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa const JPH_Vec3 direction = { x2 - x1, y2 - y1, z2 - z1 }; JPH_AllHit_CastRayCollector* collector = JPH_AllHit_CastRayCollector_Create(); JPH_NarrowPhaseQuery_CastRayAll(query, &origin, &direction, collector, NULL, NULL, NULL); - size_t hit_count; - JPH_RayCastResult* hit_array = JPH_AllHit_CastRayCollector_GetHits(collector, &hit_count); - for (int i = 0; i < hit_count; i++) { - float x = x1 + hit_array[i].fraction * (x2 - x1); - float y = y1 + hit_array[i].fraction * (y2 - y1); - float z = z1 + hit_array[i].fraction * (z2 - z1); - // todo: assuming one shape per collider; doesn't support compound shape - Collider* collider = (Collider*) JPH_BodyInterface_GetUserData( - world->bodies, - hit_array[i].bodyID); - size_t count; - Shape* shape = lovrColliderGetShape(collider); - const JPH_RVec3 position = { x, y, z }; + + size_t count; + JPH_RayCastResult* hits = JPH_AllHit_CastRayCollector_GetHits(collector, &count); + + for (size_t i = 0; i < count; i++) { + Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, hits[i].bodyID); + + uint32_t shape = 0; + if (collider->shape->type == SHAPE_COMPOUND) { + JPH_SubShapeID id = hits[i].subShapeID2; + JPH_SubShapeID remainder; + shape = JPH_CompoundShape_GetSubShapeIndexFromID((JPH_CompoundShape*) collider->shape, id, &remainder); + } + + JPH_RVec3 position = { + x1 + hits[i].fraction * (x2 - x1), + y1 + hits[i].fraction * (y2 - y1), + z1 + hits[i].fraction * (z2 - z1) + }; + JPH_Vec3 normal; - JPH_Body_GetWorldSpaceSurfaceNormal(collider->body, hit_array[i].subShapeID2, &position, &normal); + JPH_Body_GetWorldSpaceSurfaceNormal(collider->body, hits[i].subShapeID2, &position, &normal); - bool shouldStop = callback( - shape, // assumes one shape per collider; todo: compound shapes - x, y, z, - normal.x, normal.y, normal.z, - userdata); - - if (shouldStop) { + if (callback(collider, shape, &position.x, &normal.x, userdata)) { break; } } + JPH_AllHit_CastRayCollector_Destroy(collector); } @@ -208,26 +210,25 @@ static bool lovrWorldQueryShape(World* world, JPH_Shape* shape, float position[3 mat4_translate(m, position[0], position[1], position[2]); mat4_scale(m, scale[0], scale[1], scale[2]); - JPH_Vec3 direction = { 0.f }; - JPH_RVec3 base_offset = { 0.f }; + JPH_Vec3 direction = { 0.f, 0.f, 0.f }; + JPH_RVec3 base_offset = { 0.f, 0.f, 0.f }; const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system); JPH_AllHit_CastShapeCollector_Reset(state.castShapeCollector); JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, state.castShapeCollector); - size_t hit_count; - JPH_ShapeCastResult* hit_array = JPH_AllHit_CastShapeCollector_GetHits(state.castShapeCollector, &hit_count); - for (int i = 0; i < hit_count; i++) { + + size_t count; + JPH_AllHit_CastShapeCollector_GetHits(state.castShapeCollector, &count); + + for (size_t i = 0; i < count; i++) { JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(state.castShapeCollector, i); - Collider* collider = (Collider*) JPH_BodyInterface_GetUserData( - world->bodies, - id); - size_t count; - Shape* shape = lovrColliderGetShape(collider); - bool shouldStop = callback(shape, userdata); - if (shouldStop) { + Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, id); + + if (callback(collider, 0, userdata)) { break; } } - return hit_count > 0; + + return count > 0; } bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata) { From 930e71307991aeec559dc505f0a1706d25a132d5 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 21:41:12 -0700 Subject: [PATCH 10/26] Add Collider:get/setShapeOffset; --- src/api/l_physics_collider.c | 27 ++++++++++++++++++++ src/modules/physics/physics.h | 2 ++ src/modules/physics/physics_jolt.c | 40 ++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index d9ba26fd..234e0390 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -46,6 +46,31 @@ static int l_lovrColliderSetShape(lua_State* L) { return 0; } +static int l_lovrColliderGetShapeOffset(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + float position[3], orientation[4], angle, ax, ay, az; + lovrColliderGetShapeOffset(collider, position, orientation); + quat_getAngleAxis(orientation, &angle, &ax, &ay, &az); + lua_pushnumber(L, position[0]); + lua_pushnumber(L, position[1]); + lua_pushnumber(L, position[2]); + lua_pushnumber(L, angle); + lua_pushnumber(L, ax); + lua_pushnumber(L, ay); + lua_pushnumber(L, az); + return 7; +} + +static int l_lovrColliderSetShapeOffset(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + int index = 2; + float position[3], orientation[4]; + index = luax_readvec3(L, index, position, NULL); + index = luax_readquat(L, index, orientation, NULL); + lovrColliderSetShapeOffset(collider, position, orientation); + return 0; +} + static int l_lovrColliderGetJoints(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); size_t count; @@ -561,6 +586,8 @@ const luaL_Reg lovrCollider[] = { { "getWorld", l_lovrColliderGetWorld }, { "getShape", l_lovrColliderGetShape }, { "setShape", l_lovrColliderSetShape }, + { "getShapeOffset", l_lovrColliderGetShapeOffset }, + { "setShapeOffset", l_lovrColliderSetShapeOffset }, { "getJoints", l_lovrColliderGetJoints }, { "getUserData", l_lovrColliderGetUserData }, { "setUserData", l_lovrColliderSetUserData }, diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index c40b8b9d..7e8d135b 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -95,6 +95,8 @@ World* lovrColliderGetWorld(Collider* collider); Collider* lovrColliderGetNext(Collider* collider); Shape* lovrColliderGetShape(Collider* collider); void lovrColliderSetShape(Collider* collider, Shape* shape); +void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation); +void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation); Joint** lovrColliderGetJoints(Collider* collider, size_t* count); const char* lovrColliderGetTag(Collider* collider); bool lovrColliderSetTag(Collider* collider, const char* tag); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 8e1b9c75..4ced7534 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -425,6 +425,46 @@ void lovrColliderSetShape(Collider* collider, Shape* shape) { } } +void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation) { + if (!collider->shape) { + vec3_set(position, 0.f, 0.f, 0.f); + quat_identity(orientation); + return; + } + + const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id); + + if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) { + JPH_Vec3 jposition; + JPH_Quat jrotation; + JPH_RotatedTranslatedShape_GetPosition((JPH_RotatedTranslatedShape*) shape, &jposition); + JPH_RotatedTranslatedShape_GetRotation((JPH_RotatedTranslatedShape*) shape, &jrotation); + vec3_init(position, &jposition.x); + quat_init(orientation, &jrotation.x); + } else { + vec3_set(position, 0.f, 0.f, 0.f); + quat_identity(orientation); + } +} + +void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation) { + if (!collider->shape) { + return; + } + + const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id); + + if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) { + JPH_Shape_Destroy((JPH_Shape*) shape); + } + + JPH_Vec3 jposition = { position[0], position[1], position[2] }; + JPH_Quat jrotation = { orientation[0], orientation[1], orientation[2], orientation[3] }; + shape = (JPH_Shape*) JPH_RotatedTranslatedShape_Create(&jposition, &jrotation, collider->shape->shape); + bool updateMass = collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN; + JPH_BodyInterface_SetShape(collider->world->body_interface, collider->id, shape, updateMass, JPH_Activation_Activate); +} + Joint** lovrColliderGetJoints(Collider* collider, size_t* count) { *count = collider->joints.length; return collider->joints.data; From 051266f8eab89e8940722a8cddffc960fcffda50 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 21:52:51 -0700 Subject: [PATCH 11/26] Collider shape is required I think; Jolt doesn't really support bodies without shapes. --- src/api/l_physics_collider.c | 14 +++----------- src/modules/physics/physics_jolt.c | 10 ---------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index 234e0390..8c6e15ab 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -27,22 +27,14 @@ static int l_lovrColliderGetWorld(lua_State* L) { static int l_lovrColliderGetShape(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); Shape* shape = lovrColliderGetShape(collider); - if (shape) { - luax_pushshape(L, shape); - } else { - lua_pushnil(L); - } + luax_pushshape(L, shape); return 1; } static int l_lovrColliderSetShape(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - if (lua_isnoneornil(L, 2)) { - lovrColliderSetShape(collider, NULL); - } else { - Shape* shape = luax_checkshape(L, 2); - lovrColliderSetShape(collider, shape); - } + Shape* shape = luax_checkshape(L, 2); + lovrColliderSetShape(collider, shape); return 0; } diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 4ced7534..ed38ab5e 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -426,12 +426,6 @@ void lovrColliderSetShape(Collider* collider, Shape* shape) { } void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation) { - if (!collider->shape) { - vec3_set(position, 0.f, 0.f, 0.f); - quat_identity(orientation); - return; - } - const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id); if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) { @@ -448,10 +442,6 @@ void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orie } void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation) { - if (!collider->shape) { - return; - } - const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id); if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) { From b809db1d83ec4c4d2fdab00a2f696b01bd867202 Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 00:35:03 -0700 Subject: [PATCH 12/26] ODE compatibility; --- src/modules/physics/physics_ode.c | 151 +++++++++++++++++------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index f3124ba2..6d1abf2a 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -22,7 +22,7 @@ struct Collider { Collider* prev; Collider* next; uint32_t tag; - arr_t(Shape*) shapes; + Shape* shape; arr_t(Joint*) joints; float friction; float restitution; @@ -66,8 +66,9 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) { RaycastCallback callback = data->callback; void* userdata = data->userdata; Shape* shape = dGeomGetData(b); + Collider* collider = dBodyGetData(dGeomGetBody(b)); - if (!shape) { + if (!shape || !collider) { return; } @@ -75,9 +76,7 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) { int count = dCollide(a, b, MAX_CONTACTS, &contact->geom, sizeof(dContact)); for (int i = 0; i < count; i++) { dContactGeom g = contact[i].geom; - data->shouldStop = callback( - shape, g.pos[0], g.pos[1], g.pos[2], g.normal[0], g.normal[1], g.normal[2], userdata - ); + data->shouldStop = callback(collider, 0, g.pos, g.normal, userdata); } } @@ -93,14 +92,15 @@ static void queryCallback(void* d, dGeomID a, dGeomID b) { if (data->shouldStop) return; Shape* shape = dGeomGetData(b); - if (!shape) { + Collider* collider = dBodyGetData(dGeomGetBody(b)); + if (!shape || !collider) { return; } dContactGeom contact; if (dCollide(a, b, 1 | CONTACTS_UNIMPORTANT, &contact, sizeof(contact))) { if (data->callback) { - data->shouldStop = data->callback(shape, data->userdata); + data->shouldStop = data->callback(collider, 0, data->userdata); } else { data->shouldStop = true; } @@ -445,7 +445,6 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) { collider->restitution = 0; collider->tag = NO_TAG; dBodySetData(collider->body, collider); - arr_init(&collider->shapes); arr_init(&collider->joints); lovrColliderSetPosition(collider, x, y, z); @@ -467,7 +466,6 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) { void lovrColliderDestroy(void* ref) { Collider* collider = ref; lovrColliderDestroyData(collider); - arr_free(&collider->shapes); arr_free(&collider->joints); lovrFree(collider); } @@ -477,13 +475,9 @@ void lovrColliderDestroyData(Collider* collider) { return; } + lovrColliderSetShape(collider, NULL); + size_t count; - - Shape** shapes = lovrColliderGetShapes(collider, &count); - for (size_t i = 0; i < count; i++) { - lovrColliderRemoveShape(collider, shapes[i]); - } - Joint** joints = lovrColliderGetJoints(collider, &count); for (size_t i = 0; i < count; i++) { lovrRelease(joints[i], lovrJointDestroy); @@ -521,38 +515,50 @@ Collider* lovrColliderGetNext(Collider* collider) { return collider->next; } -void lovrColliderAddShape(Collider* collider, Shape* shape) { - lovrRetain(shape); - - if (shape->collider) { - lovrColliderRemoveShape(shape->collider, shape); - } - - shape->collider = collider; - dGeomSetBody(shape->id, collider->body); - dSpaceID newSpace = collider->world->space; - dSpaceAdd(newSpace, shape->id); +Shape* lovrColliderGetShape(Collider* collider) { + return collider->shape; } -void lovrColliderRemoveShape(Collider* collider, Shape* shape) { - if (shape->collider == collider) { - dSpaceRemove(collider->world->space, shape->id); - dGeomSetBody(shape->id, 0); - shape->collider = NULL; - lovrRelease(shape, lovrShapeDestroy); +void lovrColliderSetShape(Collider* collider, Shape* shape) { + if (collider->shape) { + dSpaceRemove(collider->world->space, collider->shape->id); + dGeomSetBody(collider->shape->id, 0); + collider->shape->collider = NULL; + lovrRelease(collider->shape, lovrShapeDestroy); } -} -Shape** lovrColliderGetShapes(Collider* collider, size_t* count) { - arr_clear(&collider->shapes); - for (dGeomID geom = dBodyGetFirstGeom(collider->body); geom; geom = dBodyGetNextGeom(geom)) { - Shape* shape = dGeomGetData(geom); - if (shape) { - arr_push(&collider->shapes, shape); + collider->shape = shape; + + if (shape) { + if (shape->collider) { + lovrColliderSetShape(shape->collider, NULL); } + + shape->collider = collider; + dGeomSetBody(shape->id, collider->body); + dSpaceID newSpace = collider->world->space; + dSpaceAdd(newSpace, shape->id); + lovrRetain(shape); } - *count = collider->shapes.length; - return collider->shapes.data; +} + +void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation) { + const dReal* p = dGeomGetOffsetPosition(collider->shape->id); + position[0] = p[0]; + position[1] = p[1]; + position[2] = p[2]; + dReal q[4]; + dGeomGetOffsetQuaternion(collider->shape->id, q); + orientation[0] = q[1]; + orientation[1] = q[2]; + orientation[2] = q[3]; + orientation[3] = q[0]; +} + +void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation) { + dGeomSetOffsetPosition(collider->shape->id, position[0], position[1], position[2]); + dReal q[4] = { orientation[3], orientation[0], orientation[1], orientation[2] }; + dGeomSetOffsetQuaternion(collider->shape->id, q); } Joint** lovrColliderGetJoints(Collider* collider, size_t* count) { @@ -908,31 +914,6 @@ void lovrShapeSetSensor(Shape* shape, bool sensor) { shape->sensor = sensor; } -void lovrShapeGetPosition(Shape* shape, float* x, float* y, float* z) { - const dReal* position = dGeomGetOffsetPosition(shape->id); - *x = position[0]; - *y = position[1]; - *z = position[2]; -} - -void lovrShapeSetPosition(Shape* shape, float x, float y, float z) { - dGeomSetOffsetPosition(shape->id, x, y, z); -} - -void lovrShapeGetOrientation(Shape* shape, float* orientation) { - dReal q[4]; - dGeomGetOffsetQuaternion(shape->id, q); - orientation[0] = q[1]; - orientation[1] = q[2]; - orientation[2] = q[3]; - orientation[3] = q[0]; -} - -void lovrShapeSetOrientation(Shape* shape, float* orientation) { - dReal q[4] = { orientation[3], orientation[0], orientation[1], orientation[2] }; - dGeomSetOffsetQuaternion(shape->id, q); -} - void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) { dMass m; dMassSetZero(&m); @@ -973,6 +954,8 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* case SHAPE_TERRAIN: { break; } + + default: break; } const dReal* position = dGeomGetOffsetPosition(shape->id); @@ -1131,6 +1114,42 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, return terrain; } +CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze) { + lovrThrow("ODE does not support compound shape"); +} + +bool lovrCompoundShapeIsFrozen(CompoundShape* shape) { + return false; +} + +void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) { + // +} + +void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { + // +} + +void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) { + // +} + +Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) { + return NULL; +} + +uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { + return 0; +} + +void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { + // +} + +void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { + // +} + void lovrJointDestroy(void* ref) { Joint* joint = ref; lovrJointDestroyData(joint); From ff0f39fc7b4192b98cbd1d107dcbaf980880fc7b Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 00:38:34 -0700 Subject: [PATCH 13/26] rm unused shape prototypes; --- src/modules/physics/physics.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 7e8d135b..ea83aaf7 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -164,10 +164,6 @@ bool lovrShapeIsEnabled(Shape* shape); void lovrShapeSetEnabled(Shape* shape, bool enabled); bool lovrShapeIsSensor(Shape* shape); void lovrShapeSetSensor(Shape* shape, bool sensor); -void lovrShapeGetPosition(Shape* shape, float* x, float* y, float* z); -void lovrShapeSetPosition(Shape* shape, float x, float y, float z); -void lovrShapeGetOrientation(Shape* shape, float* orientation); -void lovrShapeSetOrientation(Shape* shape, float* orientation); void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]); void lovrShapeGetAABB(Shape* shape, float aabb[6]); From 907d89c9135ae86a9fd288a3e0482ff1b4cb3dbb Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 11:55:12 -0700 Subject: [PATCH 14/26] Add Collider:getShapes for backcompat; --- src/api/l_physics_collider.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index 8c6e15ab..c6f25e14 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -557,6 +557,16 @@ static int l_lovrColliderSetTag(lua_State* L) { return 0; } +// Deprecated +static int l_lovrColliderGetShapes(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + Shape* shape = lovrColliderGetShape(collider); + lua_createtable(L, 1, 0); + luax_pushshape(L, shape); + lua_rawseti(L, -2, 1); + return 1; +} + // Deprecated static int l_lovrColliderIsGravityIgnored(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); @@ -631,6 +641,7 @@ const luaL_Reg lovrCollider[] = { { "setTag", l_lovrColliderSetTag }, // Deprecated + { "getShapes", l_lovrColliderGetShapes }, { "isGravityIgnored", l_lovrColliderIsGravityIgnored }, { "setGravityIgnored", l_lovrColliderSetGravityIgnored }, From f35cda7db89a516456ee9dc2d86feb37a4d68faa Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 18:04:07 -0700 Subject: [PATCH 15/26] lovrColliderCreate takes shape; Jolt requires a shape, also it saves a bit of work. --- src/api/l_physics_world.c | 20 +++++++------------- src/modules/physics/physics.h | 2 +- src/modules/physics/physics_jolt.c | 10 +++++----- src/modules/physics/physics_ode.c | 3 ++- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/api/l_physics_world.c b/src/api/l_physics_world.c index a2d47b94..99c16067 100644 --- a/src/api/l_physics_world.c +++ b/src/api/l_physics_world.c @@ -104,7 +104,7 @@ static int l_lovrWorldNewCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); float position[3]; luax_readvec3(L, 2, position, NULL); - Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); + Collider* collider = lovrColliderCreate(world, NULL, position[0], position[1], position[2]); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); return 1; @@ -114,9 +114,8 @@ static int l_lovrWorldNewBoxCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); float position[3]; int index = luax_readvec3(L, 2, position, NULL); - Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); BoxShape* shape = luax_newboxshape(L, index); - lovrColliderSetShape(collider, shape); + Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -128,9 +127,8 @@ static int l_lovrWorldNewCapsuleCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); float position[3]; int index = luax_readvec3(L, 2, position, NULL); - Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); CapsuleShape* shape = luax_newcapsuleshape(L, index); - lovrColliderSetShape(collider, shape); + Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -142,9 +140,8 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); float position[3]; int index = luax_readvec3(L, 2, position, NULL); - Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); CylinderShape* shape = luax_newcylindershape(L, index); - lovrColliderSetShape(collider, shape); + Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -156,9 +153,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); float position[3]; int index = luax_readvec3(L, 2, position, NULL); - Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]); SphereShape* shape = luax_newsphereshape(L, index); - lovrColliderSetShape(collider, shape); + Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -168,9 +164,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) { static int l_lovrWorldNewMeshCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); - Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f); MeshShape* shape = luax_newmeshshape(L, 2); - lovrColliderSetShape(collider, shape); + Collider* collider = lovrColliderCreate(world, shape, 0.f, 0.f, 0.f); lovrColliderInitInertia(collider, shape); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); @@ -180,9 +175,8 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) { static int l_lovrWorldNewTerrainCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); - Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f); TerrainShape* shape = luax_newterrainshape(L, 2); - lovrColliderSetShape(collider, shape); + Collider* collider = lovrColliderCreate(world, shape, 0.f, 0.f, 0.f); lovrColliderSetKinematic(collider, true); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index ea83aaf7..cbe5a787 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -86,7 +86,7 @@ void lovrWorldSetSleepingAllowed(World* world, bool allowed); // Collider -Collider* lovrColliderCreate(World* world, float x, float y, float z); +Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z); void lovrColliderDestroy(void* ref); void lovrColliderDestroyData(Collider* collider); bool lovrColliderIsDestroyed(Collider* collider); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index ed38ab5e..1dfb055f 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -315,7 +315,7 @@ void lovrWorldSetAngularDamping(World* world, float damping, float threshold) { // Collider -Collider* lovrColliderCreate(World* world, float x, float y, float z) { +Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z) { uint32_t count = JPH_PhysicsSystem_GetNumBodies(world->system); uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system); lovrCheck(count < limit, "Too many colliders!"); @@ -331,7 +331,7 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) { const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f }; // todo: a placeholder querySphere shape is used in collider, then replaced in lovrColliderAddShape JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3( - state.querySphere, &position, &rotation, motionType, objectLayer); + shape ? shape->shape : state.querySphere, &position, &rotation, motionType, objectLayer); collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings); JPH_BodyCreationSettings_Destroy(settings); collider->id = JPH_Body_GetID(collider->body); @@ -426,7 +426,7 @@ void lovrColliderSetShape(Collider* collider, Shape* shape) { } void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation) { - const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id); + const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id); if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) { JPH_Vec3 jposition; @@ -442,7 +442,7 @@ void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orie } void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation) { - const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id); + const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id); if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) { JPH_Shape_Destroy((JPH_Shape*) shape); @@ -452,7 +452,7 @@ void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orie JPH_Quat jrotation = { orientation[0], orientation[1], orientation[2], orientation[3] }; shape = (JPH_Shape*) JPH_RotatedTranslatedShape_Create(&jposition, &jrotation, collider->shape->shape); bool updateMass = collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN; - JPH_BodyInterface_SetShape(collider->world->body_interface, collider->id, shape, updateMass, JPH_Activation_Activate); + JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape, updateMass, JPH_Activation_Activate); } Joint** lovrColliderGetJoints(Collider* collider, size_t* count) { diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index 6d1abf2a..9e9f046b 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -436,7 +436,7 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch return (world->masks[i] & (1 << j)) && (world->masks[j] & (1 << i)); } -Collider* lovrColliderCreate(World* world, float x, float y, float z) { +Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z) { Collider* collider = lovrCalloc(sizeof(Collider)); collider->ref = 1; collider->body = dBodyCreate(world->id); @@ -447,6 +447,7 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) { dBodySetData(collider->body, collider); arr_init(&collider->joints); + lovrColliderSetShape(collider, shape); lovrColliderSetPosition(collider, x, y, z); // Adjust the world's collider list From 95cc6c2753626a8d9636dd3a2d68928dc9a3b172 Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 18:40:23 -0700 Subject: [PATCH 16/26] Shape fixes; - Collider always has Shape now. When left off or set to null, it's a tiny sphere (representing a point). - Preserve shape offset when changing shape. --- src/modules/physics/physics_jolt.c | 76 ++++++++++++++++++------------ 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 1dfb055f..becc04ee 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -43,6 +43,7 @@ struct Joint { static struct { bool initialized; + Shape* pointShape; JPH_Shape* queryBox; JPH_Shape* querySphere; JPH_AllHit_CastShapeCollector* castShapeCollector; @@ -69,14 +70,16 @@ static uint32_t findTag(World* world, const char* name) { bool lovrPhysicsInit(void) { if (state.initialized) return false; JPH_Init(32 * 1024 * 1024); - state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create(); + state.pointShape = lovrSphereShapeCreate(FLT_EPSILON); state.querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f); state.queryBox = (JPH_Shape*) JPH_BoxShape_Create(&(const JPH_Vec3) { .5, .5f, .5f }, 0.f); + state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create(); return state.initialized = true; } void lovrPhysicsDestroy(void) { if (!state.initialized) return; + lovrRelease(state.pointShape, lovrShapeDestroy); JPH_Shutdown(); state.initialized = false; } @@ -320,23 +323,26 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system); lovrCheck(count < limit, "Too many colliders!"); + if (!shape) shape = state.pointShape; + Collider* collider = lovrCalloc(sizeof(Collider)); collider->ref = 1; collider->world = world; + collider->shape = shape; collider->tag = UNTAGGED; - JPH_MotionType motionType = JPH_MotionType_Dynamic; - JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1; const JPH_RVec3 position = { x, y, z }; const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f }; - // todo: a placeholder querySphere shape is used in collider, then replaced in lovrColliderAddShape - JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3( - shape ? shape->shape : state.querySphere, &position, &rotation, motionType, objectLayer); + JPH_MotionType type = JPH_MotionType_Dynamic; + JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1; + JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(shape->shape, &position, &rotation, type, objectLayer); collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings); - JPH_BodyCreationSettings_Destroy(settings); collider->id = JPH_Body_GetID(collider->body); + JPH_BodyCreationSettings_Destroy(settings); + JPH_BodyInterface_AddBody(world->bodies, collider->id, JPH_Activation_Activate); JPH_BodyInterface_SetUserData(world->bodies, collider->id, (uint64_t) collider); + lovrColliderSetLinearDamping(collider, world->defaultLinearDamping, 0.f); lovrColliderSetAngularDamping(collider, world->defaultAngularDamping, 0.f); lovrColliderSetSleepingAllowed(collider, world->defaultIsSleepingAllowed); @@ -352,8 +358,8 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float world->head = collider; } - // The world owns a reference to the collider - lovrRetain(collider); + lovrRetain(collider->shape); + lovrRetain(collider); // The world owns a reference to the collider return collider; } @@ -406,22 +412,35 @@ Collider* lovrColliderGetNext(Collider* collider) { } Shape* lovrColliderGetShape(Collider* collider) { - return collider->shape; + return collider->shape == state.pointShape ? NULL : collider->shape; } void lovrColliderSetShape(Collider* collider, Shape* shape) { - if (shape != collider->shape) { - lovrRelease(collider->shape, lovrShapeDestroy); - collider->shape = shape; - lovrRetain(shape); + shape = shape ? shape : state.pointShape; - bool updateMass = true; - if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) { - lovrColliderSetKinematic(collider, true); - updateMass = false; - } + if (shape == collider->shape) { + return; + } - JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate); + float position[3], orientation[4]; + const JPH_Shape* parent = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id); + bool hasOffset = JPH_Shape_GetSubType(parent) == JPH_ShapeSubType_RotatedTranslated; + if (hasOffset) lovrColliderGetShapeOffset(collider, position, orientation); + + lovrRelease(collider->shape, lovrShapeDestroy); + collider->shape = shape; + lovrRetain(shape); + + bool updateMass = true; + if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) { + lovrColliderSetKinematic(collider, true); + updateMass = false; + } + + JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate); + + if (hasOffset) { + lovrColliderSetShapeOffset(collider, position, orientation); } } @@ -451,7 +470,7 @@ void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orie JPH_Vec3 jposition = { position[0], position[1], position[2] }; JPH_Quat jrotation = { orientation[0], orientation[1], orientation[2], orientation[3] }; shape = (JPH_Shape*) JPH_RotatedTranslatedShape_Create(&jposition, &jrotation, collider->shape->shape); - bool updateMass = collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN; + bool updateMass = collider->shape && (collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN); JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape, updateMass, JPH_Activation_Activate); } @@ -557,20 +576,17 @@ void lovrColliderSetAwake(Collider* collider, bool awake) { } float lovrColliderGetMass(Collider* collider) { - if (!collider->shape) return 0.f; JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body); return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties); } void lovrColliderSetMass(Collider* collider, float mass) { - if (collider->shape) { - JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body); - Shape* shape = collider->shape; - JPH_MassProperties* massProperties; - JPH_Shape_GetMassProperties(shape->shape, massProperties); - JPH_MassProperties_ScaleToMass(massProperties, mass); - JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties); - } + JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body); + Shape* shape = collider->shape; + JPH_MassProperties* massProperties; + JPH_Shape_GetMassProperties(shape->shape, massProperties); + JPH_MassProperties_ScaleToMass(massProperties, mass); + JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties); } void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]) { From 481a9dafa20232e75088bd82b64f6686c09969c1 Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 5 Apr 2024 18:44:04 -0700 Subject: [PATCH 17/26] newCollider takes optional Shape as first arg; --- src/api/l_physics_world.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/l_physics_world.c b/src/api/l_physics_world.c index 99c16067..dc551ecf 100644 --- a/src/api/l_physics_world.c +++ b/src/api/l_physics_world.c @@ -102,9 +102,10 @@ static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) { static int l_lovrWorldNewCollider(lua_State* L) { World* world = luax_checktype(L, 1, World); + Shape* shape = luax_totype(L, 2, Shape); float position[3]; - luax_readvec3(L, 2, position, NULL); - Collider* collider = lovrColliderCreate(world, NULL, position[0], position[1], position[2]); + luax_readvec3(L, 2 + !!shape, position, NULL); + Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]); luax_pushtype(L, Collider, collider); lovrRelease(collider, lovrColliderDestroy); return 1; From 5751068728a10e6249e17d0c8c1d532358deae1f Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 6 Apr 2024 00:36:42 -0700 Subject: [PATCH 18/26] Move Shape:is/setSensor and Shape:is/setEnabled to Collider; --- src/api/l_physics_collider.c | 31 +++++++++++++++++++++++ src/api/l_physics_shapes.c | 30 ---------------------- src/modules/physics/physics.h | 8 +++--- src/modules/physics/physics_jolt.c | 38 ++++++++++++++-------------- src/modules/physics/physics_ode.c | 40 ++++++++++++++---------------- 5 files changed, 73 insertions(+), 74 deletions(-) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index c6f25e14..3134fb27 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -17,6 +17,20 @@ static int l_lovrColliderIsDestroyed(lua_State* L) { return 1; } +static int l_lovrColliderIsEnabled(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + bool enabled = lovrColliderIsEnabled(collider); + lua_pushboolean(L, enabled); + return 1; +} + +static int l_lovrColliderSetEnabled(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + bool enable = lua_toboolean(L, 2); + lovrColliderSetEnabled(collider, enable); + return 1; +} + static int l_lovrColliderGetWorld(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); World* world = lovrColliderGetWorld(collider); @@ -123,6 +137,19 @@ static int l_lovrColliderSetKinematic(lua_State* L) { return 0; } +static int l_lovrColliderIsSensor(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + lua_pushboolean(L, lovrColliderIsSensor(collider)); + return 1; +} + +static int l_lovrColliderSetSensor(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + bool sensor = lua_toboolean(L, 2); + lovrColliderSetSensor(collider, sensor); + return 0; +} + static int l_lovrColliderIsContinuous(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); bool continuous = lovrColliderIsContinuous(collider); @@ -585,6 +612,8 @@ static int l_lovrColliderSetGravityIgnored(lua_State* L) { const luaL_Reg lovrCollider[] = { { "destroy", l_lovrColliderDestroy }, { "isDestroyed", l_lovrColliderIsDestroyed }, + { "isEnabled", l_lovrColliderIsEnabled }, + { "setEnabled", l_lovrColliderSetEnabled }, { "getWorld", l_lovrColliderGetWorld }, { "getShape", l_lovrColliderGetShape }, { "setShape", l_lovrColliderSetShape }, @@ -595,6 +624,8 @@ const luaL_Reg lovrCollider[] = { { "setUserData", l_lovrColliderSetUserData }, { "isKinematic", l_lovrColliderIsKinematic }, { "setKinematic", l_lovrColliderSetKinematic }, + { "isSensor", l_lovrColliderIsSensor }, + { "setSensor", l_lovrColliderSetSensor }, { "isContinuous", l_lovrColliderIsContinuous }, { "setContinuous", l_lovrColliderSetContinuous }, { "getGravityScale", l_lovrColliderGetGravityScale }, diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index b3125238..8a5225fb 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -229,32 +229,6 @@ static int l_lovrShapeGetType(lua_State* L) { return 1; } -static int l_lovrShapeIsEnabled(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - lua_pushboolean(L, lovrShapeIsEnabled(shape)); - return 1; -} - -static int l_lovrShapeSetEnabled(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - bool enabled = lua_toboolean(L, 2); - lovrShapeSetEnabled(shape, enabled); - return 0; -} - -static int l_lovrShapeIsSensor(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - lua_pushboolean(L, lovrShapeIsSensor(shape)); - return 1; -} - -static int l_lovrShapeSetSensor(lua_State* L) { - Shape* shape = luax_checkshape(L, 1); - bool sensor = lua_toboolean(L, 2); - lovrShapeSetSensor(shape, sensor); - return 0; -} - static void luax_pushshapestash(lua_State* L) { lua_getfield(L, LUA_REGISTRYINDEX, "_lovrshapestash"); @@ -321,10 +295,6 @@ static int l_lovrShapeGetAABB(lua_State* L) { #define lovrShape \ { "destroy", l_lovrShapeDestroy }, \ { "getType", l_lovrShapeGetType }, \ - { "isEnabled", l_lovrShapeIsEnabled }, \ - { "setEnabled", l_lovrShapeSetEnabled }, \ - { "isSensor", l_lovrShapeIsSensor }, \ - { "setSensor", l_lovrShapeSetSensor }, \ { "getUserData", l_lovrShapeGetUserData }, \ { "setUserData", l_lovrShapeSetUserData }, \ { "getMass", l_lovrShapeGetMass }, \ diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index cbe5a787..af75b897 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -90,6 +90,8 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float void lovrColliderDestroy(void* ref); void lovrColliderDestroyData(Collider* collider); bool lovrColliderIsDestroyed(Collider* collider); +bool lovrColliderIsEnabled(Collider* collider); +void lovrColliderSetEnabled(Collider* collider, bool enable); void lovrColliderInitInertia(Collider* collider, Shape* shape); World* lovrColliderGetWorld(Collider* collider); Collider* lovrColliderGetNext(Collider* collider); @@ -106,6 +108,8 @@ float lovrColliderGetRestitution(Collider* collider); void lovrColliderSetRestitution(Collider* collider, float restitution); bool lovrColliderIsKinematic(Collider* collider); void lovrColliderSetKinematic(Collider* collider, bool kinematic); +bool lovrColliderIsSensor(Collider* collider); +void lovrColliderSetSensor(Collider* collider, bool sensor); bool lovrColliderIsContinuous(Collider* collider); void lovrColliderSetContinuous(Collider* collider, bool continuous); float lovrColliderGetGravityScale(Collider* collider); @@ -160,10 +164,6 @@ typedef enum { void lovrShapeDestroy(void* ref); void lovrShapeDestroyData(Shape* shape); ShapeType lovrShapeGetType(Shape* shape); -bool lovrShapeIsEnabled(Shape* shape); -void lovrShapeSetEnabled(Shape* shape, bool enabled); -bool lovrShapeIsSensor(Shape* shape); -void lovrShapeSetSensor(Shape* shape, bool sensor); void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]); void lovrShapeGetAABB(Shape* shape, float aabb[6]); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index becc04ee..f6bddad7 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -399,6 +399,18 @@ bool lovrColliderIsDestroyed(Collider* collider) { return !collider->body; } +bool lovrColliderIsEnabled(Collider* collider) { + return JPH_BodyInterface_IsAdded(collider->world->bodies, collider->id); +} + +void lovrColliderSetEnabled(Collider* collider, bool enable) { + if (enable && !lovrColliderIsEnabled(collider)) { + JPH_BodyInterface_AddBody(collider->world->bodies, collider->id, JPH_Activation_DontActivate); + } else if (!enable && lovrColliderIsEnabled(collider)) { + JPH_BodyInterface_RemoveBody(collider->world->bodies, collider->id); + } +} + void lovrColliderInitInertia(Collider* collider, Shape* shape) { // } @@ -538,6 +550,14 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) { } } +bool lovrColliderIsSensor(Collider* collider) { + return JPH_Body_IsSensor(collider->body); +} + +void lovrColliderSetSensor(Collider* collider, bool sensor) { + JPH_Body_SetIsSensor(collider->body, sensor); +} + bool lovrColliderIsContinuous(Collider* collider) { return JPH_BodyInterface_GetMotionQuality(collider->world->bodies, collider->id) == JPH_MotionQuality_LinearCast; } @@ -825,24 +845,6 @@ ShapeType lovrShapeGetType(Shape* shape) { return shape->type; } -bool lovrShapeIsEnabled(Shape* shape) { - return true; -} - -void lovrShapeSetEnabled(Shape* shape, bool enabled) { - if (!enabled) { - lovrLog(LOG_WARN, "PHY", "Jolt doesn't support disabling shapes"); - } -} - -bool lovrShapeIsSensor(Shape* shape) { - lovrThrow("NYI"); -} - -void lovrShapeSetSensor(Shape* shape, bool sensor) { - lovrThrow("NYI"); -} - void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) { // } diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index 9e9f046b..8004b7b7 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -26,6 +26,7 @@ struct Collider { arr_t(Joint*) joints; float friction; float restitution; + bool sensor; }; struct Shape { @@ -35,7 +36,6 @@ struct Shape { Collider* collider; void* vertices; void* indices; - bool sensor; }; struct Joint { @@ -279,7 +279,7 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float res int contactCount = dCollide(a->id, b->id, MAX_CONTACTS, &contacts[0].geom, sizeof(dContact)); - if (!a->sensor && !b->sensor) { + if (!colliderA->sensor && !colliderB->sensor) { for (int c = 0; c < contactCount; c++) { dJointID joint = dJointCreateContact(world->id, world->contactGroup, &contacts[c]); dJointAttach(joint, colliderA->body, colliderB->body); @@ -500,6 +500,14 @@ bool lovrColliderIsDestroyed(Collider* collider) { return !collider->body; } +bool lovrColliderIsEnabled(Collider* collider) { + return true; +} + +void lovrColliderSetEnabled(Collider* collider, bool enable) { + // +} + void lovrColliderInitInertia(Collider* collider, Shape* shape) { // compute inertia matrix for default density const float density = 1.0f; @@ -617,6 +625,14 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) { } } +bool lovrColliderIsSensor(Collider* collider) { + return collider->sensor; +} + +void lovrColliderSetSensor(Collider* collider, bool sensor) { + collider->sensor = sensor; +} + bool lovrColliderIsContinuous(Collider* collider) { return false; } @@ -895,26 +911,6 @@ Collider* lovrShapeGetCollider(Shape* shape) { return shape->collider; } -bool lovrShapeIsEnabled(Shape* shape) { - return dGeomIsEnabled(shape->id); -} - -void lovrShapeSetEnabled(Shape* shape, bool enabled) { - if (enabled) { - dGeomEnable(shape->id); - } else { - dGeomDisable(shape->id); - } -} - -bool lovrShapeIsSensor(Shape* shape) { - return shape->sensor; -} - -void lovrShapeSetSensor(Shape* shape, bool sensor) { - shape->sensor = sensor; -} - void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) { dMass m; dMassSetZero(&m); From 8bdab9f2d4335a3cfec5415ffa36f0cab17e9658 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 6 Apr 2024 13:28:30 -0700 Subject: [PATCH 19/26] Shape:getAABB; --- src/api/l_physics_shapes.c | 11 +++++++++-- src/modules/physics/physics.h | 2 +- src/modules/physics/physics_jolt.c | 18 ++++++++++++++++-- src/modules/physics/physics_ode.c | 2 +- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 8a5225fb..25183021 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -284,8 +284,15 @@ static int l_lovrShapeGetMass(lua_State* L) { static int l_lovrShapeGetAABB(lua_State* L) { Shape* shape = luax_checkshape(L, 1); - float aabb[6]; - lovrShapeGetAABB(shape, aabb); + float position[3], orientation[4], aabb[6]; + if (lua_gettop(L) >= 2) { + int index = 2; + index = luax_readvec3(L, index, position, NULL); + index = luax_readquat(L, index, orientation, NULL); + lovrShapeGetAABB(shape, position, orientation, aabb); + } else { + lovrShapeGetAABB(shape, NULL, NULL, aabb); + } for (int i = 0; i < 6; i++) { lua_pushnumber(L, aabb[i]); } diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index af75b897..42871e78 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -165,7 +165,7 @@ void lovrShapeDestroy(void* ref); void lovrShapeDestroyData(Shape* shape); ShapeType lovrShapeGetType(Shape* shape); void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]); -void lovrShapeGetAABB(Shape* shape, float aabb[6]); +void lovrShapeGetAABB(Shape* shape, float position[3], float orientation[4], float aabb[6]); SphereShape* lovrSphereShapeCreate(float radius); float lovrSphereShapeGetRadius(SphereShape* sphere); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index f6bddad7..745eaa10 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -849,8 +849,22 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* // } -void lovrShapeGetAABB(Shape* shape, float aabb[6]) { - // TODO +void lovrShapeGetAABB(Shape* shape, float position[3], float orientation[4], float aabb[6]) { + JPH_AABox box; + if (!position && !orientation) { + JPH_Shape_GetLocalBounds(shape->shape, &box); + } else { + JPH_RMatrix4x4 transform; + JPH_Vec3 scale = { 1.f, 1.f, 1.f }; + mat4_fromPose(&transform.m11, position, orientation); + JPH_Shape_GetWorldSpaceBounds(shape->shape, &transform, &scale, &box); + } + aabb[0] = box.min.x; + aabb[1] = box.max.x; + aabb[2] = box.min.y; + aabb[3] = box.max.y; + aabb[4] = box.min.z; + aabb[5] = box.max.z; } SphereShape* lovrSphereShapeCreate(float radius) { diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index 8004b7b7..ed3ab4a2 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -976,7 +976,7 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* inertia[5] = m.I[9]; } -void lovrShapeGetAABB(Shape* shape, float aabb[6]) { +void lovrShapeGetAABB(Shape* shape, float position[3], float orientation[4], float aabb[6]) { dGeomGetAABB(shape->id, aabb); } From b589cec9753fe3cede2ce5a11789856044384612 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:22:24 -0700 Subject: [PATCH 20/26] Collider:getShape takes optional child index; For convenience when you're trying to dig a leaf shape out of a CompoundShape. It's ignored if the collider's shape is not a CompoundShape. --- src/api/l_physics_collider.c | 5 +++-- src/modules/physics/physics.h | 2 +- src/modules/physics/physics_jolt.c | 18 ++++++++++++------ src/modules/physics/physics_ode.c | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index 3134fb27..7ad574b6 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -40,7 +40,8 @@ static int l_lovrColliderGetWorld(lua_State* L) { static int l_lovrColliderGetShape(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - Shape* shape = lovrColliderGetShape(collider); + uint32_t child = lua_gettop(L) == 1 ? ~0u : luax_checku32(L, 2) - 1; + Shape* shape = lovrColliderGetShape(collider, child); luax_pushshape(L, shape); return 1; } @@ -587,7 +588,7 @@ static int l_lovrColliderSetTag(lua_State* L) { // Deprecated static int l_lovrColliderGetShapes(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - Shape* shape = lovrColliderGetShape(collider); + Shape* shape = lovrColliderGetShape(collider, ~0u); lua_createtable(L, 1, 0); luax_pushshape(L, shape); lua_rawseti(L, -2, 1); diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 42871e78..f573db68 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -95,7 +95,7 @@ void lovrColliderSetEnabled(Collider* collider, bool enable); void lovrColliderInitInertia(Collider* collider, Shape* shape); World* lovrColliderGetWorld(Collider* collider); Collider* lovrColliderGetNext(Collider* collider); -Shape* lovrColliderGetShape(Collider* collider); +Shape* lovrColliderGetShape(Collider* collider, uint32_t child); void lovrColliderSetShape(Collider* collider, Shape* shape); void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation); void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 745eaa10..806d3f7f 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -323,19 +323,17 @@ Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system); lovrCheck(count < limit, "Too many colliders!"); - if (!shape) shape = state.pointShape; - Collider* collider = lovrCalloc(sizeof(Collider)); collider->ref = 1; collider->world = world; - collider->shape = shape; + collider->shape = shape ? shape : state.pointShape; collider->tag = UNTAGGED; const JPH_RVec3 position = { x, y, z }; const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f }; JPH_MotionType type = JPH_MotionType_Dynamic; JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1; - JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(shape->shape, &position, &rotation, type, objectLayer); + JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(collider->shape->shape, &position, &rotation, type, objectLayer); collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings); collider->id = JPH_Body_GetID(collider->body); JPH_BodyCreationSettings_Destroy(settings); @@ -423,8 +421,16 @@ Collider* lovrColliderGetNext(Collider* collider) { return collider->next; } -Shape* lovrColliderGetShape(Collider* collider) { - return collider->shape == state.pointShape ? NULL : collider->shape; +Shape* lovrColliderGetShape(Collider* collider, uint32_t child) { + if (collider->shape == state.pointShape) { + return NULL; + } + + if (child == ~0u || collider->shape->type != SHAPE_COMPOUND) { + return collider->shape; + } + + return lovrCompoundShapeGetShape(collider->shape, child); } void lovrColliderSetShape(Collider* collider, Shape* shape) { diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index ed3ab4a2..1d72ffe7 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -524,7 +524,7 @@ Collider* lovrColliderGetNext(Collider* collider) { return collider->next; } -Shape* lovrColliderGetShape(Collider* collider) { +Shape* lovrColliderGetShape(Collider* collider, uint32_t child) { return collider->shape; } From 2ac0d6946e467c0bd1449f3983428d32092c01bf Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:27:30 -0700 Subject: [PATCH 21/26] Move shape arg to last argument of query callbacks; Also fix an off-by-one error. --- src/api/l_physics_world.c | 14 +++++++------- src/modules/physics/physics.h | 4 ++-- src/modules/physics/physics_jolt.c | 6 +++--- src/modules/physics/physics_ode.c | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/api/l_physics_world.c b/src/api/l_physics_world.c index dc551ecf..8a036deb 100644 --- a/src/api/l_physics_world.c +++ b/src/api/l_physics_world.c @@ -27,17 +27,17 @@ static int nextOverlap(lua_State* L) { } } -static bool raycastCallback(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata) { +static bool raycastCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) { lua_State* L = userdata; lua_pushvalue(L, -1); luax_pushtype(L, Collider, collider); - lua_pushinteger(L, shape); lua_pushnumber(L, position[0]); lua_pushnumber(L, position[1]); lua_pushnumber(L, position[2]); lua_pushnumber(L, normal[0]); lua_pushnumber(L, normal[1]); lua_pushnumber(L, normal[2]); + lua_pushinteger(L, shape + 1); lua_call(L, 8, 1); bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1); lua_pop(L, 1); @@ -54,7 +54,7 @@ typedef struct { float normal[3]; } RaycastData; -static bool raycastAnyCallback(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata) { +static bool raycastAnyCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) { RaycastData* data = userdata; if (data->tag) { const char* tag = lovrColliderGetTag(collider); @@ -70,7 +70,7 @@ static bool raycastAnyCallback(Collider* collider, uint32_t shape, float positio return true; } -static bool raycastClosestCallback(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata) { +static bool raycastClosestCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) { RaycastData* data = userdata; if (data->tag) { const char* tag = lovrColliderGetTag(collider); @@ -93,7 +93,7 @@ static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) { lua_State* L = userdata; lua_pushvalue(L, -1); luax_pushtype(L, Collider, collider); - lua_pushinteger(L, shape); + lua_pushinteger(L, shape + 1); lua_call(L, 2, 1); bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1); lua_pop(L, 1); @@ -309,13 +309,13 @@ static int l_lovrWorldRaycastAny(lua_State* L) { lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastAnyCallback, &data); if (data.collider) { luax_pushtype(L, Collider, data.collider); - lua_pushinteger(L, data.shape); lua_pushnumber(L, data.position[0]); lua_pushnumber(L, data.position[1]); lua_pushnumber(L, data.position[2]); lua_pushnumber(L, data.normal[0]); lua_pushnumber(L, data.normal[1]); lua_pushnumber(L, data.normal[2]); + lua_pushinteger(L, data.shape + 1); return 8; } else { lua_pushnil(L); @@ -334,13 +334,13 @@ static int l_lovrWorldRaycastClosest(lua_State* L) { lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastClosestCallback, &data); if (data.shape) { luax_pushtype(L, Collider, data.collider); - lua_pushinteger(L, data.shape); lua_pushnumber(L, data.position[0]); lua_pushnumber(L, data.position[1]); lua_pushnumber(L, data.position[2]); lua_pushnumber(L, data.normal[0]); lua_pushnumber(L, data.normal[1]); lua_pushnumber(L, data.normal[2]); + lua_pushinteger(L, data.shape + 1); return 8; } else { lua_pushnil(L); diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index f573db68..8cf4eba2 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -27,8 +27,8 @@ typedef Joint HingeJoint; typedef Joint SliderJoint; typedef void (*CollisionResolver)(World* world, void* userdata); -typedef bool (*RaycastCallback)(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata); -typedef bool (*QueryCallback)(Collider* collider, uint32_t shape, void* userdata); +typedef bool (*RaycastCallback)(Collider* collider, float position[3], float normal[3], uint32_t child, void* userdata); +typedef bool (*QueryCallback)(Collider* collider, uint32_t child, void* userdata); bool lovrPhysicsInit(void); void lovrPhysicsDestroy(void); diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 806d3f7f..7b778dca 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -181,12 +181,12 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa for (size_t i = 0; i < count; i++) { Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, hits[i].bodyID); + uint32_t child = 0; - uint32_t shape = 0; if (collider->shape->type == SHAPE_COMPOUND) { JPH_SubShapeID id = hits[i].subShapeID2; JPH_SubShapeID remainder; - shape = JPH_CompoundShape_GetSubShapeIndexFromID((JPH_CompoundShape*) collider->shape, id, &remainder); + child = JPH_CompoundShape_GetSubShapeIndexFromID((JPH_CompoundShape*) collider->shape, id, &remainder); } JPH_RVec3 position = { @@ -198,7 +198,7 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa JPH_Vec3 normal; JPH_Body_GetWorldSpaceSurfaceNormal(collider->body, hits[i].subShapeID2, &position, &normal); - if (callback(collider, shape, &position.x, &normal.x, userdata)) { + if (callback(collider, &position.x, &normal.x, child, userdata)) { break; } } diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index 1d72ffe7..bfb99abe 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -76,7 +76,7 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) { int count = dCollide(a, b, MAX_CONTACTS, &contact->geom, sizeof(dContact)); for (int i = 0; i < count; i++) { dContactGeom g = contact[i].geom; - data->shouldStop = callback(collider, 0, g.pos, g.normal, userdata); + data->shouldStop = callback(collider, g.pos, g.normal, 0, userdata); } } From 98601b3425a3ba8d81f3753e49b0b517a55d88a6 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:30:14 -0700 Subject: [PATCH 22/26] Collider:setShape accepts nil; Internally it still uses a teeny tiny sphere (it's kinda like the collider's shape is a "point"). --- src/api/l_physics_collider.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/api/l_physics_collider.c b/src/api/l_physics_collider.c index 7ad574b6..0b653fae 100644 --- a/src/api/l_physics_collider.c +++ b/src/api/l_physics_collider.c @@ -42,13 +42,17 @@ static int l_lovrColliderGetShape(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); uint32_t child = lua_gettop(L) == 1 ? ~0u : luax_checku32(L, 2) - 1; Shape* shape = lovrColliderGetShape(collider, child); - luax_pushshape(L, shape); + if (shape) { + luax_pushshape(L, shape); + } else { + lua_pushnil(L); + } return 1; } static int l_lovrColliderSetShape(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - Shape* shape = luax_checkshape(L, 2); + Shape* shape = lua_isnoneornil(L, 2) ? NULL : luax_checkshape(L, 2); lovrColliderSetShape(collider, shape); return 0; } From e36374c4cfbbe1e277def4362612abf1c6c45029 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:31:36 -0700 Subject: [PATCH 23/26] rm useless check; --- src/api/l_physics_shapes.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 25183021..d133291f 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -159,7 +159,6 @@ Shape* luax_newcompoundshape(lua_State* L, int index) { lua_rawgeti(L, -1, 1); shapes[i] = luax_checkshape(L, -1); - lovrCheck(shapes[i], "Expected a Shape for CompoundShape entry #%d", i + 1); lua_pop(L, 1); int index = 2; From 582ee1625ff890eb6e3c5799fe5387c8d458a33f Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:35:16 -0700 Subject: [PATCH 24/26] CompoundShape:replaceShape fixes; --- src/api/l_physics_shapes.c | 2 +- src/modules/physics/physics_jolt.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index d133291f..2d9f49a8 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -402,7 +402,7 @@ static int l_lovrCompoundShapeAddShape(lua_State* L) { static int l_lovrCompoundShapeReplaceShape(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - uint32_t index = luax_checku32(L, 2); + uint32_t index = luax_checku32(L, 2) - 1; Shape* child = luax_checkshape(L, 3); float position[3], orientation[4]; int i = 4; diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 7b778dca..2f2aa1cb 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -1041,6 +1041,7 @@ void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol"); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; + lovrRelease(lovrCompoundShapeGetShape(shape, index), lovrShapeDestroy); JPH_MutableCompoundShape_ModifyShape2((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot, child->shape); lovrRetain(child); } From 47dec01772ece84ad81c226d1ddb7ed4578d79b3 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:37:08 -0700 Subject: [PATCH 25/26] rm more useless checks; --- src/modules/physics/physics_jolt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 2f2aa1cb..20bf4035 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -1027,7 +1027,6 @@ bool lovrCompoundShapeIsFrozen(CompoundShape* shape) { void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); - lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol"); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; JPH_MutableCompoundShape_AddShape((JPH_MutableCompoundShape*) shape->shape, &pos, &rot, child->shape, 0); @@ -1038,7 +1037,6 @@ void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); - lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol"); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; lovrRelease(lovrCompoundShapeGetShape(shape, index), lovrShapeDestroy); From 060e72c525a5d9746c36b3365858690d5b250bd9 Mon Sep 17 00:00:00 2001 From: bjorn Date: Sun, 7 Apr 2024 13:44:24 -0700 Subject: [PATCH 26/26] Rename CompoundShape 'shape' to 'child'; Maybe slightly less ambiguous/confusing? --- src/api/l_physics_shapes.c | 52 +++++++++++++++--------------- src/modules/physics/physics.h | 14 ++++---- src/modules/physics/physics_jolt.c | 46 +++++++++++++------------- src/modules/physics/physics_ode.c | 14 ++++---- 4 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/api/l_physics_shapes.c b/src/api/l_physics_shapes.c index 2d9f49a8..ced3443d 100644 --- a/src/api/l_physics_shapes.c +++ b/src/api/l_physics_shapes.c @@ -389,18 +389,18 @@ static int l_lovrCompoundShapeIsFrozen(lua_State* L) { return 1; } -static int l_lovrCompoundShapeAddShape(lua_State* L) { +static int l_lovrCompoundShapeAddChild(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); Shape* child = luax_checkshape(L, 2); float position[3], orientation[4]; int index = 3; index = luax_readvec3(L, index, position, NULL); index = luax_readquat(L, index, orientation, NULL); - lovrCompoundShapeAddShape(shape, child, position, orientation); + lovrCompoundShapeAddChild(shape, child, position, orientation); return 0; } -static int l_lovrCompoundShapeReplaceShape(lua_State* L) { +static int l_lovrCompoundShapeReplaceChild(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); uint32_t index = luax_checku32(L, 2) - 1; Shape* child = luax_checkshape(L, 3); @@ -408,49 +408,49 @@ static int l_lovrCompoundShapeReplaceShape(lua_State* L) { int i = 4; i = luax_readvec3(L, i, position, NULL); i = luax_readquat(L, i, orientation, NULL); - lovrCompoundShapeReplaceShape(shape, index, child, position, orientation); + lovrCompoundShapeReplaceChild(shape, index, child, position, orientation); return 0; } -static int l_lovrCompoundShapeRemoveShape(lua_State* L) { +static int l_lovrCompoundShapeRemoveChild(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); uint32_t index = luax_checku32(L, 2) - 1; - lovrCompoundShapeRemoveShape(shape, index); + lovrCompoundShapeRemoveChild(shape, index); return 0; } -static int l_lovrCompoundShapeGetShape(lua_State* L) { +static int l_lovrCompoundShapeGetChild(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); uint32_t index = luax_checku32(L, 2) - 1; - Shape* child = lovrCompoundShapeGetShape(shape, index); + Shape* child = lovrCompoundShapeGetChild(shape, index); luax_pushshape(L, child); return 1; } -static int l_lovrCompoundShapeGetShapes(lua_State* L) { +static int l_lovrCompoundShapeGetChildren(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - int count = (int) lovrCompoundShapeGetShapeCount(shape); + int count = (int) lovrCompoundShapeGetChildCount(shape); lua_createtable(L, count, 0); for (int i = 0; i < count; i++) { - Shape* child = lovrCompoundShapeGetShape(shape, (uint32_t) i); + Shape* child = lovrCompoundShapeGetChild(shape, (uint32_t) i); luax_pushshape(L, child); lua_rawseti(L, -2, i + 1); } return 1; } -static int l_lovrCompoundShapeGetShapeCount(lua_State* L) { +static int l_lovrCompoundShapeGetChildCount(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); - uint32_t count = lovrCompoundShapeGetShapeCount(shape); + uint32_t count = lovrCompoundShapeGetChildCount(shape); lua_pushinteger(L, count); return 1; } -static int l_lovrCompoundShapeGetShapeOffset(lua_State* L) { +static int l_lovrCompoundShapeGetChildOffset(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); uint32_t index = luax_checku32(L, 2) - 1; float position[3], orientation[4], angle, ax, ay, az; - lovrCompoundShapeGetShapeOffset(shape, index, position, orientation); + lovrCompoundShapeGetChildOffset(shape, index, position, orientation); quat_getAngleAxis(orientation, &angle, &ax, &ay, &az); lua_pushnumber(L, position[0]); lua_pushnumber(L, position[1]); @@ -462,28 +462,28 @@ static int l_lovrCompoundShapeGetShapeOffset(lua_State* L) { return 7; } -static int l_lovrCompoundShapeSetShapeOffset(lua_State* L) { +static int l_lovrCompoundShapeSetChildOffset(lua_State* L) { CompoundShape* shape = luax_checktype(L, 1, CompoundShape); uint32_t index = luax_checku32(L, 2) - 1; float position[3], orientation[4]; int i = 3; i = luax_readvec3(L, i, position, NULL); i = luax_readquat(L, i, orientation, NULL); - lovrCompoundShapeSetShapeOffset(shape, index, position, orientation); + lovrCompoundShapeSetChildOffset(shape, index, position, orientation); return 0; } const luaL_Reg lovrCompoundShape[] = { lovrShape, { "isFrozen", l_lovrCompoundShapeIsFrozen }, - { "addShape", l_lovrCompoundShapeAddShape }, - { "replaceShape", l_lovrCompoundShapeReplaceShape }, - { "removeShape", l_lovrCompoundShapeRemoveShape }, - { "getShape", l_lovrCompoundShapeGetShape }, - { "getShapes", l_lovrCompoundShapeGetShapes }, - { "getShapeCount", l_lovrCompoundShapeGetShapeCount }, - { "getShapeOffset", l_lovrCompoundShapeGetShapeOffset }, - { "setShapeOffset", l_lovrCompoundShapeSetShapeOffset }, - { "__len", l_lovrCompoundShapeGetShapeCount }, // :) + { "addChild", l_lovrCompoundShapeAddChild }, + { "replaceChild", l_lovrCompoundShapeReplaceChild }, + { "removeChild", l_lovrCompoundShapeRemoveChild }, + { "getChild", l_lovrCompoundShapeGetChild }, + { "getChildren", l_lovrCompoundShapeGetChildren }, + { "getChildCount", l_lovrCompoundShapeGetChildCount }, + { "getChildOffset", l_lovrCompoundShapeGetChildOffset }, + { "setChildOffset", l_lovrCompoundShapeSetChildOffset }, + { "__len", l_lovrCompoundShapeGetChildCount }, // :) { NULL, NULL } }; diff --git a/src/modules/physics/physics.h b/src/modules/physics/physics.h index 8cf4eba2..ebea6098 100644 --- a/src/modules/physics/physics.h +++ b/src/modules/physics/physics.h @@ -187,13 +187,13 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze); bool lovrCompoundShapeIsFrozen(CompoundShape* shape); -void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation); -void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation); -void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index); -Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index); -uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape); -void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation); -void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation); +void lovrCompoundShapeAddChild(CompoundShape* shape, Shape* child, float* position, float* orientation); +void lovrCompoundShapeReplaceChild(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation); +void lovrCompoundShapeRemoveChild(CompoundShape* shape, uint32_t index); +Shape* lovrCompoundShapeGetChild(CompoundShape* shape, uint32_t index); +uint32_t lovrCompoundShapeGetChildCount(CompoundShape* shape); +void lovrCompoundShapeGetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation); +void lovrCompoundShapeSetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation); // These tokens need to exist for Lua bindings #define lovrSphereShapeDestroy lovrShapeDestroy diff --git a/src/modules/physics/physics_jolt.c b/src/modules/physics/physics_jolt.c index 20bf4035..cea42c79 100644 --- a/src/modules/physics/physics_jolt.c +++ b/src/modules/physics/physics_jolt.c @@ -430,7 +430,7 @@ Shape* lovrColliderGetShape(Collider* collider, uint32_t child) { return collider->shape; } - return lovrCompoundShapeGetShape(collider->shape, child); + return lovrCompoundShapeGetChild(collider->shape, child); } void lovrColliderSetShape(Collider* collider, Shape* shape) { @@ -835,9 +835,9 @@ void lovrShapeDestroy(void* ref) { void lovrShapeDestroyData(Shape* shape) { if (shape->shape) { if (shape->type == SHAPE_COMPOUND) { - uint32_t count = lovrCompoundShapeGetShapeCount(shape); + uint32_t count = lovrCompoundShapeGetChildCount(shape); for (uint32_t i = 0; i < count; i++) { - Shape* child = lovrCompoundShapeGetShape(shape, i); + Shape* child = lovrCompoundShapeGetChild(shape, i); lovrRelease(child, lovrShapeDestroy); } } @@ -994,9 +994,9 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count, bool freeze) { lovrCheck(!freeze || count >= 2, "A frozen CompoundShape must contain at least two shapes"); - CompoundShape* parent = lovrCalloc(sizeof(CompoundShape)); - parent->ref = 1; - parent->type = SHAPE_COMPOUND; + CompoundShape* shape = lovrCalloc(sizeof(CompoundShape)); + shape->ref = 1; + shape->type = SHAPE_COMPOUND; JPH_CompoundShapeSettings* settings = freeze ? (JPH_CompoundShapeSettings*) JPH_StaticCompoundShapeSettings_Create() : @@ -1011,20 +1011,20 @@ CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orie } if (freeze) { - parent->shape = (JPH_Shape*) JPH_StaticCompoundShape_Create((JPH_StaticCompoundShapeSettings*) settings); + shape->shape = (JPH_Shape*) JPH_StaticCompoundShape_Create((JPH_StaticCompoundShapeSettings*) settings); } else { - parent->shape = (JPH_Shape*) JPH_MutableCompoundShape_Create((JPH_MutableCompoundShapeSettings*) settings); + shape->shape = (JPH_Shape*) JPH_MutableCompoundShape_Create((JPH_MutableCompoundShapeSettings*) settings); } JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) settings); - return parent; + return shape; } bool lovrCompoundShapeIsFrozen(CompoundShape* shape) { return JPH_Shape_GetSubType(shape->shape) == JPH_ShapeSubType_StaticCompound; } -void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) { +void lovrCompoundShapeAddChild(CompoundShape* shape, Shape* child, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); JPH_Vec3 pos = { position[0], position[1], position[2] }; @@ -1033,27 +1033,27 @@ void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* positi lovrRetain(child); } -void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { +void lovrCompoundShapeReplaceChild(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported"); - lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); + lovrCheck(index < lovrCompoundShapeGetChildCount(shape), "CompoundShape has no child at index %d", index + 1); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; - lovrRelease(lovrCompoundShapeGetShape(shape, index), lovrShapeDestroy); + lovrRelease(lovrCompoundShapeGetChild(shape, index), lovrShapeDestroy); JPH_MutableCompoundShape_ModifyShape2((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot, child->shape); lovrRetain(child); } -void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) { +void lovrCompoundShapeRemoveChild(CompoundShape* shape, uint32_t index) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); - lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); - Shape* child = lovrCompoundShapeGetShape(shape, index); + lovrCheck(index < lovrCompoundShapeGetChildCount(shape), "CompoundShape has no child at index %d", index + 1); + Shape* child = lovrCompoundShapeGetChild(shape, index); JPH_MutableCompoundShape_RemoveShape((JPH_MutableCompoundShape*) shape->shape, index); lovrRelease(child, lovrShapeDestroy); } -Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) { - if (index < lovrCompoundShapeGetShapeCount(shape)) { +Shape* lovrCompoundShapeGetChild(CompoundShape* shape, uint32_t index) { + if (index < lovrCompoundShapeGetChildCount(shape)) { const JPH_Shape* child; JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, NULL, NULL, NULL); return (Shape*) (uintptr_t) JPH_Shape_GetUserData(child); @@ -1062,12 +1062,12 @@ Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) { } } -uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { +uint32_t lovrCompoundShapeGetChildCount(CompoundShape* shape) { return JPH_CompoundShape_GetNumSubShapes((JPH_CompoundShape*) shape->shape); } -void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { - lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); +void lovrCompoundShapeGetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { + lovrCheck(index < lovrCompoundShapeGetChildCount(shape), "CompoundShape has no child at index %d", index + 1); const JPH_Shape* child; JPH_Vec3 pos; JPH_Quat rot; @@ -1077,9 +1077,9 @@ void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float quat_init(orientation, &rot.x); } -void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { +void lovrCompoundShapeSetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed"); - lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1); + lovrCheck(index < lovrCompoundShapeGetChildCount(shape), "CompoundShape has no child at index %d", index + 1); JPH_Vec3 pos = { position[0], position[1], position[2] }; JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] }; JPH_MutableCompoundShape_ModifyShape((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot); diff --git a/src/modules/physics/physics_ode.c b/src/modules/physics/physics_ode.c index bfb99abe..0d413c83 100644 --- a/src/modules/physics/physics_ode.c +++ b/src/modules/physics/physics_ode.c @@ -1119,31 +1119,31 @@ bool lovrCompoundShapeIsFrozen(CompoundShape* shape) { return false; } -void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) { +void lovrCompoundShapeAddChild(CompoundShape* shape, Shape* child, float* position, float* orientation) { // } -void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { +void lovrCompoundShapeReplaceChild(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) { // } -void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) { +void lovrCompoundShapeRemoveChild(CompoundShape* shape, uint32_t index) { // } -Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) { +Shape* lovrCompoundShapeGetChild(CompoundShape* shape, uint32_t index) { return NULL; } -uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) { +uint32_t lovrCompoundShapeGetChildCount(CompoundShape* shape) { return 0; } -void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { +void lovrCompoundShapeGetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { // } -void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { +void lovrCompoundShapeSetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) { // }