From 7474192e780224e0eebfa94500f13abe27bdf6da Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 4 Apr 2024 12:34:49 -0700 Subject: [PATCH] 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]) {