diff --git a/src/api/physics.c b/src/api/physics.c index 57a5b183..c5a2d647 100644 --- a/src/api/physics.c +++ b/src/api/physics.c @@ -16,7 +16,8 @@ int l_lovrPhysicsInit(lua_State* L) { luax_extendtype(L, "Shape", "CylinderShape", lovrShape, lovrCylinderShape); map_init(&JointTypes); - map_set(&ShapeTypes, "ball", JOINT_BALL); + map_set(&JointTypes, "ball", JOINT_BALL); + map_set(&JointTypes, "hinge", JOINT_HINGE); map_init(&ShapeTypes); map_set(&ShapeTypes, "sphere", SHAPE_SPHERE); @@ -70,6 +71,20 @@ int l_lovrPhysicsNewCylinderShape(lua_State* L) { return 1; } +int l_lovrPhysicsNewHingeJoint(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); + float ax = luaL_optnumber(L, 6, 0.f); + float ay = luaL_optnumber(L, 7, 0.f); + float az = luaL_optnumber(L, 8, 0.f); + Joint* joint = lovrHingeJointCreate(a, b, x, y, z, ax, ay, az); + luax_pushtype(L, HingeJoint, joint); + return 1; +} + int l_lovrPhysicsNewSphereShape(lua_State* L) { float radius = luaL_optnumber(L, 1, 1.f); SphereShape* sphere = lovrSphereShapeCreate(radius); @@ -83,6 +98,7 @@ const luaL_Reg lovrPhysics[] = { { "newBoxShape", l_lovrPhysicsNewBoxShape }, { "newCapsuleShape", l_lovrPhysicsNewCapsuleShape }, { "newCylinderShape", l_lovrPhysicsNewCylinderShape }, + { "newHingeJoint", l_lovrPhysicsNewHingeJoint }, { "newSphereShape", l_lovrPhysicsNewSphereShape }, { NULL, NULL } }; diff --git a/src/api/types/joints.c b/src/api/types/joints.c index e014ef89..f453feb0 100644 --- a/src/api/types/joints.c +++ b/src/api/types/joints.c @@ -90,3 +90,59 @@ const luaL_Reg lovrBallJoint[] = { { "setAnchor", l_lovrBallJointSetAnchor }, { NULL, NULL } }; + +int l_lovrHingeJointGetAnchors(lua_State* L) { + HingeJoint* hinge = luax_checktype(L, 1, HingeJoint); + float x1, y1, z1, x2, y2, z2; + lovrHingeJointGetAnchors(hinge, &x1, &y1, &z1, &x2, &y2, &z2); + lua_pushnumber(L, x1); + lua_pushnumber(L, y1); + lua_pushnumber(L, z1); + lua_pushnumber(L, x2); + lua_pushnumber(L, y2); + lua_pushnumber(L, z2); + return 6; +} + +int l_lovrHingeJointSetAnchor(lua_State* L) { + HingeJoint* hinge = luax_checktype(L, 1, HingeJoint); + float x = luaL_checknumber(L, 2); + float y = luaL_checknumber(L, 3); + float z = luaL_checknumber(L, 4); + lovrHingeJointSetAnchor(hinge, x, y, z); + return 0; +} + +int l_lovrHingeJointGetAxis(lua_State* L) { + HingeJoint* hinge = luax_checktype(L, 1, HingeJoint); + float x, y, z; + lovrHingeJointGetAxis(hinge, &x, &y, &z); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + lua_pushnumber(L, z); + return 3; +} + +int l_lovrHingeJointSetAxis(lua_State* L) { + HingeJoint* hinge = luax_checktype(L, 1, HingeJoint); + float x = luaL_checknumber(L, 2); + float y = luaL_checknumber(L, 3); + float z = luaL_checknumber(L, 4); + lovrHingeJointSetAxis(hinge, x, y, z); + return 0; +} + +int l_lovrHingeJointGetAngle(lua_State* L) { + HingeJoint* hinge = luax_checktype(L, 1, HingeJoint); + lua_pushnumber(L, lovrHingeJointGetAngle(hinge)); + return 1; +} + +const luaL_Reg lovrHingeJoint[] = { + { "getAnchors", l_lovrHingeJointGetAnchors }, + { "setAnchor", l_lovrHingeJointSetAnchor }, + { "getAxis", l_lovrHingeJointGetAxis }, + { "setAxis", l_lovrHingeJointSetAxis }, + { "getAngle", l_lovrHingeJointGetAngle }, + { NULL, NULL } +}; diff --git a/src/physics/physics.c b/src/physics/physics.c index 9bde2fd0..78e1c64a 100644 --- a/src/physics/physics.c +++ b/src/physics/physics.c @@ -814,3 +814,53 @@ void lovrBallJointGetAnchors(BallJoint* ball, float* x1, float* y1, float* z1, f void lovrBallJointSetAnchor(BallJoint* ball, float x, float y, float z) { dJointSetBallAnchor(ball->id, x, y, z); } + +HingeJoint* lovrHingeJointCreate(Collider* a, Collider* b, float x, float y, float z, float ax, float ay, float az) { + if (a->world != b->world) { + error("Joint bodies must exist in same World"); + } + + HingeJoint* joint = lovrAlloc(sizeof(HingeJoint), lovrJointDestroy); + if (!joint) return NULL; + + joint->type = JOINT_HINGE; + joint->id = dJointCreateHinge(a->world->id, 0); + dJointSetData(joint->id, joint); + dJointAttach(joint->id, a->body, b->body); + dJointSetHingeAnchor(joint->id, x, y, z); + dJointSetHingeAxis(joint->id, ax, ay, az); + + return joint; +} + +void lovrHingeJointGetAnchors(HingeJoint* hinge, float* x1, float* y1, float* z1, float* x2, float* y2, float* z2) { + float anchor[3]; + dJointGetHingeAnchor(hinge->id, anchor); + *x1 = anchor[0]; + *y1 = anchor[1]; + *z1 = anchor[2]; + dJointGetHingeAnchor2(hinge->id, anchor); + *x2 = anchor[0]; + *y2 = anchor[1]; + *z2 = anchor[2]; +} + +void lovrHingeJointSetAnchor(HingeJoint* hinge, float x, float y, float z) { + dJointSetHingeAnchor(hinge->id, x, y, z); +} + +void lovrHingeJointGetAxis(HingeJoint* hinge, float* x, float* y, float* z) { + float anchor[3]; + dJointGetHingeAxis(hinge->id, anchor); + *x = anchor[0]; + *y = anchor[1]; + *z = anchor[2]; +} + +void lovrHingeJointSetAxis(HingeJoint* hinge, float x, float y, float z) { + dJointSetHingeAxis(hinge->id, x, y, z); +} + +float lovrHingeJointGetAngle(HingeJoint* hinge) { + return dJointGetHingeAngle(hinge->id); +} diff --git a/src/physics/physics.h b/src/physics/physics.h index 3f0d17d8..833b69cd 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -16,6 +16,7 @@ typedef enum { typedef enum { JOINT_BALL, + JOINT_HINGE } JointType; typedef struct { @@ -58,6 +59,7 @@ typedef struct { } Joint; typedef Joint BallJoint; +typedef Joint HingeJoint; typedef void (*CollisionResolver)(World* world, void* userdata); typedef void (*RaycastCallback)(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata); @@ -182,3 +184,10 @@ void lovrJointSetUserData(Joint* joint, void* data); BallJoint* lovrBallJointCreate(Collider* a, Collider* b, float x, float y, float z); void lovrBallJointGetAnchors(BallJoint* ball, float* x1, float* y1, float* z1, float* x2, float* y2, float* z2); void lovrBallJointSetAnchor(BallJoint* ball, float x, float y, float z); + +HingeJoint* lovrHingeJointCreate(Collider* a, Collider* b, float x, float y, float z, float ax, float ay, float az); +void lovrHingeJointGetAnchors(HingeJoint* hinge, float* x1, float* y1, float* z1, float* x2, float* y2, float* z2); +void lovrHingeJointSetAnchor(HingeJoint* hinge, float x, float y, float z); +void lovrHingeJointGetAxis(HingeJoint* hinge, float* x, float* y, float* z); +void lovrHingeJointSetAxis(HingeJoint* hinge, float x, float y, float z); +float lovrHingeJointGetAngle(HingeJoint* hinge);