Add ConvexShape;

Also luax_readmesh supports ModelData input, and the indices pointer can
be NULL to only request the vertex positions.
This commit is contained in:
bjorn 2024-04-09 13:01:30 -07:00
parent f1ba4d1a1e
commit aef71192ac
9 changed files with 97 additions and 23 deletions

View File

@ -515,18 +515,13 @@ void luax_optcolor(lua_State* L, int index, float color[4]) {
int luax_readmesh(lua_State* L, int index, float** vertices, uint32_t* vertexCount, uint32_t** indices, uint32_t* indexCount, bool* shouldFree) {
if (lua_istable(L, index)) {
luaL_checktype(L, index + 1, LUA_TTABLE);
lua_rawgeti(L, index, 1);
bool nested = lua_type(L, -1) == LUA_TTABLE;
lua_pop(L, 1);
*vertexCount = luax_len(L, index) / (nested ? 1 : 3);
*indexCount = luax_len(L, index + 1);
lovrCheck(*vertexCount > 0, "Invalid mesh data: vertex count is zero");
lovrCheck(*indexCount > 0, "Invalid mesh data: index count is zero");
lovrCheck(*indexCount % 3 == 0, "Index count must be a multiple of 3");
*vertices = lovrMalloc(sizeof(float) * *vertexCount * 3);
*indices = lovrMalloc(sizeof(uint32_t) * *indexCount);
*shouldFree = true;
if (nested) {
@ -548,17 +543,33 @@ int luax_readmesh(lua_State* L, int index, float** vertices, uint32_t* vertexCou
}
}
for (uint32_t i = 0; i < *indexCount; i++) {
lua_rawgeti(L, index + 1, i + 1);
uint32_t index = luaL_checkinteger(L, -1) - 1;
lovrCheck(index < *vertexCount, "Invalid vertex index %d (expected [%d, %d])", index + 1, 1, *vertexCount);
(*indices)[i] = index;
lua_pop(L, 1);
if (indices) {
luaL_checktype(L, index + 1, LUA_TTABLE);
*indexCount = luax_len(L, index + 1);
lovrCheck(*indexCount > 0, "Invalid mesh data: index count is zero");
lovrCheck(*indexCount % 3 == 0, "Index count must be a multiple of 3");
*indices = lovrMalloc(sizeof(uint32_t) * *indexCount);
for (uint32_t i = 0; i < *indexCount; i++) {
lua_rawgeti(L, index + 1, i + 1);
uint32_t index = luaL_checkinteger(L, -1) - 1;
lovrCheck(index < *vertexCount, "Invalid vertex index %d (expected [%d, %d])", index + 1, 1, *vertexCount);
(*indices)[i] = index;
lua_pop(L, 1);
}
}
return index + 2;
}
ModelData* modelData = luax_totype(L, index, ModelData);
if (modelData) {
lovrModelDataGetTriangles(modelData, vertices, indices, vertexCount, indexCount);
*shouldFree = false;
return index + 1;
}
#ifndef LOVR_DISABLE_GRAPHICS
Model* model = luax_totype(L, index, Model);
@ -576,7 +587,9 @@ int luax_readmesh(lua_State* L, int index, float** vertices, uint32_t* vertexCou
*shouldFree = true;
return index + 1;
}
#endif
return luaL_argerror(L, index, "table, Mesh, or Model");
return luaL_argerror(L, index, "table, ModelData, Model, or Mesh expected");
#else
return luaL_argerror(L, index, "table or ModelData expected");
#endif
}

View File

@ -201,6 +201,7 @@ struct Shape* luax_newsphereshape(lua_State* L, int index);
struct Shape* luax_newboxshape(lua_State* L, int index);
struct Shape* luax_newcapsuleshape(lua_State* L, int index);
struct Shape* luax_newcylindershape(lua_State* L, int index);
struct Shape* luax_newconvexshape(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);

View File

@ -7,6 +7,7 @@ StringEntry lovrShapeType[] = {
[SHAPE_BOX] = ENTRY("box"),
[SHAPE_CAPSULE] = ENTRY("capsule"),
[SHAPE_CYLINDER] = ENTRY("cylinder"),
[SHAPE_CONVEX] = ENTRY("convex"),
[SHAPE_MESH] = ENTRY("mesh"),
[SHAPE_TERRAIN] = ENTRY("terrain"),
[SHAPE_COMPOUND] = ENTRY("compound"),
@ -121,6 +122,13 @@ static int l_lovrPhysicsNewCapsuleShape(lua_State* L) {
return 1;
}
static int l_lovrPhysicsNewConvexShape(lua_State* L) {
ConvexShape* convex = luax_newconvexshape(L, 1);
luax_pushtype(L, ConvexShape, convex);
lovrRelease(convex, lovrShapeDestroy);
return 1;
}
static int l_lovrPhysicsNewCylinderShape(lua_State* L) {
CylinderShape* cylinder = luax_newcylindershape(L, 1);
luax_pushtype(L, CylinderShape, cylinder);
@ -196,6 +204,7 @@ static const luaL_Reg lovrPhysics[] = {
{ "newBallJoint", l_lovrPhysicsNewBallJoint },
{ "newBoxShape", l_lovrPhysicsNewBoxShape },
{ "newCapsuleShape", l_lovrPhysicsNewCapsuleShape },
{ "newConvexShape", l_lovrPhysicsNewConvexShape },
{ "newCylinderShape", l_lovrPhysicsNewCylinderShape },
{ "newDistanceJoint", l_lovrPhysicsNewDistanceJoint },
{ "newHingeJoint", l_lovrPhysicsNewHingeJoint },
@ -217,6 +226,7 @@ extern const luaL_Reg lovrSphereShape[];
extern const luaL_Reg lovrBoxShape[];
extern const luaL_Reg lovrCapsuleShape[];
extern const luaL_Reg lovrCylinderShape[];
extern const luaL_Reg lovrConvexShape[];
extern const luaL_Reg lovrMeshShape[];
extern const luaL_Reg lovrTerrainShape[];
extern const luaL_Reg lovrCompoundShape[];
@ -234,6 +244,7 @@ int luaopen_lovr_physics(lua_State* L) {
luax_registertype(L, BoxShape);
luax_registertype(L, CapsuleShape);
luax_registertype(L, CylinderShape);
luax_registertype(L, ConvexShape);
luax_registertype(L, MeshShape);
luax_registertype(L, TerrainShape);
luax_registertype(L, CompoundShape);

View File

@ -12,6 +12,7 @@ void luax_pushshape(lua_State* L, Shape* shape) {
case SHAPE_BOX: luax_pushtype(L, BoxShape, shape); break;
case SHAPE_CAPSULE: luax_pushtype(L, CapsuleShape, shape); break;
case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, shape); break;
case SHAPE_CONVEX: luax_pushtype(L, ConvexShape, 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;
@ -28,6 +29,7 @@ Shape* luax_checkshape(lua_State* L, int index) {
hash64("BoxShape", strlen("BoxShape")),
hash64("CapsuleShape", strlen("CapsuleShape")),
hash64("CylinderShape", strlen("CylinderShape")),
hash64("ConvexShape", strlen("ConvexShape")),
hash64("MeshShape", strlen("MeshShape")),
hash64("TerrainShape", strlen("TerrainShape")),
hash64("CompoundShape", strlen("CompoundShape"))
@ -67,6 +69,16 @@ Shape* luax_newcylindershape(lua_State* L, int index) {
return lovrCylinderShapeCreate(radius, length);
}
Shape* luax_newconvexshape(lua_State* L, int index) {
float* points;
uint32_t count;
bool shouldFree;
luax_readmesh(L, index, &points, &count, NULL, NULL, &shouldFree);
ConvexShape* shape = lovrConvexShapeCreate(points, count);
if (shouldFree) lovrFree(points);
return shape;
}
Shape* luax_newmeshshape(lua_State* L, int index) {
float* vertices;
uint32_t* indices;
@ -371,6 +383,11 @@ const luaL_Reg lovrCylinderShape[] = {
{ NULL, NULL }
};
const luaL_Reg lovrConvexShape[] = {
lovrShape,
{ NULL, NULL }
};
const luaL_Reg lovrMeshShape[] = {
lovrShape,
{ NULL, NULL }

View File

@ -150,6 +150,19 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) {
return 1;
}
static int l_lovrWorldNewConvexCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
ConvexShape* shape = luax_newconvexshape(L, index);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
return 1;
}
static int l_lovrWorldNewSphereCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
@ -530,6 +543,7 @@ const luaL_Reg lovrWorld[] = {
{ "newBoxCollider", l_lovrWorldNewBoxCollider },
{ "newCapsuleCollider", l_lovrWorldNewCapsuleCollider },
{ "newCylinderCollider", l_lovrWorldNewCylinderCollider },
{ "newConvexCollider", l_lovrWorldNewConvexCollider },
{ "newSphereCollider", l_lovrWorldNewSphereCollider },
{ "newMeshCollider", l_lovrWorldNewMeshCollider },
{ "newTerrainCollider", l_lovrWorldNewTerrainCollider },

View File

@ -527,7 +527,7 @@ static void collectVertices(ModelData* model, uint32_t nodeIndex, float** vertic
*baseIndex += positions->count;
}
if (index) {
if (indices && index) {
lovrAssert(index->type == U16 || index->type == U32, "Unreachable");
char* data = (char*) model->buffers[index->buffer].data + index->offset;
@ -558,19 +558,18 @@ void lovrModelDataGetTriangles(ModelData* model, float** vertices, uint32_t** in
}
if (vertices && !model->vertices) {
uint32_t* tempIndices;
uint32_t baseIndex = 0;
model->vertices = lovrMalloc(model->totalVertexCount * 3 * sizeof(float));
model->indices = lovrMalloc(model->totalIndexCount * sizeof(uint32_t));
*vertices = model->vertices;
*indices = model->indices;
collectVertices(model, model->rootNode, vertices, indices, &baseIndex, (float[16]) MAT4_IDENTITY);
tempIndices = model->indices;
collectVertices(model, model->rootNode, vertices, &tempIndices, &baseIndex, (float[16]) MAT4_IDENTITY);
}
*vertexCount = model->totalVertexCount;
*indexCount = model->totalIndexCount;
if (vertexCount) *vertexCount = model->totalVertexCount;
if (indexCount) *indexCount = model->totalIndexCount;
if (vertices) {
*vertices = model->vertices;
*indices = model->indices;
}
if (vertices) *vertices = model->vertices;
if (indices) *indices = model->indices;
}

View File

@ -17,6 +17,7 @@ typedef Shape SphereShape;
typedef Shape BoxShape;
typedef Shape CapsuleShape;
typedef Shape CylinderShape;
typedef Shape ConvexShape;
typedef Shape MeshShape;
typedef Shape TerrainShape;
typedef Shape CompoundShape;
@ -157,6 +158,7 @@ typedef enum {
SHAPE_BOX,
SHAPE_CAPSULE,
SHAPE_CYLINDER,
SHAPE_CONVEX,
SHAPE_MESH,
SHAPE_TERRAIN,
SHAPE_COMPOUND
@ -182,6 +184,8 @@ CylinderShape* lovrCylinderShapeCreate(float radius, float length);
float lovrCylinderShapeGetRadius(CylinderShape* cylinder);
float lovrCylinderShapeGetLength(CylinderShape* cylinder);
ConvexShape* lovrConvexShapeCreate(float points[], uint32_t count);
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]);
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY);
@ -201,6 +205,7 @@ void lovrCompoundShapeSetChildOffset(CompoundShape* shape, uint32_t index, float
#define lovrBoxShapeDestroy lovrShapeDestroy
#define lovrCapsuleShapeDestroy lovrShapeDestroy
#define lovrCylinderShapeDestroy lovrShapeDestroy
#define lovrConvexShapeDestroy lovrShapeDestroy
#define lovrMeshShapeDestroy lovrShapeDestroy
#define lovrTerrainShapeDestroy lovrShapeDestroy
#define lovrCompoundShapeDestroy lovrShapeDestroy

View File

@ -915,6 +915,16 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder) {
return JPH_CylinderShape_GetHalfHeight((JPH_CylinderShape*) cylinder->shape) * 2.f;
}
ConvexShape* lovrConvexShapeCreate(float points[], uint32_t count) {
ConvexShape* convex = lovrCalloc(sizeof(ConvexShape));
convex->ref = 1;
convex->type = SHAPE_CONVEX;
JPH_ConvexHullShapeSettings* settings = JPH_ConvexHullShapeSettings_Create((const JPH_Vec3*) points, count, .05f);
convex->shape = (JPH_Shape*) JPH_ConvexHullShapeSettings_CreateShape(settings);
JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) settings);
return convex;
}
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]) {
MeshShape* mesh = lovrCalloc(sizeof(MeshShape));
mesh->ref = 1;

View File

@ -1048,6 +1048,10 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder) {
return length;
}
ConvexShape* lovrConvexShapeCreate(float positions[], uint32_t count) {
lovrThrow("ODE does not support ConvexShape");
}
MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount, dTriIndex* indices) {
MeshShape* mesh = lovrCalloc(sizeof(MeshShape));
mesh->ref = 1;
@ -1075,7 +1079,7 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ,
}
CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze) {
lovrThrow("ODE does not support compound shape");
lovrThrow("ODE does not support CompoundShape");
}
bool lovrCompoundShapeIsFrozen(CompoundShape* shape) {