Compare commits

...

6 Commits

Author SHA1 Message Date
bjorn 5e521b7698 Collider:applyLinear/AngularImpulse; 2024-04-05 19:16:39 -07:00
bjorn fb6b402034 Add Collider:is/setContinuous; 2024-04-05 19:05:25 -07:00
bjorn e9fe088521 Add Collider:get/setGravityScale; Deprecate Collider:get/setGravityIgnored; 2024-04-05 14:22:02 -07:00
bjorn 01194a80c7 Deprecate several World methods;
They still work on ODE, and Jolt makes a best-effort attempt to support
them, but they will be removed in a future version.

- Damping should be set explicitly on colliders.
- Tightness and response time will be supported via spring forces, and
  also some global settings in newWorld will affect joints too.
- Step count will be added to :update soon.  Since the correct value is
  dt-dependent in Jolt, a persistent accessor doesn't make sense.
- Sleeping allowed will be an immutable setting in newWorld soon, but
  otherwise should be changed per-collider.
2024-04-05 14:07:56 -07:00
bjorn ffc23497a9 Details; 2024-04-05 13:58:28 -07:00
bjorn d756cc2b1d Add variant of newWorld that takes an options table; 2024-04-05 13:25:32 -07:00
6 changed files with 390 additions and 319 deletions

View File

@ -21,28 +21,70 @@ StringEntry lovrJointType[] = {
}; };
static int l_lovrPhysicsNewWorld(lua_State* L) { static int l_lovrPhysicsNewWorld(lua_State* L) {
float xg = luax_optfloat(L, 1, 0.f); WorldInfo info = {
float yg = luax_optfloat(L, 2, -9.81f); .maxColliders = 65536,
float zg = luax_optfloat(L, 3, 0.f); .maxColliderPairs = 65536,
bool allowSleep = lua_gettop(L) < 4 || lua_toboolean(L, 4); .maxContacts = 16384,
const char* tags[MAX_TAGS]; .allowSleep = true,
int tagCount; .gravity = { 0.f, -9.81f, 0.f }
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); if (lua_istable(L, 1)) {
for (int i = 0; i < tagCount; i++) { lua_getfield(L, 1, "maxColliders");
lua_rawgeti(L, -1, i + 1); if (!lua_isnil(L, -1)) info.maxColliders = luax_checku32(L, -1);
if (lua_isstring(L, -1)) { lua_pop(L, 1);
tags[i] = lua_tostring(L, -1);
} else { lua_getfield(L, 1, "maxColliderPairs");
return luaL_error(L, "World tags must be a table of strings"); 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 { lua_pop(L, 1);
tagCount = 0; } 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); luax_pushtype(L, World, world);
lovrRelease(world, lovrWorldDestroy); lovrRelease(world, lovrWorldDestroy);
return 1; return 1;

View File

@ -110,16 +110,31 @@ static int l_lovrColliderSetKinematic(lua_State* L) {
return 0; return 0;
} }
static int l_lovrColliderIsGravityIgnored(lua_State* L) { static int l_lovrColliderIsContinuous(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider); Collider* collider = luax_checktype(L, 1, Collider);
lua_pushboolean(L, lovrColliderIsGravityIgnored(collider)); bool continuous = lovrColliderIsContinuous(collider);
lua_pushboolean(L, continuous);
return 1; return 1;
} }
static int l_lovrColliderSetGravityIgnored(lua_State* L) { static int l_lovrColliderSetContinuous(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider); Collider* collider = luax_checktype(L, 1, Collider);
bool ignored = lua_toboolean(L, 2); bool continuous = lua_toboolean(L, 2);
lovrColliderSetGravityIgnored(collider, ignored); lovrColliderSetContinuous(collider, continuous);
return 0;
}
static int l_lovrColliderGetGravityScale(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float scale = lovrColliderGetGravityScale(collider);
lua_pushnumber(L, scale);
return 1;
}
static int l_lovrColliderSetGravityScale(lua_State* L) {
Collider* collider = luax_checktype(L, 1, Collider);
float scale = luax_checkfloat(L, 2);
lovrColliderSetGravityScale(collider, scale);
return 0; return 0;
} }
@ -368,6 +383,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;
@ -507,6 +544,21 @@ static int l_lovrColliderSetTag(lua_State* L) {
return 0; return 0;
} }
// 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[] = { const luaL_Reg lovrCollider[] = {
{ "destroy", l_lovrColliderDestroy }, { "destroy", l_lovrColliderDestroy },
{ "isDestroyed", l_lovrColliderIsDestroyed }, { "isDestroyed", l_lovrColliderIsDestroyed },
@ -519,8 +571,10 @@ const luaL_Reg lovrCollider[] = {
{ "setUserData", l_lovrColliderSetUserData }, { "setUserData", l_lovrColliderSetUserData },
{ "isKinematic", l_lovrColliderIsKinematic }, { "isKinematic", l_lovrColliderIsKinematic },
{ "setKinematic", l_lovrColliderSetKinematic }, { "setKinematic", l_lovrColliderSetKinematic },
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored }, { "isContinuous", l_lovrColliderIsContinuous },
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored }, { "setContinuous", l_lovrColliderSetContinuous },
{ "getGravityScale", l_lovrColliderGetGravityScale },
{ "setGravityScale", l_lovrColliderSetGravityScale },
{ "isSleepingAllowed", l_lovrColliderIsSleepingAllowed }, { "isSleepingAllowed", l_lovrColliderIsSleepingAllowed },
{ "setSleepingAllowed", l_lovrColliderSetSleepingAllowed }, { "setSleepingAllowed", l_lovrColliderSetSleepingAllowed },
{ "isAwake", l_lovrColliderIsAwake }, { "isAwake", l_lovrColliderIsAwake },
@ -545,6 +599,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 },
@ -559,5 +615,10 @@ const luaL_Reg lovrCollider[] = {
{ "setRestitution", l_lovrColliderSetRestitution }, { "setRestitution", l_lovrColliderSetRestitution },
{ "getTag", l_lovrColliderGetTag }, { "getTag", l_lovrColliderGetTag },
{ "setTag", l_lovrColliderSetTag }, { "setTag", l_lovrColliderSetTag },
// Deprecated
{ "isGravityIgnored", l_lovrColliderIsGravityIgnored },
{ "setGravityIgnored", l_lovrColliderSetGravityIgnored },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -375,11 +375,11 @@ static int l_lovrWorldQuerySphere(lua_State* L) {
static int l_lovrWorldGetGravity(lua_State* L) { static int l_lovrWorldGetGravity(lua_State* L) {
World* world = luax_checktype(L, 1, World); World* world = luax_checktype(L, 1, World);
float x, y, z; float gravity[3];
lovrWorldGetGravity(world, &x, &y, &z); lovrWorldGetGravity(world, gravity);
lua_pushnumber(L, x); lua_pushnumber(L, gravity[0]);
lua_pushnumber(L, y); lua_pushnumber(L, gravity[1]);
lua_pushnumber(L, z); lua_pushnumber(L, gravity[2]);
return 3; return 3;
} }
@ -387,7 +387,7 @@ static int l_lovrWorldSetGravity(lua_State* L) {
World* world = luax_checktype(L, 1, World); World* world = luax_checktype(L, 1, World);
float gravity[3]; float gravity[3];
luax_readvec3(L, 2, gravity, NULL); luax_readvec3(L, 2, gravity, NULL);
lovrWorldSetGravity(world, gravity[0], gravity[1], gravity[2]); lovrWorldSetGravity(world, gravity);
return 0; return 0;
} }
@ -529,6 +529,11 @@ const luaL_Reg lovrWorld[] = {
{ "querySphere", l_lovrWorldQuerySphere }, { "querySphere", l_lovrWorldQuerySphere },
{ "getGravity", l_lovrWorldGetGravity }, { "getGravity", l_lovrWorldGetGravity },
{ "setGravity", l_lovrWorldSetGravity }, { "setGravity", l_lovrWorldSetGravity },
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
// Deprecated
{ "getTightness", l_lovrWorldGetTightness }, { "getTightness", l_lovrWorldGetTightness },
{ "setTightness", l_lovrWorldSetTightness }, { "setTightness", l_lovrWorldSetTightness },
{ "getResponseTime", l_lovrWorldGetResponseTime }, { "getResponseTime", l_lovrWorldGetResponseTime },
@ -539,10 +544,8 @@ const luaL_Reg lovrWorld[] = {
{ "setAngularDamping", l_lovrWorldSetAngularDamping }, { "setAngularDamping", l_lovrWorldSetAngularDamping },
{ "isSleepingAllowed", l_lovrWorldIsSleepingAllowed }, { "isSleepingAllowed", l_lovrWorldIsSleepingAllowed },
{ "setSleepingAllowed", l_lovrWorldSetSleepingAllowed }, { "setSleepingAllowed", l_lovrWorldSetSleepingAllowed },
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
{ "getStepCount", l_lovrWorldGetStepCount }, { "getStepCount", l_lovrWorldGetStepCount },
{ "setStepCount", l_lovrWorldSetStepCount }, { "setStepCount", l_lovrWorldSetStepCount },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -40,12 +40,20 @@ typedef struct {
float depth; float depth;
} Contact; } 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 lovrWorldDestroy(void* ref);
void lovrWorldDestroyData(World* world); void lovrWorldDestroyData(World* world);
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata); void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata);
int lovrWorldGetStepCount(World* world);
void lovrWorldSetStepCount(World* world, int iterations);
void lovrWorldComputeOverlaps(World* world); void lovrWorldComputeOverlaps(World* world);
int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b); int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b);
int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution); int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution);
@ -54,8 +62,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 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); bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata);
Collider* lovrWorldGetFirstCollider(World* world); Collider* lovrWorldGetFirstCollider(World* world);
void lovrWorldGetGravity(World* world, float* x, float* y, float* z); void lovrWorldGetGravity(World* world, float gravity[3]);
void lovrWorldSetGravity(World* world, float x, float y, float z); 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); float lovrWorldGetResponseTime(World* world);
void lovrWorldSetResponseTime(World* world, float responseTime); void lovrWorldSetResponseTime(World* world, float responseTime);
float lovrWorldGetTightness(World* world); float lovrWorldGetTightness(World* world);
@ -66,10 +82,6 @@ void lovrWorldGetAngularDamping(World* world, float* damping, float* threshold);
void lovrWorldSetAngularDamping(World* world, float damping, float threshold); void lovrWorldSetAngularDamping(World* world, float damping, float threshold);
bool lovrWorldIsSleepingAllowed(World* world); bool lovrWorldIsSleepingAllowed(World* world);
void lovrWorldSetSleepingAllowed(World* world, bool allowed); 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
@ -92,8 +104,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 lovrColliderIsGravityIgnored(Collider* collider); bool lovrColliderIsContinuous(Collider* collider);
void lovrColliderSetGravityIgnored(Collider* collider, bool ignored); void lovrColliderSetContinuous(Collider* collider, bool continuous);
float lovrColliderGetGravityScale(Collider* collider);
void lovrColliderSetGravityScale(Collider* collider, float scale);
bool lovrColliderIsSleepingAllowed(Collider* collider); bool lovrColliderIsSleepingAllowed(Collider* collider);
void lovrColliderSetSleepingAllowed(Collider* collider, bool allowed); void lovrColliderSetSleepingAllowed(Collider* collider, bool allowed);
bool lovrColliderIsAwake(Collider* collider); bool lovrColliderIsAwake(Collider* collider);
@ -117,6 +131,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);

View File

@ -4,24 +4,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <joltc.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 { struct World {
uint32_t ref; uint32_t ref;
JPH_PhysicsSystem* physics_system; JPH_PhysicsSystem* system;
JPH_BodyInterface* body_interface; JPH_BodyInterface* bodies;
int collision_steps; JPH_ObjectLayerPairFilter* objectLayerPairFilter;
int collisionSteps;
Collider* head; Collider* head;
JPH_BroadPhaseLayerInterface* broad_phase_layer_interface;
JPH_ObjectVsBroadPhaseLayerFilter* broad_phase_layer_filter;
JPH_ObjectLayerPairFilter* object_layer_pair_filter;
float defaultLinearDamping; float defaultLinearDamping;
float defaultAngularDamping; float defaultAngularDamping;
bool defaultIsSleepingAllowed; bool defaultIsSleepingAllowed;
@ -53,6 +42,13 @@ struct Joint {
JPH_Constraint* constraint; JPH_Constraint* constraint;
}; };
static struct {
bool initialized;
JPH_Shape* queryBox;
JPH_Shape* querySphere;
JPH_AllHit_CastShapeCollector* castShapeCollector;
} state;
// Broad phase and object phase layers // Broad phase and object phase layers
#define NUM_OP_LAYERS ((MAX_TAGS + 1) * 2) #define NUM_OP_LAYERS ((MAX_TAGS + 1) * 2)
#define NUM_BP_LAYERS 2 #define NUM_BP_LAYERS 2
@ -72,69 +68,70 @@ static uint32_t findTag(World* world, const char* name) {
} }
bool lovrPhysicsInit(void) { bool lovrPhysicsInit(void) {
if (initialized) return false; if (state.initialized) return false;
JPH_Init(32 * 1024 * 1024); JPH_Init(32 * 1024 * 1024);
cast_shape_collector = JPH_AllHit_CastShapeCollector_Create(); state.castShapeCollector = JPH_AllHit_CastShapeCollector_Create();
querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f); state.querySphere = (JPH_Shape*) JPH_SphereShape_Create(1.f);
const JPH_Vec3 halfExtent = { .5f, .5f, .5f }; state.queryBox = (JPH_Shape*) JPH_BoxShape_Create(&(const JPH_Vec3) { .5, .5f, .5f }, 0.f);
queryBox = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f); return state.initialized = true;
return initialized = true;
} }
void lovrPhysicsDestroy(void) { void lovrPhysicsDestroy(void) {
if (!initialized) return; if (!state.initialized) return;
JPH_Shutdown(); 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* world = lovrCalloc(sizeof(World));
world->ref = 1; world->ref = 1;
world->collision_steps = 1; world->collisionSteps = 1;
world->defaultLinearDamping = .05f; world->defaultLinearDamping = .05f;
world->defaultAngularDamping = .05f; world->defaultAngularDamping = .05f;
world->defaultIsSleepingAllowed = true; world->defaultIsSleepingAllowed = info->allowSleep;
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); 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 i = 0; i < NUM_OP_LAYERS; i++) {
for (uint32_t j = i; j < NUM_OP_LAYERS; j++) { 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) { 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 { } 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( JPH_ObjectVsBroadPhaseLayerFilter* broadPhaseLayerFilter = JPH_ObjectVsBroadPhaseLayerFilterTable_Create(
world->broad_phase_layer_interface, NUM_BP_LAYERS, broadPhaseLayerInterface, NUM_BP_LAYERS,
world->object_layer_pair_filter, NUM_OP_LAYERS); world->objectLayerPairFilter, NUM_OP_LAYERS);
JPH_PhysicsSystemSettings settings = { JPH_PhysicsSystemSettings settings = {
.maxBodies = MAX_BODIES, .maxBodies = info->maxColliders,
.maxBodyPairs = MAX_BODY_PAIRS, .maxBodyPairs = info->maxColliderPairs,
.maxContactConstraints = MAX_CONTACT_CONSTRAINTS, .maxContactConstraints = info->maxContacts,
.broadPhaseLayerInterface = world->broad_phase_layer_interface, .broadPhaseLayerInterface = broadPhaseLayerInterface,
.objectLayerPairFilter = world->object_layer_pair_filter, .objectLayerPairFilter = world->objectLayerPairFilter,
.objectVsBroadPhaseLayerFilter = world->broad_phase_layer_filter .objectVsBroadPhaseLayerFilter = broadPhaseLayerFilter
}; };
world->physics_system = JPH_PhysicsSystem_Create(&settings); world->system = JPH_PhysicsSystem_Create(&settings);
world->body_interface = JPH_PhysicsSystem_GetBodyInterface(world->physics_system); world->bodies = JPH_PhysicsSystem_GetBodyInterface(world->system);
lovrWorldSetGravity(world, xg, yg, zg); lovrWorldSetGravity(world, info->gravity);
for (uint32_t i = 0; i < tagCount; i++) {
size_t size = strlen(tags[i]) + 1; for (uint32_t i = 0; i < info->tagCount; i++) {
size_t size = strlen(info->tags[i]) + 1;
world->tags[i] = lovrMalloc(size); world->tags[i] = lovrMalloc(size);
memcpy(world->tags[i], tags[i], size); memcpy(world->tags[i], info->tags[i], size);
} }
return world; return world;
} }
void lovrWorldDestroy(void* ref) { void lovrWorldDestroy(void* ref) {
World* world = ref; World* world = ref;
lovrWorldDestroyData(world); 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++) { for (uint32_t i = 0; i < MAX_TAGS - 1 && world->tags[i]; i++) {
lovrFree(world->tags[i]); lovrFree(world->tags[i]);
} }
@ -147,20 +144,11 @@ void lovrWorldDestroyData(World* world) {
lovrColliderDestroyData(world->head); lovrColliderDestroyData(world->head);
world->head = next; world->head = next;
} }
JPH_PhysicsSystem_Destroy(world->physics_system); JPH_PhysicsSystem_Destroy(world->system);
} }
void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata) { void lovrWorldUpdate(World* world, float dt, CollisionResolver resolver, void* userdata) {
JPH_PhysicsSystem_Step(world->physics_system, dt, world->collision_steps); JPH_PhysicsSystem_Step(world->system, dt, world->collisionSteps);
}
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;
} }
void lovrWorldComputeOverlaps(World* world) { void lovrWorldComputeOverlaps(World* world) {
@ -180,7 +168,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) { 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_RVec3 origin = { x1, y1, z1 };
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();
@ -193,7 +181,7 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa
float z = z1 + hit_array[i].fraction * (z2 - z1); float z = z1 + hit_array[i].fraction * (z2 - z1);
// todo: assuming one shape per collider; doesn't support compound shape // todo: assuming one shape per collider; doesn't support compound shape
Collider* collider = (Collider*) JPH_BodyInterface_GetUserData( Collider* collider = (Collider*) JPH_BodyInterface_GetUserData(
world->body_interface, world->bodies,
hit_array[i].bodyID); hit_array[i].bodyID);
size_t count; size_t count;
Shape** shape = lovrColliderGetShapes(collider, &count); Shape** shape = lovrColliderGetShapes(collider, &count);
@ -223,15 +211,15 @@ static bool lovrWorldQueryShape(World* world, JPH_Shape* shape, float position[3
JPH_Vec3 direction = { 0.f }; JPH_Vec3 direction = { 0.f };
JPH_RVec3 base_offset = { 0.f }; JPH_RVec3 base_offset = { 0.f };
const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->physics_system); const JPH_NarrowPhaseQuery* query = JPC_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system);
JPH_AllHit_CastShapeCollector_Reset(cast_shape_collector); JPH_AllHit_CastShapeCollector_Reset(state.castShapeCollector);
JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, cast_shape_collector); JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, &direction, &base_offset, state.castShapeCollector);
size_t hit_count; size_t hit_count;
JPH_ShapeCastResult* hit_array = JPH_AllHit_CastShapeCollector_GetHits(cast_shape_collector, &hit_count); JPH_ShapeCastResult* hit_array = JPH_AllHit_CastShapeCollector_GetHits(state.castShapeCollector, &hit_count);
for (int i = 0; i < hit_count; i++) { for (int i = 0; i < hit_count; i++) {
JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(cast_shape_collector, i); JPH_BodyID id = JPH_AllHit_CastShapeCollector_GetBodyID2(state.castShapeCollector, i);
Collider* collider = (Collider*) JPH_BodyInterface_GetUserData( Collider* collider = (Collider*) JPH_BodyInterface_GetUserData(
world->body_interface, world->bodies,
id); id);
size_t count; size_t count;
Shape** shape = lovrColliderGetShapes(collider, &count); Shape** shape = lovrColliderGetShapes(collider, &count);
@ -244,81 +232,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) { 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) { bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata) {
float scale[3] = {radius, radius, radius}; float scale[3] = { radius, radius, radius };
return lovrWorldQueryShape(world, querySphere, position, scale, callback, userdata); return lovrWorldQueryShape(world, state.querySphere, position, scale, callback, userdata);
} }
Collider* lovrWorldGetFirstCollider(World* world) { Collider* lovrWorldGetFirstCollider(World* world) {
return world->head; return world->head;
} }
void lovrWorldGetGravity(World* world, float* x, float* y, float* z) { void lovrWorldGetGravity(World* world, float gravity[3]) {
JPH_Vec3 gravity; JPH_Vec3 g;
JPH_PhysicsSystem_GetGravity(world->physics_system, &gravity); JPH_PhysicsSystem_GetGravity(world->system, &g);
*x = gravity.x; vec3_init(gravity, &g.x);
*y = gravity.y;
*z = gravity.z;
} }
void lovrWorldSetGravity(World* world, float x, float y, float z) { void lovrWorldSetGravity(World* world, float gravity[3]) {
const JPH_Vec3 gravity = { JPH_PhysicsSystem_SetGravity(world->system, &(const JPH_Vec3) { gravity[0], gravity[1], gravity[2] });
.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;
} }
const char* lovrWorldGetTagName(World* world, uint32_t tag) { const char* lovrWorldGetTagName(World* world, uint32_t tag) {
@ -335,9 +268,9 @@ void lovrWorldDisableCollisionBetween(World* world, const char* tag1, const char
uint32_t jStatic = j * 2; uint32_t jStatic = j * 2;
uint32_t iDynamic = i * 2 + 1; uint32_t iDynamic = i * 2 + 1;
uint32_t jDynamic = j * 2 + 1; uint32_t jDynamic = j * 2 + 1;
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, iDynamic, jDynamic); JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, iDynamic, jDynamic);
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, iDynamic, jStatic); JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, iDynamic, jStatic);
JPH_ObjectLayerPairFilterTable_DisableCollision(world->object_layer_pair_filter, iStatic, jDynamic); JPH_ObjectLayerPairFilterTable_DisableCollision(world->objectLayerPairFilter, iStatic, jDynamic);
} }
void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2) { void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char* tag2) {
@ -350,9 +283,9 @@ void lovrWorldEnableCollisionBetween(World* world, const char* tag1, const char*
uint32_t jStatic = j * 2; uint32_t jStatic = j * 2;
uint32_t iDynamic = i * 2 + 1; uint32_t iDynamic = i * 2 + 1;
uint32_t jDynamic = j * 2 + 1; uint32_t jDynamic = j * 2 + 1;
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, iDynamic, jDynamic); JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, iDynamic, jDynamic);
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, iDynamic, jStatic); JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, iDynamic, jStatic);
JPH_ObjectLayerPairFilterTable_EnableCollision(world->object_layer_pair_filter, iStatic, jDynamic); JPH_ObjectLayerPairFilterTable_EnableCollision(world->objectLayerPairFilter, iStatic, jDynamic);
} }
bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag2) { bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const char* tag2) {
@ -363,9 +296,25 @@ bool lovrWorldIsCollisionEnabledBetween(World* world, const char* tag1, const ch
} }
uint32_t iDynamic = i * 2 + 1; uint32_t iDynamic = i * 2 + 1;
uint32_t jDynamic = j * 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);
} }
// 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, float x, float y, float z) { Collider* lovrColliderCreate(World* world, float x, float y, float z) {
// todo: crashes when too many are added // todo: crashes when too many are added
Collider* collider = lovrCalloc(sizeof(Collider)); Collider* collider = lovrCalloc(sizeof(Collider));
@ -375,16 +324,16 @@ Collider* lovrColliderCreate(World* world, float x, float y, float z) {
JPH_MotionType motionType = JPH_MotionType_Dynamic; JPH_MotionType motionType = JPH_MotionType_Dynamic;
JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1; JPH_ObjectLayer objectLayer = UNTAGGED * 2 + 1;
const JPH_RVec3 position = { .x = x, .y = y, .z = z }; const JPH_RVec3 position = { x, y, z };
const JPH_Quat rotation = { .x = 0.f, .y = 0.f, .z = 0.f, .w = 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 // todo: a placeholder querySphere shape is used in collider, then replaced in lovrColliderAddShape
JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3( JPH_BodyCreationSettings* settings = JPH_BodyCreationSettings_Create3(
querySphere, &position, &rotation, motionType, objectLayer); state.querySphere, &position, &rotation, motionType, objectLayer);
collider->body = JPH_BodyInterface_CreateBody(world->body_interface, settings); collider->body = JPH_BodyInterface_CreateBody(world->bodies, settings);
JPH_BodyCreationSettings_Destroy(settings); JPH_BodyCreationSettings_Destroy(settings);
collider->id = JPH_Body_GetID(collider->body); collider->id = JPH_Body_GetID(collider->body);
JPH_BodyInterface_AddBody(world->body_interface, collider->id, JPH_Activation_Activate); JPH_BodyInterface_AddBody(world->bodies, collider->id, JPH_Activation_Activate);
JPH_BodyInterface_SetUserData(world->body_interface, 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);
@ -431,7 +380,7 @@ void lovrColliderDestroyData(Collider* collider) {
lovrRelease(joints[i], lovrJointDestroy); lovrRelease(joints[i], lovrJointDestroy);
} }
JPH_BodyInterface_RemoveBody(collider->world->body_interface, collider->id); JPH_BodyInterface_RemoveBody(collider->world->bodies, collider->id);
collider->body = NULL; collider->body = NULL;
if (collider->next) collider->next->prev = collider->prev; if (collider->next) collider->next->prev = collider->prev;
@ -468,7 +417,7 @@ void lovrColliderAddShape(Collider* collider, Shape* shape) {
if (isMeshOrTerrain) { if (isMeshOrTerrain) {
lovrColliderSetKinematic(shape->collider, true); lovrColliderSetKinematic(shape->collider, true);
} }
JPH_BodyInterface_SetShape(collider->world->body_interface, collider->id, shape->shape, shouldUpdateMass, JPH_Activation_Activate); JPH_BodyInterface_SetShape(collider->world->bodies, collider->id, shape->shape, shouldUpdateMass, JPH_Activation_Activate);
} }
void lovrColliderRemoveShape(Collider* collider, Shape* shape) { void lovrColliderRemoveShape(Collider* collider, Shape* shape) {
@ -504,59 +453,65 @@ bool lovrColliderSetTag(Collider* collider, const char* tag) {
} }
bool kinematic = lovrColliderIsKinematic(collider); bool kinematic = lovrColliderIsKinematic(collider);
JPH_ObjectLayer objectLayer = collider->tag * 2 + (kinematic ? 0 : 1); 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; return true;
} }
float lovrColliderGetFriction(Collider* collider) { 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) { 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) { 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) { 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) { 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; return objectLayer % 2 == 0;
} }
void lovrColliderSetKinematic(Collider* collider, bool kinematic) { void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
JPH_ObjectLayer objectLayer = collider->tag * 2 + (kinematic ? 0 : 1); 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) { if (kinematic) {
JPH_BodyInterface_DeactivateBody(collider->world->body_interface, collider->id); JPH_BodyInterface_DeactivateBody(collider->world->bodies, collider->id);
JPH_BodyInterface_SetMotionType( JPH_BodyInterface_SetMotionType(
collider->world->body_interface, collider->world->bodies,
collider->id, collider->id,
JPH_MotionType_Kinematic, JPH_MotionType_Kinematic,
JPH_Activation_DontActivate); JPH_Activation_DontActivate);
} else { } else {
JPH_BodyInterface_SetMotionType( JPH_BodyInterface_SetMotionType(
collider->world->body_interface, collider->world->bodies,
collider->id, collider->id,
JPH_MotionType_Dynamic, JPH_MotionType_Dynamic,
JPH_Activation_Activate); JPH_Activation_Activate);
} }
} }
bool lovrColliderIsGravityIgnored(Collider* collider) { bool lovrColliderIsContinuous(Collider* collider) {
return JPH_BodyInterface_GetGravityFactor(collider->world->body_interface, collider->id) == 0.f; return JPH_BodyInterface_GetMotionQuality(collider->world->bodies, collider->id) == JPH_MotionQuality_LinearCast;
} }
void lovrColliderSetGravityIgnored(Collider* collider, bool ignored) { void lovrColliderSetContinuous(Collider* collider, bool continuous) {
JPH_BodyInterface_SetGravityFactor( JPH_MotionQuality quality = continuous ? JPH_MotionQuality_LinearCast : JPH_MotionQuality_Discrete;
collider->world->body_interface, return JPH_BodyInterface_SetMotionQuality(collider->world->bodies, collider->id, quality);
collider->id, }
ignored ? 0.f : 1.f);
float lovrColliderGetGravityScale(Collider* collider) {
return JPH_BodyInterface_GetGravityFactor(collider->world->bodies, collider->id);
}
void lovrColliderSetGravityScale(Collider* collider, float scale) {
return JPH_BodyInterface_SetGravityFactor(collider->world->bodies, collider->id, scale);
} }
bool lovrColliderIsSleepingAllowed(Collider* collider) { bool lovrColliderIsSleepingAllowed(Collider* collider) {
@ -568,33 +523,33 @@ void lovrColliderSetSleepingAllowed(Collider* collider, bool allowed) {
} }
bool lovrColliderIsAwake(Collider* collider) { 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) { void lovrColliderSetAwake(Collider* collider, bool awake) {
if (awake) { if (awake) {
JPH_BodyInterface_ActivateBody(collider->world->body_interface, collider->id); JPH_BodyInterface_ActivateBody(collider->world->bodies, collider->id);
} else { } else {
JPH_BodyInterface_DeactivateBody(collider->world->body_interface, collider->id); JPH_BodyInterface_DeactivateBody(collider->world->bodies, collider->id);
} }
} }
float lovrColliderGetMass(Collider* collider) { float lovrColliderGetMass(Collider* collider) {
if (collider->shapes.length > 0) { if (collider->shapes.length > 0) {
JPH_MotionProperties* motion_properties = JPH_Body_GetMotionProperties(collider->body); JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motion_properties); return 1.f / JPH_MotionProperties_GetInverseMassUnchecked(motionProperties);
} }
return 0.f; return 0.f;
} }
void lovrColliderSetMass(Collider* collider, float mass) { void lovrColliderSetMass(Collider* collider, float mass) {
if (collider->shapes.length > 0) { if (collider->shapes.length > 0) {
JPH_MotionProperties* motion_properties = JPH_Body_GetMotionProperties(collider->body); JPH_MotionProperties* motionProperties = JPH_Body_GetMotionProperties(collider->body);
Shape* shape = collider->shapes.data[0]; Shape* shape = collider->shapes.data[0];
JPH_MassProperties* mass_properties; JPH_MassProperties* massProperties;
JPH_Shape_GetMassProperties(shape->shape, mass_properties); JPH_Shape_GetMassProperties(shape->shape, massProperties);
JPH_MassProperties_ScaleToMass(mass_properties, mass); JPH_MassProperties_ScaleToMass(massProperties, mass);
JPH_MotionProperties_SetMassProperties(motion_properties, JPH_AllowedDOFs_All, mass_properties); JPH_MotionProperties_SetMassProperties(motionProperties, JPH_AllowedDOFs_All, massProperties);
} }
} }
@ -616,7 +571,7 @@ void lovrColliderGetPosition(Collider* collider, float* x, float* y, float* z) {
void lovrColliderSetPosition(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_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) { void lovrColliderGetOrientation(Collider* collider, float* orientation) {
@ -636,7 +591,7 @@ void lovrColliderSetOrientation(Collider* collider, float* orientation) {
.w = orientation[3] .w = orientation[3]
}; };
JPH_BodyInterface_SetRotation( JPH_BodyInterface_SetRotation(
collider->world->body_interface, collider->world->bodies,
collider->id, collider->id,
&rotation, &rotation,
JPH_Activation_Activate); JPH_Activation_Activate);
@ -644,7 +599,7 @@ void lovrColliderSetOrientation(Collider* collider, float* orientation) {
void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float* z) { void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float* z) {
JPH_Vec3 velocity; 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; *x = velocity.x;
*y = velocity.y; *y = velocity.y;
*z = velocity.z; *z = velocity.z;
@ -652,12 +607,12 @@ void lovrColliderGetLinearVelocity(Collider* collider, float* x, float* y, float
void lovrColliderSetLinearVelocity(Collider* collider, float x, float y, float z) { void lovrColliderSetLinearVelocity(Collider* collider, float x, float y, float z) {
const JPH_Vec3 velocity = { x, y, 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) { void lovrColliderGetAngularVelocity(Collider* collider, float* x, float* y, float* z) {
JPH_Vec3 velocity; 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; *x = velocity.x;
*y = velocity.y; *y = velocity.y;
*z = velocity.z; *z = velocity.z;
@ -665,7 +620,7 @@ void lovrColliderGetAngularVelocity(Collider* collider, float* x, float* y, floa
void lovrColliderSetAngularVelocity(Collider* collider, float x, float y, float z) { void lovrColliderSetAngularVelocity(Collider* collider, float x, float y, float z) {
JPH_Vec3 velocity = { x, y, 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) { void lovrColliderGetLinearDamping(Collider* collider, float* damping, float* threshold) {
@ -698,18 +653,34 @@ 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) {
JPH_Vec3 force = { x, y, 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) { void lovrColliderApplyForceAtPosition(Collider* collider, float x, float y, float z, float cx, float cy, float cz) {
JPH_Vec3 force = { x, y, z }; JPH_Vec3 force = { x, y, z };
JPH_RVec3 position = { cx, cy, cz }; 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) { void lovrColliderApplyTorque(Collider* collider, float x, float y, float z) {
JPH_Vec3 torque = { x, y, 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 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) {
@ -774,7 +745,7 @@ void lovrColliderGetLinearVelocityFromLocalPoint(Collider* collider, float x, fl
void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float wx, float wy, float wz, float* vx, float* vy, float* vz) { void lovrColliderGetLinearVelocityFromWorldPoint(Collider* collider, float wx, float wy, float wz, float* vx, float* vy, float* vz) {
JPH_RVec3 point = { wx, wy, wz }; JPH_RVec3 point = { wx, wy, wz };
JPH_Vec3 velocity; 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; *vx = velocity.x;
*vy = velocity.y; *vy = velocity.y;
*vz = velocity.z; *vz = velocity.z;
@ -884,11 +855,7 @@ 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 = { const JPH_Vec3 halfExtent = { w / 2.f, h / 2.f, d / 2.f };
.x = w / 2,
.y = h / 2,
.z = d / 2
};
box->shape = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f); box->shape = (JPH_Shape*) JPH_BoxShape_Create(&halfExtent, 0.f);
return box; return box;
} }
@ -995,9 +962,9 @@ TerrainShape* lovrTerrainShapeCreate(float* vertices, uint32_t widthSamples, uin
terrain->ref = 1; terrain->ref = 1;
terrain->type = SHAPE_TERRAIN; terrain->type = SHAPE_TERRAIN;
const JPH_Vec3 offset = { const JPH_Vec3 offset = {
.x = -0.5f * horizontalScale, .x = -.5f * horizontalScale,
.y = 0.f, .y = 0.f,
.z = -0.5f * horizontalScale .z = -.5f * horizontalScale
}; };
const JPH_Vec3 scale = { const JPH_Vec3 scale = {
.x = horizontalScale / widthSamples, .x = horizontalScale / widthSamples,
@ -1023,26 +990,14 @@ void lovrJointGetAnchors(Joint* joint, float anchor1[3], float anchor2[3]) {
JPH_Matrix4x4 constraintToBody2; JPH_Matrix4x4 constraintToBody2;
JPH_TwoBodyConstraint_GetConstraintToBody1Matrix((JPH_TwoBodyConstraint*) joint->constraint, &constraintToBody1); JPH_TwoBodyConstraint_GetConstraintToBody1Matrix((JPH_TwoBodyConstraint*) joint->constraint, &constraintToBody1);
JPH_TwoBodyConstraint_GetConstraintToBody2Matrix((JPH_TwoBodyConstraint*) joint->constraint, &constraintToBody2); JPH_TwoBodyConstraint_GetConstraintToBody2Matrix((JPH_TwoBodyConstraint*) joint->constraint, &constraintToBody2);
float translation1[4] = { mat4_mulVec4(&centerOfMassTransform1.m11, &constraintToBody1.m41);
constraintToBody1.m41, mat4_mulVec4(&centerOfMassTransform2.m11, &constraintToBody2.m41);
constraintToBody1.m42, anchor1[0] = constraintToBody1.m41;
constraintToBody1.m43, anchor1[1] = constraintToBody1.m42;
constraintToBody1.m44 anchor1[2] = constraintToBody1.m43;
}; anchor2[0] = constraintToBody2.m41;
float translation2[4] = { anchor2[1] = constraintToBody2.m42;
constraintToBody2.m41, anchor2[2] = constraintToBody2.m43;
constraintToBody2.m42,
constraintToBody2.m43,
constraintToBody2.m44
};
mat4_mulVec4(&centerOfMassTransform1.m11, translation1);
mat4_mulVec4(&centerOfMassTransform2.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];
} }
void lovrJointDestroy(void* ref) { void lovrJointDestroy(void* ref) {
@ -1052,13 +1007,15 @@ void lovrJointDestroy(void* ref) {
} }
void lovrJointDestroyData(Joint* joint) { void lovrJointDestroyData(Joint* joint) {
if (!joint->constraint) if (!joint->constraint) {
return; return;
JPH_PhysicsSystem* physics_system; }
JPH_PhysicsSystem* system;
JPH_Body* bodyA = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*) joint->constraint); JPH_Body* bodyA = JPH_TwoBodyConstraint_GetBody1((JPH_TwoBodyConstraint*) joint->constraint);
if (bodyA) { if (bodyA) {
Collider* collider = (Collider*) JPH_Body_GetUserData(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++) { for (size_t i = 0; i < collider->joints.length; i++) {
if (collider->joints.data[i] == joint) { if (collider->joints.data[i] == joint) {
arr_splice(&collider->joints, i, 1); arr_splice(&collider->joints, i, 1);
@ -1077,8 +1034,8 @@ void lovrJointDestroyData(Joint* joint) {
} }
} }
} }
if (physics_system) { if (system) {
JPH_PhysicsSystem_RemoveConstraint(physics_system, joint->constraint); JPH_PhysicsSystem_RemoveConstraint(system, joint->constraint);
} }
joint->constraint = NULL; joint->constraint = NULL;
lovrRelease(joint, lovrJointDestroy); lovrRelease(joint, lovrJointDestroy);
@ -1116,21 +1073,13 @@ BallJoint* lovrBallJointCreate(Collider* a, Collider* b, float anchor[3]) {
joint->type = JOINT_BALL; joint->type = JOINT_BALL;
JPH_PointConstraintSettings* settings = JPH_PointConstraintSettings_Create(); JPH_PointConstraintSettings* settings = JPH_PointConstraintSettings_Create();
JPH_RVec3 point1 = { JPH_RVec3 point1 = { anchor[0], anchor[1], anchor[2] };
.x = anchor[0], JPH_RVec3 point2 = { anchor[0], anchor[1], anchor[2] };
.y = anchor[1],
.z = anchor[2]
};
JPH_RVec3 point2 = {
.x = anchor[0],
.y = anchor[1],
.z = anchor[2]
};
JPH_PointConstraintSettings_SetPoint1(settings, &point1); JPH_PointConstraintSettings_SetPoint1(settings, &point1);
JPH_PointConstraintSettings_SetPoint2(settings, &point2); JPH_PointConstraintSettings_SetPoint2(settings, &point2);
joint->constraint = (JPH_Constraint*) JPH_PointConstraintSettings_CreateConstraint(settings, a->body, b->body); joint->constraint = (JPH_Constraint*) JPH_PointConstraintSettings_CreateConstraint(settings, a->body, b->body);
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings); 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(&a->joints, joint);
arr_push(&b->joints, joint); arr_push(&b->joints, joint);
lovrRetain(joint); lovrRetain(joint);
@ -1173,21 +1122,13 @@ DistanceJoint* lovrDistanceJointCreate(Collider* a, Collider* b, float anchor1[3
joint->type = JOINT_DISTANCE; joint->type = JOINT_DISTANCE;
JPH_DistanceConstraintSettings* settings = JPH_DistanceConstraintSettings_Create(); JPH_DistanceConstraintSettings* settings = JPH_DistanceConstraintSettings_Create();
JPH_RVec3 point1 = { JPH_RVec3 point1 = { anchor1[0], anchor1[1], anchor1[2] };
.x = anchor1[0], JPH_RVec3 point2 = { anchor2[0], anchor2[1], anchor2[2] };
.y = anchor1[1],
.z = anchor1[2]
};
JPH_RVec3 point2 = {
.x = anchor2[0],
.y = anchor2[1],
.z = anchor2[2]
};
JPH_DistanceConstraintSettings_SetPoint1(settings, &point1); JPH_DistanceConstraintSettings_SetPoint1(settings, &point1);
JPH_DistanceConstraintSettings_SetPoint2(settings, &point2); JPH_DistanceConstraintSettings_SetPoint2(settings, &point2);
joint->constraint = (JPH_Constraint*) JPH_DistanceConstraintSettings_CreateConstraint(settings, a->body, b->body); joint->constraint = (JPH_Constraint*) JPH_DistanceConstraintSettings_CreateConstraint(settings, a->body, b->body);
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings); 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(&a->joints, joint);
arr_push(&b->joints, joint); arr_push(&b->joints, joint);
lovrRetain(joint); lovrRetain(joint);
@ -1242,24 +1183,15 @@ HingeJoint* lovrHingeJointCreate(Collider* a, Collider* b, float anchor[3], floa
JPH_HingeConstraintSettings* settings = JPH_HingeConstraintSettings_Create(); JPH_HingeConstraintSettings* settings = JPH_HingeConstraintSettings_Create();
JPH_RVec3 point = { JPH_RVec3 point = { anchor[0], anchor[1], anchor[2] };
.x = anchor[0], JPH_Vec3 axisVec = { axis[0], axis[1], axis[2] };
.y = anchor[1],
.z = anchor[2]
};
JPH_Vec3 axisVec = {
.x = axis[0],
.y = axis[1],
.z = axis[2]
};
JPH_HingeConstraintSettings_SetPoint1(settings, &point); JPH_HingeConstraintSettings_SetPoint1(settings, &point);
JPH_HingeConstraintSettings_SetPoint2(settings, &point); JPH_HingeConstraintSettings_SetPoint2(settings, &point);
JPH_HingeConstraintSettings_SetHingeAxis1(settings, &axisVec); JPH_HingeConstraintSettings_SetHingeAxis1(settings, &axisVec);
JPH_HingeConstraintSettings_SetHingeAxis2(settings, &axisVec); JPH_HingeConstraintSettings_SetHingeAxis2(settings, &axisVec);
joint->constraint = (JPH_Constraint*) JPH_HingeConstraintSettings_CreateConstraint(settings, a->body, b->body); joint->constraint = (JPH_Constraint*) JPH_HingeConstraintSettings_CreateConstraint(settings, a->body, b->body);
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings); 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(&a->joints, joint);
arr_push(&b->joints, joint); arr_push(&b->joints, joint);
lovrRetain(joint); lovrRetain(joint);
@ -1267,7 +1199,7 @@ HingeJoint* lovrHingeJointCreate(Collider* a, Collider* b, float anchor[3], floa
} }
void lovrHingeJointGetAnchors(HingeJoint* joint, float anchor1[3], float anchor2[3]) { 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]) { void lovrHingeJointSetAnchor(HingeJoint* joint, float anchor[3]) {
@ -1332,15 +1264,11 @@ SliderJoint* lovrSliderJointCreate(Collider* a, Collider* b, float axis[3]) {
joint->type = JOINT_SLIDER; joint->type = JOINT_SLIDER;
JPH_SliderConstraintSettings* settings = JPH_SliderConstraintSettings_Create(); JPH_SliderConstraintSettings* settings = JPH_SliderConstraintSettings_Create();
const JPH_Vec3 axisVec = { const JPH_Vec3 axisVec = { axis[0], axis[1], axis[2] };
.x = axis[0],
.y = axis[1],
.z = axis[2]
};
JPH_SliderConstraintSettings_SetSliderAxis(settings, &axisVec); JPH_SliderConstraintSettings_SetSliderAxis(settings, &axisVec);
joint->constraint = (JPH_Constraint*) JPH_SliderConstraintSettings_CreateConstraint(settings, a->body, b->body); joint->constraint = (JPH_Constraint*) JPH_SliderConstraintSettings_CreateConstraint(settings, a->body, b->body);
JPH_ConstraintSettings_Destroy((JPH_ConstraintSettings*) settings); 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(&a->joints, joint);
arr_push(&b->joints, joint); arr_push(&b->joints, joint);
lovrRetain(joint); lovrRetain(joint);

View File

@ -154,7 +154,7 @@ void lovrPhysicsDestroy(void) {
dCloseODE(); 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* world = lovrCalloc(sizeof(World));
world->ref = 1; world->ref = 1;
world->id = dWorldCreate(); world->id = dWorldCreate();
@ -162,12 +162,12 @@ World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char
dHashSpaceSetLevels(world->space, -4, 8); dHashSpaceSetLevels(world->space, -4, 8);
world->contactGroup = dJointGroupCreate(0); world->contactGroup = dJointGroupCreate(0);
arr_init(&world->overlaps); arr_init(&world->overlaps);
lovrWorldSetGravity(world, xg, yg, zg); lovrWorldSetGravity(world, info->gravity);
lovrWorldSetSleepingAllowed(world, allowSleep); lovrWorldSetSleepingAllowed(world, info->allowSleep);
for (uint32_t i = 0; i < tagCount; i++) { for (uint32_t i = 0; i < info->tagCount; i++) {
size_t size = strlen(tags[i]) + 1; size_t size = strlen(info->tags[i]) + 1;
world->tags[i] = lovrMalloc(size); 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)); memset(world->masks, 0xff, sizeof(world->masks));
return world; return world;
@ -339,16 +339,16 @@ Collider* lovrWorldGetFirstCollider(World* world) {
return world->head; return world->head;
} }
void lovrWorldGetGravity(World* world, float* x, float* y, float* z) { void lovrWorldGetGravity(World* world, float gravity[3]) {
dReal gravity[4]; dReal g[4];
dWorldGetGravity(world->id, gravity); dWorldGetGravity(world->id, g);
*x = gravity[0]; gravity[0] = g[0];
*y = gravity[1]; gravity[1] = g[1];
*z = gravity[2]; gravity[2] = g[2];
} }
void lovrWorldSetGravity(World* world, float x, float y, float z) { void lovrWorldSetGravity(World* world, float gravity[3]) {
dWorldSetGravity(world->id, x, y, z); dWorldSetGravity(world->id, gravity[0], gravity[1], gravity[2]);
} }
float lovrWorldGetResponseTime(World* world) { float lovrWorldGetResponseTime(World* world) {
@ -610,12 +610,20 @@ void lovrColliderSetKinematic(Collider* collider, bool kinematic) {
} }
} }
bool lovrColliderIsGravityIgnored(Collider* collider) { bool lovrColliderIsContinuous(Collider* collider) {
return !dBodyGetGravityMode(collider->body); return false;
} }
void lovrColliderSetGravityIgnored(Collider* collider, bool ignored) { void lovrColliderSetContinuous(Collider* collider, bool continuous) {
dBodySetGravityMode(collider->body, !ignored); //
}
float lovrColliderGetGravityScale(Collider* collider) {
return dBodyGetGravityMode(collider->body) ? 1.f : 0.f;
}
void lovrColliderSetGravityScale(Collider* collider, float scale) {
dBodySetGravityMode(collider->body, scale == 0.f ? false : true);
} }
bool lovrColliderIsSleepingAllowed(Collider* collider) { bool lovrColliderIsSleepingAllowed(Collider* collider) {
@ -760,6 +768,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);