lovr/src/api/l_physics_world.c

574 lines
18 KiB
C
Raw Normal View History

2017-12-10 20:40:37 +00:00
#include "api.h"
2017-05-16 05:02:08 +00:00
#include "physics/physics.h"
#include "core/maf.h"
2022-03-22 07:13:21 +00:00
#include "util.h"
#include <float.h>
2017-10-31 08:14:09 +00:00
#include <stdbool.h>
2022-03-31 05:01:51 +00:00
#include <string.h>
2017-05-16 05:02:08 +00:00
2017-05-19 21:04:34 +00:00
static void collisionResolver(World* world, void* userdata) {
lua_State* L = userdata;
luaL_checktype(L, -1, LUA_TFUNCTION);
luax_pushtype(L, World, world);
2017-05-19 21:04:34 +00:00
lua_call(L, 1, 0);
}
static int nextOverlap(lua_State* L) {
World* world = luax_checktype(L, lua_upvalueindex(1), World);
Shape* a;
Shape* b;
if (lovrWorldGetNextOverlap(world, &a, &b)) {
luax_pushshape(L, a);
luax_pushshape(L, b);
2017-05-19 21:04:34 +00:00
return 2;
} else {
lua_pushnil(L);
return 1;
}
}
static bool raycastCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) {
2017-05-25 00:40:02 +00:00
lua_State* L = userdata;
2017-09-04 00:01:48 +00:00
lua_pushvalue(L, -1);
luax_pushtype(L, Collider, collider);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
lua_pushnumber(L, normal[0]);
lua_pushnumber(L, normal[1]);
lua_pushnumber(L, normal[2]);
lua_pushinteger(L, shape + 1);
lua_call(L, 8, 1);
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
lua_pop(L, 1);
return shouldStop;
2017-05-25 00:40:02 +00:00
}
typedef struct {
const char* tag;
Collider* collider;
uint32_t shape;
float distance;
float origin[3];
float position[3];
float normal[3];
} RaycastData;
static bool raycastAnyCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) {
RaycastData* data = userdata;
if (data->tag) {
const char* tag = lovrColliderGetTag(collider);
if (!tag || strcmp(tag, data->tag)) {
return false;
}
}
data->collider = collider;
data->shape = shape;
vec3_init(data->position, position);
vec3_init(data->normal, normal);
data->distance = vec3_distance(data->origin, data->position);
return true;
}
static bool raycastClosestCallback(Collider* collider, float position[3], float normal[3], uint32_t shape, void* userdata) {
RaycastData* data = userdata;
if (data->tag) {
const char* tag = lovrColliderGetTag(collider);
if (!tag || strcmp(tag, data->tag)) {
return false;
}
}
float distance = vec3_distance(data->origin, position);
if (distance < data->distance) {
vec3_init(data->position, position);
vec3_init(data->normal, normal);
data->distance = distance;
data->collider = collider;
data->shape = shape;
}
return false;
}
static bool queryCallback(Collider* collider, uint32_t shape, void* userdata) {
2023-07-11 06:20:01 +00:00
lua_State* L = userdata;
lua_pushvalue(L, -1);
luax_pushtype(L, Collider, collider);
lua_pushinteger(L, shape + 1);
lua_call(L, 2, 1);
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
lua_pop(L, 1);
return shouldStop;
2023-07-11 06:20:01 +00:00
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldNewCollider(lua_State* L) {
2017-05-20 02:11:58 +00:00
World* world = luax_checktype(L, 1, World);
Shape* shape = luax_totype(L, 2, Shape);
float position[3];
luax_readvec3(L, 2 + !!shape, position, NULL);
Collider* collider = lovrColliderCreate(world, shape, position);
luax_pushtype(L, Collider, collider);
2021-02-09 00:52:26 +00:00
lovrRelease(collider, lovrColliderDestroy);
2017-05-20 02:11:58 +00:00
return 1;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldNewBoxCollider(lua_State* L) {
2017-05-20 02:11:58 +00:00
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
BoxShape* shape = luax_newboxshape(L, index);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
2021-02-09 00:52:26 +00:00
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
2017-05-20 02:11:58 +00:00
return 1;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldNewCapsuleCollider(lua_State* L) {
2017-05-20 02:11:58 +00:00
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
CapsuleShape* shape = luax_newcapsuleshape(L, index);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
2021-02-09 00:52:26 +00:00
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
2017-05-20 02:11:58 +00:00
return 1;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldNewCylinderCollider(lua_State* L) {
2017-05-20 02:11:58 +00:00
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
CylinderShape* shape = luax_newcylindershape(L, index);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
2021-02-09 00:52:26 +00:00
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
2017-05-20 02:11:58 +00:00
return 1;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldNewSphereCollider(lua_State* L) {
2017-05-20 02:11:58 +00:00
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
SphereShape* shape = luax_newsphereshape(L, index);
Collider* collider = lovrColliderCreate(world, shape, position);
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
2021-02-09 00:52:26 +00:00
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
2017-05-20 02:11:58 +00:00
return 1;
}
2020-09-13 10:34:36 +00:00
static int l_lovrWorldNewMeshCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
MeshShape* shape = luax_newmeshshape(L, 2);
float position[3] = { 0.f, 0.f, 0.f };
Collider* collider = lovrColliderCreate(world, shape, position);
2020-09-13 10:34:36 +00:00
lovrColliderInitInertia(collider, shape);
luax_pushtype(L, Collider, collider);
2021-02-09 00:52:26 +00:00
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
2020-09-13 10:34:36 +00:00
return 1;
}
2022-08-12 05:04:59 +00:00
static int l_lovrWorldNewTerrainCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
TerrainShape* shape = luax_newterrainshape(L, 2);
float position[3] = { 0.f, 0.f, 0.f };
Collider* collider = lovrColliderCreate(world, shape, position);
2022-08-12 05:04:59 +00:00
lovrColliderSetKinematic(collider, true);
luax_pushtype(L, Collider, collider);
lovrRelease(collider, lovrColliderDestroy);
lovrRelease(shape, lovrShapeDestroy);
return 1;
}
static int l_lovrWorldDestroy(lua_State* L) {
2020-05-11 18:05:30 +00:00
World* world = luax_checktype(L, 1, World);
lovrWorldDestroyData(world);
return 0;
}
2020-05-11 18:05:30 +00:00
static int l_lovrWorldGetTags(lua_State* L) {
World* world = luax_checktype(L, 1, World);
lua_newtable(L);
for (uint32_t i = 0; i < MAX_TAGS; i++) {
const char* tag = lovrWorldGetTagName(world, i);
if (tag == NULL)
break;
lua_pushstring(L, tag);
lua_rawseti(L, -2, i + 1);
2020-05-11 18:05:30 +00:00
}
return 1;
}
2020-05-11 18:05:30 +00:00
2024-04-08 18:11:28 +00:00
static int l_lovrWorldGetColliderCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
2024-04-08 18:11:28 +00:00
uint32_t count = lovrWorldGetColliderCount(world);
lua_pushinteger(L, count);
return 1;
}
2020-05-11 18:05:30 +00:00
2024-04-08 18:11:28 +00:00
static int l_lovrWorldGetJointCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
2024-04-08 18:11:28 +00:00
uint32_t count = lovrWorldGetJointCount(world);
lua_pushinteger(L, count);
2020-05-11 18:05:30 +00:00
return 1;
}
2024-04-08 18:11:28 +00:00
static int l_lovrWorldGetColliders(lua_State* L) {
2022-12-26 08:50:14 +00:00
World* world = luax_checktype(L, 1, World);
int index = 1;
2024-04-08 18:11:28 +00:00
Collider* collider = NULL;
lua_createtable(L, (int) lovrWorldGetColliderCount(world), 0);
while ((collider = lovrWorldGetColliders(world, collider)) != NULL) {
luax_pushtype(L, Collider, collider);
lua_rawseti(L, -2, index++);
2022-12-26 08:50:14 +00:00
}
return 1;
}
2024-04-08 18:11:28 +00:00
static int l_lovrWorldGetJoints(lua_State* L) {
2017-05-20 04:09:33 +00:00
World* world = luax_checktype(L, 1, World);
2024-04-08 18:11:28 +00:00
int index = 1;
Joint* joint = NULL;
lua_createtable(L, (int) lovrWorldGetJointCount(world), 0);
while ((joint = lovrWorldGetJoints(world, joint)) != NULL) {
luax_pushjoint(L, joint);
lua_rawseti(L, -2, index++);
}
return 1;
2017-05-20 04:09:33 +00:00
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldUpdate(lua_State* L) {
2017-05-20 04:09:33 +00:00
lua_settop(L, 3);
World* world = luax_checktype(L, 1, World);
float dt = luax_checkfloat(L, 2);
2017-05-20 04:09:33 +00:00
CollisionResolver resolver = lua_type(L, 3) == LUA_TFUNCTION ? collisionResolver : NULL;
lovrWorldUpdate(world, dt, resolver, L);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldComputeOverlaps(lua_State* L) {
2017-05-20 04:09:33 +00:00
World* world = luax_checktype(L, 1, World);
lovrWorldComputeOverlaps(world);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldOverlaps(lua_State* L) {
2017-05-20 04:09:33 +00:00
luax_checktype(L, 1, World);
lua_settop(L, 1);
lua_pushcclosure(L, nextOverlap, 1);
return 1;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldCollide(lua_State* L) {
2017-05-20 04:09:33 +00:00
World* world = luax_checktype(L, 1, World);
Shape* a = luax_checkshape(L, 2);
Shape* b = luax_checkshape(L, 3);
float friction = luax_optfloat(L, 4, -1.f);
float restitution = luax_optfloat(L, 5, -1.f);
2017-05-25 00:39:12 +00:00
lua_pushboolean(L, lovrWorldCollide(world, a, b, friction, restitution));
2017-05-20 04:09:33 +00:00
return 1;
}
2022-03-31 05:32:20 +00:00
static int l_lovrWorldGetContacts(lua_State* L) {
World* world = luax_checktype(L, 1, World);
Shape* a = luax_checkshape(L, 2);
Shape* b = luax_checkshape(L, 3);
uint32_t count;
Contact contacts[MAX_CONTACTS];
lovrWorldGetContacts(world, a, b, contacts, &count);
lua_createtable(L, count, 0);
for (uint32_t i = 0; i < count; i++) {
lua_createtable(L, 7, 0);
lua_pushnumber(L, contacts[i].x);
lua_rawseti(L, -2, 1);
lua_pushnumber(L, contacts[i].y);
lua_rawseti(L, -2, 2);
lua_pushnumber(L, contacts[i].z);
lua_rawseti(L, -2, 3);
lua_pushnumber(L, contacts[i].nx);
lua_rawseti(L, -2, 4);
lua_pushnumber(L, contacts[i].ny);
lua_rawseti(L, -2, 5);
lua_pushnumber(L, contacts[i].nz);
lua_rawseti(L, -2, 6);
lua_pushnumber(L, contacts[i].depth);
lua_rawseti(L, -2, 7);
lua_rawseti(L, -2, i + 1);
}
return 1;
}
2022-03-31 05:01:51 +00:00
static int l_lovrWorldRaycast(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float start[3], end[3];
int index = 2;
index = luax_readvec3(L, index, start, NULL);
2022-03-31 05:01:51 +00:00
index = luax_readvec3(L, index, end, NULL);
luaL_checktype(L, index, LUA_TFUNCTION);
lua_settop(L, index);
lovrWorldRaycast(world, start, end, raycastCallback, L);
2022-03-31 05:01:51 +00:00
return 0;
}
static int l_lovrWorldRaycastAny(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float start[3], end[3];
int index = 2;
index = luax_readvec3(L, index, start, NULL);
index = luax_readvec3(L, index, end, NULL);
RaycastData data = { 0 };
data.tag = lua_tostring(L, index);
lovrWorldRaycast(world, start, end, raycastAnyCallback, &data);
if (data.collider) {
luax_pushtype(L, Collider, data.collider);
lua_pushnumber(L, data.position[0]);
lua_pushnumber(L, data.position[1]);
lua_pushnumber(L, data.position[2]);
lua_pushnumber(L, data.normal[0]);
lua_pushnumber(L, data.normal[1]);
lua_pushnumber(L, data.normal[2]);
lua_pushinteger(L, data.shape + 1);
return 8;
} else {
lua_pushnil(L);
return 1;
}
}
static int l_lovrWorldRaycastClosest(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float start[3], end[3];
int index = 2;
index = luax_readvec3(L, index, start, NULL);
index = luax_readvec3(L, index, end, NULL);
RaycastData data = { .distance = FLT_MAX };
data.tag = lua_tostring(L, index);
lovrWorldRaycast(world, start, end, raycastClosestCallback, &data);
if (data.shape) {
luax_pushtype(L, Collider, data.collider);
lua_pushnumber(L, data.position[0]);
lua_pushnumber(L, data.position[1]);
lua_pushnumber(L, data.position[2]);
lua_pushnumber(L, data.normal[0]);
lua_pushnumber(L, data.normal[1]);
lua_pushnumber(L, data.normal[2]);
lua_pushinteger(L, data.shape + 1);
return 8;
} else {
lua_pushnil(L);
return 1;
}
}
2023-07-11 06:20:01 +00:00
static int l_lovrWorldQueryBox(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3], size[3];
int index = 2;
index = luax_readvec3(L, index, position, NULL);
index = luax_readvec3(L, index, size, NULL);
bool function = lua_type(L, index) == LUA_TFUNCTION;
2023-07-11 06:20:01 +00:00
lua_settop(L, index);
bool any = lovrWorldQueryBox(world, position, size, function ? queryCallback : NULL, L);
lua_pushboolean(L, any);
return 1;
2023-07-11 06:20:01 +00:00
}
static int l_lovrWorldQuerySphere(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
int index = luax_readvec3(L, 2, position, NULL);
float radius = luax_checkfloat(L, index++);
bool function = lua_type(L, index) == LUA_TFUNCTION;
2023-07-11 06:20:01 +00:00
lua_settop(L, index);
bool any = lovrWorldQuerySphere(world, position, radius, function ? queryCallback : NULL, L);
lua_pushboolean(L, any);
return 1;
2023-07-11 06:20:01 +00:00
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldGetGravity(lua_State* L) {
2017-05-16 05:03:01 +00:00
World* world = luax_checktype(L, 1, World);
2024-04-05 20:46:05 +00:00
float gravity[3];
lovrWorldGetGravity(world, gravity);
lua_pushnumber(L, gravity[0]);
lua_pushnumber(L, gravity[1]);
lua_pushnumber(L, gravity[2]);
2017-05-16 05:03:01 +00:00
return 3;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldSetGravity(lua_State* L) {
2017-05-16 05:03:01 +00:00
World* world = luax_checktype(L, 1, World);
float gravity[3];
luax_readvec3(L, 2, gravity, NULL);
2024-04-05 20:46:05 +00:00
lovrWorldSetGravity(world, gravity);
2017-05-16 05:03:01 +00:00
return 0;
}
Get/set World and Joint simulation parameters Tightness parameter is amount of force is exerted on collider to resolve collisions and enforce joint operation. Low values make joints loose, high values make it tight and can cause collider to overshot the joint target. With tightness set to 0 the joint loses its function. Going above 1 puts even more energy into joint oscillations. Tightness parameter is called ERP in ODE manual. The responseTime affects the time constant of physics simulation, both for collisions and for joint inertia. Low responseTime values make simulation tight and fast, higher values make it sluggish. For collisions it affects how fast penetration is resolved, with higher values resulting in spongy objects with more surface penetration and slower collision resolving. For joints the responseTime is similar to inertia, with higher responseTime values resulting in slow oscillations. The oscillation frequency is also affected by collider mass, so responseTime can be used to tweak the joint to get desired frequency with specific collider mass. Values higher than 1 are often desirable, especially for very light objects. Unlike tightness, responseTime is tweaked in orders of magnitude with useful values (depending on mass) being between 10^-8 and 10^8. Both parameters can be applied to World for simulation-wide usage, or specified per-joint in case of distance and ball joints. Other joints don't allow customizing these parameters, and will use World settings instead..
2020-05-29 14:38:32 +00:00
static int l_lovrWorldGetTightness(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float tightness = lovrWorldGetTightness(world);
2024-03-10 07:22:32 +00:00
lovrCheck(tightness >= 0, "Negative tightness factor causes simulation instability");
Get/set World and Joint simulation parameters Tightness parameter is amount of force is exerted on collider to resolve collisions and enforce joint operation. Low values make joints loose, high values make it tight and can cause collider to overshot the joint target. With tightness set to 0 the joint loses its function. Going above 1 puts even more energy into joint oscillations. Tightness parameter is called ERP in ODE manual. The responseTime affects the time constant of physics simulation, both for collisions and for joint inertia. Low responseTime values make simulation tight and fast, higher values make it sluggish. For collisions it affects how fast penetration is resolved, with higher values resulting in spongy objects with more surface penetration and slower collision resolving. For joints the responseTime is similar to inertia, with higher responseTime values resulting in slow oscillations. The oscillation frequency is also affected by collider mass, so responseTime can be used to tweak the joint to get desired frequency with specific collider mass. Values higher than 1 are often desirable, especially for very light objects. Unlike tightness, responseTime is tweaked in orders of magnitude with useful values (depending on mass) being between 10^-8 and 10^8. Both parameters can be applied to World for simulation-wide usage, or specified per-joint in case of distance and ball joints. Other joints don't allow customizing these parameters, and will use World settings instead..
2020-05-29 14:38:32 +00:00
lua_pushnumber(L, tightness);
return 1;
}
static int l_lovrWorldSetTightness(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float tightness = luax_checkfloat(L, 2);
lovrWorldSetTightness(world, tightness);
return 0;
}
static int l_lovrWorldGetResponseTime(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float responseTime = lovrWorldGetResponseTime(world);
lua_pushnumber(L, responseTime);
return 1;
}
static int l_lovrWorldSetResponseTime(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float responseTime = luax_checkfloat(L, 2);
2024-03-10 07:22:32 +00:00
lovrCheck(responseTime >= 0, "Negative response time causes simulation instability");
Get/set World and Joint simulation parameters Tightness parameter is amount of force is exerted on collider to resolve collisions and enforce joint operation. Low values make joints loose, high values make it tight and can cause collider to overshot the joint target. With tightness set to 0 the joint loses its function. Going above 1 puts even more energy into joint oscillations. Tightness parameter is called ERP in ODE manual. The responseTime affects the time constant of physics simulation, both for collisions and for joint inertia. Low responseTime values make simulation tight and fast, higher values make it sluggish. For collisions it affects how fast penetration is resolved, with higher values resulting in spongy objects with more surface penetration and slower collision resolving. For joints the responseTime is similar to inertia, with higher responseTime values resulting in slow oscillations. The oscillation frequency is also affected by collider mass, so responseTime can be used to tweak the joint to get desired frequency with specific collider mass. Values higher than 1 are often desirable, especially for very light objects. Unlike tightness, responseTime is tweaked in orders of magnitude with useful values (depending on mass) being between 10^-8 and 10^8. Both parameters can be applied to World for simulation-wide usage, or specified per-joint in case of distance and ball joints. Other joints don't allow customizing these parameters, and will use World settings instead..
2020-05-29 14:38:32 +00:00
lovrWorldSetResponseTime(world, responseTime);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldGetLinearDamping(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float damping, threshold;
lovrWorldGetLinearDamping(world, &damping, &threshold);
lua_pushnumber(L, damping);
lua_pushnumber(L, threshold);
return 2;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldSetLinearDamping(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float damping = luax_checkfloat(L, 2);
float threshold = luax_optfloat(L, 3, 0.0f);
lovrWorldSetLinearDamping(world, damping, threshold);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldGetAngularDamping(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float damping, threshold;
lovrWorldGetAngularDamping(world, &damping, &threshold);
lua_pushnumber(L, damping);
lua_pushnumber(L, threshold);
return 2;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldSetAngularDamping(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float damping = luax_checkfloat(L, 2);
float threshold = luax_optfloat(L, 3, 0.0f);
lovrWorldSetAngularDamping(world, damping, threshold);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldIsSleepingAllowed(lua_State* L) {
World* world = luax_checktype(L, 1, World);
lua_pushboolean(L, lovrWorldIsSleepingAllowed(world));
return 1;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldSetSleepingAllowed(lua_State* L) {
World* world = luax_checktype(L, 1, World);
2017-10-31 08:14:09 +00:00
bool allowed = lua_toboolean(L, 2);
lovrWorldSetSleepingAllowed(world, allowed);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldDisableCollisionBetween(lua_State* L) {
2017-05-25 22:01:40 +00:00
World* world = luax_checktype(L, 1, World);
const char* tag1 = luaL_checkstring(L, 2);
const char* tag2 = luaL_checkstring(L, 3);
lovrWorldDisableCollisionBetween(world, tag1, tag2);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldEnableCollisionBetween(lua_State* L) {
2017-05-25 22:01:40 +00:00
World* world = luax_checktype(L, 1, World);
const char* tag1 = luaL_checkstring(L, 2);
const char* tag2 = luaL_checkstring(L, 3);
lovrWorldEnableCollisionBetween(world, tag1, tag2);
return 0;
}
2019-02-17 22:52:22 +00:00
static int l_lovrWorldIsCollisionEnabledBetween(lua_State* L) {
2017-05-25 22:01:40 +00:00
World* world = luax_checktype(L, 1, World);
const char* tag1 = lua_tostring(L, 2);
const char* tag2 = lua_tostring(L, 3);
2017-05-25 22:01:40 +00:00
lua_pushboolean(L, lovrWorldIsCollisionEnabledBetween(world, tag1, tag2));
return 1;
}
static int l_lovrWorldGetStepCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
int iterations = lovrWorldGetStepCount(world);
lua_pushnumber(L, iterations);
return 1;
}
static int l_lovrWorldSetStepCount(lua_State* L) {
World* world = luax_checktype(L, 1, World);
int iterations = luaL_checkinteger(L, 2);
lovrWorldSetStepCount(world, iterations);
return 0;
}
2017-05-16 05:02:08 +00:00
const luaL_Reg lovrWorld[] = {
2017-05-20 02:11:58 +00:00
{ "newCollider", l_lovrWorldNewCollider },
{ "newBoxCollider", l_lovrWorldNewBoxCollider },
{ "newCapsuleCollider", l_lovrWorldNewCapsuleCollider },
{ "newCylinderCollider", l_lovrWorldNewCylinderCollider },
{ "newSphereCollider", l_lovrWorldNewSphereCollider },
2020-09-13 10:34:36 +00:00
{ "newMeshCollider", l_lovrWorldNewMeshCollider },
2022-08-12 05:04:59 +00:00
{ "newTerrainCollider", l_lovrWorldNewTerrainCollider },
2017-05-20 04:09:33 +00:00
{ "destroy", l_lovrWorldDestroy },
{ "getTags", l_lovrWorldGetTags },
{ "getColliderCount", l_lovrWorldGetColliderCount },
{ "getJointCount", l_lovrWorldGetJointCount },
{ "getColliders", l_lovrWorldGetColliders },
{ "getJoints", l_lovrWorldGetJoints },
2017-05-20 04:09:33 +00:00
{ "update", l_lovrWorldUpdate },
{ "computeOverlaps", l_lovrWorldComputeOverlaps },
{ "overlaps", l_lovrWorldOverlaps },
{ "collide", l_lovrWorldCollide },
2022-03-31 05:32:20 +00:00
{ "getContacts", l_lovrWorldGetContacts },
2022-03-31 05:01:51 +00:00
{ "raycast", l_lovrWorldRaycast },
{ "raycastAny", l_lovrWorldRaycastAny },
{ "raycastClosest", l_lovrWorldRaycastClosest },
2023-07-11 06:20:01 +00:00
{ "queryBox", l_lovrWorldQueryBox },
{ "querySphere", l_lovrWorldQuerySphere },
2017-05-16 05:03:01 +00:00
{ "getGravity", l_lovrWorldGetGravity },
{ "setGravity", l_lovrWorldSetGravity },
{ "disableCollisionBetween", l_lovrWorldDisableCollisionBetween },
{ "enableCollisionBetween", l_lovrWorldEnableCollisionBetween },
{ "isCollisionEnabledBetween", l_lovrWorldIsCollisionEnabledBetween },
// Deprecated
Get/set World and Joint simulation parameters Tightness parameter is amount of force is exerted on collider to resolve collisions and enforce joint operation. Low values make joints loose, high values make it tight and can cause collider to overshot the joint target. With tightness set to 0 the joint loses its function. Going above 1 puts even more energy into joint oscillations. Tightness parameter is called ERP in ODE manual. The responseTime affects the time constant of physics simulation, both for collisions and for joint inertia. Low responseTime values make simulation tight and fast, higher values make it sluggish. For collisions it affects how fast penetration is resolved, with higher values resulting in spongy objects with more surface penetration and slower collision resolving. For joints the responseTime is similar to inertia, with higher responseTime values resulting in slow oscillations. The oscillation frequency is also affected by collider mass, so responseTime can be used to tweak the joint to get desired frequency with specific collider mass. Values higher than 1 are often desirable, especially for very light objects. Unlike tightness, responseTime is tweaked in orders of magnitude with useful values (depending on mass) being between 10^-8 and 10^8. Both parameters can be applied to World for simulation-wide usage, or specified per-joint in case of distance and ball joints. Other joints don't allow customizing these parameters, and will use World settings instead..
2020-05-29 14:38:32 +00:00
{ "getTightness", l_lovrWorldGetTightness },
{ "setTightness", l_lovrWorldSetTightness },
{ "getResponseTime", l_lovrWorldGetResponseTime },
{ "setResponseTime", l_lovrWorldSetResponseTime },
{ "getLinearDamping", l_lovrWorldGetLinearDamping },
{ "setLinearDamping", l_lovrWorldSetLinearDamping },
{ "getAngularDamping", l_lovrWorldGetAngularDamping },
{ "setAngularDamping", l_lovrWorldSetAngularDamping },
{ "isSleepingAllowed", l_lovrWorldIsSleepingAllowed },
{ "setSleepingAllowed", l_lovrWorldSetSleepingAllowed },
{ "getStepCount", l_lovrWorldGetStepCount },
{ "setStepCount", l_lovrWorldSetStepCount },
2017-05-16 05:02:08 +00:00
{ NULL, NULL }
};