CompoundShape API;

This commit is contained in:
bjorn 2024-04-04 12:34:49 -07:00
parent 6f0b6391df
commit b3e9e55b8a
3 changed files with 241 additions and 6 deletions

View File

@ -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 }
};

View File

@ -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

View File

@ -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]) {