mirror of https://github.com/bjornbytes/lovr.git
Support for trimesh shape colliders
This commit is contained in:
parent
61abb6f02b
commit
75591fde42
|
@ -1 +1 @@
|
|||
Subproject commit b85a951862d13d1f731daaf960249ebbbe12730f
|
||||
Subproject commit dbc457549169d04fa6baece760d052133ac2e3ba
|
|
@ -50,6 +50,7 @@ extern const luaL_Reg lovrSliderJoint[];
|
|||
extern const luaL_Reg lovrSoundData[];
|
||||
extern const luaL_Reg lovrSource[];
|
||||
extern const luaL_Reg lovrSphereShape[];
|
||||
extern const luaL_Reg lovrMeshShape[];
|
||||
extern const luaL_Reg lovrTexture[];
|
||||
extern const luaL_Reg lovrTextureData[];
|
||||
extern const luaL_Reg lovrThread[];
|
||||
|
|
|
@ -7,6 +7,7 @@ StringEntry ShapeTypes[] = {
|
|||
[SHAPE_BOX] = ENTRY("box"),
|
||||
[SHAPE_CAPSULE] = ENTRY("capsule"),
|
||||
[SHAPE_CYLINDER] = ENTRY("cylinder"),
|
||||
[SHAPE_MESH] = ENTRY("mesh"),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -153,6 +154,7 @@ int luaopen_lovr_physics(lua_State* L) {
|
|||
luax_registertype(L, BoxShape);
|
||||
luax_registertype(L, CapsuleShape);
|
||||
luax_registertype(L, CylinderShape);
|
||||
luax_registertype(L, MeshShape);
|
||||
if (lovrPhysicsInit()) {
|
||||
luax_atexit(L, lovrPhysicsDestroy);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,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_MESH: luax_pushtype(L, MeshShape, shape); break;
|
||||
default: lovrThrow("Unreachable");
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +20,8 @@ Shape* luax_checkshape(lua_State* L, int index) {
|
|||
hash64("SphereShape", strlen("SphereShape")),
|
||||
hash64("BoxShape", strlen("BoxShape")),
|
||||
hash64("CapsuleShape", strlen("CapsuleShape")),
|
||||
hash64("CylinderShape", strlen("CylinderShape"))
|
||||
hash64("CylinderShape", strlen("CylinderShape")),
|
||||
hash64("MeshShape", strlen("MeshShape")),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(hashes) / sizeof(hashes[0]); i++) {
|
||||
|
@ -298,3 +300,8 @@ const luaL_Reg lovrCylinderShape[] = {
|
|||
{ "setLength", l_lovrCylinderShapeSetLength },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
const luaL_Reg lovrMeshShape[] = {
|
||||
lovrShape,
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -110,6 +110,44 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
lovrAssert(lua_istable(L, 2), "Vertices must be a table");
|
||||
lovrAssert(lua_istable(L, 3), "Indices must be a table");
|
||||
int vertexCount = luax_len(L, 2);
|
||||
int indexCount = luax_len(L, 3);
|
||||
// TODO: this never gets deallocated
|
||||
float * vertices = malloc(sizeof(float) * vertexCount * 3);
|
||||
unsigned * indices = malloc(sizeof(unsigned) * indexCount);
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
lovrAssert(lua_istable(L, -1), "Each verticle must be a table of coordinates");
|
||||
lua_rawgeti(L, -1, 1); // x
|
||||
vertices[i * 3 + 0] = luaL_optnumber(L, -1, 0.);
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 2); // y
|
||||
vertices[i * 3 + 1] = luaL_optnumber(L, -1, 0.);
|
||||
lua_pop(L, 1);
|
||||
lua_rawgeti(L, -1, 3); // z
|
||||
vertices[i * 3 + 2] = luaL_optnumber(L, -1, 0.);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
for (int i = 0; i < indexCount; i++) {
|
||||
lua_rawgeti(L, 3, i + 1);
|
||||
indices[i] = luaL_checkinteger(L, -1) - 1;
|
||||
}
|
||||
lua_pop(L, indexCount);
|
||||
Collider* collider = lovrColliderCreate(world, 0,0,0);
|
||||
MeshShape* shape = lovrMeshShapeCreate(vertexCount, vertices, indexCount, indices);
|
||||
lovrColliderAddShape(collider, shape);
|
||||
lovrColliderInitInertia(collider, shape);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(Collider, collider);
|
||||
lovrRelease(Shape, shape);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrWorldGetColliders(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
|
||||
|
@ -306,6 +344,7 @@ const luaL_Reg lovrWorld[] = {
|
|||
{ "newCapsuleCollider", l_lovrWorldNewCapsuleCollider },
|
||||
{ "newCylinderCollider", l_lovrWorldNewCylinderCollider },
|
||||
{ "newSphereCollider", l_lovrWorldNewSphereCollider },
|
||||
{ "newMeshCollider", l_lovrWorldNewMeshCollider },
|
||||
{ "getColliders", l_lovrWorldGetColliders },
|
||||
{ "destroy", l_lovrWorldDestroy },
|
||||
{ "update", l_lovrWorldUpdate },
|
||||
|
|
|
@ -687,6 +687,10 @@ void lovrShapeDestroy(void* ref) {
|
|||
|
||||
void lovrShapeDestroyData(Shape* shape) {
|
||||
if (shape->id) {
|
||||
if (shape->type == SHAPE_MESH) {
|
||||
dTriMeshDataID dataID = dGeomTriMeshGetData(shape->id);
|
||||
dGeomTriMeshDataDestroy(dataID);
|
||||
}
|
||||
dGeomDestroy(shape->id);
|
||||
shape->id = NULL;
|
||||
}
|
||||
|
@ -779,6 +783,13 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float*
|
|||
dMassSetCylinder(&m, density, 3, radius, length);
|
||||
break;
|
||||
}
|
||||
|
||||
case SHAPE_MESH: {
|
||||
dMassSetTrimesh(&m, density, shape->id);
|
||||
dGeomSetPosition(shape->id, -m.c[0], -m.c[1], -m.c[2]);
|
||||
dMassTranslate(&m, -m.c[0], -m.c[1], -m.c[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const dReal* position = dGeomGetOffsetPosition(shape->id);
|
||||
|
@ -894,6 +905,17 @@ void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) {
|
|||
dGeomCylinderSetParams(cylinder->id, lovrCylinderShapeGetRadius(cylinder), length);
|
||||
}
|
||||
|
||||
MeshShape* lovrMeshShapeInit(MeshShape* mesh, int vertexCount, float vertices[], int indexCount, dTriIndex indices[]) {
|
||||
dTriMeshDataID dataID = dGeomTriMeshDataCreate();
|
||||
dGeomTriMeshDataBuildSingle(dataID, vertices, 3 * sizeof(float), vertexCount,
|
||||
indices, indexCount, 3 * sizeof(dTriIndex));
|
||||
dGeomTriMeshDataPreprocess2(dataID, (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES), NULL);
|
||||
mesh->id = dCreateTriMesh(0, dataID, 0, 0, 0);
|
||||
mesh->type = SHAPE_MESH;
|
||||
dGeomSetData(mesh->id, mesh);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void lovrJointDestroy(void* ref) {
|
||||
Joint* joint = ref;
|
||||
lovrJointDestroyData(joint);
|
||||
|
|
|
@ -14,7 +14,8 @@ typedef enum {
|
|||
SHAPE_SPHERE,
|
||||
SHAPE_BOX,
|
||||
SHAPE_CAPSULE,
|
||||
SHAPE_CYLINDER
|
||||
SHAPE_CYLINDER,
|
||||
SHAPE_MESH,
|
||||
} ShapeType;
|
||||
|
||||
typedef enum {
|
||||
|
@ -63,6 +64,7 @@ typedef Shape SphereShape;
|
|||
typedef Shape BoxShape;
|
||||
typedef Shape CapsuleShape;
|
||||
typedef Shape CylinderShape;
|
||||
typedef Shape MeshShape;
|
||||
|
||||
struct Joint {
|
||||
JointType type;
|
||||
|
@ -212,6 +214,10 @@ void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius);
|
|||
float lovrCylinderShapeGetLength(CylinderShape* cylinder);
|
||||
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
|
||||
|
||||
MeshShape* lovrMeshShapeInit(MeshShape* mesh, int vertexCount, float vertices[], int indexCount, dTriIndex indices[]);
|
||||
#define lovrMeshShapeCreate(...) lovrMeshShapeInit(lovrAlloc(MeshShape), __VA_ARGS__)
|
||||
#define lovrMeshShapeDestroy lovrShapeDestroy
|
||||
|
||||
void lovrJointDestroy(void* ref);
|
||||
void lovrJointDestroyData(Joint* joint);
|
||||
JointType lovrJointGetType(Joint* joint);
|
||||
|
|
Loading…
Reference in New Issue