World:queryBox; World:querySphere;

This commit is contained in:
bjorn 2023-07-10 23:20:01 -07:00
parent 9bf2def86d
commit b268cd1776
3 changed files with 71 additions and 1 deletions

View File

@ -27,7 +27,6 @@ static int nextOverlap(lua_State* L) {
static void raycastCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) {
lua_State* L = userdata;
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, -1);
luax_pushshape(L, shape);
lua_pushnumber(L, x);
@ -39,6 +38,13 @@ static void raycastCallback(Shape* shape, float x, float y, float z, float nx, f
lua_call(L, 7, 0);
}
static void queryCallback(Shape* shape, void* userdata) {
lua_State* L = userdata;
lua_pushvalue(L, -1);
luax_pushshape(L, shape);
lua_call(L, 1, 0);
}
static int l_lovrWorldNewCollider(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float position[3];
@ -242,6 +248,29 @@ static int l_lovrWorldRaycast(lua_State* L) {
return 0;
}
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);
luaL_checktype(L, index, LUA_TFUNCTION);
lua_settop(L, index);
lovrWorldQueryBox(world, position, size, queryCallback, L);
return 0;
}
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++);
luaL_checktype(L, index, LUA_TFUNCTION);
lua_settop(L, index);
lovrWorldQuerySphere(world, position, radius, queryCallback, L);
return 0;
}
static int l_lovrWorldGetGravity(lua_State* L) {
World* world = luax_checktype(L, 1, World);
float x, y, z;
@ -392,6 +421,8 @@ const luaL_Reg lovrWorld[] = {
{ "collide", l_lovrWorldCollide },
{ "getContacts", l_lovrWorldGetContacts },
{ "raycast", l_lovrWorldRaycast },
{ "queryBox", l_lovrWorldQueryBox },
{ "querySphere", l_lovrWorldQuerySphere },
{ "getGravity", l_lovrWorldGetGravity },
{ "setGravity", l_lovrWorldSetGravity },
{ "getTightness", l_lovrWorldGetTightness },

View File

@ -79,6 +79,26 @@ static void raycastCallback(void* data, dGeomID a, dGeomID b) {
}
}
typedef struct {
QueryCallback callback;
void* userdata;
} QueryData;
static void queryCallback(void* data, dGeomID a, dGeomID b) {
QueryCallback callback = ((QueryData*) data)->callback;
void* userdata = ((QueryData*) data)->userdata;
Shape* shape = dGeomGetData(b);
if (!shape) {
return;
}
dContactGeom contact;
if (dCollide(a, b, 1 | CONTACTS_UNIMPORTANT, &contact, sizeof(contact))) {
callback(shape, userdata);
}
}
// XXX slow, but probably fine (tag names are not on any critical path), could switch to hashing if needed
static uint32_t findTag(World* world, const char* name) {
for (uint32_t i = 0; i < MAX_TAGS && world->tags[i]; i++) {
@ -288,6 +308,22 @@ void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, floa
dGeomDestroy(ray);
}
void lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata) {
QueryData data = { .callback = callback, .userdata = userdata };
dGeomID box = dCreateBox(world->space, fabsf(size[0]), fabsf(size[1]), fabsf(size[2]));
dGeomSetPosition(box, position[0], position[1], position[2]);
dSpaceCollide2(box, (dGeomID) world->space, &data, queryCallback);
dGeomDestroy(box);
}
void lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata) {
QueryData data = { .callback = callback, .userdata = userdata };
dGeomID sphere = dCreateSphere(world->space, fabsf(radius));
dGeomSetPosition(sphere, position[0], position[1], position[2]);
dSpaceCollide2(sphere, (dGeomID) world->space, &data, queryCallback);
dGeomDestroy(sphere);
}
Collider* lovrWorldGetFirstCollider(World* world) {
return world->head;
}

View File

@ -27,6 +27,7 @@ typedef Joint SliderJoint;
typedef void (*CollisionResolver)(World* world, void* userdata);
typedef void (*RaycastCallback)(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata);
typedef void (*QueryCallback)(Shape* shape, void* userdata);
bool lovrPhysicsInit(void);
void lovrPhysicsDestroy(void);
@ -50,6 +51,8 @@ int lovrWorldGetNextOverlap(World* world, Shape** a, Shape** b);
int lovrWorldCollide(World* world, Shape* a, Shape* b, float friction, float restitution);
void lovrWorldGetContacts(World* world, Shape* a, Shape* b, Contact contacts[MAX_CONTACTS], uint32_t* count);
void lovrWorldRaycast(World* world, float x1, float y1, float z1, float x2, float y2, float z2, RaycastCallback callback, void* userdata);
void lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback callback, void* userdata);
void lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata);
Collider* lovrWorldGetFirstCollider(World* world);
void lovrWorldGetGravity(World* world, float* x, float* y, float* z);
void lovrWorldSetGravity(World* world, float x, float y, float z);