Compare commits

...

31 Commits

Author SHA1 Message Date
bjorn 5df8405af3 Cleanup; Methods take vectors;
Ugh this was way worse than I thought
2024-04-07 20:27:10 -07:00
bjorn 2952ed764d Fix issue with Collider:getJoints;
This can probably be simplified somehow...
2024-04-07 15:22:06 -07:00
bjorn 985ba6bd13 Fix collider leak; 2024-04-07 15:13:33 -07:00
bjorn 15649802c8 Rework World Collider/Joint lists;
- Add World:getColliderCount
- Add World:getJointCount
- Add World:getJoints
- Add Joint:isDestroyed
- Destroy joints when either of their colliders are destroyed (Jolt
  seems to require this).
- Fix joint memory leak.
- Change joints to be stored in some crazy graph thing.
  - Reduces allocations, allows constant time insertion/removal.
2024-04-07 15:08:22 -07:00
Bjorn e3b42fe24b
Merge pull request #762 from bjornbytes/compound-shape
CompoundShape
2024-04-07 14:34:28 -07:00
bjorn 060e72c525 Rename CompoundShape 'shape' to 'child';
Maybe slightly less ambiguous/confusing?
2024-04-07 13:47:52 -07:00
bjorn 47dec01772 rm more useless checks; 2024-04-07 13:47:52 -07:00
bjorn 582ee1625f CompoundShape:replaceShape fixes; 2024-04-07 13:47:52 -07:00
bjorn e36374c4cf rm useless check; 2024-04-07 13:47:52 -07:00
bjorn 98601b3425 Collider:setShape accepts nil;
Internally it still uses a teeny tiny sphere (it's kinda like the
collider's shape is a "point").
2024-04-07 13:47:52 -07:00
bjorn 2ac0d6946e Move shape arg to last argument of query callbacks;
Also fix an off-by-one error.
2024-04-07 13:47:52 -07:00
bjorn b589cec975 Collider:getShape takes optional child index;
For convenience when you're trying to dig a leaf shape out of a CompoundShape.

It's ignored if the collider's shape is not a CompoundShape.
2024-04-07 13:47:52 -07:00
bjorn 8bdab9f2d4 Shape:getAABB; 2024-04-07 13:47:52 -07:00
bjorn 5751068728 Move Shape:is/setSensor and Shape:is/setEnabled to Collider; 2024-04-07 13:47:52 -07:00
bjorn 481a9dafa2 newCollider takes optional Shape as first arg; 2024-04-07 13:47:52 -07:00
bjorn 95cc6c2753 Shape fixes;
- Collider always has Shape now.  When left off or set to null, it's a
  tiny sphere (representing a point).
- Preserve shape offset when changing shape.
2024-04-07 13:47:52 -07:00
bjorn f35cda7db8 lovrColliderCreate takes shape;
Jolt requires a shape, also it saves a bit of work.
2024-04-07 13:47:52 -07:00
bjorn 907d89c913 Add Collider:getShapes for backcompat; 2024-04-07 13:47:52 -07:00
bjorn ff0f39fc7b rm unused shape prototypes; 2024-04-07 13:47:52 -07:00
bjorn b809db1d83 ODE compatibility; 2024-04-07 13:47:52 -07:00
bjorn 051266f8ea Collider shape is required I think;
Jolt doesn't really support bodies without shapes.
2024-04-07 13:47:52 -07:00
bjorn 930e713079 Add Collider:get/setShapeOffset; 2024-04-07 13:47:52 -07:00
bjorn 4f26182595 World queries return collider/shapeindex instead of Shape; 2024-04-07 13:47:52 -07:00
bjorn 8cbdda00f3 Require frozen CompoundShapes to have at least 2 children;
If you create a StaticCompoundShape with 1 child, Jolt creates a
RotatedTranslatedShape.  It would be a pain to have to branch on that,
so let's just require 2 children.
2024-04-07 13:47:52 -07:00
bjorn 10f965d69e rm Shape setters;
Jolt doesn't support this and requires you to recreate the shape.  Since
the shape -> collider relationship is 1:N, we can't really create a new
shape because we'd have to figure out which colliders/compoundshapes to
assign it to, which isn't feasible.
2024-04-07 13:47:52 -07:00
bjorn a7bf4ca2a4 CompoundShape fixes; 2024-04-07 13:47:52 -07:00
bjorn c27694fd8e Shapes set their userdata; 2024-04-07 13:47:52 -07:00
bjorn b3e9e55b8a CompoundShape API; 2024-04-07 13:47:52 -07:00
bjorn 6f0b6391df Start CompoundShape; 2024-04-07 13:47:52 -07:00
bjorn ce58619094 Colliders can only have 1 shape; rm shape pose; 2024-04-07 13:47:52 -07:00
bjorn 9b6f58ac1e Update Jolt; 2024-04-07 13:47:52 -07:00
10 changed files with 1255 additions and 995 deletions

@ -1 +1 @@
Subproject commit 29fe07e8088279c47d7108107856ec3c826d1817
Subproject commit 2cda386d71174bec355888539679f7a4f7be1c2a

View File

@ -203,4 +203,5 @@ struct Shape* luax_newcapsuleshape(lua_State* L, int index);
struct Shape* luax_newcylindershape(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);
#endif

View File

@ -9,6 +9,7 @@ StringEntry lovrShapeType[] = {
[SHAPE_CYLINDER] = ENTRY("cylinder"),
[SHAPE_MESH] = ENTRY("mesh"),
[SHAPE_TERRAIN] = ENTRY("terrain"),
[SHAPE_COMPOUND] = ENTRY("compound"),
{ 0 }
};
@ -25,8 +26,7 @@ static int l_lovrPhysicsNewWorld(lua_State* L) {
.maxColliders = 65536,
.maxColliderPairs = 65536,
.maxContacts = 16384,
.allowSleep = true,
.gravity = { 0.f, -9.81f, 0.f }
.allowSleep = true
};
if (lua_istable(L, 1)) {
@ -63,9 +63,6 @@ static int l_lovrPhysicsNewWorld(lua_State* L) {
}
lua_pop(L, 1);
} else { // Deprecated
info.gravity[0] = luax_optfloat(L, 1, 0.f);
info.gravity[1] = luax_optfloat(L, 2, -9.81f);
info.gravity[2] = luax_optfloat(L, 3, 0.f);
info.allowSleep = lua_gettop(L) < 4 || lua_toboolean(L, 4);
if (lua_type(L, 5) == LUA_TTABLE) {
info.tagCount = luax_len(L, 5);
@ -85,6 +82,15 @@ static int l_lovrPhysicsNewWorld(lua_State* L) {
}
World* world = lovrWorldCreate(&info);
if (!lua_istable(L, 1)) {
float gravity[3];
gravity[0] = luax_optfloat(L, 1, 0.f);
gravity[1] = luax_optfloat(L, 2, -9.81f);
gravity[2] = luax_optfloat(L, 3, 0.f);
lovrWorldSetGravity(world, gravity);
}
luax_pushtype(L, World, world);
lovrRelease(world, lovrWorldDestroy);
return 1;
@ -178,6 +184,13 @@ static int l_lovrPhysicsNewTerrainShape(lua_State* L) {
return 1;
}
static int l_lovrPhysicsNewCompoundShape(lua_State* L) {
CompoundShape* shape = luax_newcompoundshape(L, 1);
luax_pushtype(L, CompoundShape, shape);
lovrRelease(shape, lovrShapeDestroy);
return 1;
}
static const luaL_Reg lovrPhysics[] = {
{ "newWorld", l_lovrPhysicsNewWorld },
{ "newBallJoint", l_lovrPhysicsNewBallJoint },
@ -190,6 +203,7 @@ static const luaL_Reg lovrPhysics[] = {
{ "newSliderJoint", l_lovrPhysicsNewSliderJoint },
{ "newSphereShape", l_lovrPhysicsNewSphereShape },
{ "newTerrainShape", l_lovrPhysicsNewTerrainShape },
{ "newCompoundShape", l_lovrPhysicsNewCompoundShape },
{ NULL, NULL }
};
@ -205,6 +219,7 @@ extern const luaL_Reg lovrCapsuleShape[];
extern const luaL_Reg lovrCylinderShape[];
extern const luaL_Reg lovrMeshShape[];
extern const luaL_Reg lovrTerrainShape[];
extern const luaL_Reg lovrCompoundShape[];
int luaopen_lovr_physics(lua_State* L) {
lua_newtable(L);
@ -221,6 +236,7 @@ int luaopen_lovr_physics(lua_State* L) {
luax_registertype(L, CylinderShape);
luax_registertype(L, MeshShape);
luax_registertype(L, TerrainShape);
luax_registertype(L, CompoundShape);
lovrPhysicsInit();
luax_atexit(L, lovrPhysicsDestroy);
return 1;

View File

@ -17,6 +17,20 @@ static int l_lovrColliderIsDestroyed(lua_State* L) {
return 1;
}
static int l_lovrColliderIsEnabled(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool enabled = lovrColliderIsEnabled(collider);
lua_pushboolean(L, enabled);
return 1;
}
static int l_lovrColliderSetEnabled(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool enable = lua_toboolean(L, 2);
lovrColliderSetEnabled(collider, enable);
return 1;
}
static int l_lovrColliderGetWorld(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
World* world = lovrColliderGetWorld(collider);
@ -24,40 +38,59 @@ static int l_lovrColliderGetWorld(lua_State* L) {
return 1;
}
static int l_lovrColliderAddShape(lua_State* L) {
static int l_lovrColliderGetShape(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
Shape* shape = luax_checkshape(L, 2);
lovrColliderAddShape(collider, shape);
return 0;
}
static int l_lovrColliderRemoveShape(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
Shape* shape = luax_checkshape(L, 2);
lovrColliderRemoveShape(collider, shape);
return 0;
}
static int l_lovrColliderGetShapes(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
size_t count;
Shape** shapes = lovrColliderGetShapes(collider, &count);
lua_createtable(L, (int) count, 0);
for (size_t i = 0; i < count; i++) {
luax_pushshape(L, shapes[i]);
lua_rawseti(L, -2, (int) i + 1);
uint32_t child = lua_gettop(L) == 1 ? ~0u : luax_checku32(L, 2) - 1;
Shape* shape = lovrColliderGetShape(collider, child);
if (shape) {
luax_pushshape(L, shape);
} else {
lua_pushnil(L);
}
return 1;
}
static int l_lovrColliderSetShape(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
Shape* shape = lua_isnoneornil(L, 2) ? NULL : luax_checkshape(L, 2);
lovrColliderSetShape(collider, shape);
return 0;
}
static int l_lovrColliderGetShapeOffset(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float position[3], orientation[4], angle, ax, ay, az;
lovrColliderGetShapeOffset(collider, 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_lovrColliderSetShapeOffset(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
int index = 2;
float position[3], orientation[4];
index = luax_readvec3(L, index, position, NULL);
index = luax_readquat(L, index, orientation, NULL);
lovrColliderSetShapeOffset(collider, position, orientation);
return 0;
}
static int l_lovrColliderGetJoints(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
size_t count;
Joint** joints = lovrColliderGetJoints(collider, &count);
lua_createtable(L, (int) count, 0);
for (size_t i = 0; i < count; i++) {
luax_pushjoint(L, joints[i]);
lua_rawseti(L, -2, (int) i + 1);
lua_newtable(L);
int index = 1;
void* private;
Joint* joint = NULL;
while ((joint = lovrColliderEnumerateJoints(collider, joint, &private)) != NULL) {
luax_pushjoint(L, joint);
lua_rawseti(L, -2, index++);
}
return 1;
}
@ -110,6 +143,19 @@ static int l_lovrColliderSetKinematic(lua_State* L) {
return 0;
}
static int l_lovrColliderIsSensor(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
lua_pushboolean(L, lovrColliderIsSensor(collider));
return 1;
}
static int l_lovrColliderSetSensor(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool sensor = lua_toboolean(L, 2);
lovrColliderSetSensor(collider, sensor);
return 0;
}
static int l_lovrColliderIsContinuous(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
bool continuous = lovrColliderIsContinuous(collider);
@ -179,12 +225,11 @@ static int l_lovrColliderSetMass(lua_State* L) {
static int l_lovrColliderGetMassData(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float cx, cy, cz, mass;
float inertia[6];
lovrColliderGetMassData(collider, &cx, &cy, &cz, &mass, inertia);
lua_pushnumber(L, cx);
lua_pushnumber(L, cy);
lua_pushnumber(L, cz);
float centerOfMass[3], mass, inertia[6];
lovrColliderGetMassData(collider, centerOfMass, &mass, inertia);
lua_pushnumber(L, centerOfMass[0]);
lua_pushnumber(L, centerOfMass[1]);
lua_pushnumber(L, centerOfMass[2]);
lua_pushnumber(L, mass);
lua_newtable(L);
for (int i = 0; i < 6; i++) {
@ -196,14 +241,13 @@ static int l_lovrColliderGetMassData(lua_State* L) {
static int l_lovrColliderSetMassData(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float cx = luax_checkfloat(L, 2);
float cy = luax_checkfloat(L, 3);
float cz = luax_checkfloat(L, 4);
float mass = luax_checkfloat(L, 5);
float centerOfMass[3];
int index = luax_readvec3(L, 2, centerOfMass, NULL);
float mass = luax_checkfloat(L, index++);
float inertia[6];
if (lua_istable(L, 6) && luax_len(L, 6) >= 6) {
if (lua_istable(L, index) && luax_len(L, index) >= 6) {
for (int i = 0; i < 6; i++) {
lua_rawgeti(L, 6, i + 1);
lua_rawgeti(L, index, i + 1);
if (!lua_isnumber(L, -1)) {
return luaL_argerror(L, 6, "Expected 6 numbers or a table with 6 numbers");
}
@ -212,25 +256,25 @@ static int l_lovrColliderSetMassData(lua_State* L) {
lua_pop(L, 1);
}
} else {
for (int i = 6; i < 12; i++) {
for (int i = index; i < index + 6; i++) {
if (lua_isnumber(L, i)) {
inertia[i - 6] = lua_tonumber(L, i);
inertia[i - index] = lua_tonumber(L, i);
} else {
return luaL_argerror(L, i, "Expected 6 numbers or a table with 6 numbers");
}
}
}
lovrColliderSetMassData(collider, cx, cy, cz, mass, inertia);
lovrColliderSetMassData(collider, centerOfMass, mass, inertia);
return 0;
}
static int l_lovrColliderGetPosition(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float x, y, z;
lovrColliderGetPosition(collider, &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
float position[3];
lovrColliderGetPosition(collider, position);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
return 3;
}
@ -238,13 +282,13 @@ static int l_lovrColliderSetPosition(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float position[3];
luax_readvec3(L, 2, position, NULL);
lovrColliderSetPosition(collider, position[0], position[1], position[2]);
lovrColliderSetPosition(collider, position);
return 0;
}
static int l_lovrColliderGetOrientation(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float angle, x, y, z, orientation[4];
float orientation[4], angle, x, y, z;
lovrColliderGetOrientation(collider, orientation);
quat_getAngleAxis(orientation, &angle, &x, &y, &z);
lua_pushnumber(L, angle);
@ -264,13 +308,13 @@ static int l_lovrColliderSetOrientation(lua_State* L) {
static int l_lovrColliderGetPose(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float x, y, z, angle, ax, ay, az, orientation[4];
lovrColliderGetPosition(collider, &x, &y, &z);
float position[3], orientation[4], angle, ax, ay, az;
lovrColliderGetPosition(collider, position);
lovrColliderGetOrientation(collider, orientation);
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
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);
@ -283,18 +327,18 @@ static int l_lovrColliderSetPose(lua_State* L) {
float position[3], orientation[4];
int index = luax_readvec3(L, 2, position, NULL);
luax_readquat(L, index, orientation, NULL);
lovrColliderSetPosition(collider, position[0], position[1], position[2]);
lovrColliderSetPosition(collider, position);
lovrColliderSetOrientation(collider, orientation);
return 0;
}
static int l_lovrColliderGetLinearVelocity(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float x, y, z;
lovrColliderGetLinearVelocity(collider, &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
float velocity[3];
lovrColliderGetLinearVelocity(collider, velocity);
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
lua_pushnumber(L, velocity[2]);
return 3;
}
@ -302,17 +346,17 @@ static int l_lovrColliderSetLinearVelocity(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float velocity[3];
luax_readvec3(L, 2, velocity, NULL);
lovrColliderSetLinearVelocity(collider, velocity[0], velocity[1], velocity[2]);
lovrColliderSetLinearVelocity(collider, velocity);
return 0;
}
static int l_lovrColliderGetAngularVelocity(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float x, y, z;
lovrColliderGetAngularVelocity(collider, &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
float velocity[3];
lovrColliderGetAngularVelocity(collider, velocity);
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
lua_pushnumber(L, velocity[2]);
return 3;
}
@ -320,7 +364,7 @@ static int l_lovrColliderSetAngularVelocity(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float velocity[3];
luax_readvec3(L, 2, velocity, NULL);
lovrColliderSetAngularVelocity(collider, velocity[0], velocity[1], velocity[2]);
lovrColliderSetAngularVelocity(collider, velocity);
return 0;
}
@ -366,10 +410,9 @@ static int l_lovrColliderApplyForce(lua_State* L) {
if (lua_gettop(L) >= index) {
float position[3];
luax_readvec3(L, index, position, NULL);
lovrColliderApplyForceAtPosition(collider, force[0], force[1], force[2],
position[0], position[1], position[2]);
lovrColliderApplyForceAtPosition(collider, force, position);
} else {
lovrColliderApplyForce(collider, force[0], force[1], force[2]);
lovrColliderApplyForce(collider, force);
}
return 0;
@ -377,9 +420,9 @@ static int l_lovrColliderApplyForce(lua_State* L) {
static int l_lovrColliderApplyTorque(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float force[3];
luax_readvec3(L, 2, force, NULL);
lovrColliderApplyTorque(collider, force[0], force[1], force[2]);
float torque[3];
luax_readvec3(L, 2, torque, NULL);
lovrColliderApplyTorque(collider, torque);
return 0;
}
@ -407,83 +450,77 @@ static int l_lovrColliderApplyAngularImpulse(lua_State* L) {
static int l_lovrColliderGetLocalCenter(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float x, y, z;
lovrColliderGetLocalCenter(collider, &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
float center[3];
lovrColliderGetLocalCenter(collider, center);
lua_pushnumber(L, center[0]);
lua_pushnumber(L, center[1]);
lua_pushnumber(L, center[2]);
return 3;
}
static int l_lovrColliderGetLocalPoint(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float world[3];
float world[3], local[3];
luax_readvec3(L, 2, world, NULL);
float x, y, z;
lovrColliderGetLocalPoint(collider, world[0], world[1], world[2], &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
lovrColliderGetLocalPoint(collider, world, local);
lua_pushnumber(L, local[0]);
lua_pushnumber(L, local[1]);
lua_pushnumber(L, local[2]);
return 3;
}
static int l_lovrColliderGetWorldPoint(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float local[3];
float local[3], world[3];
luax_readvec3(L, 2, local, NULL);
float wx, wy, wz;
lovrColliderGetWorldPoint(collider, local[0], local[1], local[2], &wx, &wy, &wz);
lua_pushnumber(L, wx);
lua_pushnumber(L, wy);
lua_pushnumber(L, wz);
lovrColliderGetWorldPoint(collider, local, world);
lua_pushnumber(L, world[0]);
lua_pushnumber(L, world[1]);
lua_pushnumber(L, world[2]);
return 3;
}
static int l_lovrColliderGetLocalVector(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float world[3];
float world[3], local[3];
luax_readvec3(L, 2, world, NULL);
float x, y, z;
lovrColliderGetLocalVector(collider, world[0], world[1], world[2], &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
lovrColliderGetLocalVector(collider, world, local);
lua_pushnumber(L, local[0]);
lua_pushnumber(L, local[1]);
lua_pushnumber(L, local[2]);
return 3;
}
static int l_lovrColliderGetWorldVector(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float local[3];
float local[3], world[3];
luax_readvec3(L, 2, local, NULL);
float wx, wy, wz;
lovrColliderGetWorldVector(collider, local[0], local[1], local[2], &wx, &wy, &wz);
lua_pushnumber(L, wx);
lua_pushnumber(L, wy);
lua_pushnumber(L, wz);
lovrColliderGetWorldVector(collider, local, world);
lua_pushnumber(L, world[0]);
lua_pushnumber(L, world[1]);
lua_pushnumber(L, world[2]);
return 3;
}
static int l_lovrColliderGetLinearVelocityFromLocalPoint(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float local[3];
luax_readvec3(L, 2, local, NULL);
float vx, vy, vz;
lovrColliderGetLinearVelocityFromLocalPoint(collider, local[0], local[1], local[2], &vx, &vy, &vz);
lua_pushnumber(L, vx);
lua_pushnumber(L, vy);
lua_pushnumber(L, vz);
float point[3], velocity[3];
luax_readvec3(L, 2, point, NULL);
lovrColliderGetLinearVelocityFromLocalPoint(collider, point, velocity);
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
lua_pushnumber(L, velocity[2]);
return 3;
}
static int l_lovrColliderGetLinearVelocityFromWorldPoint(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float world[3];
luax_readvec3(L, 2, world, NULL);
float vx, vy, vz;
lovrColliderGetLinearVelocityFromWorldPoint(collider, world[0], world[1], world[2], &vx, &vy, &vz);
lua_pushnumber(L, vx);
lua_pushnumber(L, vy);
lua_pushnumber(L, vz);
float point[3], velocity[3];
luax_readvec3(L, 2, point, NULL);
lovrColliderGetLinearVelocityFromWorldPoint(collider, point, velocity);
lua_pushnumber(L, velocity[0]);
lua_pushnumber(L, velocity[1]);
lua_pushnumber(L, velocity[2]);
return 3;
}
@ -544,6 +581,16 @@ static int l_lovrColliderSetTag(lua_State* L) {
return 0;
}
// Deprecated
static int l_lovrColliderGetShapes(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
Shape* shape = lovrColliderGetShape(collider, ~0u);
lua_createtable(L, 1, 0);
luax_pushshape(L, shape);
lua_rawseti(L, -2, 1);
return 1;
}
// Deprecated
static int l_lovrColliderIsGravityIgnored(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
@ -562,15 +609,20 @@ static int l_lovrColliderSetGravityIgnored(lua_State* L) {
const luaL_Reg lovrCollider[] = {
{ "destroy", l_lovrColliderDestroy },
{ "isDestroyed", l_lovrColliderIsDestroyed },
{ "isEnabled", l_lovrColliderIsEnabled },
{ "setEnabled", l_lovrColliderSetEnabled },
{ "getWorld", l_lovrColliderGetWorld },
{ "addShape", l_lovrColliderAddShape },
{ "removeShape", l_lovrColliderRemoveShape },
{ "getShapes", l_lovrColliderGetShapes },
{ "getShape", l_lovrColliderGetShape },
{ "setShape", l_lovrColliderSetShape },
{ "getShapeOffset", l_lovrColliderGetShapeOffset },
{ "setShapeOffset", l_lovrColliderSetShapeOffset },
{ "getJoints", l_lovrColliderGetJoints },
{ "getUserData", l_lovrColliderGetUserData },
{ "setUserData", l_lovrColliderSetUserData },
{ "isKinematic", l_lovrColliderIsKinematic },
{ "setKinematic", l_lovrColliderSetKinematic },
{ "isSensor", l_lovrColliderIsSensor },
{ "setSensor", l_lovrColliderSetSensor },
{ "isContinuous", l_lovrColliderIsContinuous },
{ "setContinuous", l_lovrColliderSetContinuous },
{ "getGravityScale", l_lovrColliderGetGravityScale },
@ -617,6 +669,7 @@ const luaL_Reg lovrCollider[] = {
{ "setTag", l_lovrColliderSetTag },
// Deprecated
{ "getShapes", l_lovrColliderGetShapes },
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored },
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored },

View File

@ -41,6 +41,13 @@ static int l_lovrJointDestroy(lua_State* L) {
return 0;
}
static int l_lovrJointIsDestroyed(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
bool destroyed = lovrJointIsDestroyed(joint);
lua_pushboolean(L, destroyed);
return 1;
}
static int l_lovrJointGetType(lua_State* L) {
Joint* joint = luax_checkjoint(L, 1);
luax_pushenum(L, JointType, lovrJointGetType(joint));
@ -107,6 +114,7 @@ static int l_lovrJointSetEnabled(lua_State* L) {
#define lovrJoint \
{ "destroy", l_lovrJointDestroy }, \
{ "isDestroyed", l_lovrJointIsDestroyed }, \
{ "getType", l_lovrJointGetType }, \
{ "getColliders", l_lovrJointGetColliders }, \
{ "getUserData", l_lovrJointGetUserData }, \

View File

@ -14,6 +14,7 @@ void luax_pushshape(lua_State* L, Shape* shape) {
case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, 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;
default: lovrUnreachable();
}
}
@ -28,7 +29,8 @@ Shape* luax_checkshape(lua_State* L, int index) {
hash64("CapsuleShape", strlen("CapsuleShape")),
hash64("CylinderShape", strlen("CylinderShape")),
hash64("MeshShape", strlen("MeshShape")),
hash64("TerrainShape", strlen("TerrainShape"))
hash64("TerrainShape", strlen("TerrainShape")),
hash64("CompoundShape", strlen("CompoundShape"))
};
for (size_t i = 0; i < COUNTOF(hashes); i++) {
@ -50,7 +52,7 @@ Shape* luax_newsphereshape(lua_State* L, int index) {
Shape* luax_newboxshape(lua_State* L, int index) {
float size[3];
luax_readscale(L, index, size, 3, NULL);
return lovrBoxShapeCreate(size[0], size[1], size[2]);
return lovrBoxShapeCreate(size);
}
Shape* luax_newcapsuleshape(lua_State* L, int index) {
@ -135,6 +137,85 @@ Shape* luax_newterrainshape(lua_State* L, int index) {
}
}
Shape* luax_newcompoundshape(lua_State* L, int index) {
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_checkshape(L, -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 + 1);
lua_rawgeti(L, -3, index + 2);
vec3_set(&positions[3 * i], luax_tofloat(L, -3), luax_tofloat(L, -2), luax_tofloat(L, -1));
lua_pop(L, 3);
index += 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) {
Shape* shape = luax_checkshape(L, 1);
lovrShapeDestroyData(shape);
@ -147,38 +228,6 @@ static int l_lovrShapeGetType(lua_State* L) {
return 1;
}
static int l_lovrShapeGetCollider(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
luax_pushtype(L, Collider, lovrShapeGetCollider(shape));
return 1;
}
static int l_lovrShapeIsEnabled(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lua_pushboolean(L, lovrShapeIsEnabled(shape));
return 1;
}
static int l_lovrShapeSetEnabled(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
bool enabled = lua_toboolean(L, 2);
lovrShapeSetEnabled(shape, enabled);
return 0;
}
static int l_lovrShapeIsSensor(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lua_pushboolean(L, lovrShapeIsSensor(shape));
return 1;
}
static int l_lovrShapeSetSensor(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
bool sensor = lua_toboolean(L, 2);
lovrShapeSetSensor(shape, sensor);
return 0;
}
static void luax_pushshapestash(lua_State* L) {
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrshapestash");
@ -214,83 +263,14 @@ static int l_lovrShapeSetUserData(lua_State* L) {
return 0;
}
static int l_lovrShapeGetPosition(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
float x, y, z;
lovrShapeGetPosition(shape, &x, &y, &z);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
return 3;
}
static int l_lovrShapeSetPosition(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lovrCheck(lovrShapeGetCollider(shape) != NULL, "Shape must be attached to collider");
float position[3];
luax_readvec3(L, 2, position, NULL);
lovrShapeSetPosition(shape, position[0], position[1], position[2]);
return 0;
}
static int l_lovrShapeGetOrientation(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
float angle, x, y, z, orientation[4];
lovrShapeGetOrientation(shape, orientation);
quat_getAngleAxis(orientation, &angle, &x, &y, &z);
lua_pushnumber(L, angle);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
return 4;
}
static int l_lovrShapeSetOrientation(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lovrCheck(lovrShapeGetCollider(shape) != NULL, "Shape must be attached to collider");
float orientation[4];
luax_readquat(L, 2, orientation, NULL);
lovrShapeSetOrientation(shape, orientation);
return 0;
}
static int l_lovrShapeGetPose(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
float x, y, z;
lovrShapeGetPosition(shape, &x, &y, &z);
float angle, ax, ay, az, orientation[4];
lovrShapeGetOrientation(shape, orientation);
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 7;
}
static int l_lovrShapeSetPose(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
lovrCheck(lovrShapeGetCollider(shape) != NULL, "Shape must be attached to collider");
float position[3], orientation[4];
int index = luax_readvec3(L, 2, position, NULL);
luax_readquat(L, index, orientation, NULL);
lovrShapeSetPosition(shape, position[0], position[1], position[2]);
lovrShapeSetOrientation(shape, orientation);
return 0;
}
static int l_lovrShapeGetMass(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
float density = luax_checkfloat(L, 2);
float cx, cy, cz, mass;
float inertia[6];
lovrShapeGetMass(shape, density, &cx, &cy, &cz, &mass, inertia);
lua_pushnumber(L, cx);
lua_pushnumber(L, cy);
lua_pushnumber(L, cz);
float centerOfMass[3], mass, inertia[6];
lovrShapeGetMass(shape, density, centerOfMass, &mass, inertia);
lua_pushnumber(L, centerOfMass[0]);
lua_pushnumber(L, centerOfMass[1]);
lua_pushnumber(L, centerOfMass[2]);
lua_pushnumber(L, mass);
lua_newtable(L);
for (int i = 0; i < 6; i++) {
@ -302,8 +282,15 @@ static int l_lovrShapeGetMass(lua_State* L) {
static int l_lovrShapeGetAABB(lua_State* L) {
Shape* shape = luax_checkshape(L, 1);
float aabb[6];
lovrShapeGetAABB(shape, aabb);
float position[3], orientation[4], aabb[6];
if (lua_gettop(L) >= 2) {
int index = 2;
index = luax_readvec3(L, index, position, NULL);
index = luax_readquat(L, index, orientation, NULL);
lovrShapeGetAABB(shape, position, orientation, aabb);
} else {
lovrShapeGetAABB(shape, NULL, NULL, aabb);
}
for (int i = 0; i < 6; i++) {
lua_pushnumber(L, aabb[i]);
}
@ -313,19 +300,8 @@ static int l_lovrShapeGetAABB(lua_State* L) {
#define lovrShape \
{ "destroy", l_lovrShapeDestroy }, \
{ "getType", l_lovrShapeGetType }, \
{ "getCollider", l_lovrShapeGetCollider }, \
{ "isEnabled", l_lovrShapeIsEnabled }, \
{ "setEnabled", l_lovrShapeSetEnabled }, \
{ "isSensor", l_lovrShapeIsSensor }, \
{ "setSensor", l_lovrShapeSetSensor }, \
{ "getUserData", l_lovrShapeGetUserData }, \
{ "setUserData", l_lovrShapeSetUserData }, \
{ "getPosition", l_lovrShapeGetPosition }, \
{ "setPosition", l_lovrShapeSetPosition }, \
{ "getOrientation", l_lovrShapeGetOrientation }, \
{ "setOrientation", l_lovrShapeSetOrientation }, \
{ "getPose", l_lovrShapeGetPose }, \
{ "setPose", l_lovrShapeSetPose }, \
{ "getMass", l_lovrShapeGetMass }, \
{ "getAABB", l_lovrShapeGetAABB }
@ -335,42 +311,25 @@ static int l_lovrSphereShapeGetRadius(lua_State* L) {
return 1;
}
static int l_lovrSphereShapeSetRadius(lua_State* L) {
SphereShape* sphere = luax_checktype(L, 1, SphereShape);
float radius = luax_checkfloat(L, 2);
lovrSphereShapeSetRadius(sphere, radius);
return 0;
}
const luaL_Reg lovrSphereShape[] = {
lovrShape,
{ "getRadius", l_lovrSphereShapeGetRadius },
{ "setRadius", l_lovrSphereShapeSetRadius },
{ NULL, NULL }
};
static int l_lovrBoxShapeGetDimensions(lua_State* L) {
BoxShape* box = luax_checktype(L, 1, BoxShape);
float w, h, d;
lovrBoxShapeGetDimensions(box, &w, &h, &d);
lua_pushnumber(L, w);
lua_pushnumber(L, h);
lua_pushnumber(L, d);
float dimensions[3];
lovrBoxShapeGetDimensions(box, dimensions);
lua_pushnumber(L, dimensions[0]);
lua_pushnumber(L, dimensions[1]);
lua_pushnumber(L, dimensions[2]);
return 3;
}
static int l_lovrBoxShapeSetDimensions(lua_State* L) {
BoxShape* box = luax_checktype(L, 1, BoxShape);
float size[3];
luax_readscale(L, 2, size, 3, NULL);
lovrBoxShapeSetDimensions(box, size[0], size[1], size[2]);
return 0;
}
const luaL_Reg lovrBoxShape[] = {
lovrShape,
{ "getDimensions", l_lovrBoxShapeGetDimensions },
{ "setDimensions", l_lovrBoxShapeSetDimensions },
{ NULL, NULL }
};
@ -380,32 +339,16 @@ static int l_lovrCapsuleShapeGetRadius(lua_State* L) {
return 1;
}
static int l_lovrCapsuleShapeSetRadius(lua_State* L) {
CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape);
float radius = luax_checkfloat(L, 2);
lovrCapsuleShapeSetRadius(capsule, radius);
return 0;
}
static int l_lovrCapsuleShapeGetLength(lua_State* L) {
CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape);
lua_pushnumber(L, lovrCapsuleShapeGetLength(capsule));
return 1;
}
static int l_lovrCapsuleShapeSetLength(lua_State* L) {
CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape);
float length = luax_checkfloat(L, 2);
lovrCapsuleShapeSetLength(capsule, length);
return 0;
}
const luaL_Reg lovrCapsuleShape[] = {
lovrShape,
{ "getRadius", l_lovrCapsuleShapeGetRadius },
{ "setRadius", l_lovrCapsuleShapeSetRadius },
{ "getLength", l_lovrCapsuleShapeGetLength },
{ "setLength", l_lovrCapsuleShapeSetLength },
{ NULL, NULL }
};
@ -415,32 +358,16 @@ static int l_lovrCylinderShapeGetRadius(lua_State* L) {
return 1;
}
static int l_lovrCylinderShapeSetRadius(lua_State* L) {
CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape);
float radius = luax_checkfloat(L, 2);
lovrCylinderShapeSetRadius(cylinder, radius);
return 0;
}
static int l_lovrCylinderShapeGetLength(lua_State* L) {
CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape);
lua_pushnumber(L, lovrCylinderShapeGetLength(cylinder));
return 1;
}
static int l_lovrCylinderShapeSetLength(lua_State* L) {
CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape);
float length = luax_checkfloat(L, 2);
lovrCylinderShapeSetLength(cylinder, length);
return 0;
}
const luaL_Reg lovrCylinderShape[] = {
lovrShape,
{ "getRadius", l_lovrCylinderShapeGetRadius },
{ "setRadius", l_lovrCylinderShapeSetRadius },
{ "getLength", l_lovrCylinderShapeGetLength },
{ "setLength", l_lovrCylinderShapeSetLength },
{ NULL, NULL }
};
@ -453,3 +380,109 @@ const luaL_Reg lovrTerrainShape[] = {
lovrShape,
{ 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_lovrCompoundShapeAddChild(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);
lovrCompoundShapeAddChild(shape, child, position, orientation);
return 0;
}
static int l_lovrCompoundShapeReplaceChild(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
uint32_t index = luax_checku32(L, 2) - 1;
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);
lovrCompoundShapeReplaceChild(shape, index, child, position, orientation);
return 0;
}
static int l_lovrCompoundShapeRemoveChild(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
uint32_t index = luax_checku32(L, 2) - 1;
lovrCompoundShapeRemoveChild(shape, index);
return 0;
}
static int l_lovrCompoundShapeGetChild(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
uint32_t index = luax_checku32(L, 2) - 1;
Shape* child = lovrCompoundShapeGetChild(shape, index);
luax_pushshape(L, child);
return 1;
}
static int l_lovrCompoundShapeGetChildren(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
int count = (int) lovrCompoundShapeGetChildCount(shape);
lua_createtable(L, count, 0);
for (int i = 0; i < count; i++) {
Shape* child = lovrCompoundShapeGetChild(shape, (uint32_t) i);
luax_pushshape(L, child);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
static int l_lovrCompoundShapeGetChildCount(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
uint32_t count = lovrCompoundShapeGetChildCount(shape);
lua_pushinteger(L, count);
return 1;
}
static int l_lovrCompoundShapeGetChildOffset(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
uint32_t index = luax_checku32(L, 2) - 1;
float position[3], orientation[4], angle, ax, ay, az;
lovrCompoundShapeGetChildOffset(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_lovrCompoundShapeSetChildOffset(lua_State* L) {
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
uint32_t index = luax_checku32(L, 2) - 1;
float position[3], orientation[4];
int i = 3;
i = luax_readvec3(L, i, position, NULL);
i = luax_readquat(L, i, orientation, NULL);
lovrCompoundShapeSetChildOffset(shape, index, position, orientation);
return 0;
}
const luaL_Reg lovrCompoundShape[] = {
lovrShape,
{ "isFrozen", l_lovrCompoundShapeIsFrozen },
{ "addChild", l_lovrCompoundShapeAddChild },
{ "replaceChild", l_lovrCompoundShapeReplaceChild },
{ "removeChild", l_lovrCompoundShapeRemoveChild },
{ "getChild", l_lovrCompoundShapeGetChild },
{ "getChildren", l_lovrCompoundShapeGetChildren },
{ "getChildCount", l_lovrCompoundShapeGetChildCount },
{ "getChildOffset", l_lovrCompoundShapeGetChildOffset },
{ "setChildOffset", l_lovrCompoundShapeSetChildOffset },
{ "__len", l_lovrCompoundShapeGetChildCount }, // :)
{ NULL, NULL }
};

View File

@ -27,17 +27,18 @@ static int nextOverlap(lua_State* L) {
}
}
static bool raycastCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) {
static bool raycastCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) {
lua_State* L = userdata;
lua_pushvalue(L, -1);
luax_pushshape(L, shape);
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_pushnumber(L, z);
lua_pushnumber(L, nx);
lua_pushnumber(L, ny);
lua_pushnumber(L, nz);
lua_call(L, 7, 1);
luax_pushtype(L, Collider, collider);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
lua_pushnumber(L, normal[0]);
lua_pushnumber(L, normal[1]);
lua_pushnumber(L, normal[2]);
lua_pushinteger(L, shape + 1);
lua_call(L, 8, 1);
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
lua_pop(L, 1);
return shouldStop;
@ -45,53 +46,55 @@ static bool raycastCallback(Shape* shape, float x, float y, float z, float nx, f
typedef struct {
const char* tag;
Shape* shape;
Collider* collider;
uint32_t shape;
float distance;
float origin[3];
float position[3];
float normal[3];
} RaycastData;
static bool raycastAnyCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) {
static bool raycastAnyCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) {
RaycastData* data = userdata;
if (data->tag) {
const char* tag = lovrColliderGetTag(lovrShapeGetCollider(shape));
const char* tag = lovrColliderGetTag(collider);
if (!tag || strcmp(tag, data->tag)) {
return false;
}
}
data->collider = collider;
data->shape = shape;
vec3_set(data->position, x, y, z);
vec3_set(data->normal, nx, ny, nz);
vec3_init(data->position, position);
vec3_init(data->normal, normal);
data->distance = vec3_distance(data->origin, data->position);
return true;
}
static bool raycastClosestCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) {
static bool raycastClosestCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) {
RaycastData* data = userdata;
if (data->tag) {
const char* tag = lovrColliderGetTag(lovrShapeGetCollider(shape));
const char* tag = lovrColliderGetTag(collider);
if (!tag || strcmp(tag, data->tag)) {
return false;
}
}
float position[3];
vec3_set(position, x, y, z);
float distance = vec3_distance(data->origin, position);
if (distance < data->distance) {
vec3_init(data->position, position);
vec3_set(data->normal, nx, ny, nz);
vec3_init(data->normal, normal);
data->distance = distance;
data->collider = collider;
data->shape = shape;
}
return false;
}
static bool queryCallback(Shape* shape, void* userdata) {
static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) {
lua_State* L = userdata;
lua_pushvalue(L, -1);
luax_pushshape(L, shape);
lua_call(L, 1, 1);
luax_pushtype(L, Collider, collider);
lua_pushinteger(L, shape + 1);
lua_call(L, 2, 1);
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
lua_pop(L, 1);
return shouldStop;
@ -99,9 +102,10 @@ static bool queryCallback(Shape* shape, void* userdata) {
static int l_lovrWorldNewCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
Shape* shape = luax_totype(L, 2, Shape);
float position[3];
luax_readvec3(L, 2, position, NULL);
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
luax_readvec3(L, 2 + !!shape, position, NULL);
Collider* collider = lovrColliderCreate(world, shape, position);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
return 1;
@ -111,9 +115,8 @@ static int l_lovrWorldNewBoxCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
BoxShape* shape = luax_newboxshape(L, index);
lovrColliderAddShape(collider, shape);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
@ -125,9 +128,8 @@ static int l_lovrWorldNewCapsuleCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
CapsuleShape* shape = luax_newcapsuleshape(L, index);
lovrColliderAddShape(collider, shape);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
@ -139,9 +141,8 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
CylinderShape* shape = luax_newcylindershape(L, index);
lovrColliderAddShape(collider, shape);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
@ -153,9 +154,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
SphereShape* shape = luax_newsphereshape(L, index);
lovrColliderAddShape(collider, shape);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
@ -165,9 +165,9 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
static int l_lovrWorldNewMeshCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
MeshShape* shape = luax_newmeshshape(L, 2);
lovrColliderAddShape(collider, shape);
float position[3] = { 0.f, 0.f, 0.f };
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
@ -177,9 +177,9 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) {
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
TerrainShape* shape = luax_newterrainshape(L, 2);
lovrColliderAddShape(collider, shape);
float position[3] = { 0.f, 0.f, 0.f };
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderSetKinematic(collider, true);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
@ -187,25 +187,10 @@ static int l_lovrWorldNewTerrainCollider(lua_State* L) {
return 1;
}
static int l_lovrWorldGetColliders(lua_State* L) {
static int l_lovrWorldDestroy(lua_State* L) {
World* world = luax_checktype(L, 1, World);
if (lua_istable(L, 2)) {
lua_settop(L, 2);
} else {
lua_newtable(L);
}
Collider* collider = lovrWorldGetFirstCollider(world);
int index = 1;
while (collider) {
luax_pushtype(L, Collider, collider);
lua_rawseti(L, -2, index++);
collider = lovrColliderGetNext(collider);
}
return 1;
lovrWorldDestroyData(world);
return 0;
}
static int l_lovrWorldGetTags(lua_State* L) {
@ -221,10 +206,42 @@ static int l_lovrWorldGetTags(lua_State* L) {
return 1;
}
static int l_lovrWorldDestroy(lua_State* L) {
static int l_lovrWorldGetColliders(lua_State* L) {
World* world = luax_checktype(L, 1, World);
lovrWorldDestroyData(world);
return 0;
lua_createtable(L, (int) lovrWorldGetColliderCount(world), 0);
Collider* collider = NULL;
int index = 1;
while ((collider = lovrWorldEnumerateColliders(world, collider)) != NULL) {
luax_pushtype(L, Collider, collider);
lua_rawseti(L, -2, index++);
}
return 1;
}
static int l_lovrWorldGetColliderCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
uint32_t count = lovrWorldGetColliderCount(world);
lua_pushinteger(L, count);
return 1;
}
static int l_lovrWorldGetJoints(lua_State* L) {
World* world = luax_checktype(L, 1, World);
lua_createtable(L, (int) lovrWorldGetJointCount(world), 0);
Joint* joint = NULL;
int index = 1;
while ((joint = lovrWorldEnumerateJoints(world, joint)) != NULL) {
luax_pushjoint(L, joint);
lua_rawseti(L, -2, index++);
}
return 1;
}
static int l_lovrWorldGetJointCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
uint32_t count = lovrWorldGetJointCount(world);
lua_pushinteger(L, count);
return 1;
}
static int l_lovrWorldUpdate(lua_State* L) {
@ -296,7 +313,7 @@ static int l_lovrWorldRaycast(lua_State* L) {
index = luax_readvec3(L, index, end, NULL);
luaL_checktype(L, index, LUA_TFUNCTION);
lua_settop(L, index);
lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastCallback, L);
lovrWorldRaycast(world, start, end, raycastCallback, L);
return 0;
}
@ -308,16 +325,17 @@ static int l_lovrWorldRaycastAny(lua_State* L) {
index = luax_readvec3(L, index, end, NULL);
RaycastData data = { 0 };
data.tag = lua_tostring(L, index);
lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastAnyCallback, &data);
if (data.shape) {
luax_pushshape(L, data.shape);
lovrWorldRaycast(world, start, end, raycastAnyCallback, &data);
if (data.collider) {
luax_pushtype(L, Collider, data.collider);
lua_pushnumber(L, data.position[0]);
lua_pushnumber(L, data.position[1]);
lua_pushnumber(L, data.position[2]);
lua_pushnumber(L, data.normal[0]);
lua_pushnumber(L, data.normal[1]);
lua_pushnumber(L, data.normal[2]);
return 7;
lua_pushinteger(L, data.shape + 1);
return 8;
} else {
lua_pushnil(L);
return 1;
@ -332,16 +350,17 @@ static int l_lovrWorldRaycastClosest(lua_State* L) {
index = luax_readvec3(L, index, end, NULL);
RaycastData data = { .distance = FLT_MAX };
data.tag = lua_tostring(L, index);
lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastClosestCallback, &data);
lovrWorldRaycast(world, start, end, raycastClosestCallback, &data);
if (data.shape) {
luax_pushshape(L, data.shape);
luax_pushtype(L, Collider, data.collider);
lua_pushnumber(L, data.position[0]);
lua_pushnumber(L, data.position[1]);
lua_pushnumber(L, data.position[2]);
lua_pushnumber(L, data.normal[0]);
lua_pushnumber(L, data.normal[1]);
lua_pushnumber(L, data.normal[2]);
return 7;
lua_pushinteger(L, data.shape + 1);
return 8;
} else {
lua_pushnil(L);
return 1;
@ -514,9 +533,12 @@ const luaL_Reg lovrWorld[] = {
{ "newSphereCollider", l_lovrWorldNewSphereCollider },
{ "newMeshCollider", l_lovrWorldNewMeshCollider },
{ "newTerrainCollider", l_lovrWorldNewTerrainCollider },
{ "getColliders", l_lovrWorldGetColliders },
{ "getTags", l_lovrWorldGetTags },
{ "destroy", l_lovrWorldDestroy },
{ "getTags", l_lovrWorldGetTags },
{ "getColliderCount", l_lovrWorldGetColliderCount },
{ "getJointCount", l_lovrWorldGetJointCount },
{ "getColliders", l_lovrWorldGetColliders },
{ "getJoints", l_lovrWorldGetJoints },
{ "update", l_lovrWorldUpdate },
{ "computeOverlaps", l_lovrWorldComputeOverlaps },
{ "overlaps", l_lovrWorldOverlaps },

View File

@ -19,6 +19,7 @@ typedef Shape CapsuleShape;
typedef Shape CylinderShape;
typedef Shape MeshShape;
typedef Shape TerrainShape;
typedef Shape CompoundShape;
typedef Joint BallJoint;
typedef Joint DistanceJoint;
@ -26,8 +27,8 @@ typedef Joint HingeJoint;
typedef Joint SliderJoint;
typedef void (*CollisionResolver)(World* world, void* userdata);
typedef bool (*RaycastCallback)(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata);
typedef bool (*QueryCallback)(Shape* shape, void* userdata);
typedef bool (*RaycastCallback)(Collider* collider, float position[3], float normal[3], uint32_t child, void* userdata);
typedef bool (*QueryCallback)(Collider* collider, uint32_t child, void* userdata);
bool lovrPhysicsInit(void);
void lovrPhysicsDestroy(void);
@ -47,21 +48,23 @@ typedef struct {
bool allowSleep;
const char* tags[MAX_TAGS];
uint32_t tagCount;
float gravity[3]; // Deprecated
} WorldInfo;
World* lovrWorldCreate(WorldInfo* info);
void lovrWorldDestroy(void* ref);
void lovrWorldDestroyData(World* world);
uint32_t lovrWorldGetColliderCount(World* world);
uint32_t lovrWorldGetJointCount(World* world);
Collider* lovrWorldEnumerateColliders(World* world, Collider* collider);
Joint* lovrWorldEnumerateJoints(World* world, Joint* joint);
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata);
void lovrWorldComputeOverlaps(World* world);
int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b);
int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution);
void lovrWorldGetContacts(World* world, Shape* a, Shape* b, Contact contacts[MAX_CONTACTS], uint32_t* count);
void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, float y2, float z2, RaycastCallback callback, void* userdata);
void lovrWorldRaycast(World* world, float start[3], float end[3], RaycastCallback callback, void* userdata);
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata);
bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata);
Collider* lovrWorldGetFirstCollider(World* world);
void lovrWorldGetGravity(World* world, float gravity[3]);
void lovrWorldSetGravity(World* world, float gravity[3]);
const char* lovrWorldGetTagName(World* world, uint32_t tag);
@ -85,17 +88,19 @@ void lovrWorldSetSleepingAllowed(World* world, bool allowed);
// Collider
Collider* lovrColliderCreate(World* world, float x, float y, float z);
Collider* lovrColliderCreate(World* world, Shape* shape, float position[3]);
void lovrColliderDestroy(void* ref);
void lovrColliderDestroyData(Collider* collider);
bool lovrColliderIsDestroyed(Collider* collider);
bool lovrColliderIsEnabled(Collider* collider);
void lovrColliderSetEnabled(Collider* collider, bool enable);
void lovrColliderInitInertia(Collider* collider, Shape* shape);
World* lovrColliderGetWorld(Collider* collider);
Collider* lovrColliderGetNext(Collider* collider);
void lovrColliderAddShape(Collider* collider, Shape* shape);
void lovrColliderRemoveShape(Collider* collider, Shape* shape);
Shape** lovrColliderGetShapes(Collider* collider, size_t* count);
Joint** lovrColliderGetJoints(Collider* collider, size_t* count);
Shape* lovrColliderGetShape(Collider* collider, uint32_t child);
void lovrColliderSetShape(Collider* collider, Shape* shape);
void lovrColliderGetShapeOffset(Collider* collider, float position[3], float orientation[4]);
void lovrColliderSetShapeOffset(Collider* collider, float position[3], float orientation[4]);
Joint* lovrColliderEnumerateJoints(Collider* collider, Joint* joint, void** private);
const char* lovrColliderGetTag(Collider* collider);
bool lovrColliderSetTag(Collider* collider, const char* tag);
float lovrColliderGetFriction(Collider* collider);
@ -104,6 +109,8 @@ float lovrColliderGetRestitution(Collider* collider);
void lovrColliderSetRestitution(Collider* collider, float restitution);
bool lovrColliderIsKinematic(Collider* collider);
void lovrColliderSetKinematic(Collider* collider, bool kinematic);
bool lovrColliderIsSensor(Collider* collider);
void lovrColliderSetSensor(Collider* collider, bool sensor);
bool lovrColliderIsContinuous(Collider* collider);
void lovrColliderSetContinuous(Collider* collider, bool continuous);
float lovrColliderGetGravityScale(Collider* collider);
@ -114,33 +121,33 @@ bool lovrColliderIsAwake(Collider* collider);
void lovrColliderSetAwake(Collider* collider, bool awake);
float lovrColliderGetMass(Collider* collider);
void lovrColliderSetMass(Collider* collider, float mass);
void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]);
void lovrColliderSetMassData(Collider* collider, float cx, float cy, float cz, float mass, float inertia[6]);
void lovrColliderGetPosition(Collider* collider, float* x, float* y, float* z);
void lovrColliderSetPosition(Collider* collider, float x, float y, float z);
void lovrColliderGetOrientation(Collider* collider, float* orientation);
void lovrColliderSetOrientation(Collider* collider, float* orientation);
void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float* z);
void lovrColliderSetLinearVelocity(Collider* collider, float x, float y, float z);
void lovrColliderGetAngularVelocity(Collider* collider, float* x, float* y, float* z);
void lovrColliderSetAngularVelocity(Collider* collider, float x, float y, float z);
void lovrColliderGetMassData(Collider* collider, float centerOfMass[3], float* mass, float inertia[6]);
void lovrColliderSetMassData(Collider* collider, float centerOfMass[3], float mass, float inertia[6]);
void lovrColliderGetPosition(Collider* collider, float position[3]);
void lovrColliderSetPosition(Collider* collider, float position[3]);
void lovrColliderGetOrientation(Collider* collider, float orientation[4]);
void lovrColliderSetOrientation(Collider* collider, float orientation[4]);
void lovrColliderGetLinearVelocity(Collider* collider, float velocity[3]);
void lovrColliderSetLinearVelocity(Collider* collider, float velocity[3]);
void lovrColliderGetAngularVelocity(Collider* collider, float velocity[3]);
void lovrColliderSetAngularVelocity(Collider* collider, float velocity[3]);
void lovrColliderGetLinearDamping(Collider* collider, float* damping, float* threshold);
void lovrColliderSetLinearDamping(Collider* collider, float damping, float threshold);
void lovrColliderGetAngularDamping(Collider* collider, float* damping, float* threshold);
void lovrColliderSetAngularDamping(Collider* collider, float damping, float threshold);
void lovrColliderApplyForce(Collider* collider, float x, float y, float z);
void lovrColliderApplyForceAtPosition(Collider* collider, float x, float y, float z, float cx, float cy, float cz);
void lovrColliderApplyTorque(Collider* collider, float x, float y, float z);
void lovrColliderApplyForce(Collider* collider, float force[3]);
void lovrColliderApplyForceAtPosition(Collider* collider, float force[3], float position[3]);
void lovrColliderApplyTorque(Collider* collider, float torque[3]);
void lovrColliderApplyLinearImpulse(Collider* collider, float impulse[3]);
void lovrColliderApplyLinearImpulseAtPosition(Collider* collider, float impulse[3], float position[3]);
void lovrColliderApplyAngularImpulse(Collider* collider, float impulse[3]);
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z);
void lovrColliderGetLocalPoint(Collider* collider, float wx, float wy, float wz, float* x, float* y, float* z);
void lovrColliderGetWorldPoint(Collider* collider, float x, float y, float z, float* wx, float* wy, float* wz);
void lovrColliderGetLocalVector(Collider* collider, float wx, float wy, float wz, float* x, float* y, float* z);
void lovrColliderGetWorldVector(Collider* collider, float x, float y, float z, float* wx, float* wy, float* wz);
void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float x, float y, float z, float* vx, float* vy, float* vz);
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float wx, float wy, float wz, float* vx, float* vy, float* vz);
void lovrColliderGetLocalCenter(Collider* collider, float center[3]);
void lovrColliderGetLocalPoint(Collider* collider, float world[3], float local[3]);
void lovrColliderGetWorldPoint(Collider* collider, float local[3], float world[3]);
void lovrColliderGetLocalVector(Collider* collider, float world[3], float local[3]);
void lovrColliderGetWorldVector(Collider* collider, float local[3], float world[3]);
void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float point[3], float velocity[3]);
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float point[3], float velocity[3]);
void lovrColliderGetAABB(Collider* collider, float aabb[6]);
// Shapes
@ -151,48 +158,44 @@ typedef enum {
SHAPE_CAPSULE,
SHAPE_CYLINDER,
SHAPE_MESH,
SHAPE_TERRAIN
SHAPE_TERRAIN,
SHAPE_COMPOUND
} ShapeType;
void lovrShapeDestroy(void* ref);
void lovrShapeDestroyData(Shape* shape);
ShapeType lovrShapeGetType(Shape* shape);
Collider* lovrShapeGetCollider(Shape* shape);
bool lovrShapeIsEnabled(Shape* shape);
void lovrShapeSetEnabled(Shape* shape, bool enabled);
bool lovrShapeIsSensor(Shape* shape);
void lovrShapeSetSensor(Shape* shape, bool sensor);
void lovrShapeGetPosition(Shape* shape, float* x, float* y, float* z);
void lovrShapeSetPosition(Shape* shape, float x, float y, float z);
void lovrShapeGetOrientation(Shape* shape, float* orientation);
void lovrShapeSetOrientation(Shape* shape, float* orientation);
void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]);
void lovrShapeGetAABB(Shape* shape, float aabb[6]);
void lovrShapeGetMass(Shape* shape, float density, float centerOfMass[3], float* mass, float inertia[6]);
void lovrShapeGetAABB(Shape* shape, float position[3], float orientation[4], float aabb[6]);
SphereShape* lovrSphereShapeCreate(float radius);
float lovrSphereShapeGetRadius(SphereShape* sphere);
void lovrSphereShapeSetRadius(SphereShape* sphere, float radius);
BoxShape* lovrBoxShapeCreate(float w, float h, float d);
void lovrBoxShapeGetDimensions(BoxShape* box, float* w, float* h, float* d);
void lovrBoxShapeSetDimensions(BoxShape* box, float w, float h, float d);
BoxShape* lovrBoxShapeCreate(float dimensions[3]);
void lovrBoxShapeGetDimensions(BoxShape* box, float dimensions[3]);
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length);
float lovrCapsuleShapeGetRadius(CapsuleShape* capsule);
void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius);
float lovrCapsuleShapeGetLength(CapsuleShape* capsule);
void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length);
CylinderShape* lovrCylinderShapeCreate(float radius, float length);
float lovrCylinderShapeGetRadius(CylinderShape* cylinder);
void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius);
float lovrCylinderShapeGetLength(CylinderShape* cylinder);
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]);
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY);
CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze);
bool lovrCompoundShapeIsFrozen(CompoundShape* shape);
void lovrCompoundShapeAddChild(CompoundShape* shape, Shape* child, float position[3], float orientation[4]);
void lovrCompoundShapeReplaceChild(CompoundShape* shape, uint32_t index, Shape* child, float position[3], float orientation[4]);
void lovrCompoundShapeRemoveChild(CompoundShape* shape, uint32_t index);
Shape* lovrCompoundShapeGetChild(CompoundShape* shape, uint32_t index);
uint32_t lovrCompoundShapeGetChildCount(CompoundShape* shape);
void lovrCompoundShapeGetChildOffset(CompoundShape* shape, uint32_t index, float position[3], float orientation[4]);
void lovrCompoundShapeSetChildOffset(CompoundShape* shape, uint32_t index, float position[3], float orientation[4]);
// These tokens need to exist for Lua bindings
#define lovrSphereShapeDestroy lovrShapeDestroy
#define lovrBoxShapeDestroy lovrShapeDestroy
@ -200,6 +203,7 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ,
#define lovrCylinderShapeDestroy lovrShapeDestroy
#define lovrMeshShapeDestroy lovrShapeDestroy
#define lovrTerrainShapeDestroy lovrShapeDestroy
#define lovrCompoundShapeDestroy lovrShapeDestroy
// Joints
@ -212,6 +216,7 @@ typedef enum {
void lovrJointDestroy(void* ref);
void lovrJointDestroyData(Joint* joint);
bool lovrJointIsDestroyed(Joint* joint);
JointType lovrJointGetType(Joint* joint);
float lovrJointGetCFM(Joint* joint);
void lovrJointSetCFM(Joint* joint, float cfm);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
#include "physics.h"
#include "core/maf.h"
#include "util.h"
#include <ode/ode.h>
#include <stdatomic.h>
@ -22,10 +23,11 @@ struct Collider {
Collider* prev;
Collider* next;
uint32_t tag;
arr_t(Shape*) shapes;
Shape* shape;
arr_t(Joint*) joints;
float friction;
float restitution;
bool sensor;
};
struct Shape {
@ -35,7 +37,6 @@ struct Shape {
Collider* collider;
void* vertices;
void* indices;
bool sensor;
};
struct Joint {
@ -66,8 +67,9 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) {
RaycastCallback callback = data->callback;
void* userdata = data->userdata;
Shape* shape = dGeomGetData(b);
Collider* collider = dBodyGetData(dGeomGetBody(b));
if (!shape) {
if (!shape || !collider) {
return;
}
@ -75,9 +77,7 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) {
int count = dCollide(a, b, MAX_CONTACTS, &contact->geom, sizeof(dContact));
for (int i = 0; i < count; i++) {
dContactGeom g = contact[i].geom;
data->shouldStop = callback(
shape, g.pos[0], g.pos[1], g.pos[2], g.normal[0], g.normal[1], g.normal[2], userdata
);
data->shouldStop = callback(collider, g.pos, g.normal, 0, userdata);
}
}
@ -93,14 +93,15 @@ static void queryCallback(void* d, dGeomID a, dGeomID b) {
if (data->shouldStop) return;
Shape* shape = dGeomGetData(b);
if (!shape) {
Collider* collider = dBodyGetData(dGeomGetBody(b));
if (!shape || !collider) {
return;
}
dContactGeom contact;
if (dCollide(a, b, 1 | CONTACTS_UNIMPORTANT, &contact, sizeof(contact))) {
if (data->callback) {
data->shouldStop = data->callback(shape, data->userdata);
data->shouldStop = data->callback(collider, 0, data->userdata);
} else {
data->shouldStop = true;
}
@ -162,7 +163,6 @@ World* lovrWorldCreate(WorldInfo* info) {
dHashSpaceSetLevels(world->space, -4, 8);
world->contactGroup = dJointGroupCreate(0);
arr_init(&world->overlaps);
lovrWorldSetGravity(world, info->gravity);
lovrWorldSetSleepingAllowed(world, info->allowSleep);
for (uint32_t i = 0; i < info->tagCount; i++) {
size_t size = strlen(info->tags[i]) + 1;
@ -206,6 +206,28 @@ void lovrWorldDestroyData(World* world) {
}
}
uint32_t lovrWorldGetColliderCount(World* world) {
Collider* collider = world->head;
uint32_t count = 0;
while (collider) {
collider = collider->next;
count++;
}
return count;
}
uint32_t lovrWorldGetJointCount(World* world) {
return 0;
}
Collider* lovrWorldEnumerateColliders(World* world, Collider* collider) {
return collider ? collider->next : world->head;
}
Joint* lovrWorldEnumerateJoints(World* world, Joint* joint) {
return NULL;
}
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata) {
if (resolver) {
resolver(world, userdata);
@ -279,7 +301,7 @@ int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float res
int contactCount = dCollide(a->id, b->id, MAX_CONTACTS, &contacts[0].geom, sizeof(dContact));
if (!a->sensor && !b->sensor) {
if (!colliderA->sensor && !colliderB->sensor) {
for (int c = 0; c < contactCount; c++) {
dJointID joint = dJointCreateContact(world->id, world->contactGroup, &contacts[c]);
dJointAttach(joint, colliderA->body, colliderB->body);
@ -305,14 +327,14 @@ void lovrWorldGetContacts(World* world, Shape* a, Shape* b, Contact contacts[MAX
}
}
void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, float y2, float z2, RaycastCallback callback, void* userdata) {
void lovrWorldRaycast(World* world, float start[3], float end[3], RaycastCallback callback, void* userdata) {
RaycastData data = { .callback = callback, .userdata = userdata, .shouldStop = false };
float dx = x2 - x1;
float dy = y2 - y1;
float dz = z2 - z1;
float dx = start[0] - end[0];
float dy = start[1] - end[1];
float dz = start[2] - end[2];
float length = sqrtf(dx * dx + dy * dy + dz * dz);
dGeomID ray = dCreateRay(world->space, length);
dGeomRaySet(ray, x1, y1, z1, dx, dy, dz);
dGeomRaySet(ray, start[0], start[1], start[2], end[0], end[1], end[2]);
dSpaceCollide2(ray, (dGeomID) world->space, &data, raycastCallback);
dGeomDestroy(ray);
}
@ -335,10 +357,6 @@ bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCa
return data.called;
}
Collider* lovrWorldGetFirstCollider(World* world) {
return world->head;
}
void lovrWorldGetGravity(World* world, float gravity[3]) {
dReal g[4];
dWorldGetGravity(world->id, g);
@ -436,7 +454,7 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
return (world->masks[i] & (1 << j)) && (world->masks[j] & (1 << i));
}
Collider* lovrColliderCreate(World* world, float x, float y, float z) {
Collider* lovrColliderCreate(World* world, Shape* shape, float position[3]) {
Collider* collider = lovrCalloc(sizeof(Collider));
collider->ref = 1;
collider->body = dBodyCreate(world->id);
@ -445,10 +463,10 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
collider->restitution = 0;
collider->tag = NO_TAG;
dBodySetData(collider->body, collider);
arr_init(&collider->shapes);
arr_init(&collider->joints);
lovrColliderSetPosition(collider, x, y, z);
lovrColliderSetShape(collider, shape);
lovrColliderSetPosition(collider, position);
// Adjust the world's collider list
if (!collider->world->head) {
@ -467,7 +485,6 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
void lovrColliderDestroy(void* ref) {
Collider* collider = ref;
lovrColliderDestroyData(collider);
arr_free(&collider->shapes);
arr_free(&collider->joints);
lovrFree(collider);
}
@ -477,14 +494,10 @@ void lovrColliderDestroyData(Collider* collider) {
return;
}
size_t count;
lovrColliderSetShape(collider, NULL);
Shape** shapes = lovrColliderGetShapes(collider, &count);
for (size_t i = 0; i < count; i++) {
lovrColliderRemoveShape(collider, shapes[i]);
}
Joint** joints = lovrColliderGetJoints(collider, &count);
Joint** joints = collider->joints.data;
size_t count = collider->joints.length;
for (size_t i = 0; i < count; i++) {
lovrRelease(joints[i], lovrJointDestroy);
}
@ -505,12 +518,20 @@ bool lovrColliderIsDestroyed(Collider* collider) {
return !collider->body;
}
bool lovrColliderIsEnabled(Collider* collider) {
return true;
}
void lovrColliderSetEnabled(Collider* collider, bool enable) {
//
}
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
// compute inertia matrix for default density
const float density = 1.0f;
float cx, cy, cz, mass, inertia[6];
lovrShapeGetMass(shape, density, &cx, &cy, &cz, &mass, inertia);
lovrColliderSetMassData(collider, cx, cy, cz, mass, inertia);
float centerOfMass[3], mass, inertia[6];
lovrShapeGetMass(shape, density, centerOfMass, &mass, inertia);
lovrColliderSetMassData(collider, centerOfMass, mass, inertia);
}
World* lovrColliderGetWorld(Collider* collider) {
@ -521,38 +542,50 @@ Collider* lovrColliderGetNext(Collider* collider) {
return collider->next;
}
void lovrColliderAddShape(Collider* collider, Shape* shape) {
lovrRetain(shape);
if (shape->collider) {
lovrColliderRemoveShape(shape->collider, shape);
}
shape->collider = collider;
dGeomSetBody(shape->id, collider->body);
dSpaceID newSpace = collider->world->space;
dSpaceAdd(newSpace, shape->id);
Shape* lovrColliderGetShape(Collider* collider, uint32_t child) {
return collider->shape;
}
void lovrColliderRemoveShape(Collider* collider, Shape* shape) {
if (shape->collider == collider) {
dSpaceRemove(collider->world->space, shape->id);
dGeomSetBody(shape->id, 0);
shape->collider = NULL;
lovrRelease(shape, lovrShapeDestroy);
void lovrColliderSetShape(Collider* collider, Shape* shape) {
if (collider->shape) {
dSpaceRemove(collider->world->space, collider->shape->id);
dGeomSetBody(collider->shape->id, 0);
collider->shape->collider = NULL;
lovrRelease(collider->shape, lovrShapeDestroy);
}
}
Shape** lovrColliderGetShapes(Collider* collider, size_t* count) {
arr_clear(&collider->shapes);
for (dGeomID geom = dBodyGetFirstGeom(collider->body); geom; geom = dBodyGetNextGeom(geom)) {
Shape* shape = dGeomGetData(geom);
if (shape) {
arr_push(&collider->shapes, shape);
collider->shape = shape;
if (shape) {
if (shape->collider) {
lovrColliderSetShape(shape->collider, NULL);
}
shape->collider = collider;
dGeomSetBody(shape->id, collider->body);
dSpaceID newSpace = collider->world->space;
dSpaceAdd(newSpace, shape->id);
lovrRetain(shape);
}
*count = collider->shapes.length;
return collider->shapes.data;
}
void lovrColliderGetShapeOffset(Collider* collider, float position[3], float orientation[4]) {
const dReal* p = dGeomGetOffsetPosition(collider->shape->id);
position[0] = p[0];
position[1] = p[1];
position[2] = p[2];
dReal q[4];
dGeomGetOffsetQuaternion(collider->shape->id, q);
orientation[0] = q[1];
orientation[1] = q[2];
orientation[2] = q[3];
orientation[3] = q[0];
}
void lovrColliderSetShapeOffset(Collider* collider, float position[3], float orientation[4]) {
dGeomSetOffsetPosition(collider->shape->id, position[0], position[1], position[2]);
dReal q[4] = { orientation[3], orientation[0], orientation[1], orientation[2] };
dGeomSetOffsetQuaternion(collider->shape->id, q);
}
Joint** lovrColliderGetJoints(Collider* collider, size_t* count) {
@ -568,6 +601,15 @@ Joint** lovrColliderGetJoints(Collider* collider, size_t* count) {
return collider->joints.data;
}
Joint* lovrColliderEnumerateJoints(Collider* collider, Joint* joint, void** private) {
if (!joint) {
*private = NULL;
}
uintptr_t index = (uintptr_t) *private;
return index < collider->joints.length ? collider->joints.data[index] : NULL;
}
const char* lovrColliderGetTag(Collider* collider) {
return lovrWorldGetTagName(collider->world, collider->tag);
}
@ -610,6 +652,14 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
}
}
bool lovrColliderIsSensor(Collider* collider) {
return collider->sensor;
}
void lovrColliderSetSensor(Collider* collider, bool sensor) {
collider->sensor = sensor;
}
bool lovrColliderIsContinuous(Collider* collider) {
return false;
}
@ -659,12 +709,10 @@ void lovrColliderSetMass(Collider* collider, float mass) {
dBodySetMass(collider->body, &m);
}
void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
void lovrColliderGetMassData(Collider* collider, float centerOfMass[3], float* mass, float inertia[6]) {
dMass m;
dBodyGetMass(collider->body, &m);
*cx = m.c[0];
*cy = m.c[1];
*cz = m.c[2];
vec3_set(centerOfMass, m.c[0], m.c[1], m.c[2]);
*mass = m.mass;
// Diagonal
@ -678,30 +726,25 @@ void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz
inertia[5] = m.I[9];
}
void lovrColliderSetMassData(Collider* collider, float cx, float cy, float cz, float mass, float inertia[6]) {
void lovrColliderSetMassData(Collider* collider, float centerOfMass[3], float mass, float inertia[6]) {
dMass m;
dBodyGetMass(collider->body, &m);
dMassSetParameters(&m, mass, cx, cy, cz, inertia[0], inertia[1], inertia[2], inertia[3], inertia[4], inertia[5]);
dMassSetParameters(&m, mass, centerOfMass[0], centerOfMass[1], centerOfMass[2], inertia[0], inertia[1], inertia[2], inertia[3], inertia[4], inertia[5]);
dBodySetMass(collider->body, &m);
}
void lovrColliderGetPosition(Collider* collider, float* x, float* y, float* z) {
const dReal* position = dBodyGetPosition(collider->body);
*x = position[0];
*y = position[1];
*z = position[2];
void lovrColliderGetPosition(Collider* collider, float position[3]) {
const dReal* p = dBodyGetPosition(collider->body);
vec3_set(position, p[0], p[1], p[2]);
}
void lovrColliderSetPosition(Collider* collider, float x, float y, float z) {
dBodySetPosition(collider->body, x, y, z);
void lovrColliderSetPosition(Collider* collider, float position[3]) {
dBodySetPosition(collider->body, position[0], position[1], position[2]);
}
void lovrColliderGetOrientation(Collider* collider, float* orientation) {
void lovrColliderGetOrientation(Collider* collider, float orientation[4]) {
const dReal* q = dBodyGetQuaternion(collider->body);
orientation[0] = q[1];
orientation[1] = q[2];
orientation[2] = q[3];
orientation[3] = q[0];
quat_set(orientation, q[1], q[2], q[3], q[0]);
}
void lovrColliderSetOrientation(Collider* collider, float* orientation) {
@ -709,28 +752,24 @@ void lovrColliderSetOrientation(Collider* collider, float* orientation) {
dBodySetQuaternion(collider->body, q);
}
void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float* z) {
const dReal* velocity = dBodyGetLinearVel(collider->body);
*x = velocity[0];
*y = velocity[1];
*z = velocity[2];
void lovrColliderGetLinearVelocity(Collider* collider, float velocity[3]) {
const dReal* v = dBodyGetLinearVel(collider->body);
vec3_set(velocity, v[0], v[1], v[2]);
}
void lovrColliderSetLinearVelocity(Collider* collider, float x, float y, float z) {
void lovrColliderSetLinearVelocity(Collider* collider, float velocity[3]) {
dBodyEnable(collider->body);
dBodySetLinearVel(collider->body, x, y, z);
dBodySetLinearVel(collider->body, velocity[0], velocity[1], velocity[2]);
}
void lovrColliderGetAngularVelocity(Collider* collider, float* x, float* y, float* z) {
const dReal* velocity = dBodyGetAngularVel(collider->body);
*x = velocity[0];
*y = velocity[1];
*z = velocity[2];
void lovrColliderGetAngularVelocity(Collider* collider, float velocity[3]) {
const dReal* v = dBodyGetAngularVel(collider->body);
vec3_set(velocity, v[0], v[1], v[2]);
}
void lovrColliderSetAngularVelocity(Collider* collider, float x, float y, float z) {
void lovrColliderSetAngularVelocity(Collider* collider, float velocity[3]) {
dBodyEnable(collider->body);
dBodySetAngularVel(collider->body, x, y, z);
dBodySetAngularVel(collider->body, velocity[0], velocity[1], velocity[2]);
}
void lovrColliderGetLinearDamping(Collider* collider, float* damping, float* threshold) {
@ -753,19 +792,19 @@ void lovrColliderSetAngularDamping(Collider* collider, float damping, float thre
dBodySetAngularDampingThreshold(collider->body, threshold);
}
void lovrColliderApplyForce(Collider* collider, float x, float y, float z) {
void lovrColliderApplyForce(Collider* collider, float force[3]) {
dBodyEnable(collider->body);
dBodyAddForce(collider->body, x, y, z);
dBodyAddForce(collider->body, force[0], force[1], force[2]);
}
void lovrColliderApplyForceAtPosition(Collider* collider, float x, float y, float z, float cx, float cy, float cz) {
void lovrColliderApplyForceAtPosition(Collider* collider, float force[3], float position[3]) {
dBodyEnable(collider->body);
dBodyAddForceAtPos(collider->body, x, y, z, cx, cy, cz);
dBodyAddForceAtPos(collider->body, force[0], force[1], force[2], position[0], position[1], position[2]);
}
void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
void lovrColliderApplyTorque(Collider* collider, float torque[3]) {
dBodyEnable(collider->body);
dBodyAddTorque(collider->body, x, y, z);
dBodyAddTorque(collider->body, torque[0], torque[1], torque[2]);
}
void lovrColliderApplyLinearImpulse(Collider* collider, float impulse[3]) {
@ -780,60 +819,46 @@ void lovrColliderApplyAngularImpulse(Collider* collider, float impulse[3]) {
//
}
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
void lovrColliderGetLocalCenter(Collider* collider, float center[3]) {
dMass m;
dBodyGetMass(collider->body, &m);
*x = m.c[0];
*y = m.c[1];
*z = m.c[2];
vec3_set(center, m.c[0], m.c[1], m.c[2]);
}
void lovrColliderGetLocalPoint(Collider* collider, float wx, float wy, float wz, float* x, float* y, float* z) {
dReal local[4];
dBodyGetPosRelPoint(collider->body, wx, wy, wz, local);
*x = local[0];
*y = local[1];
*z = local[2];
void lovrColliderGetLocalPoint(Collider* collider, float world[3], float local[3]) {
dReal point[4];
dBodyGetPosRelPoint(collider->body, world[0], world[1], world[2], point);
vec3_set(local, point[0], point[1], point[2]);
}
void lovrColliderGetWorldPoint(Collider* collider, float x, float y, float z, float* wx, float* wy, float* wz) {
dReal world[4];
dBodyGetRelPointPos(collider->body, x, y, z, world);
*wx = world[0];
*wy = world[1];
*wz = world[2];
void lovrColliderGetWorldPoint(Collider* collider, float local[3], float world[3]) {
dReal point[4];
dBodyGetRelPointPos(collider->body, local[0], local[1], local[2], point);
vec3_set(world, point[0], point[1], point[2]);
}
void lovrColliderGetLocalVector(Collider* collider, float wx, float wy, float wz, float* x, float* y, float* z) {
dReal local[4];
dBodyVectorFromWorld(collider->body, wx, wy, wz, local);
*x = local[0];
*y = local[1];
*z = local[2];
void lovrColliderGetLocalVector(Collider* collider, float world[3], float local[3]) {
dReal vector[4];
dBodyVectorFromWorld(collider->body, world[0], world[1], world[2], local);
vec3_set(local, vector[0], vector[1], vector[2]);
}
void lovrColliderGetWorldVector(Collider* collider, float x, float y, float z, float* wx, float* wy, float* wz) {
dReal world[4];
dBodyVectorToWorld(collider->body, x, y, z, world);
*wx = world[0];
*wy = world[1];
*wz = world[2];
void lovrColliderGetWorldVector(Collider* collider, float local[3], float world[3]) {
dReal vector[4];
dBodyVectorToWorld(collider->body, local[0], local[1], local[2], world);
vec3_set(world, vector[0], vector[1], vector[2]);
}
void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float x, float y, float z, float* vx, float* vy, float* vz) {
dReal velocity[4];
dBodyGetRelPointVel(collider->body, x, y, z, velocity);
*vx = velocity[0];
*vy = velocity[1];
*vz = velocity[2];
void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float point[3], float velocity[3]) {
dReal vector[4];
dBodyGetRelPointVel(collider->body, point[0], point[1], point[2], vector);
vec3_set(velocity, vector[0], vector[1], vector[2]);
}
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float wx, float wy, float wz, float* vx, float* vy, float* vz) {
dReal velocity[4];
dBodyGetPointVel(collider->body, wx, wy, wz, velocity);
*vx = velocity[0];
*vy = velocity[1];
*vz = velocity[2];
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float point[3], float velocity[3]) {
dReal vector[4];
dBodyGetPointVel(collider->body, point[0], point[1], point[2], velocity);
vec3_set(velocity, vector[0], vector[1], vector[2]);
}
void lovrColliderGetAABB(Collider* collider, float aabb[6]) {
@ -888,52 +913,7 @@ Collider* lovrShapeGetCollider(Shape* shape) {
return shape->collider;
}
bool lovrShapeIsEnabled(Shape* shape) {
return dGeomIsEnabled(shape->id);
}
void lovrShapeSetEnabled(Shape* shape, bool enabled) {
if (enabled) {
dGeomEnable(shape->id);
} else {
dGeomDisable(shape->id);
}
}
bool lovrShapeIsSensor(Shape* shape) {
return shape->sensor;
}
void lovrShapeSetSensor(Shape* shape, bool sensor) {
shape->sensor = sensor;
}
void lovrShapeGetPosition(Shape* shape, float* x, float* y, float* z) {
const dReal* position = dGeomGetOffsetPosition(shape->id);
*x = position[0];
*y = position[1];
*z = position[2];
}
void lovrShapeSetPosition(Shape* shape, float x, float y, float z) {
dGeomSetOffsetPosition(shape->id, x, y, z);
}
void lovrShapeGetOrientation(Shape* shape, float* orientation) {
dReal q[4];
dGeomGetOffsetQuaternion(shape->id, q);
orientation[0] = q[1];
orientation[1] = q[2];
orientation[2] = q[3];
orientation[3] = q[0];
}
void lovrShapeSetOrientation(Shape* shape, float* orientation) {
dReal q[4] = { orientation[3], orientation[0], orientation[1], orientation[2] };
dGeomSetOffsetQuaternion(shape->id, q);
}
void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
void lovrShapeGetMass(Shape* shape, float density, float centerOfMass[3], float* mass, float inertia[6]) {
dMass m;
dMassSetZero(&m);
switch (shape->type) {
@ -973,6 +953,8 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float*
case SHAPE_TERRAIN: {
break;
}
default: break;
}
const dReal* position = dGeomGetOffsetPosition(shape->id);
@ -980,9 +962,9 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float*
const dReal* rotation = dGeomGetOffsetRotation(shape->id);
dMassRotate(&m, rotation);
*cx = m.c[0];
*cy = m.c[1];
*cz = m.c[2];
centerOfMass[0] = m.c[0];
centerOfMass[1] = m.c[1];
centerOfMass[2] = m.c[2];
*mass = m.mass;
// Diagonal
@ -996,7 +978,7 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float*
inertia[5] = m.I[9];
}
void lovrShapeGetAABB(Shape* shape, float aabb[6]) {
void lovrShapeGetAABB(Shape* shape, float position[3], float orientation[4], float aabb[6]) {
dGeomGetAABB(shape->id, aabb);
}
@ -1019,26 +1001,19 @@ void lovrSphereShapeSetRadius(SphereShape* sphere, float radius) {
dGeomSphereSetRadius(sphere->id, radius);
}
BoxShape* lovrBoxShapeCreate(float w, float h, float d) {
BoxShape* lovrBoxShapeCreate(float dimensions[3]) {
BoxShape* box = lovrCalloc(sizeof(BoxShape));
box->ref = 1;
box->type = SHAPE_BOX;
box->id = dCreateBox(0, w, h, d);
box->id = dCreateBox(0, dimensions[0], dimensions[1], dimensions[2]);
dGeomSetData(box->id, box);
return box;
}
void lovrBoxShapeGetDimensions(BoxShape* box, float* w, float* h, float* d) {
dReal dimensions[4];
dGeomBoxGetLengths(box->id, dimensions);
*w = dimensions[0];
*h = dimensions[1];
*d = dimensions[2];
}
void lovrBoxShapeSetDimensions(BoxShape* box, float w, float h, float d) {
lovrCheck(w > 0.f && h > 0.f && d > 0.f, "BoxShape dimensions must be positive");
dGeomBoxSetLengths(box->id, w, h, d);
void lovrBoxShapeGetDimensions(BoxShape* box, float dimensions[3]) {
dReal d[4];
dGeomBoxGetLengths(box->id, d);
vec3_set(dimensions, d[0], d[1], d[2]);
}
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length) {
@ -1057,22 +1032,12 @@ float lovrCapsuleShapeGetRadius(CapsuleShape* capsule) {
return radius;
}
void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius) {
lovrCheck(radius > 0.f, "CapsuleShape dimensions must be positive");
dGeomCapsuleSetParams(capsule->id, radius, lovrCapsuleShapeGetLength(capsule));
}
float lovrCapsuleShapeGetLength(CapsuleShape* capsule) {
dReal radius, length;
dGeomCapsuleGetParams(capsule->id, &radius, &length);
return length;
}
void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length) {
lovrCheck(length > 0.f, "CapsuleShape dimensions must be positive");
dGeomCapsuleSetParams(capsule->id, lovrCapsuleShapeGetRadius(capsule), length);
}
CylinderShape* lovrCylinderShapeCreate(float radius, float length) {
lovrCheck(radius > 0.f && length > 0.f, "CylinderShape dimensions must be positive");
CylinderShape* cylinder = lovrCalloc(sizeof(CylinderShape));
@ -1089,22 +1054,12 @@ float lovrCylinderShapeGetRadius(CylinderShape* cylinder) {
return radius;
}
void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius) {
lovrCheck(radius > 0.f, "CylinderShape dimensions must be positive");
dGeomCylinderSetParams(cylinder->id, radius, lovrCylinderShapeGetLength(cylinder));
}
float lovrCylinderShapeGetLength(CylinderShape* cylinder) {
dReal radius, length;
dGeomCylinderGetParams(cylinder->id, &radius, &length);
return length;
}
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) {
lovrCheck(length > 0.f, "CylinderShape dimensions must be positive");
dGeomCylinderSetParams(cylinder->id, lovrCylinderShapeGetRadius(cylinder), length);
}
MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount, dTriIndex* indices) {
MeshShape* mesh = lovrCalloc(sizeof(MeshShape));
mesh->ref = 1;
@ -1131,6 +1086,42 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ,
return terrain;
}
CompoundShape* lovrCompoundShapeCreate(Shape** shapes, float* positions, float* orientations, uint32_t count, bool freeze) {
lovrThrow("ODE does not support compound shape");
}
bool lovrCompoundShapeIsFrozen(CompoundShape* shape) {
return false;
}
void lovrCompoundShapeAddChild(CompoundShape* shape, Shape* child, float* position, float* orientation) {
//
}
void lovrCompoundShapeReplaceChild(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) {
//
}
void lovrCompoundShapeRemoveChild(CompoundShape* shape, uint32_t index) {
//
}
Shape* lovrCompoundShapeGetChild(CompoundShape* shape, uint32_t index) {
return NULL;
}
uint32_t lovrCompoundShapeGetChildCount(CompoundShape* shape) {
return 0;
}
void lovrCompoundShapeGetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) {
//
}
void lovrCompoundShapeSetChildOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) {
//
}
void lovrJointDestroy(void* ref) {
Joint* joint = ref;
lovrJointDestroyData(joint);
@ -1144,6 +1135,10 @@ void lovrJointDestroyData(Joint* joint) {
}
}
bool lovrJointIsDestroyed(Joint* joint) {
return joint->id == NULL;
}
JointType lovrJointGetType(Joint* joint) {
return joint->type;
}