mirror of https://github.com/bjornbytes/lovr.git
Compare commits
24 Commits
e2fdba6f24
...
5b4ee30187
Author | SHA1 | Date |
---|---|---|
bjorn | 5b4ee30187 | |
bjorn | e24ba87bb4 | |
bjorn | 23895ba8a0 | |
bjorn | 726e00cf60 | |
bjorn | dba9c28cde | |
bjorn | d2002711f0 | |
bjorn | f30f3c7944 | |
bjorn | d5b69ed135 | |
bjorn | df43f4b4b4 | |
bjorn | fd4207a40f | |
bjorn | 2880f1f6bf | |
bjorn | 0061bdb98d | |
bjorn | a7c5151200 | |
bjorn | 98a75410a3 | |
bjorn | 5312acaaf9 | |
bjorn | 9389ac0b97 | |
bjorn | 9e12c89b20 | |
bjorn | e9fe088521 | |
bjorn | 01194a80c7 | |
bjorn | ffc23497a9 | |
bjorn | d756cc2b1d | |
bjorn | 77abad4e21 | |
bjorn | 40879f383a | |
bjorn | 8596bb06a0 |
|
@ -32,13 +32,14 @@ extern const luaL_Reg lovrQuat[];
|
|||
extern const luaL_Reg lovrMat4[];
|
||||
|
||||
static LOVR_THREAD_LOCAL Pool* pool;
|
||||
static LOVR_THREAD_LOCAL int metaref[MAX_VECTOR_TYPES];
|
||||
|
||||
static struct { const char* name; lua_CFunction constructor, indexer; const luaL_Reg* api; int metaref; } lovrVectorInfo[] = {
|
||||
[V_VEC2] = { "vec2", l_lovrMathVec2, l_lovrVec2__metaindex, lovrVec2, LUA_REFNIL },
|
||||
[V_VEC3] = { "vec3", l_lovrMathVec3, l_lovrVec3__metaindex, lovrVec3, LUA_REFNIL },
|
||||
[V_VEC4] = { "vec4", l_lovrMathVec4, l_lovrVec4__metaindex, lovrVec4, LUA_REFNIL },
|
||||
[V_QUAT] = { "quat", l_lovrMathQuat, l_lovrQuat__metaindex, lovrQuat, LUA_REFNIL },
|
||||
[V_MAT4] = { "mat4", l_lovrMathMat4, l_lovrMat4__metaindex, lovrMat4, LUA_REFNIL }
|
||||
static struct { const char* name; lua_CFunction constructor, indexer; const luaL_Reg* api; } lovrVectorInfo[] = {
|
||||
[V_VEC2] = { "vec2", l_lovrMathVec2, l_lovrVec2__metaindex, lovrVec2 },
|
||||
[V_VEC3] = { "vec3", l_lovrMathVec3, l_lovrVec3__metaindex, lovrVec3 },
|
||||
[V_VEC4] = { "vec4", l_lovrMathVec4, l_lovrVec4__metaindex, lovrVec4 },
|
||||
[V_QUAT] = { "quat", l_lovrMathQuat, l_lovrQuat__metaindex, lovrQuat },
|
||||
[V_MAT4] = { "mat4", l_lovrMathMat4, l_lovrMat4__metaindex, lovrMat4 }
|
||||
};
|
||||
|
||||
static void luax_destroypool(void) {
|
||||
|
@ -78,7 +79,7 @@ float* luax_checkvector(lua_State* L, int index, VectorType type, const char* ex
|
|||
static float* luax_newvector(lua_State* L, VectorType type, size_t components) {
|
||||
VectorType* p = lua_newuserdata(L, sizeof(VectorType) + components * sizeof(float));
|
||||
*p = type;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metaref);
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, metaref[type]);
|
||||
lua_setmetatable(L, -2);
|
||||
return (float*) (p + 1);
|
||||
}
|
||||
|
@ -302,7 +303,7 @@ static int l_lovrLightUserdata__index(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metaref);
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, metaref[type]);
|
||||
lua_pushvalue(L, 2);
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isnil(L, -1)) {
|
||||
|
@ -334,7 +335,7 @@ static int l_lovrLightUserdataOp(lua_State* L) {
|
|||
return luaL_error(L, "Unsupported lightuserdata operator %q", lua_tostring(L, lua_upvalueindex(1)));
|
||||
}
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorInfo[type].metaref);
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, metaref[type]);
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_gettable(L, -2);
|
||||
lua_pushvalue(L, 1);
|
||||
|
@ -369,7 +370,7 @@ int luaopen_lovr_math(lua_State* L) {
|
|||
lua_settable(L, -4);
|
||||
|
||||
luax_register(L, lovrVectorInfo[i].api);
|
||||
lovrVectorInfo[i].metaref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
metaref[i] = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
// Global lightuserdata metatable
|
||||
|
|
|
@ -22,28 +22,70 @@ StringEntry lovrJointType[] = {
|
|||
};
|
||||
|
||||
static int l_lovrPhysicsNewWorld(lua_State* L) {
|
||||
float xg = luax_optfloat(L, 1, 0.f);
|
||||
float yg = luax_optfloat(L, 2, -9.81f);
|
||||
float zg = luax_optfloat(L, 3, 0.f);
|
||||
bool allowSleep = lua_gettop(L) < 4 || lua_toboolean(L, 4);
|
||||
const char* tags[MAX_TAGS];
|
||||
int tagCount;
|
||||
if (lua_type(L, 5) == LUA_TTABLE) {
|
||||
tagCount = luax_len(L, 5);
|
||||
lovrCheck(tagCount <= MAX_TAGS, "Max number of world tags is %d", MAX_TAGS);
|
||||
for (int i = 0; i < tagCount; i++) {
|
||||
lua_rawgeti(L, -1, i + 1);
|
||||
if (lua_isstring(L, -1)) {
|
||||
tags[i] = lua_tostring(L, -1);
|
||||
} else {
|
||||
return luaL_error(L, "World tags must be a table of strings");
|
||||
WorldInfo info = {
|
||||
.maxColliders = 65536,
|
||||
.maxColliderPairs = 65536,
|
||||
.maxContacts = 16384,
|
||||
.allowSleep = true,
|
||||
.gravity = { 0.f, -9.81f, 0.f }
|
||||
};
|
||||
|
||||
if (lua_istable(L, 1)) {
|
||||
lua_getfield(L, 1, "maxColliders");
|
||||
if (!lua_isnil(L, -1)) info.maxColliders = luax_checku32(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxColliderPairs");
|
||||
if (!lua_isnil(L, -1)) info.maxColliderPairs = luax_checku32(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "maxContacts");
|
||||
if (!lua_isnil(L, -1)) info.maxContacts = luax_checku32(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "allowSleep");
|
||||
if (!lua_isnil(L, -1)) info.allowSleep = lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "tags");
|
||||
if (!lua_isnil(L, -1)) {
|
||||
lovrCheck(lua_istable(L, -1), "World tag list should be a table");
|
||||
lovrCheck(info.tagCount <= MAX_TAGS, "Max number of world tags is %d", MAX_TAGS);
|
||||
info.tagCount = luax_len(L, 5);
|
||||
for (uint32_t i = 0; i < info.tagCount; i++) {
|
||||
lua_rawgeti(L, -1, (int) i + 1);
|
||||
if (lua_isstring(L, -1)) {
|
||||
info.tags[i] = lua_tostring(L, -1);
|
||||
} else {
|
||||
return luaL_error(L, "World tags must be a table of strings");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
tagCount = 0;
|
||||
lua_pop(L, 1);
|
||||
} else { // Deprecated
|
||||
info.gravity[0] = luax_optfloat(L, 1, 0.f);
|
||||
info.gravity[1] = luax_optfloat(L, 2, -9.81f);
|
||||
info.gravity[2] = luax_optfloat(L, 3, 0.f);
|
||||
info.allowSleep = lua_gettop(L) < 4 || lua_toboolean(L, 4);
|
||||
if (lua_type(L, 5) == LUA_TTABLE) {
|
||||
info.tagCount = luax_len(L, 5);
|
||||
lovrCheck(info.tagCount <= MAX_TAGS, "Max number of world tags is %d", MAX_TAGS);
|
||||
for (uint32_t i = 0; i < info.tagCount; i++) {
|
||||
lua_rawgeti(L, -1, (int) i + 1);
|
||||
if (lua_isstring(L, -1)) {
|
||||
info.tags[i] = lua_tostring(L, -1);
|
||||
} else {
|
||||
return luaL_error(L, "World tags must be a table of strings");
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
info.tagCount = 0;
|
||||
}
|
||||
}
|
||||
World* world = lovrWorldCreate(xg, yg, zg, allowSleep, tags, tagCount);
|
||||
|
||||
World* world = lovrWorldCreate(&info);
|
||||
luax_pushtype(L, World, world);
|
||||
lovrRelease(world, lovrWorldDestroy);
|
||||
return 1;
|
||||
|
|
|
@ -123,16 +123,17 @@ static int l_lovrColliderSetKinematic(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrColliderIsGravityIgnored(lua_State* L) {
|
||||
static int l_lovrColliderGetGravityScale(lua_State* L) {
|
||||
Collider* collider = luax_checktype(L, 1, Collider);
|
||||
lua_pushboolean(L, lovrColliderIsGravityIgnored(collider));
|
||||
float scale = lovrColliderGetGravityScale(collider);
|
||||
lua_pushnumber(L, scale);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrColliderSetGravityIgnored(lua_State* L) {
|
||||
static int l_lovrColliderSetGravityScale(lua_State* L) {
|
||||
Collider* collider = luax_checktype(L, 1, Collider);
|
||||
bool ignored = lua_toboolean(L, 2);
|
||||
lovrColliderSetGravityIgnored(collider, ignored);
|
||||
float scale = luax_checkfloat(L, 2);
|
||||
lovrColliderSetGravityScale(collider, scale);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -530,6 +531,21 @@ static int l_lovrColliderGetShapes(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
static int l_lovrColliderIsGravityIgnored(lua_State* L) {
|
||||
Collider* collider = luax_checktype(L, 1, Collider);
|
||||
lua_pushboolean(L, lovrColliderGetGravityScale(collider) == 0.f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
static int l_lovrColliderSetGravityIgnored(lua_State* L) {
|
||||
Collider* collider = luax_checktype(L, 1, Collider);
|
||||
bool ignored = lua_toboolean(L, 2);
|
||||
lovrColliderSetGravityScale(collider, ignored ? 0.f : 1.f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrCollider[] = {
|
||||
{ "destroy", l_lovrColliderDestroy },
|
||||
{ "isDestroyed", l_lovrColliderIsDestroyed },
|
||||
|
@ -543,8 +559,8 @@ const luaL_Reg lovrCollider[] = {
|
|||
{ "setUserData", l_lovrColliderSetUserData },
|
||||
{ "isKinematic", l_lovrColliderIsKinematic },
|
||||
{ "setKinematic", l_lovrColliderSetKinematic },
|
||||
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored },
|
||||
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored },
|
||||
{ "getGravityScale", l_lovrColliderGetGravityScale },
|
||||
{ "setGravityScale", l_lovrColliderSetGravityScale },
|
||||
{ "isSleepingAllowed", l_lovrColliderIsSleepingAllowed },
|
||||
{ "setSleepingAllowed", l_lovrColliderSetSleepingAllowed },
|
||||
{ "isAwake", l_lovrColliderIsAwake },
|
||||
|
@ -586,6 +602,8 @@ const luaL_Reg lovrCollider[] = {
|
|||
|
||||
// Deprecated
|
||||
{ "getShapes", l_lovrColliderGetShapes },
|
||||
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored },
|
||||
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -102,9 +102,10 @@ static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) {
|
|||
|
||||
static int l_lovrWorldNewCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
Shape* shape = luax_totype(L, 2, Shape);
|
||||
float position[3];
|
||||
luax_readvec3(L, 2, position, NULL);
|
||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||
luax_readvec3(L, 2 + !!shape, position, NULL);
|
||||
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
return 1;
|
||||
|
@ -114,9 +115,8 @@ static int l_lovrWorldNewBoxCollider(lua_State* L) {
|
|||
World* world = luax_checktype(L, 1, World);
|
||||
float position[3];
|
||||
int index = luax_readvec3(L, 2, position, NULL);
|
||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||
BoxShape* shape = luax_newboxshape(L, index);
|
||||
lovrColliderSetShape(collider, shape);
|
||||
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||
lovrColliderInitInertia(collider, shape);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
|
@ -128,9 +128,8 @@ static int l_lovrWorldNewCapsuleCollider(lua_State* L) {
|
|||
World* world = luax_checktype(L, 1, World);
|
||||
float position[3];
|
||||
int index = luax_readvec3(L, 2, position, NULL);
|
||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||
CapsuleShape* shape = luax_newcapsuleshape(L, index);
|
||||
lovrColliderSetShape(collider, shape);
|
||||
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||
lovrColliderInitInertia(collider, shape);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
|
@ -142,9 +141,8 @@ static int l_lovrWorldNewCylinderCollider(lua_State* L) {
|
|||
World* world = luax_checktype(L, 1, World);
|
||||
float position[3];
|
||||
int index = luax_readvec3(L, 2, position, NULL);
|
||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||
CylinderShape* shape = luax_newcylindershape(L, index);
|
||||
lovrColliderSetShape(collider, shape);
|
||||
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||
lovrColliderInitInertia(collider, shape);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
|
@ -156,9 +154,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
|||
World* world = luax_checktype(L, 1, World);
|
||||
float position[3];
|
||||
int index = luax_readvec3(L, 2, position, NULL);
|
||||
Collider* collider = lovrColliderCreate(world, position[0], position[1], position[2]);
|
||||
SphereShape* shape = luax_newsphereshape(L, index);
|
||||
lovrColliderSetShape(collider, shape);
|
||||
Collider* collider = lovrColliderCreate(world, shape, position[0], position[1], position[2]);
|
||||
lovrColliderInitInertia(collider, shape);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
|
@ -168,9 +165,8 @@ static int l_lovrWorldNewSphereCollider(lua_State* L) {
|
|||
|
||||
static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
|
||||
MeshShape* shape = luax_newmeshshape(L, 2);
|
||||
lovrColliderSetShape(collider, shape);
|
||||
Collider* collider = lovrColliderCreate(world, shape, 0.f, 0.f, 0.f);
|
||||
lovrColliderInitInertia(collider, shape);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
|
@ -180,9 +176,8 @@ static int l_lovrWorldNewMeshCollider(lua_State* L) {
|
|||
|
||||
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
Collider* collider = lovrColliderCreate(world, 0.f, 0.f, 0.f);
|
||||
TerrainShape* shape = luax_newterrainshape(L, 2);
|
||||
lovrColliderSetShape(collider, shape);
|
||||
Collider* collider = lovrColliderCreate(world, shape, 0.f, 0.f, 0.f);
|
||||
lovrColliderSetKinematic(collider, true);
|
||||
luax_pushtype(L, Collider, collider);
|
||||
lovrRelease(collider, lovrColliderDestroy);
|
||||
|
@ -380,11 +375,11 @@ static int l_lovrWorldQuerySphere(lua_State* L) {
|
|||
|
||||
static int l_lovrWorldGetGravity(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
float x, y, z;
|
||||
lovrWorldGetGravity(world, &x, &y, &z);
|
||||
lua_pushnumber(L, x);
|
||||
lua_pushnumber(L, y);
|
||||
lua_pushnumber(L, z);
|
||||
float gravity[3];
|
||||
lovrWorldGetGravity(world, gravity);
|
||||
lua_pushnumber(L, gravity[0]);
|
||||
lua_pushnumber(L, gravity[1]);
|
||||
lua_pushnumber(L, gravity[2]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -392,7 +387,7 @@ static int l_lovrWorldSetGravity(lua_State* L) {
|
|||
World* world = luax_checktype(L, 1, World);
|
||||
float gravity[3];
|
||||
luax_readvec3(L, 2, gravity, NULL);
|
||||
lovrWorldSetGravity(world, gravity[0], gravity[1], gravity[2]);
|
||||
lovrWorldSetGravity(world, gravity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -534,6 +529,11 @@ const luaL_Reg lovrWorld[] = {
|
|||
{ "querySphere", l_lovrWorldQuerySphere },
|
||||
{ "getGravity", l_lovrWorldGetGravity },
|
||||
{ "setGravity", l_lovrWorldSetGravity },
|
||||
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
|
||||
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
|
||||
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
|
||||
|
||||
// Deprecated
|
||||
{ "getTightness", l_lovrWorldGetTightness },
|
||||
{ "setTightness", l_lovrWorldSetTightness },
|
||||
{ "getResponseTime", l_lovrWorldGetResponseTime },
|
||||
|
@ -544,10 +544,8 @@ const luaL_Reg lovrWorld[] = {
|
|||
{ "setAngularDamping", l_lovrWorldSetAngularDamping },
|
||||
{ "isSleepingAllowed", l_lovrWorldIsSleepingAllowed },
|
||||
{ "setSleepingAllowed", l_lovrWorldSetSleepingAllowed },
|
||||
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
|
||||
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
|
||||
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
|
||||
{ "getStepCount", l_lovrWorldGetStepCount },
|
||||
{ "setStepCount", l_lovrWorldSetStepCount },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -41,12 +41,20 @@ typedef struct {
|
|||
float depth;
|
||||
} Contact;
|
||||
|
||||
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, uint32_t tagCount);
|
||||
typedef struct {
|
||||
uint32_t maxColliders;
|
||||
uint32_t maxColliderPairs;
|
||||
uint32_t maxContacts;
|
||||
bool allowSleep;
|
||||
const char* tags[MAX_TAGS];
|
||||
uint32_t tagCount;
|
||||
float gravity[3]; // Deprecated
|
||||
} WorldInfo;
|
||||
|
||||
World* lovrWorldCreate(WorldInfo* info);
|
||||
void lovrWorldDestroy(void* ref);
|
||||
void lovrWorldDestroyData(World* world);
|
||||
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata);
|
||||
int lovrWorldGetStepCount(World* world);
|
||||
void lovrWorldSetStepCount(World* world, int iterations);
|
||||
void lovrWorldComputeOverlaps(World* world);
|
||||
int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b);
|
||||
int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution);
|
||||
|
@ -55,8 +63,16 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa
|
|||
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata);
|
||||
bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata);
|
||||
Collider* lovrWorldGetFirstCollider(World* world);
|
||||
void lovrWorldGetGravity(World* world, float* x, float* y, float* z);
|
||||
void lovrWorldSetGravity(World* world, float x, float y, float z);
|
||||
void lovrWorldGetGravity(World* world, float gravity[3]);
|
||||
void lovrWorldSetGravity(World* world, float gravity[3]);
|
||||
const char* lovrWorldGetTagName(World* world, uint32_t tag);
|
||||
void lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||
void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||
bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag);
|
||||
|
||||
// Deprecated
|
||||
int lovrWorldGetStepCount(World* world);
|
||||
void lovrWorldSetStepCount(World* world, int iterations);
|
||||
float lovrWorldGetResponseTime(World* world);
|
||||
void lovrWorldSetResponseTime(World* world, float responseTime);
|
||||
float lovrWorldGetTightness(World* world);
|
||||
|
@ -67,14 +83,10 @@ void lovrWorldGetAngularDamping(World* world, float* damping, float* threshold);
|
|||
void lovrWorldSetAngularDamping(World* world, float damping, float threshold);
|
||||
bool lovrWorldIsSleepingAllowed(World* world);
|
||||
void lovrWorldSetSleepingAllowed(World* world, bool allowed);
|
||||
const char* lovrWorldGetTagName(World* world, uint32_t tag);
|
||||
void lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||
void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2);
|
||||
bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag);
|
||||
|
||||
// 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 lovrColliderDestroyData(Collider* collider);
|
||||
bool lovrColliderIsDestroyed(Collider* collider);
|
||||
|
@ -94,8 +106,8 @@ float lovrColliderGetRestitution(Collider* collider);
|
|||
void lovrColliderSetRestitution(Collider* collider, float restitution);
|
||||
bool lovrColliderIsKinematic(Collider* collider);
|
||||
void lovrColliderSetKinematic(Collider* collider, bool kinematic);
|
||||
bool lovrColliderIsGravityIgnored(Collider* collider);
|
||||
void lovrColliderSetGravityIgnored(Collider* collider, bool ignored);
|
||||
float lovrColliderGetGravityScale(Collider* collider);
|
||||
void lovrColliderSetGravityScale(Collider* collider, float scale);
|
||||
bool lovrColliderIsSleepingAllowed(Collider* collider);
|
||||
void lovrColliderSetSleepingAllowed(Collider* collider, bool allowed);
|
||||
bool lovrColliderIsAwake(Collider* collider);
|
||||
|
|
|
@ -4,24 +4,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <joltc.h>
|
||||
|
||||
#define MAX_BODIES 65535
|
||||
#define MAX_BODY_PAIRS 65535
|
||||
#define MAX_CONTACT_CONSTRAINTS 10240
|
||||
|
||||
static bool initialized = false;
|
||||
static JPH_Shape* queryBox;
|
||||
static JPH_Shape* querySphere;
|
||||
static JPH_AllHit_CastShapeCollector* cast_shape_collector;
|
||||
|
||||
struct World {
|
||||
uint32_t ref;
|
||||
JPH_PhysicsSystem* physics_system;
|
||||
JPH_BodyInterface* body_interface;
|
||||
int collision_steps;
|
||||
JPH_PhysicsSystem* system;
|
||||
JPH_BodyInterface* bodies;
|
||||
JPH_ObjectLayerPairFilter* objectLayerPairFilter;
|
||||
int collisionSteps;
|
||||
Collider* head;
|
||||
JPH_BroadPhaseLayerInterface* broad_phase_layer_interface;
|
||||
JPH_ObjectVsBroadPhaseLayerFilter* broad_phase_layer_filter;
|
||||
JPH_ObjectLayerPairFilter* object_layer_pair_filter;
|
||||
float defaultLinearDamping;
|
||||
float defaultAngularDamping;
|
||||
bool defaultIsSleepingAllowed;
|
||||
|
@ -52,6 +41,14 @@ struct Joint {
|
|||
JPH_Constraint* constraint;
|
||||
};
|
||||
|
||||
static struct {
|
||||
bool initialized;
|
||||
Shape* pointShape;
|
||||
JPH_Shape* queryBox;
|
||||
JPH_Shape* querySphere;
|
||||
JPH_AllHit_CastShapeCollector* castShapeCollector;
|
||||
} state;
|
||||
|
||||
// Broad phase and object phase layers
|
||||
#define NUM_OP_LAYERS ((MAX_TAGS + 1) * 2)
|
||||
#define NUM_BP_LAYERS 2
|
||||
|
@ -71,69 +68,72 @@ static uint32_t findTag(World* world, const char* name) {
|
|||
}
|
||||
|
||||
bool lovrPhysicsInit(void) {
|
||||
if (initialized) return false;
|
||||
if (state.initialized) return false;
|
||||
JPH_Init(32 * 1024 * 1024);
|
||||
cast_shape_collector = JPH_AllHit_CastShapeCollector_Create();
|
||||
querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f);
|
||||
const JPH_Vec3 halfExtent = { .5f, .5f, .5f };
|
||||
queryBox = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f);
|
||||
return initialized = true;
|
||||
state.pointShape = lovrSphereShapeCreate(FLT_EPSILON);
|
||||
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.castShapeCollector = JPH_AllHit_CastShapeCollector_Create();
|
||||
return state.initialized = true;
|
||||
}
|
||||
|
||||
void lovrPhysicsDestroy(void) {
|
||||
if (!initialized) return;
|
||||
if (!state.initialized) return;
|
||||
lovrRelease(state.pointShape, lovrShapeDestroy);
|
||||
JPH_Shutdown();
|
||||
initialized = false;
|
||||
state.initialized = false;
|
||||
}
|
||||
|
||||
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, uint32_t tagCount) {
|
||||
World* lovrWorldCreate(WorldInfo* info) {
|
||||
World* world = lovrCalloc(sizeof(World));
|
||||
|
||||
world->ref = 1;
|
||||
world->collision_steps = 1;
|
||||
world->collisionSteps = 1;
|
||||
world->defaultLinearDamping = .05f;
|
||||
world->defaultAngularDamping = .05f;
|
||||
world->defaultIsSleepingAllowed = true;
|
||||
world->broad_phase_layer_interface = JPH_BroadPhaseLayerInterfaceTable_Create(NUM_OP_LAYERS, NUM_BP_LAYERS);
|
||||
world->object_layer_pair_filter = JPH_ObjectLayerPairFilterTable_Create(NUM_OP_LAYERS);
|
||||
world->defaultIsSleepingAllowed = info->allowSleep;
|
||||
|
||||
JPH_BroadPhaseLayerInterface* broadPhaseLayerInterface = JPH_BroadPhaseLayerInterfaceTable_Create(NUM_OP_LAYERS, NUM_BP_LAYERS);
|
||||
world->objectLayerPairFilter = JPH_ObjectLayerPairFilterTable_Create(NUM_OP_LAYERS);
|
||||
for (uint32_t i = 0; i < NUM_OP_LAYERS; i++) {
|
||||
for (uint32_t j = i; j < NUM_OP_LAYERS; j++) {
|
||||
JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(world->broad_phase_layer_interface, i, i % 2);
|
||||
JPH_BroadPhaseLayerInterfaceTable_MapObjectToBroadPhaseLayer(broadPhaseLayerInterface, i, i % 2);
|
||||
if (i % 2 == 0 && j % 2 == 0) {
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, i, j);
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, i, j);
|
||||
} else {
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, i, j);
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
world->broad_phase_layer_filter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
|
||||
world->broad_phase_layer_interface, NUM_BP_LAYERS,
|
||||
world->object_layer_pair_filter, NUM_OP_LAYERS);
|
||||
JPH_ObjectVsBroadPhaseLayerFilter* broadPhaseLayerFilter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
|
||||
broadPhaseLayerInterface, NUM_BP_LAYERS,
|
||||
world->objectLayerPairFilter, NUM_OP_LAYERS);
|
||||
|
||||
JPH_PhysicsSystemSettings settings = {
|
||||
.maxBodies = MAX_BODIES,
|
||||
.maxBodyPairs = MAX_BODY_PAIRS,
|
||||
.maxContactConstraints = MAX_CONTACT_CONSTRAINTS,
|
||||
.broadPhaseLayerInterface = world->broad_phase_layer_interface,
|
||||
.objectLayerPairFilter = world->object_layer_pair_filter,
|
||||
.objectVsBroadPhaseLayerFilter = world->broad_phase_layer_filter
|
||||
.maxBodies = info->maxColliders,
|
||||
.maxBodyPairs = info->maxColliderPairs,
|
||||
.maxContactConstraints = info->maxContacts,
|
||||
.broadPhaseLayerInterface = broadPhaseLayerInterface,
|
||||
.objectLayerPairFilter = world->objectLayerPairFilter,
|
||||
.objectVsBroadPhaseLayerFilter = broadPhaseLayerFilter
|
||||
};
|
||||
world->physics_system = JPH_PhysicsSystem_Create(&settings);
|
||||
world->body_interface = JPH_PhysicsSystem_GetBodyInterface(world->physics_system);
|
||||
world->system = JPH_PhysicsSystem_Create(&settings);
|
||||
world->bodies = JPH_PhysicsSystem_GetBodyInterface(world->system);
|
||||
|
||||
lovrWorldSetGravity(world, xg, yg, zg);
|
||||
for (uint32_t i = 0; i < tagCount; i++) {
|
||||
size_t size = strlen(tags[i]) + 1;
|
||||
lovrWorldSetGravity(world, info->gravity);
|
||||
|
||||
for (uint32_t i = 0; i < info->tagCount; i++) {
|
||||
size_t size = strlen(info->tags[i]) + 1;
|
||||
world->tags[i] = lovrMalloc(size);
|
||||
memcpy(world->tags[i], tags[i], size);
|
||||
memcpy(world->tags[i], info->tags[i], size);
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
void lovrWorldDestroy(void* ref) {
|
||||
World* world = ref;
|
||||
lovrWorldDestroyData(world);
|
||||
// todo: free up overlaps/contacts (once their allocation is implemented)
|
||||
for (uint32_t i = 0; i < MAX_TAGS - 1 && world->tags[i]; i++) {
|
||||
lovrFree(world->tags[i]);
|
||||
}
|
||||
|
@ -146,20 +146,11 @@ void lovrWorldDestroyData(World* world) {
|
|||
lovrColliderDestroyData(world->head);
|
||||
world->head = next;
|
||||
}
|
||||
JPH_PhysicsSystem_Destroy(world->physics_system);
|
||||
JPH_PhysicsSystem_Destroy(world->system);
|
||||
}
|
||||
|
||||
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata) {
|
||||
JPH_PhysicsSystem_Step(world->physics_system, dt, world->collision_steps);
|
||||
}
|
||||
|
||||
int lovrWorldGetStepCount(World* world) {
|
||||
return world->collision_steps;
|
||||
}
|
||||
|
||||
void lovrWorldSetStepCount(World* world, int iterations) {
|
||||
// todo: with too big count JobSystemThreadPool.cpp:124: (false) No jobs available!
|
||||
world->collision_steps = iterations;
|
||||
JPH_PhysicsSystem_Step(world->system, dt, world->collisionSteps);
|
||||
}
|
||||
|
||||
void lovrWorldComputeOverlaps(World* world) {
|
||||
|
@ -179,7 +170,7 @@ void lovrWorldGetContacts(World* world, Shape* a, Shape* b, Contact contacts[MAX
|
|||
}
|
||||
|
||||
void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, float y2, float z2, RaycastCallback callback, void* userdata) {
|
||||
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->physics_system);
|
||||
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system);
|
||||
const JPH_RVec3 origin = { x1, y1, z1 };
|
||||
const JPH_Vec3 direction = { x2 - x1, y2 - y1, z2 - z1 };
|
||||
JPH_AllHit_CastRayCollector* collector = JPH_AllHit_CastRayCollector_Create();
|
||||
|
@ -189,7 +180,7 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa
|
|||
JPH_RayCastResult* hits = JPH_AllHit_CastRayCollector_GetHits(collector, &count);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->body_interface, hits[i].bodyID);
|
||||
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, hits[i].bodyID);
|
||||
|
||||
uint32_t shape = 0;
|
||||
if (collider->shape->type == SHAPE_COMPOUND) {
|
||||
|
@ -224,16 +215,16 @@ static bool lovrWorldQueryShape(World* world, JPH_Shape* shape, float position[3
|
|||
|
||||
JPH_Vec3 direction = { 0.f, 0.f, 0.f };
|
||||
JPH_RVec3 base_offset = { 0.f, 0.f, 0.f };
|
||||
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->physics_system);
|
||||
JPH_AllHit_CastShapeCollector_Reset(cast_shape_collector);
|
||||
JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, cast_shape_collector);
|
||||
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system);
|
||||
JPH_AllHit_CastShapeCollector_Reset(state.castShapeCollector);
|
||||
JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, state.castShapeCollector);
|
||||
|
||||
size_t count;
|
||||
JPH_AllHit_CastShapeCollector_GetHits(cast_shape_collector, &count);
|
||||
JPH_AllHit_CastShapeCollector_GetHits(state.castShapeCollector, &count);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(cast_shape_collector, i);
|
||||
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->body_interface, id);
|
||||
JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(state.castShapeCollector, i);
|
||||
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(world->bodies, id);
|
||||
|
||||
if (callback(collider, 0, userdata)) {
|
||||
break;
|
||||
|
@ -244,81 +235,26 @@ static bool lovrWorldQueryShape(World* world, JPH_Shape* shape, float position[3
|
|||
}
|
||||
|
||||
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata) {
|
||||
return lovrWorldQueryShape(world, queryBox, position, size, callback, userdata);
|
||||
return lovrWorldQueryShape(world, state.queryBox, position, size, callback, userdata);
|
||||
}
|
||||
|
||||
bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata) {
|
||||
float scale[3] = {radius, radius, radius};
|
||||
return lovrWorldQueryShape(world, querySphere, position, scale, callback, userdata);
|
||||
float scale[3] = { radius, radius, radius };
|
||||
return lovrWorldQueryShape(world, state.querySphere, position, scale, callback, userdata);
|
||||
}
|
||||
|
||||
Collider* lovrWorldGetFirstCollider(World* world) {
|
||||
return world->head;
|
||||
}
|
||||
|
||||
void lovrWorldGetGravity(World* world, float* x, float* y, float* z) {
|
||||
JPH_Vec3 gravity;
|
||||
JPH_PhysicsSystem_GetGravity(world->physics_system, &gravity);
|
||||
*x = gravity.x;
|
||||
*y = gravity.y;
|
||||
*z = gravity.z;
|
||||
void lovrWorldGetGravity(World* world, float gravity[3]) {
|
||||
JPH_Vec3 g;
|
||||
JPH_PhysicsSystem_GetGravity(world->system, &g);
|
||||
vec3_init(gravity, &g.x);
|
||||
}
|
||||
|
||||
void lovrWorldSetGravity(World* world, float x, float y, float z) {
|
||||
const JPH_Vec3 gravity = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.z = z
|
||||
};
|
||||
JPH_PhysicsSystem_SetGravity(world->physics_system, &gravity);
|
||||
}
|
||||
|
||||
float lovrWorldGetResponseTime(World* world) {
|
||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support global ResponseTime option");
|
||||
}
|
||||
|
||||
void lovrWorldSetResponseTime(World* world, float responseTime) {
|
||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support global ResponseTime option");
|
||||
}
|
||||
|
||||
float lovrWorldGetTightness(World* world) {
|
||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support Tightness option");
|
||||
}
|
||||
|
||||
void lovrWorldSetTightness(World* world, float tightness) {
|
||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support Tightness option");
|
||||
}
|
||||
|
||||
void lovrWorldGetLinearDamping(World* world, float* damping, float* threshold) {
|
||||
*damping = world->defaultLinearDamping;
|
||||
*threshold = 0.f;
|
||||
}
|
||||
|
||||
void lovrWorldSetLinearDamping(World* world, float damping, float threshold) {
|
||||
world->defaultLinearDamping = damping;
|
||||
if (threshold != 0.f) {
|
||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support LinearDamping threshold");
|
||||
}
|
||||
}
|
||||
|
||||
void lovrWorldGetAngularDamping(World* world, float* damping, float* threshold) {
|
||||
*damping = world->defaultAngularDamping;
|
||||
*threshold = 0.f;
|
||||
}
|
||||
|
||||
void lovrWorldSetAngularDamping(World* world, float damping, float threshold) {
|
||||
world->defaultAngularDamping = damping;
|
||||
if (threshold != 0.f) {
|
||||
lovrLog(LOG_WARN, "PHY", "Jolt doesn't support AngularDamping threshold");
|
||||
}
|
||||
}
|
||||
|
||||
bool lovrWorldIsSleepingAllowed(World* world) {
|
||||
return world->defaultIsSleepingAllowed;
|
||||
}
|
||||
|
||||
void lovrWorldSetSleepingAllowed(World* world, bool allowed) {
|
||||
world->defaultIsSleepingAllowed = allowed;
|
||||
void lovrWorldSetGravity(World* world, float gravity[3]) {
|
||||
JPH_PhysicsSystem_SetGravity(world->system, &(const JPH_Vec3) { gravity[0], gravity[1], gravity[2] });
|
||||
}
|
||||
|
||||
const char* lovrWorldGetTagName(World* world, uint32_t tag) {
|
||||
|
@ -335,9 +271,9 @@ void lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char
|
|||
uint32_t jStatic = j * 2;
|
||||
uint32_t iDynamic = i * 2 + 1;
|
||||
uint32_t jDynamic = j * 2 + 1;
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, iDynamic, jDynamic);
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, iDynamic, jStatic);
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, iStatic, jDynamic);
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, iDynamic, jDynamic);
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, iDynamic, jStatic);
|
||||
JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, iStatic, jDynamic);
|
||||
}
|
||||
|
||||
void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2) {
|
||||
|
@ -350,9 +286,9 @@ void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char*
|
|||
uint32_t jStatic = j * 2;
|
||||
uint32_t iDynamic = i * 2 + 1;
|
||||
uint32_t jDynamic = j * 2 + 1;
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, iDynamic, jDynamic);
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, iDynamic, jStatic);
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, iStatic, jDynamic);
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, iDynamic, jDynamic);
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, iDynamic, jStatic);
|
||||
JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, iStatic, jDynamic);
|
||||
}
|
||||
|
||||
bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag2) {
|
||||
|
@ -363,28 +299,47 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
|
|||
}
|
||||
uint32_t iDynamic = i * 2 + 1;
|
||||
uint32_t jDynamic = j * 2 + 1;
|
||||
return JPH_ObjectLayerPairFilterTable_ShouldCollide(world->object_layer_pair_filter, iDynamic, jDynamic);
|
||||
return JPH_ObjectLayerPairFilterTable_ShouldCollide(world->objectLayerPairFilter, iDynamic, jDynamic);
|
||||
}
|
||||
|
||||
Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
||||
// Deprecated
|
||||
int lovrWorldGetStepCount(World* world) { return world->collisionSteps; }
|
||||
void lovrWorldSetStepCount(World* world, int iterations) { world->collisionSteps = iterations;}
|
||||
float lovrWorldGetResponseTime(World* world) {}
|
||||
void lovrWorldSetResponseTime(World* world, float responseTime) {}
|
||||
float lovrWorldGetTightness(World* world) {}
|
||||
void lovrWorldSetTightness(World* world, float tightness) {}
|
||||
bool lovrWorldIsSleepingAllowed(World* world) { return world->defaultIsSleepingAllowed; }
|
||||
void lovrWorldSetSleepingAllowed(World* world, bool allowed) { world->defaultIsSleepingAllowed = allowed; }
|
||||
void lovrWorldGetLinearDamping(World* world, float* damping, float* threshold) { *damping = world->defaultLinearDamping, *threshold = 0.f; }
|
||||
void lovrWorldSetLinearDamping(World* world, float damping, float threshold) { world->defaultLinearDamping = damping; }
|
||||
void lovrWorldGetAngularDamping(World* world, float* damping, float* threshold) { *damping = world->defaultAngularDamping, *threshold = 0.f; }
|
||||
void lovrWorldSetAngularDamping(World* world, float damping, float threshold) { world->defaultAngularDamping = damping; }
|
||||
|
||||
// Collider
|
||||
|
||||
Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z) {
|
||||
if (!shape) shape = state.pointShape;
|
||||
|
||||
// todo: crashes when too many are added
|
||||
Collider* collider = lovrCalloc(sizeof(Collider));
|
||||
collider->ref = 1;
|
||||
collider->world = world;
|
||||
collider->shape = shape;
|
||||
collider->tag = UNTAGGED;
|
||||
JPH_MotionType motionType = JPH_MotionType_Dynamic;
|
||||
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
|
||||
|
||||
const JPH_RVec3 position = { .x = x, .y = y, .z = z };
|
||||
const JPH_Quat rotation = { .x = 0.f, .y = 0.f, .z = 0.f, .w = 1.f };
|
||||
// todo: a placeholder querySphere shape is used in collider, then replaced in lovrColliderAddShape
|
||||
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(
|
||||
querySphere, &position, &rotation, motionType, objectLayer);
|
||||
collider->body = JPH_BodyInterface_CreateBody(world->body_interface, settings);
|
||||
JPH_BodyCreationSettings_Destroy(settings);
|
||||
const JPH_RVec3 position = { x, y, z };
|
||||
const JPH_Quat rotation = { 0.f, 0.f, 0.f, 1.f };
|
||||
JPH_MotionType type = JPH_MotionType_Dynamic;
|
||||
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
|
||||
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(shape->shape, &position, &rotation, type, objectLayer);
|
||||
collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings);
|
||||
collider->id = JPH_Body_GetID(collider->body);
|
||||
JPH_BodyInterface_AddBody(world->body_interface, collider->id, JPH_Activation_Activate);
|
||||
JPH_BodyInterface_SetUserData(world->body_interface, collider->id, (uint64_t) collider);
|
||||
JPH_BodyCreationSettings_Destroy(settings);
|
||||
|
||||
JPH_BodyInterface_AddBody(world->bodies, collider->id, JPH_Activation_Activate);
|
||||
JPH_BodyInterface_SetUserData(world->bodies, collider->id, (uint64_t) collider);
|
||||
|
||||
lovrColliderSetLinearDamping(collider, world->defaultLinearDamping, 0.f);
|
||||
lovrColliderSetAngularDamping(collider, world->defaultAngularDamping, 0.f);
|
||||
lovrColliderSetSleepingAllowed(collider, world->defaultIsSleepingAllowed);
|
||||
|
@ -400,8 +355,8 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
|||
world->head = collider;
|
||||
}
|
||||
|
||||
// The world owns a reference to the collider
|
||||
lovrRetain(collider);
|
||||
lovrRetain(collider->shape);
|
||||
lovrRetain(collider); // The world owns a reference to the collider
|
||||
return collider;
|
||||
}
|
||||
|
||||
|
@ -425,7 +380,7 @@ void lovrColliderDestroyData(Collider* collider) {
|
|||
lovrRelease(joints[i], lovrJointDestroy);
|
||||
}
|
||||
|
||||
JPH_BodyInterface_RemoveBody(collider->world->body_interface, collider->id);
|
||||
JPH_BodyInterface_RemoveBody(collider->world->bodies, collider->id);
|
||||
collider->body = NULL;
|
||||
|
||||
if (collider->next) collider->next->prev = collider->prev;
|
||||
|
@ -454,27 +409,40 @@ Collider* lovrColliderGetNext(Collider* collider) {
|
|||
}
|
||||
|
||||
Shape* lovrColliderGetShape(Collider* collider) {
|
||||
return collider->shape;
|
||||
return collider->shape == state.pointShape ? NULL : collider->shape;
|
||||
}
|
||||
|
||||
void lovrColliderSetShape(Collider* collider, Shape* shape) {
|
||||
if (shape != collider->shape) {
|
||||
lovrRelease(collider->shape, lovrShapeDestroy);
|
||||
collider->shape = shape;
|
||||
lovrRetain(shape);
|
||||
shape = shape ? shape : state.pointShape;
|
||||
|
||||
bool updateMass = true;
|
||||
if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) {
|
||||
lovrColliderSetKinematic(collider, true);
|
||||
updateMass = false;
|
||||
}
|
||||
if (shape == collider->shape) {
|
||||
return;
|
||||
}
|
||||
|
||||
JPH_BodyInterface_SetShape(collider->world->body_interface, collider->id, shape->shape, updateMass, JPH_Activation_Activate);
|
||||
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);
|
||||
|
||||
bool updateMass = true;
|
||||
if (shape->type == SHAPE_MESH || shape->type == SHAPE_TERRAIN) {
|
||||
lovrColliderSetKinematic(collider, true);
|
||||
updateMass = false;
|
||||
}
|
||||
|
||||
JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, updateMass, JPH_Activation_Activate);
|
||||
|
||||
if (hasOffset) {
|
||||
lovrColliderSetShapeOffset(collider, position, orientation);
|
||||
}
|
||||
}
|
||||
|
||||
void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orientation) {
|
||||
const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id);
|
||||
const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->bodies, collider->id);
|
||||
|
||||
if (JPH_Shape_GetSubType(shape) == JPH_ShapeSubType_RotatedTranslated) {
|
||||
JPH_Vec3 jposition;
|
||||
|
@ -490,7 +458,7 @@ void lovrColliderGetShapeOffset(Collider* collider, float* position, float* orie
|
|||
}
|
||||
|
||||
void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orientation) {
|
||||
const JPH_Shape* shape = JPH_BodyInterface_GetShape(collider->world->body_interface, collider->id);
|
||||
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);
|
||||
|
@ -499,8 +467,8 @@ void lovrColliderSetShapeOffset(Collider* collider, float* position, float* orie
|
|||
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->type == SHAPE_MESH || collider->shape->type == SHAPE_TERRAIN;
|
||||
JPH_BodyInterface_SetShape(collider->world->body_interface, collider->id, shape, updateMass, JPH_Activation_Activate);
|
||||
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) {
|
||||
|
@ -523,59 +491,56 @@ bool lovrColliderSetTag(Collider* collider, const char* tag) {
|
|||
}
|
||||
bool kinematic = lovrColliderIsKinematic(collider);
|
||||
JPH_ObjectLayer objectLayer = collider->tag * 2 + (kinematic ? 0 : 1);
|
||||
JPH_BodyInterface_SetObjectLayer(collider->world->body_interface, collider->id, objectLayer);
|
||||
JPH_BodyInterface_SetObjectLayer(collider->world->bodies, collider->id, objectLayer);
|
||||
return true;
|
||||
}
|
||||
|
||||
float lovrColliderGetFriction(Collider* collider) {
|
||||
return JPH_BodyInterface_GetFriction(collider->world->body_interface, collider->id);
|
||||
return JPH_BodyInterface_GetFriction(collider->world->bodies, collider->id);
|
||||
}
|
||||
|
||||
void lovrColliderSetFriction(Collider* collider, float friction) {
|
||||
JPH_BodyInterface_SetFriction(collider->world->body_interface, collider->id, friction);
|
||||
JPH_BodyInterface_SetFriction(collider->world->bodies, collider->id, friction);
|
||||
}
|
||||
|
||||
float lovrColliderGetRestitution(Collider* collider) {
|
||||
return JPH_BodyInterface_GetRestitution(collider->world->body_interface, collider->id);
|
||||
return JPH_BodyInterface_GetRestitution(collider->world->bodies, collider->id);
|
||||
}
|
||||
|
||||
void lovrColliderSetRestitution(Collider* collider, float restitution) {
|
||||
JPH_BodyInterface_SetRestitution(collider->world->body_interface, collider->id, restitution);
|
||||
JPH_BodyInterface_SetRestitution(collider->world->bodies, collider->id, restitution);
|
||||
}
|
||||
|
||||
bool lovrColliderIsKinematic(Collider* collider) {
|
||||
JPH_ObjectLayer objectLayer = JPH_BodyInterface_GetObjectLayer(collider->world->body_interface, collider->id);
|
||||
JPH_ObjectLayer objectLayer = JPH_BodyInterface_GetObjectLayer(collider->world->bodies, collider->id);
|
||||
return objectLayer % 2 == 0;
|
||||
}
|
||||
|
||||
void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
|
||||
JPH_ObjectLayer objectLayer = collider->tag * 2 + (kinematic ? 0 : 1);
|
||||
JPH_BodyInterface_SetObjectLayer(collider->world->body_interface, collider->id, objectLayer);
|
||||
JPH_BodyInterface_SetObjectLayer(collider->world->bodies, collider->id, objectLayer);
|
||||
if (kinematic) {
|
||||
JPH_BodyInterface_DeactivateBody(collider->world->body_interface, collider->id);
|
||||
JPH_BodyInterface_DeactivateBody(collider->world->bodies, collider->id);
|
||||
JPH_BodyInterface_SetMotionType(
|
||||
collider->world->body_interface,
|
||||
collider->world->bodies,
|
||||
collider->id,
|
||||
JPH_MotionType_Kinematic,
|
||||
JPH_Activation_DontActivate);
|
||||
} else {
|
||||
JPH_BodyInterface_SetMotionType(
|
||||
collider->world->body_interface,
|
||||
collider->world->bodies,
|
||||
collider->id,
|
||||
JPH_MotionType_Dynamic,
|
||||
JPH_Activation_Activate);
|
||||
}
|
||||
}
|
||||
|
||||
bool lovrColliderIsGravityIgnored(Collider* collider) {
|
||||
return JPH_BodyInterface_GetGravityFactor(collider->world->body_interface, collider->id) == 0.f;
|
||||
float lovrColliderGetGravityScale(Collider* collider) {
|
||||
return JPH_BodyInterface_GetGravityFactor(collider->world->bodies, collider->id);
|
||||
}
|
||||
|
||||
void lovrColliderSetGravityIgnored(Collider* collider, bool ignored) {
|
||||
JPH_BodyInterface_SetGravityFactor(
|
||||
collider->world->body_interface,
|
||||
collider->id,
|
||||
ignored ? 0.f : 1.f);
|
||||
void lovrColliderSetGravityScale(Collider* collider, float scale) {
|
||||
return JPH_BodyInterface_SetGravityFactor(collider->world->bodies, collider->id, scale);
|
||||
}
|
||||
|
||||
bool lovrColliderIsSleepingAllowed(Collider* collider) {
|
||||
|
@ -587,32 +552,29 @@ void lovrColliderSetSleepingAllowed(Collider* collider, bool allowed) {
|
|||
}
|
||||
|
||||
bool lovrColliderIsAwake(Collider* collider) {
|
||||
return JPH_BodyInterface_IsActive(collider->world->body_interface, collider->id);
|
||||
return JPH_BodyInterface_IsActive(collider->world->bodies, collider->id);
|
||||
}
|
||||
|
||||
void lovrColliderSetAwake(Collider* collider, bool awake) {
|
||||
if (awake) {
|
||||
JPH_BodyInterface_ActivateBody(collider->world->body_interface, collider->id);
|
||||
JPH_BodyInterface_ActivateBody(collider->world->bodies, collider->id);
|
||||
} else {
|
||||
JPH_BodyInterface_DeactivateBody(collider->world->body_interface, collider->id);
|
||||
JPH_BodyInterface_DeactivateBody(collider->world->bodies, collider->id);
|
||||
}
|
||||
}
|
||||
|
||||
float lovrColliderGetMass(Collider* collider) {
|
||||
if (!collider->shape) return 0.f;
|
||||
JPH_MotionProperties* motion_properties = JPH_Body_GetMotionProperties(collider->body);
|
||||
return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motion_properties);
|
||||
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
|
||||
return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties);
|
||||
}
|
||||
|
||||
void lovrColliderSetMass(Collider* collider, float mass) {
|
||||
if (collider->shape) {
|
||||
JPH_MotionProperties* motion_properties = JPH_Body_GetMotionProperties(collider->body);
|
||||
Shape* shape = collider->shape;
|
||||
JPH_MassProperties* mass_properties;
|
||||
JPH_Shape_GetMassProperties(shape->shape, mass_properties);
|
||||
JPH_MassProperties_ScaleToMass(mass_properties, mass);
|
||||
JPH_MotionProperties_SetMassProperties(motion_properties, JPH_AllowedDOFs_All, mass_properties);
|
||||
}
|
||||
JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
|
||||
Shape* shape = collider->shape;
|
||||
JPH_MassProperties* massProperties;
|
||||
JPH_Shape_GetMassProperties(shape->shape, massProperties);
|
||||
JPH_MassProperties_ScaleToMass(massProperties, mass);
|
||||
JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties);
|
||||
}
|
||||
|
||||
void lovrColliderGetMassData(Collider* collider, float* cx, float* cy, float* cz, float* mass, float inertia[6]) {
|
||||
|
@ -633,7 +595,7 @@ void lovrColliderGetPosition(Collider* collider, float* x, float* y, float* z) {
|
|||
|
||||
void lovrColliderSetPosition(Collider* collider, float x, float y, float z) {
|
||||
JPH_RVec3 position = { x, y, z };
|
||||
JPH_BodyInterface_SetPosition(collider->world->body_interface, collider->id, &position, JPH_Activation_Activate);
|
||||
JPH_BodyInterface_SetPosition(collider->world->bodies, collider->id, &position, JPH_Activation_Activate);
|
||||
}
|
||||
|
||||
void lovrColliderGetOrientation(Collider* collider, float* orientation) {
|
||||
|
@ -653,7 +615,7 @@ void lovrColliderSetOrientation(Collider* collider, float* orientation) {
|
|||
.w = orientation[3]
|
||||
};
|
||||
JPH_BodyInterface_SetRotation(
|
||||
collider->world->body_interface,
|
||||
collider->world->bodies,
|
||||
collider->id,
|
||||
&rotation,
|
||||
JPH_Activation_Activate);
|
||||
|
@ -661,7 +623,7 @@ void lovrColliderSetOrientation(Collider* collider, float* orientation) {
|
|||
|
||||
void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float* z) {
|
||||
JPH_Vec3 velocity;
|
||||
JPH_BodyInterface_GetLinearVelocity(collider->world->body_interface, collider->id, &velocity);
|
||||
JPH_BodyInterface_GetLinearVelocity(collider->world->bodies, collider->id, &velocity);
|
||||
*x = velocity.x;
|
||||
*y = velocity.y;
|
||||
*z = velocity.z;
|
||||
|
@ -669,12 +631,12 @@ void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float
|
|||
|
||||
void lovrColliderSetLinearVelocity(Collider* collider, float x, float y, float z) {
|
||||
const JPH_Vec3 velocity = { x, y, z };
|
||||
JPH_BodyInterface_SetLinearVelocity(collider->world->body_interface, collider->id, &velocity);
|
||||
JPH_BodyInterface_SetLinearVelocity(collider->world->bodies, collider->id, &velocity);
|
||||
}
|
||||
|
||||
void lovrColliderGetAngularVelocity(Collider* collider, float* x, float* y, float* z) {
|
||||
JPH_Vec3 velocity;
|
||||
JPH_BodyInterface_GetAngularVelocity(collider->world->body_interface, collider->id, &velocity);
|
||||
JPH_BodyInterface_GetAngularVelocity(collider->world->bodies, collider->id, &velocity);
|
||||
*x = velocity.x;
|
||||
*y = velocity.y;
|
||||
*z = velocity.z;
|
||||
|
@ -682,7 +644,7 @@ void lovrColliderGetAngularVelocity(Collider* collider, float* x, float* y, floa
|
|||
|
||||
void lovrColliderSetAngularVelocity(Collider* collider, float x, float y, float z) {
|
||||
JPH_Vec3 velocity = { x, y, z };
|
||||
JPH_BodyInterface_SetAngularVelocity(collider->world->body_interface, collider->id, &velocity);
|
||||
JPH_BodyInterface_SetAngularVelocity(collider->world->bodies, collider->id, &velocity);
|
||||
}
|
||||
|
||||
void lovrColliderGetLinearDamping(Collider* collider, float* damping, float* threshold) {
|
||||
|
@ -715,18 +677,18 @@ void lovrColliderSetAngularDamping(Collider* collider, float damping, float thre
|
|||
|
||||
void lovrColliderApplyForce(Collider* collider, float x, float y, float z) {
|
||||
JPH_Vec3 force = { x, y, z };
|
||||
JPH_BodyInterface_AddForce(collider->world->body_interface, collider->id, &force);
|
||||
JPH_BodyInterface_AddForce(collider->world->bodies, collider->id, &force);
|
||||
}
|
||||
|
||||
void lovrColliderApplyForceAtPosition(Collider* collider, float x, float y, float z, float cx, float cy, float cz) {
|
||||
JPH_Vec3 force = { x, y, z };
|
||||
JPH_RVec3 position = { cx, cy, cz };
|
||||
JPH_BodyInterface_AddForce2(collider->world->body_interface, collider->id, &force, &position);
|
||||
JPH_BodyInterface_AddForce2(collider->world->bodies, collider->id, &force, &position);
|
||||
}
|
||||
|
||||
void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
|
||||
JPH_Vec3 torque = { x, y, z };
|
||||
JPH_BodyInterface_AddTorque(collider->world->body_interface, collider->id, &torque);
|
||||
JPH_BodyInterface_AddTorque(collider->world->bodies, collider->id, &torque);
|
||||
}
|
||||
|
||||
void lovrColliderGetLocalCenter(Collider* collider, float* x, float* y, float* z) {
|
||||
|
@ -791,7 +753,7 @@ void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float x, fl
|
|||
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float wx, float wy, float wz, float* vx, float* vy, float* vz) {
|
||||
JPH_RVec3 point = { wx, wy, wz };
|
||||
JPH_Vec3 velocity;
|
||||
JPH_BodyInterface_GetPointVelocity(collider->world->body_interface, collider->id, &point, &velocity);
|
||||
JPH_BodyInterface_GetPointVelocity(collider->world->bodies, collider->id, &point, &velocity);
|
||||
*vx = velocity.x;
|
||||
*vy = velocity.y;
|
||||
*vz = velocity.z;
|
||||
|
@ -879,11 +841,7 @@ BoxShape* lovrBoxShapeCreate(float w, float h, float d) {
|
|||
BoxShape* box = lovrCalloc(sizeof(BoxShape));
|
||||
box->ref = 1;
|
||||
box->type = SHAPE_BOX;
|
||||
const JPH_Vec3 halfExtent = {
|
||||
.x = w / 2,
|
||||
.y = h / 2,
|
||||
.z = d / 2
|
||||
};
|
||||
const JPH_Vec3 halfExtent = { w / 2.f, h / 2.f, d / 2.f };
|
||||
box->shape = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f);
|
||||
JPH_Shape_SetUserData(box->shape, (uint64_t) (uintptr_t) box);
|
||||
return box;
|
||||
|
@ -968,9 +926,9 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uin
|
|||
terrain->ref = 1;
|
||||
terrain->type = SHAPE_TERRAIN;
|
||||
const JPH_Vec3 offset = {
|
||||
.x = -0.5f * horizontalScale,
|
||||
.x = -.5f * horizontalScale,
|
||||
.y = 0.f,
|
||||
.z = -0.5f * horizontalScale
|
||||
.z = -.5f * horizontalScale
|
||||
};
|
||||
const JPH_Vec3 scale = {
|
||||
.x = horizontalScale / widthSamples,
|
||||
|
@ -1093,26 +1051,14 @@ void lovrJointGetAnchors(Joint* joint, float anchor1[3], float anchor2[3]) {
|
|||
JPH_Matrix4x4 constraintToBody2;
|
||||
JPH_TwoBodyConstraint_GetConstraintToBody1Matrix((JPH_TwoBodyConstraint*) joint->constraint, &constraintToBody1);
|
||||
JPH_TwoBodyConstraint_GetConstraintToBody2Matrix((JPH_TwoBodyConstraint*) joint->constraint, &constraintToBody2);
|
||||
float translation1[4] = {
|
||||
constraintToBody1.m41,
|
||||
constraintToBody1.m42,
|
||||
constraintToBody1.m43,
|
||||
constraintToBody1.m44
|
||||
};
|
||||
float translation2[4] = {
|
||||
constraintToBody2.m41,
|
||||
constraintToBody2.m42,
|
||||
constraintToBody2.m43,
|
||||
constraintToBody2.m44
|
||||
};
|
||||
mat4_mulVec4(¢erOfMassTransform1.m11, translation1);
|
||||
mat4_mulVec4(¢erOfMassTransform2.m11, translation2);
|
||||
anchor1[0] = translation1[0];
|
||||
anchor1[1] = translation1[1];
|
||||
anchor1[2] = translation1[2];
|
||||
anchor2[0] = translation2[0];
|
||||
anchor2[1] = translation2[1];
|
||||
anchor2[2] = translation2[2];
|
||||
mat4_mulVec4(¢erOfMassTransform1.m11, &constraintToBody1.m41);
|
||||
mat4_mulVec4(¢erOfMassTransform2.m11, &constraintToBody2.m41);
|
||||
anchor1[0] = constraintToBody1.m41;
|
||||
anchor1[1] = constraintToBody1.m42;
|
||||
anchor1[2] = constraintToBody1.m43;
|
||||
anchor2[0] = constraintToBody2.m41;
|
||||
anchor2[1] = constraintToBody2.m42;
|
||||
anchor2[2] = constraintToBody2.m43;
|
||||
}
|
||||
|
||||
void lovrJointDestroy(void* ref) {
|
||||
|
@ -1122,13 +1068,15 @@ void lovrJointDestroy(void* ref) {
|
|||
}
|
||||
|
||||
void lovrJointDestroyData(Joint* joint) {
|
||||
if (!joint->constraint)
|
||||
if (!joint->constraint) {
|
||||
return;
|
||||
JPH_PhysicsSystem* physics_system;
|
||||
}
|
||||
|
||||
JPH_PhysicsSystem* system;
|
||||
JPH_Body* bodyA = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*) joint->constraint);
|
||||
if (bodyA) {
|
||||
Collider* collider = (Collider*) JPH_Body_GetUserData(bodyA);
|
||||
physics_system = collider->world->physics_system;
|
||||
system = collider->world->system;
|
||||
for (size_t i = 0; i < collider->joints.length; i++) {
|
||||
if (collider->joints.data[i] == joint) {
|
||||
arr_splice(&collider->joints, i, 1);
|
||||
|
@ -1147,8 +1095,8 @@ void lovrJointDestroyData(Joint* joint) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (physics_system) {
|
||||
JPH_PhysicsSystem_RemoveConstraint(physics_system, joint->constraint);
|
||||
if (system) {
|
||||
JPH_PhysicsSystem_RemoveConstraint(system, joint->constraint);
|
||||
}
|
||||
joint->constraint = NULL;
|
||||
lovrRelease(joint, lovrJointDestroy);
|
||||
|
@ -1186,21 +1134,13 @@ BallJoint* lovrBallJointCreate(Collider* a, Collider* b, float anchor[3]) {
|
|||
joint->type = JOINT_BALL;
|
||||
|
||||
JPH_PointConstraintSettings* settings = JPH_PointConstraintSettings_Create();
|
||||
JPH_RVec3 point1 = {
|
||||
.x = anchor[0],
|
||||
.y = anchor[1],
|
||||
.z = anchor[2]
|
||||
};
|
||||
JPH_RVec3 point2 = {
|
||||
.x = anchor[0],
|
||||
.y = anchor[1],
|
||||
.z = anchor[2]
|
||||
};
|
||||
JPH_RVec3 point1 = { anchor[0], anchor[1], anchor[2] };
|
||||
JPH_RVec3 point2 = { anchor[0], anchor[1], anchor[2] };
|
||||
JPH_PointConstraintSettings_SetPoint1(settings, &point1);
|
||||
JPH_PointConstraintSettings_SetPoint2(settings, &point2);
|
||||
joint->constraint = (JPH_Constraint*) JPH_PointConstraintSettings_CreateConstraint(settings, a->body, b->body);
|
||||
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->physics_system, joint->constraint);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->system, joint->constraint);
|
||||
arr_push(&a->joints, joint);
|
||||
arr_push(&b->joints, joint);
|
||||
lovrRetain(joint);
|
||||
|
@ -1243,21 +1183,13 @@ DistanceJoint* lovrDistanceJointCreate(Collider* a, Collider* b, float anchor1[3
|
|||
joint->type = JOINT_DISTANCE;
|
||||
|
||||
JPH_DistanceConstraintSettings* settings = JPH_DistanceConstraintSettings_Create();
|
||||
JPH_RVec3 point1 = {
|
||||
.x = anchor1[0],
|
||||
.y = anchor1[1],
|
||||
.z = anchor1[2]
|
||||
};
|
||||
JPH_RVec3 point2 = {
|
||||
.x = anchor2[0],
|
||||
.y = anchor2[1],
|
||||
.z = anchor2[2]
|
||||
};
|
||||
JPH_RVec3 point1 = { anchor1[0], anchor1[1], anchor1[2] };
|
||||
JPH_RVec3 point2 = { anchor2[0], anchor2[1], anchor2[2] };
|
||||
JPH_DistanceConstraintSettings_SetPoint1(settings, &point1);
|
||||
JPH_DistanceConstraintSettings_SetPoint2(settings, &point2);
|
||||
joint->constraint = (JPH_Constraint*) JPH_DistanceConstraintSettings_CreateConstraint(settings, a->body, b->body);
|
||||
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->physics_system, joint->constraint);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->system, joint->constraint);
|
||||
arr_push(&a->joints, joint);
|
||||
arr_push(&b->joints, joint);
|
||||
lovrRetain(joint);
|
||||
|
@ -1312,24 +1244,15 @@ HingeJoint* lovrHingeJointCreate(Collider* a, Collider* b, float anchor[3], floa
|
|||
|
||||
JPH_HingeConstraintSettings* settings = JPH_HingeConstraintSettings_Create();
|
||||
|
||||
JPH_RVec3 point = {
|
||||
.x = anchor[0],
|
||||
.y = anchor[1],
|
||||
.z = anchor[2]
|
||||
};
|
||||
|
||||
JPH_Vec3 axisVec = {
|
||||
.x = axis[0],
|
||||
.y = axis[1],
|
||||
.z = axis[2]
|
||||
};
|
||||
JPH_RVec3 point = { anchor[0], anchor[1], anchor[2] };
|
||||
JPH_Vec3 axisVec = { axis[0], axis[1], axis[2] };
|
||||
JPH_HingeConstraintSettings_SetPoint1(settings, &point);
|
||||
JPH_HingeConstraintSettings_SetPoint2(settings, &point);
|
||||
JPH_HingeConstraintSettings_SetHingeAxis1(settings, &axisVec);
|
||||
JPH_HingeConstraintSettings_SetHingeAxis2(settings, &axisVec);
|
||||
joint->constraint = (JPH_Constraint*) JPH_HingeConstraintSettings_CreateConstraint(settings, a->body, b->body);
|
||||
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->physics_system, joint->constraint);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->system, joint->constraint);
|
||||
arr_push(&a->joints, joint);
|
||||
arr_push(&b->joints, joint);
|
||||
lovrRetain(joint);
|
||||
|
@ -1337,7 +1260,7 @@ HingeJoint* lovrHingeJointCreate(Collider* a, Collider* b, float anchor[3], floa
|
|||
}
|
||||
|
||||
void lovrHingeJointGetAnchors(HingeJoint* joint, float anchor1[3], float anchor2[3]) {
|
||||
lovrJointGetAnchors((Joint*) joint, anchor1, anchor2);
|
||||
lovrJointGetAnchors(joint, anchor1, anchor2);
|
||||
}
|
||||
|
||||
void lovrHingeJointSetAnchor(HingeJoint* joint, float anchor[3]) {
|
||||
|
@ -1402,15 +1325,11 @@ SliderJoint* lovrSliderJointCreate(Collider* a, Collider* b, float axis[3]) {
|
|||
joint->type = JOINT_SLIDER;
|
||||
|
||||
JPH_SliderConstraintSettings* settings = JPH_SliderConstraintSettings_Create();
|
||||
const JPH_Vec3 axisVec = {
|
||||
.x = axis[0],
|
||||
.y = axis[1],
|
||||
.z = axis[2]
|
||||
};
|
||||
const JPH_Vec3 axisVec = { axis[0], axis[1], axis[2] };
|
||||
JPH_SliderConstraintSettings_SetSliderAxis(settings, &axisVec);
|
||||
joint->constraint = (JPH_Constraint*) JPH_SliderConstraintSettings_CreateConstraint(settings, a->body, b->body);
|
||||
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->physics_system, joint->constraint);
|
||||
JPH_PhysicsSystem_AddConstraint(a->world->system, joint->constraint);
|
||||
arr_push(&a->joints, joint);
|
||||
arr_push(&b->joints, joint);
|
||||
lovrRetain(joint);
|
||||
|
|
|
@ -154,7 +154,7 @@ void lovrPhysicsDestroy(void) {
|
|||
dCloseODE();
|
||||
}
|
||||
|
||||
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, uint32_t tagCount) {
|
||||
World* lovrWorldCreate(WorldInfo* info) {
|
||||
World* world = lovrCalloc(sizeof(World));
|
||||
world->ref = 1;
|
||||
world->id = dWorldCreate();
|
||||
|
@ -162,12 +162,12 @@ World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char
|
|||
dHashSpaceSetLevels(world->space, -4, 8);
|
||||
world->contactGroup = dJointGroupCreate(0);
|
||||
arr_init(&world->overlaps);
|
||||
lovrWorldSetGravity(world, xg, yg, zg);
|
||||
lovrWorldSetSleepingAllowed(world, allowSleep);
|
||||
for (uint32_t i = 0; i < tagCount; i++) {
|
||||
size_t size = strlen(tags[i]) + 1;
|
||||
lovrWorldSetGravity(world, info->gravity);
|
||||
lovrWorldSetSleepingAllowed(world, info->allowSleep);
|
||||
for (uint32_t i = 0; i < info->tagCount; i++) {
|
||||
size_t size = strlen(info->tags[i]) + 1;
|
||||
world->tags[i] = lovrMalloc(size);
|
||||
memcpy(world->tags[i], tags[i], size);
|
||||
memcpy(world->tags[i], info->tags[i], size);
|
||||
}
|
||||
memset(world->masks, 0xff, sizeof(world->masks));
|
||||
return world;
|
||||
|
@ -339,16 +339,16 @@ Collider* lovrWorldGetFirstCollider(World* world) {
|
|||
return world->head;
|
||||
}
|
||||
|
||||
void lovrWorldGetGravity(World* world, float* x, float* y, float* z) {
|
||||
dReal gravity[4];
|
||||
dWorldGetGravity(world->id, gravity);
|
||||
*x = gravity[0];
|
||||
*y = gravity[1];
|
||||
*z = gravity[2];
|
||||
void lovrWorldGetGravity(World* world, float gravity[3]) {
|
||||
dReal g[4];
|
||||
dWorldGetGravity(world->id, g);
|
||||
gravity[0] = g[0];
|
||||
gravity[1] = g[1];
|
||||
gravity[2] = g[2];
|
||||
}
|
||||
|
||||
void lovrWorldSetGravity(World* world, float x, float y, float z) {
|
||||
dWorldSetGravity(world->id, x, y, z);
|
||||
void lovrWorldSetGravity(World* world, float gravity[3]) {
|
||||
dWorldSetGravity(world->id, gravity[0], gravity[1], gravity[2]);
|
||||
}
|
||||
|
||||
float lovrWorldGetResponseTime(World* world) {
|
||||
|
@ -436,7 +436,7 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
|
|||
return (world->masks[i] & (1 << j)) && (world->masks[j] & (1 << i));
|
||||
}
|
||||
|
||||
Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
||||
Collider* lovrColliderCreate(World* world, Shape* shape, float x, float y, float z) {
|
||||
Collider* collider = lovrCalloc(sizeof(Collider));
|
||||
collider->ref = 1;
|
||||
collider->body = dBodyCreate(world->id);
|
||||
|
@ -447,6 +447,7 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
|
|||
dBodySetData(collider->body, collider);
|
||||
arr_init(&collider->joints);
|
||||
|
||||
lovrColliderSetShape(collider, shape);
|
||||
lovrColliderSetPosition(collider, x, y, z);
|
||||
|
||||
// Adjust the world's collider list
|
||||
|
@ -616,12 +617,12 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
|
|||
}
|
||||
}
|
||||
|
||||
bool lovrColliderIsGravityIgnored(Collider* collider) {
|
||||
return !dBodyGetGravityMode(collider->body);
|
||||
float lovrColliderGetGravityScale(Collider* collider) {
|
||||
return dBodyGetGravityMode(collider->body) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
void lovrColliderSetGravityIgnored(Collider* collider, bool ignored) {
|
||||
dBodySetGravityMode(collider->body, !ignored);
|
||||
void lovrColliderSetGravityScale(Collider* collider, float scale) {
|
||||
dBodySetGravityMode(collider->body, scale == 0.f ? false : true);
|
||||
}
|
||||
|
||||
bool lovrColliderIsSleepingAllowed(Collider* collider) {
|
||||
|
|
Loading…
Reference in New Issue