mirror of https://github.com/bjornbytes/lovr.git
Compare commits
22 Commits
5b4ee30187
...
d876de66cb
Author | SHA1 | Date |
---|---|---|
bjorn | d876de66cb | |
bjorn | 1a8d05b8b4 | |
bjorn | 24708f7114 | |
bjorn | f82715d402 | |
bjorn | 2cc5dc8c85 | |
bjorn | 17475f7ad2 | |
bjorn | aa6b3fb6c8 | |
bjorn | f79dec31ff | |
bjorn | 6b5244a8e1 | |
bjorn | 8f40d98074 | |
bjorn | e842c2b772 | |
bjorn | 48559ccd0f | |
bjorn | 6cf9f8082e | |
bjorn | 7640be2281 | |
bjorn | 7474192e78 | |
bjorn | 50fbcf1450 | |
bjorn | 5244420828 | |
bjorn | 5bf9f874b8 | |
bjorn | f4d5c0d758 | |
bjorn | 38a68dc4e5 | |
bjorn | 5e521b7698 | |
bjorn | fb6b402034 |
|
@ -1 +1 @@
|
||||||
Subproject commit 29fe07e8088279c47d7108107856ec3c826d1817
|
Subproject commit 22a062b3729f72eaaa24148195368e8b564ecfd1
|
|
@ -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_newcylindershape(lua_State* L, int index);
|
||||||
struct Shape* luax_newmeshshape(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_newterrainshape(lua_State* L, int index);
|
||||||
|
struct Shape* luax_newcompoundshape(lua_State* L, int index);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,6 +9,7 @@ StringEntry lovrShapeType[] = {
|
||||||
[SHAPE_CYLINDER] = ENTRY("cylinder"),
|
[SHAPE_CYLINDER] = ENTRY("cylinder"),
|
||||||
[SHAPE_MESH] = ENTRY("mesh"),
|
[SHAPE_MESH] = ENTRY("mesh"),
|
||||||
[SHAPE_TERRAIN] = ENTRY("terrain"),
|
[SHAPE_TERRAIN] = ENTRY("terrain"),
|
||||||
|
[SHAPE_COMPOUND] = ENTRY("compound"),
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -178,6 +179,13 @@ static int l_lovrPhysicsNewTerrainShape(lua_State* L) {
|
||||||
return 1;
|
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[] = {
|
static const luaL_Reg lovrPhysics[] = {
|
||||||
{ "newWorld", l_lovrPhysicsNewWorld },
|
{ "newWorld", l_lovrPhysicsNewWorld },
|
||||||
{ "newBallJoint", l_lovrPhysicsNewBallJoint },
|
{ "newBallJoint", l_lovrPhysicsNewBallJoint },
|
||||||
|
@ -190,6 +198,7 @@ static const luaL_Reg lovrPhysics[] = {
|
||||||
{ "newSliderJoint", l_lovrPhysicsNewSliderJoint },
|
{ "newSliderJoint", l_lovrPhysicsNewSliderJoint },
|
||||||
{ "newSphereShape", l_lovrPhysicsNewSphereShape },
|
{ "newSphereShape", l_lovrPhysicsNewSphereShape },
|
||||||
{ "newTerrainShape", l_lovrPhysicsNewTerrainShape },
|
{ "newTerrainShape", l_lovrPhysicsNewTerrainShape },
|
||||||
|
{ "newCompoundShape", l_lovrPhysicsNewCompoundShape },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,6 +214,7 @@ extern const luaL_Reg lovrCapsuleShape[];
|
||||||
extern const luaL_Reg lovrCylinderShape[];
|
extern const luaL_Reg lovrCylinderShape[];
|
||||||
extern const luaL_Reg lovrMeshShape[];
|
extern const luaL_Reg lovrMeshShape[];
|
||||||
extern const luaL_Reg lovrTerrainShape[];
|
extern const luaL_Reg lovrTerrainShape[];
|
||||||
|
extern const luaL_Reg lovrCompoundShape[];
|
||||||
|
|
||||||
int luaopen_lovr_physics(lua_State* L) {
|
int luaopen_lovr_physics(lua_State* L) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
@ -221,6 +231,7 @@ int luaopen_lovr_physics(lua_State* L) {
|
||||||
luax_registertype(L, CylinderShape);
|
luax_registertype(L, CylinderShape);
|
||||||
luax_registertype(L, MeshShape);
|
luax_registertype(L, MeshShape);
|
||||||
luax_registertype(L, TerrainShape);
|
luax_registertype(L, TerrainShape);
|
||||||
|
luax_registertype(L, CompoundShape);
|
||||||
lovrPhysicsInit();
|
lovrPhysicsInit();
|
||||||
luax_atexit(L, lovrPhysicsDestroy);
|
luax_atexit(L, lovrPhysicsDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -17,6 +17,20 @@ static int l_lovrColliderIsDestroyed(lua_State* L) {
|
||||||
return 1;
|
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) {
|
static int l_lovrColliderGetWorld(lua_State* L) {
|
||||||
Collider* collider = luax_checktype(L, 1, Collider);
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
World* world = lovrColliderGetWorld(collider);
|
World* world = lovrColliderGetWorld(collider);
|
||||||
|
@ -24,32 +38,45 @@ static int l_lovrColliderGetWorld(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_lovrColliderAddShape(lua_State* L) {
|
static int l_lovrColliderGetShape(lua_State* L) {
|
||||||
Collider* collider = luax_checktype(L, 1, Collider);
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
Shape* shape = luax_checkshape(L, 2);
|
Shape* shape = lovrColliderGetShape(collider);
|
||||||
lovrColliderAddShape(collider, shape);
|
luax_pushshape(L, 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);
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_lovrColliderSetShape(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
Shape* shape = 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) {
|
static int l_lovrColliderGetJoints(lua_State* L) {
|
||||||
Collider* collider = luax_checktype(L, 1, Collider);
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
size_t count;
|
size_t count;
|
||||||
|
@ -110,6 +137,33 @@ static int l_lovrColliderSetKinematic(lua_State* L) {
|
||||||
return 0;
|
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);
|
||||||
|
lua_pushboolean(L, continuous);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrColliderSetContinuous(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
bool continuous = lua_toboolean(L, 2);
|
||||||
|
lovrColliderSetContinuous(collider, continuous);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int l_lovrColliderGetGravityScale(lua_State* L) {
|
static int l_lovrColliderGetGravityScale(lua_State* L) {
|
||||||
Collider* collider = luax_checktype(L, 1, Collider);
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
float scale = lovrColliderGetGravityScale(collider);
|
float scale = lovrColliderGetGravityScale(collider);
|
||||||
|
@ -369,6 +423,28 @@ static int l_lovrColliderApplyTorque(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int l_lovrColliderApplyLinearImpulse(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
float impulse[3];
|
||||||
|
int index = luax_readvec3(L, 2, impulse, NULL);
|
||||||
|
if (lua_gettop(L) >= index) {
|
||||||
|
float position[3];
|
||||||
|
luax_readvec3(L, index, position, NULL);
|
||||||
|
lovrColliderApplyLinearImpulseAtPosition(collider, impulse, position);
|
||||||
|
} else {
|
||||||
|
lovrColliderApplyLinearImpulse(collider, impulse);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrColliderApplyAngularImpulse(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
float impulse[3];
|
||||||
|
luax_readvec3(L, 2, impulse, NULL);
|
||||||
|
lovrColliderApplyAngularImpulse(collider, impulse);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int l_lovrColliderGetLocalCenter(lua_State* L) {
|
static int l_lovrColliderGetLocalCenter(lua_State* L) {
|
||||||
Collider* collider = luax_checktype(L, 1, Collider);
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
|
@ -508,6 +584,16 @@ static int l_lovrColliderSetTag(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
|
static int l_lovrColliderGetShapes(lua_State* L) {
|
||||||
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
Shape* shape = lovrColliderGetShape(collider);
|
||||||
|
lua_createtable(L, 1, 0);
|
||||||
|
luax_pushshape(L, shape);
|
||||||
|
lua_rawseti(L, -2, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
static int l_lovrColliderIsGravityIgnored(lua_State* L) {
|
static int l_lovrColliderIsGravityIgnored(lua_State* L) {
|
||||||
Collider* collider = luax_checktype(L, 1, Collider);
|
Collider* collider = luax_checktype(L, 1, Collider);
|
||||||
|
@ -526,15 +612,22 @@ static int l_lovrColliderSetGravityIgnored(lua_State* L) {
|
||||||
const luaL_Reg lovrCollider[] = {
|
const luaL_Reg lovrCollider[] = {
|
||||||
{ "destroy", l_lovrColliderDestroy },
|
{ "destroy", l_lovrColliderDestroy },
|
||||||
{ "isDestroyed", l_lovrColliderIsDestroyed },
|
{ "isDestroyed", l_lovrColliderIsDestroyed },
|
||||||
|
{ "isEnabled", l_lovrColliderIsEnabled },
|
||||||
|
{ "setEnabled", l_lovrColliderSetEnabled },
|
||||||
{ "getWorld", l_lovrColliderGetWorld },
|
{ "getWorld", l_lovrColliderGetWorld },
|
||||||
{ "addShape", l_lovrColliderAddShape },
|
{ "getShape", l_lovrColliderGetShape },
|
||||||
{ "removeShape", l_lovrColliderRemoveShape },
|
{ "setShape", l_lovrColliderSetShape },
|
||||||
{ "getShapes", l_lovrColliderGetShapes },
|
{ "getShapeOffset", l_lovrColliderGetShapeOffset },
|
||||||
|
{ "setShapeOffset", l_lovrColliderSetShapeOffset },
|
||||||
{ "getJoints", l_lovrColliderGetJoints },
|
{ "getJoints", l_lovrColliderGetJoints },
|
||||||
{ "getUserData", l_lovrColliderGetUserData },
|
{ "getUserData", l_lovrColliderGetUserData },
|
||||||
{ "setUserData", l_lovrColliderSetUserData },
|
{ "setUserData", l_lovrColliderSetUserData },
|
||||||
{ "isKinematic", l_lovrColliderIsKinematic },
|
{ "isKinematic", l_lovrColliderIsKinematic },
|
||||||
{ "setKinematic", l_lovrColliderSetKinematic },
|
{ "setKinematic", l_lovrColliderSetKinematic },
|
||||||
|
{ "isSensor", l_lovrColliderIsSensor },
|
||||||
|
{ "setSensor", l_lovrColliderSetSensor },
|
||||||
|
{ "isContinuous", l_lovrColliderIsContinuous },
|
||||||
|
{ "setContinuous", l_lovrColliderSetContinuous },
|
||||||
{ "getGravityScale", l_lovrColliderGetGravityScale },
|
{ "getGravityScale", l_lovrColliderGetGravityScale },
|
||||||
{ "setGravityScale", l_lovrColliderSetGravityScale },
|
{ "setGravityScale", l_lovrColliderSetGravityScale },
|
||||||
{ "isSleepingAllowed", l_lovrColliderIsSleepingAllowed },
|
{ "isSleepingAllowed", l_lovrColliderIsSleepingAllowed },
|
||||||
|
@ -561,6 +654,8 @@ const luaL_Reg lovrCollider[] = {
|
||||||
{ "setAngularDamping", l_lovrColliderSetAngularDamping },
|
{ "setAngularDamping", l_lovrColliderSetAngularDamping },
|
||||||
{ "applyForce", l_lovrColliderApplyForce },
|
{ "applyForce", l_lovrColliderApplyForce },
|
||||||
{ "applyTorque", l_lovrColliderApplyTorque },
|
{ "applyTorque", l_lovrColliderApplyTorque },
|
||||||
|
{ "applyLinearImpulse", l_lovrColliderApplyLinearImpulse },
|
||||||
|
{ "applyAngularImpulse", l_lovrColliderApplyAngularImpulse },
|
||||||
{ "getLocalCenter", l_lovrColliderGetLocalCenter },
|
{ "getLocalCenter", l_lovrColliderGetLocalCenter },
|
||||||
{ "getLocalPoint", l_lovrColliderGetLocalPoint },
|
{ "getLocalPoint", l_lovrColliderGetLocalPoint },
|
||||||
{ "getWorldPoint", l_lovrColliderGetWorldPoint },
|
{ "getWorldPoint", l_lovrColliderGetWorldPoint },
|
||||||
|
@ -577,6 +672,7 @@ const luaL_Reg lovrCollider[] = {
|
||||||
{ "setTag", l_lovrColliderSetTag },
|
{ "setTag", l_lovrColliderSetTag },
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
|
{ "getShapes", l_lovrColliderGetShapes },
|
||||||
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored },
|
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored },
|
||||||
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored },
|
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored },
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ void luax_pushshape(lua_State* L, Shape* shape) {
|
||||||
case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, shape); break;
|
case SHAPE_CYLINDER: luax_pushtype(L, CylinderShape, shape); break;
|
||||||
case SHAPE_MESH: luax_pushtype(L, MeshShape, shape); break;
|
case SHAPE_MESH: luax_pushtype(L, MeshShape, shape); break;
|
||||||
case SHAPE_TERRAIN: luax_pushtype(L, TerrainShape, shape); break;
|
case SHAPE_TERRAIN: luax_pushtype(L, TerrainShape, shape); break;
|
||||||
|
case SHAPE_COMPOUND: luax_pushtype(L, CompoundShape, shape); break;
|
||||||
default: lovrUnreachable();
|
default: lovrUnreachable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +29,8 @@ Shape* luax_checkshape(lua_State* L, int index) {
|
||||||
hash64("CapsuleShape", strlen("CapsuleShape")),
|
hash64("CapsuleShape", strlen("CapsuleShape")),
|
||||||
hash64("CylinderShape", strlen("CylinderShape")),
|
hash64("CylinderShape", strlen("CylinderShape")),
|
||||||
hash64("MeshShape", strlen("MeshShape")),
|
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++) {
|
for (size_t i = 0; i < COUNTOF(hashes); i++) {
|
||||||
|
@ -91,17 +93,17 @@ Shape* luax_newmeshshape(lua_State* L, int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape* luax_newterrainshape(lua_State* L, int index) {
|
Shape* luax_newterrainshape(lua_State* L, int index) {
|
||||||
float horizontalScale = luax_checkfloat(L, index++);
|
float scaleXZ = luax_checkfloat(L, index++);
|
||||||
int type = lua_type(L, index);
|
int type = lua_type(L, index);
|
||||||
if (type == LUA_TNIL || type == LUA_TNONE) {
|
if (type == LUA_TNIL || type == LUA_TNONE) {
|
||||||
float vertices[4] = { 0.f };
|
float vertices[4] = { 0.f };
|
||||||
return lovrTerrainShapeCreate(vertices, 2, 2, horizontalScale, 1.f);
|
return lovrTerrainShapeCreate(vertices, 2, scaleXZ, 1.f);
|
||||||
} else if (type == LUA_TFUNCTION) {
|
} else if (type == LUA_TFUNCTION) {
|
||||||
uint32_t samples = luax_optu32(L, index + 1, 100);
|
uint32_t n = luax_optu32(L, index + 1, 100);
|
||||||
float* vertices = lovrMalloc(sizeof(float) * samples * samples);
|
float* vertices = lovrMalloc(sizeof(float) * n * n);
|
||||||
for (uint32_t i = 0; i < samples * samples; i++) {
|
for (uint32_t i = 0; i < n * n; i++) {
|
||||||
float x = horizontalScale * (-.5f + ((float) (i % samples)) / samples);
|
float x = scaleXZ * (-.5f + ((float) (i % n)) / n);
|
||||||
float z = horizontalScale * (-.5f + ((float) (i / samples)) / samples);
|
float z = scaleXZ * (-.5f + ((float) (i / n)) / n);
|
||||||
lua_pushvalue(L, index);
|
lua_pushvalue(L, index);
|
||||||
lua_pushnumber(L, x);
|
lua_pushnumber(L, x);
|
||||||
lua_pushnumber(L, z);
|
lua_pushnumber(L, z);
|
||||||
|
@ -110,23 +112,23 @@ Shape* luax_newterrainshape(lua_State* L, int index) {
|
||||||
vertices[i] = luax_tofloat(L, -1);
|
vertices[i] = luax_tofloat(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
TerrainShape* shape = lovrTerrainShapeCreate(vertices, samples, samples, horizontalScale, 1.f);
|
TerrainShape* shape = lovrTerrainShapeCreate(vertices, n, scaleXZ, 1.f);
|
||||||
lovrFree(vertices);
|
lovrFree(vertices);
|
||||||
return shape;
|
return shape;
|
||||||
} else if (type == LUA_TUSERDATA) {
|
} else if (type == LUA_TUSERDATA) {
|
||||||
Image* image = luax_checktype(L, index, Image);
|
Image* image = luax_checktype(L, index, Image);
|
||||||
uint32_t imageWidth = lovrImageGetWidth(image, 0);
|
uint32_t n = lovrImageGetWidth(image, 0);
|
||||||
uint32_t imageHeight = lovrImageGetHeight(image, 0);
|
lovrCheck(lovrImageGetHeight(image, 0) == n, "TerrainShape images must be square");
|
||||||
float verticalScale = luax_optfloat(L, index + 1, 1.f);
|
float scaleY = luax_optfloat(L, index + 1, 1.f);
|
||||||
float* vertices = lovrMalloc(sizeof(float) * imageWidth * imageHeight);
|
float* vertices = lovrMalloc(sizeof(float) * n * n);
|
||||||
for (uint32_t y = 0; y < imageHeight; y++) {
|
for (uint32_t y = 0; y < n; y++) {
|
||||||
for (uint32_t x = 0; x < imageWidth; x++) {
|
for (uint32_t x = 0; x < n; x++) {
|
||||||
float pixel[4];
|
float pixel[4];
|
||||||
lovrImageGetPixel(image, x, y, pixel);
|
lovrImageGetPixel(image, x, y, pixel);
|
||||||
vertices[x + y * imageWidth] = pixel[0];
|
vertices[x + y * n] = pixel[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TerrainShape* shape = lovrTerrainShapeCreate(vertices, imageWidth, imageHeight, horizontalScale, verticalScale);
|
TerrainShape* shape = lovrTerrainShapeCreate(vertices, n, scaleXZ, scaleY);
|
||||||
lovrFree(vertices);
|
lovrFree(vertices);
|
||||||
return shape;
|
return shape;
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,6 +137,86 @@ 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);
|
||||||
|
lovrCheck(shapes[i], "Expected a Shape for CompoundShape entry #%d", i + 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) {
|
static int l_lovrShapeDestroy(lua_State* L) {
|
||||||
Shape* shape = luax_checkshape(L, 1);
|
Shape* shape = luax_checkshape(L, 1);
|
||||||
lovrShapeDestroyData(shape);
|
lovrShapeDestroyData(shape);
|
||||||
|
@ -147,38 +229,6 @@ static int l_lovrShapeGetType(lua_State* L) {
|
||||||
return 1;
|
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) {
|
static void luax_pushshapestash(lua_State* L) {
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrshapestash");
|
lua_getfield(L, LUA_REGISTRYINDEX, "_lovrshapestash");
|
||||||
|
|
||||||
|
@ -214,74 +264,6 @@ static int l_lovrShapeSetUserData(lua_State* L) {
|
||||||
return 0;
|
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) {
|
static int l_lovrShapeGetMass(lua_State* L) {
|
||||||
Shape* shape = luax_checkshape(L, 1);
|
Shape* shape = luax_checkshape(L, 1);
|
||||||
float density = luax_checkfloat(L, 2);
|
float density = luax_checkfloat(L, 2);
|
||||||
|
@ -313,19 +295,8 @@ static int l_lovrShapeGetAABB(lua_State* L) {
|
||||||
#define lovrShape \
|
#define lovrShape \
|
||||||
{ "destroy", l_lovrShapeDestroy }, \
|
{ "destroy", l_lovrShapeDestroy }, \
|
||||||
{ "getType", l_lovrShapeGetType }, \
|
{ "getType", l_lovrShapeGetType }, \
|
||||||
{ "getCollider", l_lovrShapeGetCollider }, \
|
|
||||||
{ "isEnabled", l_lovrShapeIsEnabled }, \
|
|
||||||
{ "setEnabled", l_lovrShapeSetEnabled }, \
|
|
||||||
{ "isSensor", l_lovrShapeIsSensor }, \
|
|
||||||
{ "setSensor", l_lovrShapeSetSensor }, \
|
|
||||||
{ "getUserData", l_lovrShapeGetUserData }, \
|
{ "getUserData", l_lovrShapeGetUserData }, \
|
||||||
{ "setUserData", l_lovrShapeSetUserData }, \
|
{ "setUserData", l_lovrShapeSetUserData }, \
|
||||||
{ "getPosition", l_lovrShapeGetPosition }, \
|
|
||||||
{ "setPosition", l_lovrShapeSetPosition }, \
|
|
||||||
{ "getOrientation", l_lovrShapeGetOrientation }, \
|
|
||||||
{ "setOrientation", l_lovrShapeSetOrientation }, \
|
|
||||||
{ "getPose", l_lovrShapeGetPose }, \
|
|
||||||
{ "setPose", l_lovrShapeSetPose }, \
|
|
||||||
{ "getMass", l_lovrShapeGetMass }, \
|
{ "getMass", l_lovrShapeGetMass }, \
|
||||||
{ "getAABB", l_lovrShapeGetAABB }
|
{ "getAABB", l_lovrShapeGetAABB }
|
||||||
|
|
||||||
|
@ -335,17 +306,9 @@ static int l_lovrSphereShapeGetRadius(lua_State* L) {
|
||||||
return 1;
|
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[] = {
|
const luaL_Reg lovrSphereShape[] = {
|
||||||
lovrShape,
|
lovrShape,
|
||||||
{ "getRadius", l_lovrSphereShapeGetRadius },
|
{ "getRadius", l_lovrSphereShapeGetRadius },
|
||||||
{ "setRadius", l_lovrSphereShapeSetRadius },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -359,18 +322,9 @@ static int l_lovrBoxShapeGetDimensions(lua_State* L) {
|
||||||
return 3;
|
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[] = {
|
const luaL_Reg lovrBoxShape[] = {
|
||||||
lovrShape,
|
lovrShape,
|
||||||
{ "getDimensions", l_lovrBoxShapeGetDimensions },
|
{ "getDimensions", l_lovrBoxShapeGetDimensions },
|
||||||
{ "setDimensions", l_lovrBoxShapeSetDimensions },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -380,32 +334,16 @@ static int l_lovrCapsuleShapeGetRadius(lua_State* L) {
|
||||||
return 1;
|
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) {
|
static int l_lovrCapsuleShapeGetLength(lua_State* L) {
|
||||||
CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape);
|
CapsuleShape* capsule = luax_checktype(L, 1, CapsuleShape);
|
||||||
lua_pushnumber(L, lovrCapsuleShapeGetLength(capsule));
|
lua_pushnumber(L, lovrCapsuleShapeGetLength(capsule));
|
||||||
return 1;
|
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[] = {
|
const luaL_Reg lovrCapsuleShape[] = {
|
||||||
lovrShape,
|
lovrShape,
|
||||||
{ "getRadius", l_lovrCapsuleShapeGetRadius },
|
{ "getRadius", l_lovrCapsuleShapeGetRadius },
|
||||||
{ "setRadius", l_lovrCapsuleShapeSetRadius },
|
|
||||||
{ "getLength", l_lovrCapsuleShapeGetLength },
|
{ "getLength", l_lovrCapsuleShapeGetLength },
|
||||||
{ "setLength", l_lovrCapsuleShapeSetLength },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,32 +353,16 @@ static int l_lovrCylinderShapeGetRadius(lua_State* L) {
|
||||||
return 1;
|
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) {
|
static int l_lovrCylinderShapeGetLength(lua_State* L) {
|
||||||
CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape);
|
CylinderShape* cylinder = luax_checktype(L, 1, CylinderShape);
|
||||||
lua_pushnumber(L, lovrCylinderShapeGetLength(cylinder));
|
lua_pushnumber(L, lovrCylinderShapeGetLength(cylinder));
|
||||||
return 1;
|
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[] = {
|
const luaL_Reg lovrCylinderShape[] = {
|
||||||
lovrShape,
|
lovrShape,
|
||||||
{ "getRadius", l_lovrCylinderShapeGetRadius },
|
{ "getRadius", l_lovrCylinderShapeGetRadius },
|
||||||
{ "setRadius", l_lovrCylinderShapeSetRadius },
|
|
||||||
{ "getLength", l_lovrCylinderShapeGetLength },
|
{ "getLength", l_lovrCylinderShapeGetLength },
|
||||||
{ "setLength", l_lovrCylinderShapeSetLength },
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -453,3 +375,109 @@ const luaL_Reg lovrTerrainShape[] = {
|
||||||
lovrShape,
|
lovrShape,
|
||||||
{ NULL, NULL }
|
{ 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_lovrCompoundShapeAddShape(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);
|
||||||
|
lovrCompoundShapeAddShape(shape, child, position, orientation);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrCompoundShapeReplaceShape(lua_State* L) {
|
||||||
|
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
|
||||||
|
uint32_t index = luax_checku32(L, 2);
|
||||||
|
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);
|
||||||
|
lovrCompoundShapeReplaceShape(shape, index, child, position, orientation);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrCompoundShapeRemoveShape(lua_State* L) {
|
||||||
|
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
|
||||||
|
uint32_t index = luax_checku32(L, 2) - 1;
|
||||||
|
lovrCompoundShapeRemoveShape(shape, index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrCompoundShapeGetShape(lua_State* L) {
|
||||||
|
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
|
||||||
|
uint32_t index = luax_checku32(L, 2) - 1;
|
||||||
|
Shape* child = lovrCompoundShapeGetShape(shape, index);
|
||||||
|
luax_pushshape(L, child);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrCompoundShapeGetShapes(lua_State* L) {
|
||||||
|
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
|
||||||
|
int count = (int) lovrCompoundShapeGetShapeCount(shape);
|
||||||
|
lua_createtable(L, count, 0);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Shape* child = lovrCompoundShapeGetShape(shape, (uint32_t) i);
|
||||||
|
luax_pushshape(L, child);
|
||||||
|
lua_rawseti(L, -2, i + 1);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrCompoundShapeGetShapeCount(lua_State* L) {
|
||||||
|
CompoundShape* shape = luax_checktype(L, 1, CompoundShape);
|
||||||
|
uint32_t count = lovrCompoundShapeGetShapeCount(shape);
|
||||||
|
lua_pushinteger(L, count);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_lovrCompoundShapeGetShapeOffset(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;
|
||||||
|
lovrCompoundShapeGetShapeOffset(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_lovrCompoundShapeSetShapeOffset(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);
|
||||||
|
lovrCompoundShapeSetShapeOffset(shape, index, position, orientation);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg lovrCompoundShape[] = {
|
||||||
|
lovrShape,
|
||||||
|
{ "isFrozen", l_lovrCompoundShapeIsFrozen },
|
||||||
|
{ "addShape", l_lovrCompoundShapeAddShape },
|
||||||
|
{ "replaceShape", l_lovrCompoundShapeReplaceShape },
|
||||||
|
{ "removeShape", l_lovrCompoundShapeRemoveShape },
|
||||||
|
{ "getShape", l_lovrCompoundShapeGetShape },
|
||||||
|
{ "getShapes", l_lovrCompoundShapeGetShapes },
|
||||||
|
{ "getShapeCount", l_lovrCompoundShapeGetShapeCount },
|
||||||
|
{ "getShapeOffset", l_lovrCompoundShapeGetShapeOffset },
|
||||||
|
{ "setShapeOffset", l_lovrCompoundShapeSetShapeOffset },
|
||||||
|
{ "__len", l_lovrCompoundShapeGetShapeCount }, // :)
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
|
@ -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, uint32_t shape, float position[3], float normal[3], void* userdata) {
|
||||||
lua_State* L = userdata;
|
lua_State* L = userdata;
|
||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
luax_pushshape(L, shape);
|
luax_pushtype(L, Collider, collider);
|
||||||
lua_pushnumber(L, x);
|
lua_pushinteger(L, shape);
|
||||||
lua_pushnumber(L, y);
|
lua_pushnumber(L, position[0]);
|
||||||
lua_pushnumber(L, z);
|
lua_pushnumber(L, position[1]);
|
||||||
lua_pushnumber(L, nx);
|
lua_pushnumber(L, position[2]);
|
||||||
lua_pushnumber(L, ny);
|
lua_pushnumber(L, normal[0]);
|
||||||
lua_pushnumber(L, nz);
|
lua_pushnumber(L, normal[1]);
|
||||||
lua_call(L, 7, 1);
|
lua_pushnumber(L, normal[2]);
|
||||||
|
lua_call(L, 8, 1);
|
||||||
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
|
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return shouldStop;
|
return shouldStop;
|
||||||
|
@ -45,53 +46,55 @@ static bool raycastCallback(Shape* shape, float x, float y, float z, float nx, f
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* tag;
|
const char* tag;
|
||||||
Shape* shape;
|
Collider* collider;
|
||||||
|
uint32_t shape;
|
||||||
float distance;
|
float distance;
|
||||||
float origin[3];
|
float origin[3];
|
||||||
float position[3];
|
float position[3];
|
||||||
float normal[3];
|
float normal[3];
|
||||||
} RaycastData;
|
} 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, uint32_t shape, float position[3], float normal[3], void* userdata) {
|
||||||
RaycastData* data = userdata;
|
RaycastData* data = userdata;
|
||||||
if (data->tag) {
|
if (data->tag) {
|
||||||
const char* tag = lovrColliderGetTag(lovrShapeGetCollider(shape));
|
const char* tag = lovrColliderGetTag(collider);
|
||||||
if (!tag || strcmp(tag, data->tag)) {
|
if (!tag || strcmp(tag, data->tag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data->collider = collider;
|
||||||
data->shape = shape;
|
data->shape = shape;
|
||||||
vec3_set(data->position, x, y, z);
|
vec3_init(data->position, position);
|
||||||
vec3_set(data->normal, nx, ny, nz);
|
vec3_init(data->normal, normal);
|
||||||
data->distance = vec3_distance(data->origin, data->position);
|
data->distance = vec3_distance(data->origin, data->position);
|
||||||
return true;
|
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, uint32_t shape, float position[3], float normal[3], void* userdata) {
|
||||||
RaycastData* data = userdata;
|
RaycastData* data = userdata;
|
||||||
if (data->tag) {
|
if (data->tag) {
|
||||||
const char* tag = lovrColliderGetTag(lovrShapeGetCollider(shape));
|
const char* tag = lovrColliderGetTag(collider);
|
||||||
if (!tag || strcmp(tag, data->tag)) {
|
if (!tag || strcmp(tag, data->tag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float position[3];
|
|
||||||
vec3_set(position, x, y, z);
|
|
||||||
float distance = vec3_distance(data->origin, position);
|
float distance = vec3_distance(data->origin, position);
|
||||||
if (distance < data->distance) {
|
if (distance < data->distance) {
|
||||||
vec3_init(data->position, position);
|
vec3_init(data->position, position);
|
||||||
vec3_set(data->normal, nx, ny, nz);
|
vec3_init(data->normal, normal);
|
||||||
data->distance = distance;
|
data->distance = distance;
|
||||||
|
data->collider = collider;
|
||||||
data->shape = shape;
|
data->shape = shape;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool queryCallback(Shape* shape, void* userdata) {
|
static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) {
|
||||||
lua_State* L = userdata;
|
lua_State* L = userdata;
|
||||||
lua_pushvalue(L, -1);
|
lua_pushvalue(L, -1);
|
||||||
luax_pushshape(L, shape);
|
luax_pushtype(L, Collider, collider);
|
||||||
lua_call(L, 1, 1);
|
lua_pushinteger(L, shape);
|
||||||
|
lua_call(L, 2, 1);
|
||||||
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
|
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return shouldStop;
|
return shouldStop;
|
||||||
|
@ -99,9 +102,10 @@ static bool queryCallback(Shape* shape, void* userdata) {
|
||||||
|
|
||||||
static int l_lovrWorldNewCollider(lua_State* L) {
|
static int l_lovrWorldNewCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
|
Shape* shape = luax_totype(L, 2, Shape);
|
||||||
float position[3];
|
float position[3];
|
||||||
luax_readvec3(L, 2, position, NULL);
|
luax_readvec3(L, 2 + !!shape, position, NULL);
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -111,9 +115,8 @@ static int l_lovrWorldNewBoxCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[3];
|
float position[3];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
|
||||||
BoxShape* shape = luax_newboxshape(L, index);
|
BoxShape* shape = luax_newboxshape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
|
@ -125,9 +128,8 @@ static int l_lovrWorldNewCapsuleCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[3];
|
float position[3];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
|
||||||
CapsuleShape* shape = luax_newcapsuleshape(L, index);
|
CapsuleShape* shape = luax_newcapsuleshape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
|
@ -139,9 +141,8 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[3];
|
float position[3];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
|
||||||
CylinderShape* shape = luax_newcylindershape(L, index);
|
CylinderShape* shape = luax_newcylindershape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
|
@ -153,9 +154,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
float position[3];
|
float position[3];
|
||||||
int index = luax_readvec3(L, 2, position, NULL);
|
int index = luax_readvec3(L, 2, position, NULL);
|
||||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
|
||||||
SphereShape* shape = luax_newsphereshape(L, index);
|
SphereShape* shape = luax_newsphereshape(L, index);
|
||||||
lovrColliderAddShape(collider, shape);
|
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
|
@ -165,9 +165,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
||||||
|
|
||||||
static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
|
|
||||||
MeshShape* shape = luax_newmeshshape(L, 2);
|
MeshShape* shape = luax_newmeshshape(L, 2);
|
||||||
lovrColliderAddShape(collider, shape);
|
Collider* collider = lovrColliderCreate(world, shape, 0.f, 0.f, 0.f);
|
||||||
lovrColliderInitInertia(collider, shape);
|
lovrColliderInitInertia(collider, shape);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
|
@ -177,9 +176,8 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
||||||
|
|
||||||
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
|
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
|
||||||
World* world = luax_checktype(L, 1, World);
|
World* world = luax_checktype(L, 1, World);
|
||||||
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
|
|
||||||
TerrainShape* shape = luax_newterrainshape(L, 2);
|
TerrainShape* shape = luax_newterrainshape(L, 2);
|
||||||
lovrColliderAddShape(collider, shape);
|
Collider* collider = lovrColliderCreate(world, shape, 0.f, 0.f, 0.f);
|
||||||
lovrColliderSetKinematic(collider, true);
|
lovrColliderSetKinematic(collider, true);
|
||||||
luax_pushtype(L, Collider, collider);
|
luax_pushtype(L, Collider, collider);
|
||||||
lovrRelease(collider, lovrColliderDestroy);
|
lovrRelease(collider, lovrColliderDestroy);
|
||||||
|
@ -309,15 +307,16 @@ static int l_lovrWorldRaycastAny(lua_State* L) {
|
||||||
RaycastData data = { 0 };
|
RaycastData data = { 0 };
|
||||||
data.tag = lua_tostring(L, index);
|
data.tag = lua_tostring(L, index);
|
||||||
lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastAnyCallback, &data);
|
lovrWorldRaycast(world, start[0], start[1], start[2], end[0], end[1], end[2], raycastAnyCallback, &data);
|
||||||
if (data.shape) {
|
if (data.collider) {
|
||||||
luax_pushshape(L, data.shape);
|
luax_pushtype(L, Collider, data.collider);
|
||||||
|
lua_pushinteger(L, data.shape);
|
||||||
lua_pushnumber(L, data.position[0]);
|
lua_pushnumber(L, data.position[0]);
|
||||||
lua_pushnumber(L, data.position[1]);
|
lua_pushnumber(L, data.position[1]);
|
||||||
lua_pushnumber(L, data.position[2]);
|
lua_pushnumber(L, data.position[2]);
|
||||||
lua_pushnumber(L, data.normal[0]);
|
lua_pushnumber(L, data.normal[0]);
|
||||||
lua_pushnumber(L, data.normal[1]);
|
lua_pushnumber(L, data.normal[1]);
|
||||||
lua_pushnumber(L, data.normal[2]);
|
lua_pushnumber(L, data.normal[2]);
|
||||||
return 7;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -334,14 +333,15 @@ static int l_lovrWorldRaycastClosest(lua_State* L) {
|
||||||
data.tag = lua_tostring(L, index);
|
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[0], start[1], start[2], end[0], end[1], end[2], raycastClosestCallback, &data);
|
||||||
if (data.shape) {
|
if (data.shape) {
|
||||||
luax_pushshape(L, data.shape);
|
luax_pushtype(L, Collider, data.collider);
|
||||||
|
lua_pushinteger(L, data.shape);
|
||||||
lua_pushnumber(L, data.position[0]);
|
lua_pushnumber(L, data.position[0]);
|
||||||
lua_pushnumber(L, data.position[1]);
|
lua_pushnumber(L, data.position[1]);
|
||||||
lua_pushnumber(L, data.position[2]);
|
lua_pushnumber(L, data.position[2]);
|
||||||
lua_pushnumber(L, data.normal[0]);
|
lua_pushnumber(L, data.normal[0]);
|
||||||
lua_pushnumber(L, data.normal[1]);
|
lua_pushnumber(L, data.normal[1]);
|
||||||
lua_pushnumber(L, data.normal[2]);
|
lua_pushnumber(L, data.normal[2]);
|
||||||
return 7;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -19,6 +19,7 @@ typedef Shape CapsuleShape;
|
||||||
typedef Shape CylinderShape;
|
typedef Shape CylinderShape;
|
||||||
typedef Shape MeshShape;
|
typedef Shape MeshShape;
|
||||||
typedef Shape TerrainShape;
|
typedef Shape TerrainShape;
|
||||||
|
typedef Shape CompoundShape;
|
||||||
|
|
||||||
typedef Joint BallJoint;
|
typedef Joint BallJoint;
|
||||||
typedef Joint DistanceJoint;
|
typedef Joint DistanceJoint;
|
||||||
|
@ -26,8 +27,8 @@ typedef Joint HingeJoint;
|
||||||
typedef Joint SliderJoint;
|
typedef Joint SliderJoint;
|
||||||
|
|
||||||
typedef void (*CollisionResolver)(World* world, void* userdata);
|
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 (*RaycastCallback)(Collider* collider, uint32_t shape, float position[3], float normal[3], void* userdata);
|
||||||
typedef bool (*QueryCallback)(Shape* shape, void* userdata);
|
typedef bool (*QueryCallback)(Collider* collider, uint32_t shape, void* userdata);
|
||||||
|
|
||||||
bool lovrPhysicsInit(void);
|
bool lovrPhysicsInit(void);
|
||||||
void lovrPhysicsDestroy(void);
|
void lovrPhysicsDestroy(void);
|
||||||
|
@ -85,16 +86,19 @@ void lovrWorldSetSleepingAllowed(World* world, bool allowed);
|
||||||
|
|
||||||
// Collider
|
// Collider
|
||||||
|
|
||||||
Collider* lovrColliderCreate(World* world, float x, float y, float z);
|
Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z);
|
||||||
void lovrColliderDestroy(void* ref);
|
void lovrColliderDestroy(void* ref);
|
||||||
void lovrColliderDestroyData(Collider* collider);
|
void lovrColliderDestroyData(Collider* collider);
|
||||||
bool lovrColliderIsDestroyed(Collider* collider);
|
bool lovrColliderIsDestroyed(Collider* collider);
|
||||||
|
bool lovrColliderIsEnabled(Collider* collider);
|
||||||
|
void lovrColliderSetEnabled(Collider* collider, bool enable);
|
||||||
void lovrColliderInitInertia(Collider* collider, Shape* shape);
|
void lovrColliderInitInertia(Collider* collider, Shape* shape);
|
||||||
World* lovrColliderGetWorld(Collider* collider);
|
World* lovrColliderGetWorld(Collider* collider);
|
||||||
Collider* lovrColliderGetNext(Collider* collider);
|
Collider* lovrColliderGetNext(Collider* collider);
|
||||||
void lovrColliderAddShape(Collider* collider, Shape* shape);
|
Shape* lovrColliderGetShape(Collider* collider);
|
||||||
void lovrColliderRemoveShape(Collider* collider, Shape* shape);
|
void lovrColliderSetShape(Collider* collider, Shape* shape);
|
||||||
Shape** lovrColliderGetShapes(Collider* collider, size_t* count);
|
void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation);
|
||||||
|
void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation);
|
||||||
Joint** lovrColliderGetJoints(Collider* collider, size_t* count);
|
Joint** lovrColliderGetJoints(Collider* collider, size_t* count);
|
||||||
const char* lovrColliderGetTag(Collider* collider);
|
const char* lovrColliderGetTag(Collider* collider);
|
||||||
bool lovrColliderSetTag(Collider* collider, const char* tag);
|
bool lovrColliderSetTag(Collider* collider, const char* tag);
|
||||||
|
@ -104,6 +108,10 @@ float lovrColliderGetRestitution(Collider* collider);
|
||||||
void lovrColliderSetRestitution(Collider* collider, float restitution);
|
void lovrColliderSetRestitution(Collider* collider, float restitution);
|
||||||
bool lovrColliderIsKinematic(Collider* collider);
|
bool lovrColliderIsKinematic(Collider* collider);
|
||||||
void lovrColliderSetKinematic(Collider* collider, bool kinematic);
|
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);
|
float lovrColliderGetGravityScale(Collider* collider);
|
||||||
void lovrColliderSetGravityScale(Collider* collider, float scale);
|
void lovrColliderSetGravityScale(Collider* collider, float scale);
|
||||||
bool lovrColliderIsSleepingAllowed(Collider* collider);
|
bool lovrColliderIsSleepingAllowed(Collider* collider);
|
||||||
|
@ -129,6 +137,9 @@ void lovrColliderSetAngularDamping(Collider* collider, float damping, float thre
|
||||||
void lovrColliderApplyForce(Collider* collider, float x, float y, float z);
|
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 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 lovrColliderApplyTorque(Collider* collider, float x, float y, float z);
|
||||||
|
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 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 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 lovrColliderGetWorldPoint(Collider* collider, float x, float y, float z, float* wx, float* wy, float* wz);
|
||||||
|
@ -146,47 +157,43 @@ typedef enum {
|
||||||
SHAPE_CAPSULE,
|
SHAPE_CAPSULE,
|
||||||
SHAPE_CYLINDER,
|
SHAPE_CYLINDER,
|
||||||
SHAPE_MESH,
|
SHAPE_MESH,
|
||||||
SHAPE_TERRAIN
|
SHAPE_TERRAIN,
|
||||||
|
SHAPE_COMPOUND
|
||||||
} ShapeType;
|
} ShapeType;
|
||||||
|
|
||||||
void lovrShapeDestroy(void* ref);
|
void lovrShapeDestroy(void* ref);
|
||||||
void lovrShapeDestroyData(Shape* shape);
|
void lovrShapeDestroyData(Shape* shape);
|
||||||
ShapeType lovrShapeGetType(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 lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]);
|
||||||
void lovrShapeGetAABB(Shape* shape, float aabb[6]);
|
void lovrShapeGetAABB(Shape* shape, float aabb[6]);
|
||||||
|
|
||||||
SphereShape* lovrSphereShapeCreate(float radius);
|
SphereShape* lovrSphereShapeCreate(float radius);
|
||||||
float lovrSphereShapeGetRadius(SphereShape* sphere);
|
float lovrSphereShapeGetRadius(SphereShape* sphere);
|
||||||
void lovrSphereShapeSetRadius(SphereShape* sphere, float radius);
|
|
||||||
|
|
||||||
BoxShape* lovrBoxShapeCreate(float w, float h, float d);
|
BoxShape* lovrBoxShapeCreate(float w, float h, float d);
|
||||||
void lovrBoxShapeGetDimensions(BoxShape* box, 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);
|
|
||||||
|
|
||||||
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length);
|
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length);
|
||||||
float lovrCapsuleShapeGetRadius(CapsuleShape* capsule);
|
float lovrCapsuleShapeGetRadius(CapsuleShape* capsule);
|
||||||
void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius);
|
|
||||||
float lovrCapsuleShapeGetLength(CapsuleShape* capsule);
|
float lovrCapsuleShapeGetLength(CapsuleShape* capsule);
|
||||||
void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length);
|
|
||||||
|
|
||||||
CylinderShape* lovrCylinderShapeCreate(float radius, float length);
|
CylinderShape* lovrCylinderShapeCreate(float radius, float length);
|
||||||
float lovrCylinderShapeGetRadius(CylinderShape* cylinder);
|
float lovrCylinderShapeGetRadius(CylinderShape* cylinder);
|
||||||
void lovrCylinderShapeSetRadius(CylinderShape* cylinder, float radius);
|
|
||||||
float lovrCylinderShapeGetLength(CylinderShape* cylinder);
|
float lovrCylinderShapeGetLength(CylinderShape* cylinder);
|
||||||
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length);
|
|
||||||
|
|
||||||
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]);
|
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]);
|
||||||
|
|
||||||
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale);
|
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 lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation);
|
||||||
|
void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation);
|
||||||
|
void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index);
|
||||||
|
Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index);
|
||||||
|
uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape);
|
||||||
|
void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation);
|
||||||
|
void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation);
|
||||||
|
|
||||||
// These tokens need to exist for Lua bindings
|
// These tokens need to exist for Lua bindings
|
||||||
#define lovrSphereShapeDestroy lovrShapeDestroy
|
#define lovrSphereShapeDestroy lovrShapeDestroy
|
||||||
|
@ -195,6 +202,7 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uin
|
||||||
#define lovrCylinderShapeDestroy lovrShapeDestroy
|
#define lovrCylinderShapeDestroy lovrShapeDestroy
|
||||||
#define lovrMeshShapeDestroy lovrShapeDestroy
|
#define lovrMeshShapeDestroy lovrShapeDestroy
|
||||||
#define lovrTerrainShapeDestroy lovrShapeDestroy
|
#define lovrTerrainShapeDestroy lovrShapeDestroy
|
||||||
|
#define lovrCompoundShapeDestroy lovrShapeDestroy
|
||||||
|
|
||||||
// Joints
|
// Joints
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ struct Collider {
|
||||||
JPH_BodyID id;
|
JPH_BodyID id;
|
||||||
JPH_Body* body;
|
JPH_Body* body;
|
||||||
World* world;
|
World* world;
|
||||||
|
Shape* shape;
|
||||||
Collider* prev;
|
Collider* prev;
|
||||||
Collider* next;
|
Collider* next;
|
||||||
arr_t(Shape*) shapes;
|
|
||||||
arr_t(Joint*) joints;
|
arr_t(Joint*) joints;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,6 @@ struct Collider {
|
||||||
struct Shape {
|
struct Shape {
|
||||||
uint32_t ref;
|
uint32_t ref;
|
||||||
ShapeType type;
|
ShapeType type;
|
||||||
Collider* collider;
|
|
||||||
JPH_Shape* shape;
|
JPH_Shape* shape;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,6 +43,7 @@ struct Joint {
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
Shape* pointShape;
|
||||||
JPH_Shape* queryBox;
|
JPH_Shape* queryBox;
|
||||||
JPH_Shape* querySphere;
|
JPH_Shape* querySphere;
|
||||||
JPH_AllHit_CastShapeCollector* castShapeCollector;
|
JPH_AllHit_CastShapeCollector* castShapeCollector;
|
||||||
|
@ -70,14 +70,16 @@ static uint32_t findTag(World* world, const char* name) {
|
||||||
bool lovrPhysicsInit(void) {
|
bool lovrPhysicsInit(void) {
|
||||||
if (state.initialized) return false;
|
if (state.initialized) return false;
|
||||||
JPH_Init(32 * 1024 * 1024);
|
JPH_Init(32 * 1024 * 1024);
|
||||||
state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create();
|
state.pointShape = lovrSphereShapeCreate(FLT_EPSILON);
|
||||||
state.querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f);
|
state.querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f);
|
||||||
state.queryBox = (JPH_Shape*) JPH_BoxShape_Create(&(const JPH_Vec3) { .5, .5f, .5f }, 0.f);
|
state.queryBox = (JPH_Shape*) JPH_BoxShape_Create(&(const JPH_Vec3) { .5, .5f, .5f }, 0.f);
|
||||||
|
state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create();
|
||||||
return state.initialized = true;
|
return state.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPhysicsDestroy(void) {
|
void lovrPhysicsDestroy(void) {
|
||||||
if (!state.initialized) return;
|
if (!state.initialized) return;
|
||||||
|
lovrRelease(state.pointShape, lovrShapeDestroy);
|
||||||
JPH_Shutdown();
|
JPH_Shutdown();
|
||||||
state.initialized = false;
|
state.initialized = false;
|
||||||
}
|
}
|
||||||
|
@ -173,32 +175,34 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa
|
||||||
const JPH_Vec3 direction = { x2 - x1, y2 - y1, z2 - z1 };
|
const JPH_Vec3 direction = { x2 - x1, y2 - y1, z2 - z1 };
|
||||||
JPH_AllHit_CastRayCollector* collector = JPH_AllHit_CastRayCollector_Create();
|
JPH_AllHit_CastRayCollector* collector = JPH_AllHit_CastRayCollector_Create();
|
||||||
JPH_NarrowPhaseQuery_CastRayAll(query, &origin, &direction, collector, NULL, NULL, NULL);
|
JPH_NarrowPhaseQuery_CastRayAll(query, &origin, &direction, collector, NULL, NULL, NULL);
|
||||||
size_t hit_count;
|
|
||||||
JPH_RayCastResult* hit_array = JPH_AllHit_CastRayCollector_GetHits(collector, &hit_count);
|
size_t count;
|
||||||
for (int i = 0; i < hit_count; i++) {
|
JPH_RayCastResult* hits = JPH_AllHit_CastRayCollector_GetHits(collector, &count);
|
||||||
float x = x1 + hit_array[i].fraction * (x2 - x1);
|
|
||||||
float y = y1 + hit_array[i].fraction * (y2 - y1);
|
for (size_t i = 0; i < count; i++) {
|
||||||
float z = z1 + hit_array[i].fraction * (z2 - z1);
|
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, hits[i].bodyID);
|
||||||
// todo: assuming one shape per collider; doesn't support compound shape
|
|
||||||
Collider* collider = (Collider*) JPH_BodyInterface_GetUserData(
|
uint32_t shape = 0;
|
||||||
world->bodies,
|
if (collider->shape->type == SHAPE_COMPOUND) {
|
||||||
hit_array[i].bodyID);
|
JPH_SubShapeID id = hits[i].subShapeID2;
|
||||||
size_t count;
|
JPH_SubShapeID remainder;
|
||||||
Shape** shape = lovrColliderGetShapes(collider, &count);
|
shape = JPH_CompoundShape_GetSubShapeIndexFromID((JPH_CompoundShape*) collider->shape, id, &remainder);
|
||||||
const JPH_RVec3 position = { x, y, z };
|
}
|
||||||
|
|
||||||
|
JPH_RVec3 position = {
|
||||||
|
x1 + hits[i].fraction * (x2 - x1),
|
||||||
|
y1 + hits[i].fraction * (y2 - y1),
|
||||||
|
z1 + hits[i].fraction * (z2 - z1)
|
||||||
|
};
|
||||||
|
|
||||||
JPH_Vec3 normal;
|
JPH_Vec3 normal;
|
||||||
JPH_Body_GetWorldSpaceSurfaceNormal(collider->body, hit_array[i].subShapeID2, &position, &normal);
|
JPH_Body_GetWorldSpaceSurfaceNormal(collider->body, hits[i].subShapeID2, &position, &normal);
|
||||||
|
|
||||||
bool shouldStop = callback(
|
if (callback(collider, shape, &position.x, &normal.x, userdata)) {
|
||||||
shape[0], // assumes one shape per collider; todo: compound shapes
|
|
||||||
x, y, z,
|
|
||||||
normal.x, normal.y, normal.z,
|
|
||||||
userdata);
|
|
||||||
|
|
||||||
if (shouldStop) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JPH_AllHit_CastRayCollector_Destroy(collector);
|
JPH_AllHit_CastRayCollector_Destroy(collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,26 +213,25 @@ static bool lovrWorldQueryShape(World* world, JPH_Shape* shape, float position[3
|
||||||
mat4_translate(m, position[0], position[1], position[2]);
|
mat4_translate(m, position[0], position[1], position[2]);
|
||||||
mat4_scale(m, scale[0], scale[1], scale[2]);
|
mat4_scale(m, scale[0], scale[1], scale[2]);
|
||||||
|
|
||||||
JPH_Vec3 direction = { 0.f };
|
JPH_Vec3 direction = { 0.f, 0.f, 0.f };
|
||||||
JPH_RVec3 base_offset = { 0.f };
|
JPH_RVec3 base_offset = { 0.f, 0.f, 0.f };
|
||||||
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system);
|
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system);
|
||||||
JPH_AllHit_CastShapeCollector_Reset(state.castShapeCollector);
|
JPH_AllHit_CastShapeCollector_Reset(state.castShapeCollector);
|
||||||
JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, state.castShapeCollector);
|
JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, state.castShapeCollector);
|
||||||
size_t hit_count;
|
|
||||||
JPH_ShapeCastResult* hit_array = JPH_AllHit_CastShapeCollector_GetHits(state.castShapeCollector, &hit_count);
|
size_t count;
|
||||||
for (int i = 0; i < hit_count; i++) {
|
JPH_AllHit_CastShapeCollector_GetHits(state.castShapeCollector, &count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(state.castShapeCollector, i);
|
JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(state.castShapeCollector, i);
|
||||||
Collider* collider = (Collider*) JPH_BodyInterface_GetUserData(
|
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, id);
|
||||||
world->bodies,
|
|
||||||
id);
|
if (callback(collider, 0, userdata)) {
|
||||||
size_t count;
|
|
||||||
Shape** shape = lovrColliderGetShapes(collider, &count);
|
|
||||||
bool shouldStop = callback(shape[0], userdata);
|
|
||||||
if (shouldStop) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hit_count > 0;
|
|
||||||
|
return count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata) {
|
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata) {
|
||||||
|
@ -315,30 +318,35 @@ void lovrWorldSetAngularDamping(World* world, float damping, float threshold) {
|
||||||
|
|
||||||
// Collider
|
// Collider
|
||||||
|
|
||||||
Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z) {
|
||||||
// todo: crashes when too many are added
|
uint32_t count = JPH_PhysicsSystem_GetNumBodies(world->system);
|
||||||
|
uint32_t limit = JPH_PhysicsSystem_GetMaxBodies(world->system);
|
||||||
|
lovrCheck(count < limit, "Too many colliders!");
|
||||||
|
|
||||||
|
if (!shape) shape = state.pointShape;
|
||||||
|
|
||||||
Collider* collider = lovrCalloc(sizeof(Collider));
|
Collider* collider = lovrCalloc(sizeof(Collider));
|
||||||
collider->ref = 1;
|
collider->ref = 1;
|
||||||
collider->world = world;
|
collider->world = world;
|
||||||
|
collider->shape = shape;
|
||||||
collider->tag = UNTAGGED;
|
collider->tag = UNTAGGED;
|
||||||
JPH_MotionType motionType = JPH_MotionType_Dynamic;
|
|
||||||
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
|
|
||||||
|
|
||||||
const JPH_RVec3 position = { x, y, z };
|
const JPH_RVec3 position = { x, y, z };
|
||||||
const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f };
|
const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f };
|
||||||
// todo: a placeholder querySphere shape is used in collider, then replaced in lovrColliderAddShape
|
JPH_MotionType type = JPH_MotionType_Dynamic;
|
||||||
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(
|
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
|
||||||
state.querySphere, &position, &rotation, motionType, objectLayer);
|
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(shape->shape, &position, &rotation, type, objectLayer);
|
||||||
collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings);
|
collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings);
|
||||||
JPH_BodyCreationSettings_Destroy(settings);
|
|
||||||
collider->id = JPH_Body_GetID(collider->body);
|
collider->id = JPH_Body_GetID(collider->body);
|
||||||
|
JPH_BodyCreationSettings_Destroy(settings);
|
||||||
|
|
||||||
JPH_BodyInterface_AddBody(world->bodies, collider->id, JPH_Activation_Activate);
|
JPH_BodyInterface_AddBody(world->bodies, collider->id, JPH_Activation_Activate);
|
||||||
JPH_BodyInterface_SetUserData(world->bodies, collider->id, (uint64_t) collider);
|
JPH_BodyInterface_SetUserData(world->bodies, collider->id, (uint64_t) collider);
|
||||||
|
|
||||||
lovrColliderSetLinearDamping(collider, world->defaultLinearDamping, 0.f);
|
lovrColliderSetLinearDamping(collider, world->defaultLinearDamping, 0.f);
|
||||||
lovrColliderSetAngularDamping(collider, world->defaultAngularDamping, 0.f);
|
lovrColliderSetAngularDamping(collider, world->defaultAngularDamping, 0.f);
|
||||||
lovrColliderSetSleepingAllowed(collider, world->defaultIsSleepingAllowed);
|
lovrColliderSetSleepingAllowed(collider, world->defaultIsSleepingAllowed);
|
||||||
|
|
||||||
arr_init(&collider->shapes);
|
|
||||||
arr_init(&collider->joints);
|
arr_init(&collider->joints);
|
||||||
|
|
||||||
// Adjust the world's collider list
|
// Adjust the world's collider list
|
||||||
|
@ -350,15 +358,14 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
||||||
world->head = collider;
|
world->head = collider;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The world owns a reference to the collider
|
lovrRetain(collider->shape);
|
||||||
lovrRetain(collider);
|
lovrRetain(collider); // The world owns a reference to the collider
|
||||||
return collider;
|
return collider;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrColliderDestroy(void* ref) {
|
void lovrColliderDestroy(void* ref) {
|
||||||
Collider* collider = ref;
|
Collider* collider = ref;
|
||||||
lovrColliderDestroyData(collider);
|
lovrColliderDestroyData(collider);
|
||||||
arr_free(&collider->shapes);
|
|
||||||
arr_free(&collider->joints);
|
arr_free(&collider->joints);
|
||||||
lovrFree(collider);
|
lovrFree(collider);
|
||||||
}
|
}
|
||||||
|
@ -368,13 +375,9 @@ void lovrColliderDestroyData(Collider* collider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lovrRelease(collider->shape, lovrShapeDestroy);
|
||||||
|
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
Shape** shapes = lovrColliderGetShapes(collider, &count);
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
lovrColliderRemoveShape(collider, shapes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Joint** joints = lovrColliderGetJoints(collider, &count);
|
Joint** joints = lovrColliderGetJoints(collider, &count);
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
lovrRelease(joints[i], lovrJointDestroy);
|
lovrRelease(joints[i], lovrJointDestroy);
|
||||||
|
@ -396,6 +399,18 @@ bool lovrColliderIsDestroyed(Collider* collider) {
|
||||||
return !collider->body;
|
return !collider->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lovrColliderIsEnabled(Collider* collider) {
|
||||||
|
return JPH_BodyInterface_IsAdded(collider->world->bodies, collider->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetEnabled(Collider* collider, bool enable) {
|
||||||
|
if (enable && !lovrColliderIsEnabled(collider)) {
|
||||||
|
JPH_BodyInterface_AddBody(collider->world->bodies, collider->id, JPH_Activation_DontActivate);
|
||||||
|
} else if (!enable && lovrColliderIsEnabled(collider)) {
|
||||||
|
JPH_BodyInterface_RemoveBody(collider->world->bodies, collider->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
|
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
@ -408,29 +423,67 @@ Collider* lovrColliderGetNext(Collider* collider) {
|
||||||
return collider->next;
|
return collider->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrColliderAddShape(Collider* collider, Shape* shape) {
|
Shape* lovrColliderGetShape(Collider* collider) {
|
||||||
|
return collider->shape == state.pointShape ? NULL : collider->shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetShape(Collider* collider, Shape* shape) {
|
||||||
|
shape = shape ? shape : state.pointShape;
|
||||||
|
|
||||||
|
if (shape == collider->shape) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float position[3], orientation[4];
|
||||||
|
const JPH_Shape* parent = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id);
|
||||||
|
bool hasOffset = JPH_Shape_GetSubType(parent) == JPH_ShapeSubType_RotatedTranslated;
|
||||||
|
if (hasOffset) lovrColliderGetShapeOffset(collider, position, orientation);
|
||||||
|
|
||||||
|
lovrRelease(collider->shape, lovrShapeDestroy);
|
||||||
|
collider->shape = shape;
|
||||||
lovrRetain(shape);
|
lovrRetain(shape);
|
||||||
shape->collider = collider;
|
|
||||||
arr_push(&collider->shapes, shape);
|
|
||||||
bool isMeshOrTerrain = (shape->type == SHAPE_TERRAIN) || (shape->type == SHAPE_MESH);
|
|
||||||
bool shouldUpdateMass = !isMeshOrTerrain;
|
|
||||||
if (isMeshOrTerrain) {
|
|
||||||
lovrColliderSetKinematic(shape->collider, true);
|
|
||||||
}
|
|
||||||
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, shouldUpdateMass, JPH_Activation_Activate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrColliderRemoveShape(Collider* collider, Shape* shape) {
|
bool updateMass = true;
|
||||||
if (shape->collider == collider) {
|
if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) {
|
||||||
// todo: actions necessary for compound shapes
|
lovrColliderSetKinematic(collider, true);
|
||||||
shape->collider = NULL;
|
updateMass = false;
|
||||||
lovrRelease(shape, lovrShapeDestroy);
|
}
|
||||||
|
|
||||||
|
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate);
|
||||||
|
|
||||||
|
if (hasOffset) {
|
||||||
|
lovrColliderSetShapeOffset(collider, position, orientation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape** lovrColliderGetShapes(Collider* collider, size_t* count) {
|
void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation) {
|
||||||
*count = collider->shapes.length;
|
const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id);
|
||||||
return collider->shapes.data;
|
|
||||||
|
if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) {
|
||||||
|
JPH_Vec3 jposition;
|
||||||
|
JPH_Quat jrotation;
|
||||||
|
JPH_RotatedTranslatedShape_GetPosition((JPH_RotatedTranslatedShape*) shape, &jposition);
|
||||||
|
JPH_RotatedTranslatedShape_GetRotation((JPH_RotatedTranslatedShape*) shape, &jrotation);
|
||||||
|
vec3_init(position, &jposition.x);
|
||||||
|
quat_init(orientation, &jrotation.x);
|
||||||
|
} else {
|
||||||
|
vec3_set(position, 0.f, 0.f, 0.f);
|
||||||
|
quat_identity(orientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation) {
|
||||||
|
const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id);
|
||||||
|
|
||||||
|
if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) {
|
||||||
|
JPH_Shape_Destroy((JPH_Shape*) shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
JPH_Vec3 jposition = { position[0], position[1], position[2] };
|
||||||
|
JPH_Quat jrotation = { orientation[0], orientation[1], orientation[2], orientation[3] };
|
||||||
|
shape = (JPH_Shape*) JPH_RotatedTranslatedShape_Create(&jposition, &jrotation, collider->shape->shape);
|
||||||
|
bool updateMass = collider->shape && (collider->shape->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN);
|
||||||
|
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape, updateMass, JPH_Activation_Activate);
|
||||||
}
|
}
|
||||||
|
|
||||||
Joint** lovrColliderGetJoints(Collider* collider, size_t* count) {
|
Joint** lovrColliderGetJoints(Collider* collider, size_t* count) {
|
||||||
|
@ -497,6 +550,23 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lovrColliderIsSensor(Collider* collider) {
|
||||||
|
return JPH_Body_IsSensor(collider->body);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetSensor(Collider* collider, bool sensor) {
|
||||||
|
JPH_Body_SetIsSensor(collider->body, sensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lovrColliderIsContinuous(Collider* collider) {
|
||||||
|
return JPH_BodyInterface_GetMotionQuality(collider->world->bodies, collider->id) == JPH_MotionQuality_LinearCast;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetContinuous(Collider* collider, bool continuous) {
|
||||||
|
JPH_MotionQuality quality = continuous ? JPH_MotionQuality_LinearCast : JPH_MotionQuality_Discrete;
|
||||||
|
return JPH_BodyInterface_SetMotionQuality(collider->world->bodies, collider->id, quality);
|
||||||
|
}
|
||||||
|
|
||||||
float lovrColliderGetGravityScale(Collider* collider) {
|
float lovrColliderGetGravityScale(Collider* collider) {
|
||||||
return JPH_BodyInterface_GetGravityFactor(collider->world->bodies, collider->id);
|
return JPH_BodyInterface_GetGravityFactor(collider->world->bodies, collider->id);
|
||||||
}
|
}
|
||||||
|
@ -526,22 +596,17 @@ void lovrColliderSetAwake(Collider* collider, bool awake) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float lovrColliderGetMass(Collider* collider) {
|
float lovrColliderGetMass(Collider* collider) {
|
||||||
if (collider->shapes.length > 0) {
|
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
|
||||||
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
|
return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties);
|
||||||
return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties);
|
|
||||||
}
|
|
||||||
return 0.f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrColliderSetMass(Collider* collider, float mass) {
|
void lovrColliderSetMass(Collider* collider, float mass) {
|
||||||
if (collider->shapes.length > 0) {
|
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
|
||||||
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
|
Shape* shape = collider->shape;
|
||||||
Shape* shape = collider->shapes.data[0];
|
JPH_MassProperties* massProperties;
|
||||||
JPH_MassProperties* massProperties;
|
JPH_Shape_GetMassProperties(shape->shape, massProperties);
|
||||||
JPH_Shape_GetMassProperties(shape->shape, massProperties);
|
JPH_MassProperties_ScaleToMass(massProperties, mass);
|
||||||
JPH_MassProperties_ScaleToMass(massProperties, mass);
|
JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties);
|
||||||
JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
|
void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
|
||||||
|
@ -658,6 +723,22 @@ void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
|
||||||
JPH_BodyInterface_AddTorque(collider->world->bodies, collider->id, &torque);
|
JPH_BodyInterface_AddTorque(collider->world->bodies, collider->id, &torque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lovrColliderApplyLinearImpulse(Collider* collider, float impulse[3]) {
|
||||||
|
JPH_Vec3 vector = { impulse[0], impulse[1], impulse[2] };
|
||||||
|
JPH_BodyInterface_AddImpulse(collider->world->bodies, collider->id, &vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderApplyLinearImpulseAtPosition(Collider* collider, float impulse[3], float position[3]) {
|
||||||
|
JPH_Vec3 vector = { impulse[0], impulse[1], impulse[2] };
|
||||||
|
JPH_Vec3 point = { position[0], position[1], position[2] };
|
||||||
|
JPH_BodyInterface_AddImpulse2(collider->world->bodies, collider->id, &vector, &point);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderApplyAngularImpulse(Collider* collider, float impulse[3]) {
|
||||||
|
JPH_Vec3 vector = { impulse[0], impulse[1], impulse[2] };
|
||||||
|
JPH_BodyInterface_AddAngularImpulse(collider->world->bodies, collider->id, &vector);
|
||||||
|
}
|
||||||
|
|
||||||
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
|
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
|
||||||
// todo: applicable for CompoundShape and OffsetCenterOfMassShape
|
// todo: applicable for CompoundShape and OffsetCenterOfMassShape
|
||||||
*x = 0.f;
|
*x = 0.f;
|
||||||
|
@ -737,6 +818,8 @@ void lovrColliderGetAABB(Collider* collider, float aabb[6]) {
|
||||||
aabb[5] = box.max.z;
|
aabb[5] = box.max.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shapes
|
||||||
|
|
||||||
void lovrShapeDestroy(void* ref) {
|
void lovrShapeDestroy(void* ref) {
|
||||||
Shape* shape = ref;
|
Shape* shape = ref;
|
||||||
lovrShapeDestroyData(shape);
|
lovrShapeDestroyData(shape);
|
||||||
|
@ -745,6 +828,14 @@ void lovrShapeDestroy(void* ref) {
|
||||||
|
|
||||||
void lovrShapeDestroyData(Shape* shape) {
|
void lovrShapeDestroyData(Shape* shape) {
|
||||||
if (shape->shape) {
|
if (shape->shape) {
|
||||||
|
if (shape->type == SHAPE_COMPOUND) {
|
||||||
|
uint32_t count = lovrCompoundShapeGetShapeCount(shape);
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
Shape* child = lovrCompoundShapeGetShape(shape, i);
|
||||||
|
lovrRelease(child, lovrShapeDestroy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JPH_Shape_Destroy(shape->shape);
|
JPH_Shape_Destroy(shape->shape);
|
||||||
shape->shape = NULL;
|
shape->shape = NULL;
|
||||||
}
|
}
|
||||||
|
@ -754,58 +845,12 @@ ShapeType lovrShapeGetType(Shape* shape) {
|
||||||
return shape->type;
|
return shape->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collider* lovrShapeGetCollider(Shape* shape) {
|
void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
|
||||||
return shape->collider;
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lovrShapeIsEnabled(Shape* shape) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrShapeSetEnabled(Shape* shape, bool enabled) {
|
|
||||||
if (!enabled) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support disabling shapes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lovrShapeIsSensor(Shape* shape) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt sensor property fetched from collider, not shape");
|
|
||||||
return JPH_Body_IsSensor(shape->collider->body);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrShapeSetSensor(Shape* shape, bool sensor) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt sensor property is applied to collider, not shape");
|
|
||||||
JPH_Body_SetIsSensor(shape->collider->body, sensor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrShapeGetPosition(Shape* shape, float* x, float* y, float* z) {
|
|
||||||
// todo: compound shapes
|
|
||||||
*x = 0.f;
|
|
||||||
*y = 0.f;
|
|
||||||
*z = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrShapeSetPosition(Shape* shape, float x, float y, float z) {
|
|
||||||
// todo: compound shapes
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrShapeGetOrientation(Shape* shape, float* orientation) {
|
|
||||||
// todo: compound shapes
|
|
||||||
orientation[0] = 0.f;
|
|
||||||
orientation[1] = 0.f;
|
|
||||||
orientation[2] = 0.f;
|
|
||||||
orientation[3] = 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrShapeSetOrientation(Shape* shape, float* orientation) {
|
|
||||||
// todo: compound shapes
|
|
||||||
}
|
|
||||||
|
|
||||||
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 lovrShapeGetAABB(Shape* shape, float aabb[6]) {
|
||||||
// todo: with compound shapes this is no longer correct
|
// TODO
|
||||||
lovrColliderGetAABB(shape->collider, aabb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SphereShape* lovrSphereShapeCreate(float radius) {
|
SphereShape* lovrSphereShapeCreate(float radius) {
|
||||||
|
@ -814,6 +859,7 @@ SphereShape* lovrSphereShapeCreate(float radius) {
|
||||||
sphere->ref = 1;
|
sphere->ref = 1;
|
||||||
sphere->type = SHAPE_SPHERE;
|
sphere->type = SHAPE_SPHERE;
|
||||||
sphere->shape = (JPH_Shape*) JPH_SphereShape_Create(radius);
|
sphere->shape = (JPH_Shape*) JPH_SphereShape_Create(radius);
|
||||||
|
JPH_Shape_SetUserData(sphere->shape, (uint64_t) (uintptr_t) sphere);
|
||||||
return sphere;
|
return sphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,17 +867,13 @@ float lovrSphereShapeGetRadius(SphereShape* sphere) {
|
||||||
return JPH_SphereShape_GetRadius((JPH_SphereShape*) sphere->shape);
|
return JPH_SphereShape_GetRadius((JPH_SphereShape*) sphere->shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrSphereShapeSetRadius(SphereShape* sphere, float radius) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt SphereShape radius is read-only");
|
|
||||||
// todo: no setter available, but the shape could be removed and re-added
|
|
||||||
}
|
|
||||||
|
|
||||||
BoxShape* lovrBoxShapeCreate(float w, float h, float d) {
|
BoxShape* lovrBoxShapeCreate(float w, float h, float d) {
|
||||||
BoxShape* box = lovrCalloc(sizeof(BoxShape));
|
BoxShape* box = lovrCalloc(sizeof(BoxShape));
|
||||||
box->ref = 1;
|
box->ref = 1;
|
||||||
box->type = SHAPE_BOX;
|
box->type = SHAPE_BOX;
|
||||||
const JPH_Vec3 halfExtent = { w / 2.f, h / 2.f, d / 2.f };
|
const JPH_Vec3 halfExtent = { w / 2.f, h / 2.f, d / 2.f };
|
||||||
box->shape = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f);
|
box->shape = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f);
|
||||||
|
JPH_Shape_SetUserData(box->shape, (uint64_t) (uintptr_t) box);
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,17 +885,13 @@ void lovrBoxShapeGetDimensions(BoxShape* box, float* w, float* h, float* d) {
|
||||||
*d = halfExtent.z * 2.f;
|
*d = halfExtent.z * 2.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrBoxShapeSetDimensions(BoxShape* box, float w, float h, float d) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt BoxShape dimensions are read-only");
|
|
||||||
// todo: no setter available, but the shape could be removed and re-added
|
|
||||||
}
|
|
||||||
|
|
||||||
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length) {
|
CapsuleShape* lovrCapsuleShapeCreate(float radius, float length) {
|
||||||
lovrCheck(radius > 0.f && length > 0.f, "CapsuleShape dimensions must be positive");
|
lovrCheck(radius > 0.f && length > 0.f, "CapsuleShape dimensions must be positive");
|
||||||
CapsuleShape* capsule = lovrCalloc(sizeof(CapsuleShape));
|
CapsuleShape* capsule = lovrCalloc(sizeof(CapsuleShape));
|
||||||
capsule->ref = 1;
|
capsule->ref = 1;
|
||||||
capsule->type = SHAPE_CAPSULE;
|
capsule->type = SHAPE_CAPSULE;
|
||||||
capsule->shape = (JPH_Shape*) JPH_CapsuleShape_Create(length / 2, radius);
|
capsule->shape = (JPH_Shape*) JPH_CapsuleShape_Create(length / 2, radius);
|
||||||
|
JPH_Shape_SetUserData(capsule->shape, (uint64_t) (uintptr_t) capsule);
|
||||||
return capsule;
|
return capsule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,45 +899,26 @@ float lovrCapsuleShapeGetRadius(CapsuleShape* capsule) {
|
||||||
return JPH_CapsuleShape_GetRadius((JPH_CapsuleShape*) capsule->shape);
|
return JPH_CapsuleShape_GetRadius((JPH_CapsuleShape*) capsule->shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrCapsuleShapeSetRadius(CapsuleShape* capsule, float radius) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt CapsuleShape radius is read-only");
|
|
||||||
// todo: no setter available, but the shape could be removed and re-added
|
|
||||||
}
|
|
||||||
|
|
||||||
float lovrCapsuleShapeGetLength(CapsuleShape* capsule) {
|
float lovrCapsuleShapeGetLength(CapsuleShape* capsule) {
|
||||||
return 2.f * JPH_CapsuleShape_GetHalfHeightOfCylinder((JPH_CapsuleShape*) capsule->shape);
|
return 2.f * JPH_CapsuleShape_GetHalfHeightOfCylinder((JPH_CapsuleShape*) capsule->shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrCapsuleShapeSetLength(CapsuleShape* capsule, float length) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt CapsuleShape length is read-only");
|
|
||||||
// todo: no setter available, but the shape could be removed and re-added
|
|
||||||
}
|
|
||||||
|
|
||||||
CylinderShape* lovrCylinderShapeCreate(float radius, float length) {
|
CylinderShape* lovrCylinderShapeCreate(float radius, float length) {
|
||||||
lovrCheck(radius > 0.f && length > 0.f, "CylinderShape dimensions must be positive");
|
lovrCheck(radius > 0.f && length > 0.f, "CylinderShape dimensions must be positive");
|
||||||
CylinderShape* Cylinder = lovrCalloc(sizeof(CylinderShape));
|
CylinderShape* cylinder = lovrCalloc(sizeof(CylinderShape));
|
||||||
Cylinder->ref = 1;
|
cylinder->ref = 1;
|
||||||
Cylinder->type = SHAPE_CYLINDER;
|
cylinder->type = SHAPE_CYLINDER;
|
||||||
Cylinder->shape = (JPH_Shape*) JPH_CylinderShape_Create(length / 2.f, radius);
|
cylinder->shape = (JPH_Shape*) JPH_CylinderShape_Create(length / 2.f, radius);
|
||||||
return Cylinder;
|
JPH_Shape_SetUserData(cylinder->shape, (uint64_t) (uintptr_t) cylinder);
|
||||||
|
return cylinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
float lovrCylinderShapeGetRadius(CylinderShape* Cylinder) {
|
float lovrCylinderShapeGetRadius(CylinderShape* cylinder) {
|
||||||
return JPH_CylinderShape_GetRadius((JPH_CylinderShape*) Cylinder->shape);
|
return JPH_CylinderShape_GetRadius((JPH_CylinderShape*) cylinder->shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrCylinderShapeSetRadius(CylinderShape* Cylinder, float radius) {
|
float lovrCylinderShapeGetLength(CylinderShape* cylinder) {
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt CylinderShape radius is read-only");
|
return JPH_CylinderShape_GetHalfHeight((JPH_CylinderShape*) cylinder->shape) * 2.f;
|
||||||
// todo: no setter available, but the shape could be removed and re-added
|
|
||||||
}
|
|
||||||
|
|
||||||
float lovrCylinderShapeGetLength(CylinderShape* Cylinder) {
|
|
||||||
return JPH_CylinderShape_GetHalfHeight((JPH_CylinderShape*) Cylinder->shape) * 2.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lovrCylinderShapeSetLength(CylinderShape* cylinder, float length) {
|
|
||||||
lovrLog(LOG_WARN, "PHY", "Jolt CylinderShape length is read-only");
|
|
||||||
// todo: no setter available, but the shape could be removed and re-added
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]) {
|
MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount, uint32_t indices[]) {
|
||||||
|
@ -931,29 +950,124 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float vertices[], int indexCount
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale) {
|
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY) {
|
||||||
lovrCheck(widthSamples == depthSamples, "Jolt needs terrain width and depth to be the same");
|
|
||||||
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
|
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
|
||||||
terrain->ref = 1;
|
terrain->ref = 1;
|
||||||
terrain->type = SHAPE_TERRAIN;
|
terrain->type = SHAPE_TERRAIN;
|
||||||
const JPH_Vec3 offset = {
|
const JPH_Vec3 offset = {
|
||||||
.x = -.5f * horizontalScale,
|
.x = -.5f * scaleXZ,
|
||||||
.y = 0.f,
|
.y = 0.f,
|
||||||
.z = -.5f * horizontalScale
|
.z = -.5f * scaleXZ
|
||||||
};
|
};
|
||||||
const JPH_Vec3 scale = {
|
const JPH_Vec3 scale = {
|
||||||
.x = horizontalScale / widthSamples,
|
.x = scaleXZ / n,
|
||||||
.y = verticalScale,
|
.y = scaleY,
|
||||||
.z = horizontalScale / depthSamples
|
.z = scaleXZ / n
|
||||||
};
|
};
|
||||||
|
|
||||||
JPH_HeightFieldShapeSettings* shape_settings = JPH_HeightFieldShapeSettings_Create(
|
JPH_HeightFieldShapeSettings* shape_settings = JPH_HeightFieldShapeSettings_Create(vertices, &offset, &scale, n);
|
||||||
vertices, &offset, &scale, widthSamples);
|
|
||||||
terrain->shape = (JPH_Shape*) JPH_HeightFieldShapeSettings_CreateShape(shape_settings);
|
terrain->shape = (JPH_Shape*) JPH_HeightFieldShapeSettings_CreateShape(shape_settings);
|
||||||
JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) shape_settings);
|
JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) shape_settings);
|
||||||
return terrain;
|
return terrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompoundShape* lovrCompoundShapeCreate(Shape** shapes, vec3 positions, quat orientations, uint32_t count, bool freeze) {
|
||||||
|
lovrCheck(!freeze || count >= 2, "A frozen CompoundShape must contain at least two shapes");
|
||||||
|
|
||||||
|
CompoundShape* parent = lovrCalloc(sizeof(CompoundShape));
|
||||||
|
parent->ref = 1;
|
||||||
|
parent->type = SHAPE_COMPOUND;
|
||||||
|
|
||||||
|
JPH_CompoundShapeSettings* settings = freeze ?
|
||||||
|
(JPH_CompoundShapeSettings*) JPH_StaticCompoundShapeSettings_Create() :
|
||||||
|
(JPH_CompoundShapeSettings*) JPH_MutableCompoundShapeSettings_Create();
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
|
lovrCheck(shapes[i]->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported");
|
||||||
|
JPH_Vec3 position = { positions[3 * i + 0], positions[3 * i + 1], positions[3 * i + 2] };
|
||||||
|
JPH_Quat rotation = { orientations[4 * i + 0], orientations[4 * i + 1], orientations[4 * i + 2], orientations[4 * i + 3] };
|
||||||
|
JPH_CompoundShapeSettings_AddShape2(settings, &position, &rotation, shapes[i]->shape, 0);
|
||||||
|
lovrRetain(shapes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freeze) {
|
||||||
|
parent->shape = (JPH_Shape*) JPH_StaticCompoundShape_Create((JPH_StaticCompoundShapeSettings*) settings);
|
||||||
|
} else {
|
||||||
|
parent->shape = (JPH_Shape*) JPH_MutableCompoundShape_Create((JPH_MutableCompoundShapeSettings*) settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
JPH_ShapeSettings_Destroy((JPH_ShapeSettings*) settings);
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lovrCompoundShapeIsFrozen(CompoundShape* shape) {
|
||||||
|
return JPH_Shape_GetSubType(shape->shape) == JPH_ShapeSubType_StaticCompound;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) {
|
||||||
|
lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed");
|
||||||
|
lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported");
|
||||||
|
lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol");
|
||||||
|
JPH_Vec3 pos = { position[0], position[1], position[2] };
|
||||||
|
JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] };
|
||||||
|
JPH_MutableCompoundShape_AddShape((JPH_MutableCompoundShape*) shape->shape, &pos, &rot, child->shape, 0);
|
||||||
|
lovrRetain(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) {
|
||||||
|
lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed");
|
||||||
|
lovrCheck(child->type != SHAPE_COMPOUND, "Currently, nesting compound shapes is not supported");
|
||||||
|
lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1);
|
||||||
|
lovrCheck(child != shape, "Don't put a CompoundShape inside itself! lol");
|
||||||
|
JPH_Vec3 pos = { position[0], position[1], position[2] };
|
||||||
|
JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] };
|
||||||
|
JPH_MutableCompoundShape_ModifyShape2((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot, child->shape);
|
||||||
|
lovrRetain(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) {
|
||||||
|
lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed");
|
||||||
|
lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1);
|
||||||
|
Shape* child = lovrCompoundShapeGetShape(shape, index);
|
||||||
|
JPH_MutableCompoundShape_RemoveShape((JPH_MutableCompoundShape*) shape->shape, index);
|
||||||
|
lovrRelease(child, lovrShapeDestroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) {
|
||||||
|
if (index < lovrCompoundShapeGetShapeCount(shape)) {
|
||||||
|
const JPH_Shape* child;
|
||||||
|
JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, NULL, NULL, NULL);
|
||||||
|
return (Shape*) (uintptr_t) JPH_Shape_GetUserData(child);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) {
|
||||||
|
return JPH_CompoundShape_GetNumSubShapes((JPH_CompoundShape*) shape->shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) {
|
||||||
|
lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1);
|
||||||
|
const JPH_Shape* child;
|
||||||
|
JPH_Vec3 pos;
|
||||||
|
JPH_Quat rot;
|
||||||
|
uint32_t userData;
|
||||||
|
JPH_CompoundShape_GetSubShape((JPH_CompoundShape*) shape->shape, index, &child, &pos, &rot, &userData);
|
||||||
|
vec3_init(position, &pos.x);
|
||||||
|
quat_init(orientation, &rot.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) {
|
||||||
|
lovrCheck(!lovrCompoundShapeIsFrozen(shape), "CompoundShape is frozen and can not be changed");
|
||||||
|
lovrCheck(index < lovrCompoundShapeGetShapeCount(shape), "CompoundShape has no shape at index %d", index + 1);
|
||||||
|
JPH_Vec3 pos = { position[0], position[1], position[2] };
|
||||||
|
JPH_Quat rot = { orientation[0], orientation[1], orientation[2], orientation[3] };
|
||||||
|
JPH_MutableCompoundShape_ModifyShape((JPH_MutableCompoundShape*) shape->shape, index, &pos, &rot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Joints
|
||||||
|
|
||||||
void lovrJointGetAnchors(Joint* joint, float anchor1[3], float anchor2[3]) {
|
void lovrJointGetAnchors(Joint* joint, float anchor1[3], float anchor2[3]) {
|
||||||
JPH_Body* body1 = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*) joint->constraint);
|
JPH_Body* body1 = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*) joint->constraint);
|
||||||
JPH_Body* body2 = JPH_TwoBodyConstraint_GetBody2((JPH_TwoBodyConstraint*) joint->constraint);
|
JPH_Body* body2 = JPH_TwoBodyConstraint_GetBody2((JPH_TwoBodyConstraint*) joint->constraint);
|
||||||
|
|
|
@ -22,10 +22,11 @@ struct Collider {
|
||||||
Collider* prev;
|
Collider* prev;
|
||||||
Collider* next;
|
Collider* next;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
arr_t(Shape*) shapes;
|
Shape* shape;
|
||||||
arr_t(Joint*) joints;
|
arr_t(Joint*) joints;
|
||||||
float friction;
|
float friction;
|
||||||
float restitution;
|
float restitution;
|
||||||
|
bool sensor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Shape {
|
struct Shape {
|
||||||
|
@ -35,7 +36,6 @@ struct Shape {
|
||||||
Collider* collider;
|
Collider* collider;
|
||||||
void* vertices;
|
void* vertices;
|
||||||
void* indices;
|
void* indices;
|
||||||
bool sensor;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Joint {
|
struct Joint {
|
||||||
|
@ -66,8 +66,9 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) {
|
||||||
RaycastCallback callback = data->callback;
|
RaycastCallback callback = data->callback;
|
||||||
void* userdata = data->userdata;
|
void* userdata = data->userdata;
|
||||||
Shape* shape = dGeomGetData(b);
|
Shape* shape = dGeomGetData(b);
|
||||||
|
Collider* collider = dBodyGetData(dGeomGetBody(b));
|
||||||
|
|
||||||
if (!shape) {
|
if (!shape || !collider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,9 +76,7 @@ static void raycastCallback(void* d, dGeomID a, dGeomID b) {
|
||||||
int count = dCollide(a, b, MAX_CONTACTS, &contact->geom, sizeof(dContact));
|
int count = dCollide(a, b, MAX_CONTACTS, &contact->geom, sizeof(dContact));
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
dContactGeom g = contact[i].geom;
|
dContactGeom g = contact[i].geom;
|
||||||
data->shouldStop = callback(
|
data->shouldStop = callback(collider, 0, g.pos, g.normal, userdata);
|
||||||
shape, g.pos[0], g.pos[1], g.pos[2], g.normal[0], g.normal[1], g.normal[2], userdata
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,14 +92,15 @@ static void queryCallback(void* d, dGeomID a, dGeomID b) {
|
||||||
if (data->shouldStop) return;
|
if (data->shouldStop) return;
|
||||||
|
|
||||||
Shape* shape = dGeomGetData(b);
|
Shape* shape = dGeomGetData(b);
|
||||||
if (!shape) {
|
Collider* collider = dBodyGetData(dGeomGetBody(b));
|
||||||
|
if (!shape || !collider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dContactGeom contact;
|
dContactGeom contact;
|
||||||
if (dCollide(a, b, 1 | CONTACTS_UNIMPORTANT, &contact, sizeof(contact))) {
|
if (dCollide(a, b, 1 | CONTACTS_UNIMPORTANT, &contact, sizeof(contact))) {
|
||||||
if (data->callback) {
|
if (data->callback) {
|
||||||
data->shouldStop = data->callback(shape, data->userdata);
|
data->shouldStop = data->callback(collider, 0, data->userdata);
|
||||||
} else {
|
} else {
|
||||||
data->shouldStop = true;
|
data->shouldStop = true;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,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));
|
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++) {
|
for (int c = 0; c < contactCount; c++) {
|
||||||
dJointID joint = dJointCreateContact(world->id, world->contactGroup, &contacts[c]);
|
dJointID joint = dJointCreateContact(world->id, world->contactGroup, &contacts[c]);
|
||||||
dJointAttach(joint, colliderA->body, colliderB->body);
|
dJointAttach(joint, colliderA->body, colliderB->body);
|
||||||
|
@ -436,7 +436,7 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
|
||||||
return (world->masks[i] & (1 << j)) && (world->masks[j] & (1 << i));
|
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 x, float y, float z) {
|
||||||
Collider* collider = lovrCalloc(sizeof(Collider));
|
Collider* collider = lovrCalloc(sizeof(Collider));
|
||||||
collider->ref = 1;
|
collider->ref = 1;
|
||||||
collider->body = dBodyCreate(world->id);
|
collider->body = dBodyCreate(world->id);
|
||||||
|
@ -445,9 +445,9 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
||||||
collider->restitution = 0;
|
collider->restitution = 0;
|
||||||
collider->tag = NO_TAG;
|
collider->tag = NO_TAG;
|
||||||
dBodySetData(collider->body, collider);
|
dBodySetData(collider->body, collider);
|
||||||
arr_init(&collider->shapes);
|
|
||||||
arr_init(&collider->joints);
|
arr_init(&collider->joints);
|
||||||
|
|
||||||
|
lovrColliderSetShape(collider, shape);
|
||||||
lovrColliderSetPosition(collider, x, y, z);
|
lovrColliderSetPosition(collider, x, y, z);
|
||||||
|
|
||||||
// Adjust the world's collider list
|
// Adjust the world's collider list
|
||||||
|
@ -467,7 +467,6 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
||||||
void lovrColliderDestroy(void* ref) {
|
void lovrColliderDestroy(void* ref) {
|
||||||
Collider* collider = ref;
|
Collider* collider = ref;
|
||||||
lovrColliderDestroyData(collider);
|
lovrColliderDestroyData(collider);
|
||||||
arr_free(&collider->shapes);
|
|
||||||
arr_free(&collider->joints);
|
arr_free(&collider->joints);
|
||||||
lovrFree(collider);
|
lovrFree(collider);
|
||||||
}
|
}
|
||||||
|
@ -477,13 +476,9 @@ void lovrColliderDestroyData(Collider* collider) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lovrColliderSetShape(collider, NULL);
|
||||||
|
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
Shape** shapes = lovrColliderGetShapes(collider, &count);
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
lovrColliderRemoveShape(collider, shapes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Joint** joints = lovrColliderGetJoints(collider, &count);
|
Joint** joints = lovrColliderGetJoints(collider, &count);
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
lovrRelease(joints[i], lovrJointDestroy);
|
lovrRelease(joints[i], lovrJointDestroy);
|
||||||
|
@ -505,6 +500,14 @@ bool lovrColliderIsDestroyed(Collider* collider) {
|
||||||
return !collider->body;
|
return !collider->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lovrColliderIsEnabled(Collider* collider) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetEnabled(Collider* collider, bool enable) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
|
void lovrColliderInitInertia(Collider* collider, Shape* shape) {
|
||||||
// compute inertia matrix for default density
|
// compute inertia matrix for default density
|
||||||
const float density = 1.0f;
|
const float density = 1.0f;
|
||||||
|
@ -521,38 +524,50 @@ Collider* lovrColliderGetNext(Collider* collider) {
|
||||||
return collider->next;
|
return collider->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrColliderAddShape(Collider* collider, Shape* shape) {
|
Shape* lovrColliderGetShape(Collider* collider) {
|
||||||
lovrRetain(shape);
|
return collider->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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrColliderRemoveShape(Collider* collider, Shape* shape) {
|
void lovrColliderSetShape(Collider* collider, Shape* shape) {
|
||||||
if (shape->collider == collider) {
|
if (collider->shape) {
|
||||||
dSpaceRemove(collider->world->space, shape->id);
|
dSpaceRemove(collider->world->space, collider->shape->id);
|
||||||
dGeomSetBody(shape->id, 0);
|
dGeomSetBody(collider->shape->id, 0);
|
||||||
shape->collider = NULL;
|
collider->shape->collider = NULL;
|
||||||
lovrRelease(shape, lovrShapeDestroy);
|
lovrRelease(collider->shape, lovrShapeDestroy);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Shape** lovrColliderGetShapes(Collider* collider, size_t* count) {
|
collider->shape = shape;
|
||||||
arr_clear(&collider->shapes);
|
|
||||||
for (dGeomID geom = dBodyGetFirstGeom(collider->body); geom; geom = dBodyGetNextGeom(geom)) {
|
if (shape) {
|
||||||
Shape* shape = dGeomGetData(geom);
|
if (shape->collider) {
|
||||||
if (shape) {
|
lovrColliderSetShape(shape->collider, NULL);
|
||||||
arr_push(&collider->shapes, shape);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, float* orientation) {
|
||||||
|
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, float* orientation) {
|
||||||
|
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) {
|
Joint** lovrColliderGetJoints(Collider* collider, size_t* count) {
|
||||||
|
@ -610,6 +625,22 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrColliderSetContinuous(Collider* collider, bool continuous) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
float lovrColliderGetGravityScale(Collider* collider) {
|
float lovrColliderGetGravityScale(Collider* collider) {
|
||||||
return dBodyGetGravityMode(collider->body) ? 1.f : 0.f;
|
return dBodyGetGravityMode(collider->body) ? 1.f : 0.f;
|
||||||
}
|
}
|
||||||
|
@ -760,6 +791,18 @@ void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
|
||||||
dBodyAddTorque(collider->body, x, y, z);
|
dBodyAddTorque(collider->body, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
|
||||||
dMass m;
|
dMass m;
|
||||||
dBodyGetMass(collider->body, &m);
|
dBodyGetMass(collider->body, &m);
|
||||||
|
@ -868,51 +911,6 @@ Collider* lovrShapeGetCollider(Shape* shape) {
|
||||||
return shape->collider;
|
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* cx, float* cy, float* cz, float* mass, float inertia[6]) {
|
||||||
dMass m;
|
dMass m;
|
||||||
dMassSetZero(&m);
|
dMassSetZero(&m);
|
||||||
|
@ -953,6 +951,8 @@ void lovrShapeGetMass(Shape* shape, float density, float* cx, float* cy, float*
|
||||||
case SHAPE_TERRAIN: {
|
case SHAPE_TERRAIN: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dReal* position = dGeomGetOffsetPosition(shape->id);
|
const dReal* position = dGeomGetOffsetPosition(shape->id);
|
||||||
|
@ -1099,19 +1099,54 @@ MeshShape* lovrMeshShapeCreate(int vertexCount, float* vertices, int indexCount,
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uint32_t depthSamples, float horizontalScale, float verticalScale) {
|
TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t n, float scaleXZ, float scaleY) {
|
||||||
const float thickness = 10.f;
|
const float thickness = 10.f;
|
||||||
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
|
TerrainShape* terrain = lovrCalloc(sizeof(TerrainShape));
|
||||||
terrain->ref = 1;
|
terrain->ref = 1;
|
||||||
dHeightfieldDataID dataID = dGeomHeightfieldDataCreate();
|
dHeightfieldDataID dataID = dGeomHeightfieldDataCreate();
|
||||||
dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, horizontalScale, horizontalScale,
|
dGeomHeightfieldDataBuildSingle(dataID, vertices, 1, scaleXZ, scaleXZ, n, n, scaleY, 0.f, thickness, 0);
|
||||||
widthSamples, depthSamples, verticalScale, 0.f, thickness, 0);
|
|
||||||
terrain->id = dCreateHeightfield(0, dataID, 1);
|
terrain->id = dCreateHeightfield(0, dataID, 1);
|
||||||
terrain->type = SHAPE_TERRAIN;
|
terrain->type = SHAPE_TERRAIN;
|
||||||
dGeomSetData(terrain->id, terrain);
|
dGeomSetData(terrain->id, terrain);
|
||||||
return terrain;
|
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 lovrCompoundShapeAddShape(CompoundShape* shape, Shape* child, float* position, float* orientation) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeReplaceShape(CompoundShape* shape, uint32_t index, Shape* child, float* position, float* orientation) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeRemoveShape(CompoundShape* shape, uint32_t index) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape* lovrCompoundShapeGetShape(CompoundShape* shape, uint32_t index) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lovrCompoundShapeGetShapeCount(CompoundShape* shape) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeGetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void lovrCompoundShapeSetShapeOffset(CompoundShape* shape, uint32_t index, float* position, float* orientation) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
void lovrJointDestroy(void* ref) {
|
void lovrJointDestroy(void* ref) {
|
||||||
Joint* joint = ref;
|
Joint* joint = ref;
|
||||||
lovrJointDestroyData(joint);
|
lovrJointDestroyData(joint);
|
||||||
|
|
Loading…
Reference in New Issue