From f1a74c34c333560cb5c3e6c33ccdc7423aa6e7d1 Mon Sep 17 00:00:00 2001 From: bjorn Date: Wed, 24 May 2017 17:38:03 -0700 Subject: [PATCH] Joints; Also no expressions in luax_pushtype; --- src/api/graphics.c | 6 ++- src/api/lovr.h | 4 ++ src/api/physics.c | 38 ++++++++++++++---- src/api/types/collider.c | 21 +++++++--- src/api/types/joints.c | 68 ++++++++++++++++++++++++++++++++ src/api/types/model.c | 3 +- src/api/types/shapes.c | 1 + src/physics/physics.c | 84 +++++++++++++++++++++++++++++++++++++--- src/physics/physics.h | 28 +++++++++++++- 9 files changed, 228 insertions(+), 25 deletions(-) create mode 100644 src/api/types/joints.c diff --git a/src/api/graphics.c b/src/api/graphics.c index f005f65d..f1893454 100644 --- a/src/api/graphics.c +++ b/src/api/graphics.c @@ -296,7 +296,8 @@ int l_lovrGraphicsSetScissor(lua_State* L) { } int l_lovrGraphicsGetShader(lua_State* L) { - luax_pushtype(L, Shader, lovrGraphicsGetShader()); + Shader* shader = lovrGraphicsGetShader(); + luax_pushtype(L, Shader, shader); return 1; } @@ -307,7 +308,8 @@ int l_lovrGraphicsSetShader(lua_State* L) { } int l_lovrGraphicsGetFont(lua_State* L) { - luax_pushtype(L, Font, lovrGraphicsGetFont()); + Font* font = lovrGraphicsGetFont(); + luax_pushtype(L, Font, font); return 1; } diff --git a/src/api/lovr.h b/src/api/lovr.h index a31b8acc..6bea80d8 100644 --- a/src/api/lovr.h +++ b/src/api/lovr.h @@ -15,6 +15,7 @@ int l_lovrPhysicsInit(lua_State* L); int l_lovrTimerInit(lua_State* L); extern const luaL_Reg lovrAudio[]; +extern const luaL_Reg lovrBallJoint[]; extern const luaL_Reg lovrBoxShape[]; extern const luaL_Reg lovrCapsuleShape[]; extern const luaL_Reg lovrController[]; @@ -26,6 +27,7 @@ extern const luaL_Reg lovrFilesystem[]; extern const luaL_Reg lovrFont[]; extern const luaL_Reg lovrGraphics[]; extern const luaL_Reg lovrHeadset[]; +extern const luaL_Reg lovrJoint[]; extern const luaL_Reg lovrMath[]; extern const luaL_Reg lovrMesh[]; extern const luaL_Reg lovrModel[]; @@ -50,6 +52,7 @@ extern map_int_t EventTypes; extern map_int_t FilterModes; extern map_int_t HeadsetEyes; extern map_int_t HorizontalAligns; +extern map_int_t JointTypes; extern map_int_t MeshAttributeTypes; extern map_int_t MeshDrawModes; extern map_int_t MeshUsages; @@ -64,3 +67,4 @@ void luax_checkmeshformat(lua_State* L, int index, MeshFormat* format); int luax_readtransform(lua_State* L, int index, mat4 transform); Blob* luax_readblob(lua_State* L, int index, const char* debug); int luax_pushshape(lua_State* L, Shape* shape); +int luax_pushjoint(lua_State* L, Joint* joint); diff --git a/src/api/physics.c b/src/api/physics.c index e6523fa8..57a5b183 100644 --- a/src/api/physics.c +++ b/src/api/physics.c @@ -2,17 +2,22 @@ #include "physics/physics.h" map_int_t ShapeTypes; +map_int_t JointTypes; int l_lovrPhysicsInit(lua_State* L) { lua_newtable(L); luaL_register(L, NULL, lovrPhysics); luax_registertype(L, "World", lovrWorld); luax_registertype(L, "Collider", lovrCollider); + luax_extendtype(L, "Joint", "BallJoint", lovrJoint, lovrBallJoint); luax_extendtype(L, "Shape", "SphereShape", lovrShape, lovrSphereShape); luax_extendtype(L, "Shape", "BoxShape", lovrShape, lovrBoxShape); luax_extendtype(L, "Shape", "CapsuleShape", lovrShape, lovrCapsuleShape); luax_extendtype(L, "Shape", "CylinderShape", lovrShape, lovrCylinderShape); + map_init(&JointTypes); + map_set(&ShapeTypes, "ball", JOINT_BALL); + map_init(&ShapeTypes); map_set(&ShapeTypes, "sphere", SHAPE_SPHERE); map_set(&ShapeTypes, "box", SHAPE_BOX); @@ -24,13 +29,19 @@ int l_lovrPhysicsInit(lua_State* L) { } int l_lovrPhysicsNewWorld(lua_State* L) { - luax_pushtype(L, World, lovrWorldCreate()); + World* world = lovrWorldCreate(); + luax_pushtype(L, World, world); return 1; } -int l_lovrPhysicsNewSphereShape(lua_State* L) { - float radius = luaL_optnumber(L, 1, 1.f); - luax_pushtype(L, SphereShape, lovrSphereShapeCreate(radius)); +int l_lovrPhysicsNewBallJoint(lua_State* L) { + Collider* a = luax_checktype(L, 1, Collider); + Collider* b = luax_checktype(L, 2, Collider); + float x = luaL_optnumber(L, 3, 0.f); + float y = luaL_optnumber(L, 4, 0.f); + float z = luaL_optnumber(L, 5, 0.f); + Joint* joint = lovrBallJointCreate(a, b, x, y, z); + luax_pushtype(L, BallJoint, joint); return 1; } @@ -38,29 +49,40 @@ int l_lovrPhysicsNewBoxShape(lua_State* L) { float x = luaL_optnumber(L, 1, 1.f); float y = luaL_optnumber(L, 2, x); float z = luaL_optnumber(L, 3, x); - luax_pushtype(L, BoxShape, lovrBoxShapeCreate(x, y, z)); + BoxShape* box = lovrBoxShapeCreate(x, y, z); + luax_pushtype(L, BoxShape, box); return 1; } int l_lovrPhysicsNewCapsuleShape(lua_State* L) { float radius = luaL_optnumber(L, 1, 1.f); float length = luaL_optnumber(L, 2, 1.f); - luax_pushtype(L, CapsuleShape, lovrCapsuleShapeCreate(radius, length)); + CapsuleShape* capsule = lovrCapsuleShapeCreate(radius, length); + luax_pushtype(L, CapsuleShape, capsule); return 1; } int l_lovrPhysicsNewCylinderShape(lua_State* L) { float radius = luaL_optnumber(L, 1, 1.f); float length = luaL_optnumber(L, 2, 1.f); - luax_pushtype(L, CylinderShape, lovrCylinderShapeCreate(radius, length)); + CylinderShape* cylinder = lovrCylinderShapeCreate(radius, length); + luax_pushtype(L, CylinderShape, cylinder); + return 1; +} + +int l_lovrPhysicsNewSphereShape(lua_State* L) { + float radius = luaL_optnumber(L, 1, 1.f); + SphereShape* sphere = lovrSphereShapeCreate(radius); + luax_pushtype(L, SphereShape, sphere); return 1; } const luaL_Reg lovrPhysics[] = { { "newWorld", l_lovrPhysicsNewWorld }, - { "newSphereShape", l_lovrPhysicsNewSphereShape }, + { "newBallJoint", l_lovrPhysicsNewBallJoint }, { "newBoxShape", l_lovrPhysicsNewBoxShape }, { "newCapsuleShape", l_lovrPhysicsNewCapsuleShape }, { "newCylinderShape", l_lovrPhysicsNewCylinderShape }, + { "newSphereShape", l_lovrPhysicsNewSphereShape }, { NULL, NULL } }; diff --git a/src/api/types/collider.c b/src/api/types/collider.c index 0b49487c..1d64a101 100644 --- a/src/api/types/collider.c +++ b/src/api/types/collider.c @@ -9,7 +9,8 @@ int l_lovrColliderDestroy(lua_State* L) { int l_lovrColliderGetWorld(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); - luax_pushtype(L, World, lovrColliderGetWorld(collider)); + World* world = lovrColliderGetWorld(collider); + luax_pushtype(L, World, world); return 1; } @@ -30,14 +31,22 @@ int l_lovrColliderRemoveShape(lua_State* L) { int l_lovrColliderGetShapeList(lua_State* L) { Collider* collider = luax_checktype(L, 1, Collider); lua_newtable(L); - int i; - Shape* shape; - - for (i = 1, shape = lovrColliderGetFirstShape(collider); shape; shape = lovrColliderGetNextShape(collider, shape), i++) { - luax_pushshape(L, shape); + vec_void_t* shapes = lovrColliderGetShapes(collider); + for (int i = 0; i < shapes->length; i++) { + luax_pushshape(L, shapes->data[i]); lua_rawseti(L, -2, i); } + return 1; +} +int l_lovrColliderGetJointList(lua_State* L) { + Collider* collider = luax_checktype(L, 1, Collider); + lua_newtable(L); + vec_void_t* joints = lovrColliderGetJoints(collider); + for (int i = 0; i < joints->length; i++) { + luax_pushshape(L, joints->data[i]); + lua_rawseti(L, -2, i); + } return 1; } diff --git a/src/api/types/joints.c b/src/api/types/joints.c new file mode 100644 index 00000000..f669e49f --- /dev/null +++ b/src/api/types/joints.c @@ -0,0 +1,68 @@ +#include "api/lovr.h" +#include "physics/physics.h" + +int luax_pushjoint(lua_State* L, Joint* joint) { + switch (lovrJointGetType(joint)) { + case JOINT_BALL: luax_pushtype(L, BallJoint, joint); return 1; + default: return 0; + } +} + +int l_lovrJointDestroy(lua_State* L) { + Joint* joint = luax_checktypeof(L, 1, Joint); + lovrJointDestroyData(joint); + return 0; +} + +int l_lovrJointGetType(lua_State* L) { + Joint* joint = luax_checktypeof(L, 1, Joint); + luax_pushenum(L, &JointTypes, lovrJointGetType(joint)); + return 1; +} + +int l_lovrJointGetColliders(lua_State* L) { + Joint* joint = luax_checktype(L, 1, Joint); + Collider* a; + Collider* b; + lovrJointGetColliders(joint, &a, &b); + luax_pushtype(L, Collider, a); + luax_pushtype(L, Collider, b); + return 2; +} + +int l_lovrJointGetUserData(lua_State* L) { + Joint* joint = luax_checktypeof(L, 1, Joint); + int ref = (int) lovrJointGetUserData(joint); + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + return 1; +} + +int l_lovrJointSetUserData(lua_State* L) { + Joint* joint = luax_checktypeof(L, 1, Joint); + uint64_t ref = (int) lovrJointGetUserData(joint); + if (ref) { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + } + + if (lua_gettop(L) < 2) { + lua_pushnil(L); + } + + lua_settop(L, 2); + ref = luaL_ref(L, LUA_REGISTRYINDEX); + lovrJointSetUserData(joint, (void*) ref); + return 0; +} + +const luaL_Reg lovrJoint[] = { + { "destroy", l_lovrJointDestroy }, + { "getType", l_lovrJointGetType }, + { "getColliders", l_lovrJointGetColliders }, + { "getUserData", l_lovrJointGetUserData }, + { "setUserData", l_lovrJointSetUserData }, + { NULL, NULL } +}; + +const luaL_Reg lovrBallJoint[] = { + { NULL, NULL } +}; diff --git a/src/api/types/model.c b/src/api/types/model.c index f1adc8f6..d10b7a8c 100644 --- a/src/api/types/model.c +++ b/src/api/types/model.c @@ -11,7 +11,8 @@ int l_lovrModelDraw(lua_State* L) { int l_lovrModelGetTexture(lua_State* L) { Model* model = luax_checktype(L, 1, Model); - luax_pushtype(L, Texture, lovrModelGetTexture(model)); + Texture* texture = lovrModelGetTexture(model); + luax_pushtype(L, Texture, texture); return 1; } diff --git a/src/api/types/shapes.c b/src/api/types/shapes.c index 6fb855a8..f68dbb7e 100644 --- a/src/api/types/shapes.c +++ b/src/api/types/shapes.c @@ -7,6 +7,7 @@ int luax_pushshape(lua_State* L, Shape* shape) { case SHAPE_BOX: luax_pushtype(L, BoxShape, shape); return 1; case SHAPE_CAPSULE: luax_pushtype(L, CapsuleShape, shape); return 1; case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, shape); return 1; + default: return 0; } } diff --git a/src/physics/physics.c b/src/physics/physics.c index 112a66b8..858fd2c2 100644 --- a/src/physics/physics.c +++ b/src/physics/physics.c @@ -163,12 +163,16 @@ Collider* lovrColliderCreate(World* world) { collider->body = dBodyCreate(world->id); collider->world = world; dBodySetData(collider->body, collider); + vec_init(&collider->shapes); + vec_init(&collider->joints); return collider; } void lovrColliderDestroy(const Ref* ref) { Collider* collider = containerof(ref, Collider); + vec_deinit(&collider->shapes); + vec_deinit(&collider->joints); lovrColliderDestroyData(collider); free(collider); } @@ -205,14 +209,27 @@ void lovrColliderRemoveShape(Collider* collider, Shape* shape) { } } -Shape* lovrColliderGetFirstShape(Collider* collider) { - dGeomID geom = dBodyGetFirstGeom(collider->body); - return geom ? dGeomGetData(geom) : NULL; +vec_void_t* lovrColliderGetShapes(Collider* collider) { + vec_clear(&collider->shapes); + for (dGeomID geom = dBodyGetFirstGeom(collider->body); geom; geom = dBodyGetNextGeom(geom)) { + Shape* shape = dGeomGetData(geom); + if (shape) { + vec_push(&collider->shapes, shape); + } + } + return &collider->shapes; } -Shape* lovrColliderGetNextShape(Collider* collider, Shape* shape) { - dGeomID geom = dBodyGetNextGeom(shape->id); - return geom ? dGeomGetData(geom) : NULL; +vec_void_t* lovrColliderGetJoints(Collider* collider) { + vec_clear(&collider->joints); + int jointCount = dBodyGetNumJoints(collider->body); + for (int i = 0; i < jointCount; i++) { + Joint* joint = dJointGetData(dBodyGetJoint(collider->body, i)); + if (joint) { + vec_push(&collider->joints, joint); + } + } + return &collider->joints; } void* lovrColliderGetUserData(Collider* collider) { @@ -675,3 +692,58 @@ float lovrCylinderShapeGetLength(CylinderShape* cylinder) { void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) { dGeomCylinderSetParams(cylinder->id, lovrCylinderShapeGetRadius(cylinder), length); } + +void lovrJointDestroy(const Ref* ref) { + Joint* joint = containerof(ref, Joint); + lovrJointDestroyData(joint); + free(joint); +} + +void lovrJointDestroyData(Joint* joint) { + if (joint->id) { + dJointDestroy(joint->id); + joint->id = NULL; + } +} + +JointType lovrJointGetType(Joint* joint) { + return joint->type; +} + +void lovrJointGetColliders(Joint* joint, Collider** a, Collider** b) { + dBodyID bodyA = dJointGetBody(joint->id, 0); + dBodyID bodyB = dJointGetBody(joint->id, 1); + + if (bodyA) { + *a = dBodyGetData(bodyA); + } + + if (bodyB) { + *b = dBodyGetData(bodyB); + } +} + +void* lovrJointGetUserData(Joint* joint) { + return joint->userdata; +} + +void lovrJointSetUserData(Joint* joint, void* data) { + joint->userdata = data; +} + +BallJoint* lovrBallJointCreate(Collider* a, Collider* b, float x, float y, float z) { + if (a->world != b->world) { + error("Joint bodies must exist in same World"); + } + + BallJoint* joint = lovrAlloc(sizeof(BallJoint), lovrJointDestroy); + if (!joint) return NULL; + + joint->type = JOINT_BALL; + joint->id = dJointCreateBall(a->world->id, 0); + dJointSetData(joint->id, joint); + dJointAttach(joint->id, a->body, b->body); + dJointSetBallAnchor(joint->id, x, y, z); + + return joint; +} diff --git a/src/physics/physics.h b/src/physics/physics.h index aaca5d5c..5f095857 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -14,6 +14,10 @@ typedef enum { SHAPE_CYLINDER } ShapeType; +typedef enum { + JOINT_BALL, +} JointType; + typedef struct { Ref ref; dWorldID id; @@ -27,6 +31,8 @@ typedef struct { dBodyID body; World* world; void* userdata; + vec_void_t shapes; + vec_void_t joints; } Collider; typedef struct { @@ -42,6 +48,15 @@ typedef Shape BoxShape; typedef Shape CapsuleShape; typedef Shape CylinderShape; +typedef struct { + Ref ref; + JointType type; + dJointID id; + void* userdata; +} Joint; + +typedef Joint BallJoint; + typedef void (*CollisionResolver)(World* world, void* userdata); void lovrPhysicsInit(); @@ -69,8 +84,8 @@ void lovrColliderDestroyData(Collider* collider); World* lovrColliderGetWorld(Collider* collider); void lovrColliderAddShape(Collider* collider, Shape* shape); void lovrColliderRemoveShape(Collider* collider, Shape* shape); -Shape* lovrColliderGetFirstShape(Collider* collider); -Shape* lovrColliderGetNextShape(Collider* collider, Shape* shape); +vec_void_t* lovrColliderGetShapes(Collider* collider); +vec_void_t* lovrColliderGetJoints(Collider* collider); void* lovrColliderGetUserData(Collider* collider); void lovrColliderSetUserData(Collider* collider, void* data); int lovrColliderIsKinematic(Collider* collider); @@ -145,3 +160,12 @@ float lovrCylinderShapeGetRadius(CylinderShape* cylinder); void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius); float lovrCylinderShapeGetLength(CylinderShape* cylinder); void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length); + +void lovrJointDestroy(const Ref* ref); +void lovrJointDestroyData(Joint* joint); +JointType lovrJointGetType(Joint* joint); +void lovrJointGetColliders(Joint* joint, Collider** a, Collider** b); +void* lovrJointGetUserData(Joint* joint); +void lovrJointSetUserData(Joint* joint, void* data); + +BallJoint* lovrBallJointCreate(Collider* a, Collider* b, float x, float y, float z);