1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-02 12:33:52 +00:00

Merge pull request #687 from xiejiangzhi/world_query_early_exit

World query early exit
This commit is contained in:
Bjorn 2023-07-20 17:15:58 -07:00 committed by GitHub
commit fd49a4a287
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 16 deletions

View file

@ -25,7 +25,7 @@ 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) {
static bool raycastCallback(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata) {
lua_State* L = userdata;
lua_pushvalue(L, -1);
luax_pushshape(L, shape);
@ -35,14 +35,20 @@ static void raycastCallback(Shape* shape, float x, float y, float z, float nx, f
lua_pushnumber(L, nx);
lua_pushnumber(L, ny);
lua_pushnumber(L, nz);
lua_call(L, 7, 0);
lua_call(L, 7, 1);
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
lua_pop(L, 1);
return shouldStop;
}
static void queryCallback(Shape* shape, void* userdata) {
static bool queryCallback(Shape* shape, void* userdata) {
lua_State* L = userdata;
lua_pushvalue(L, -1);
luax_pushshape(L, shape);
lua_call(L, 1, 0);
lua_call(L, 1, 1);
bool shouldStop = lua_type(L, -1) == LUA_TBOOLEAN && !lua_toboolean(L, -1);
lua_pop(L, 1);
return shouldStop;
}
static int l_lovrWorldNewCollider(lua_State* L) {

View file

@ -60,11 +60,14 @@ static void customNearCallback(void* data, dGeomID shapeA, dGeomID shapeB) {
typedef struct {
RaycastCallback callback;
void* userdata;
bool shouldStop;
} RaycastData;
static void raycastCallback(void* data, dGeomID a, dGeomID b) {
RaycastCallback callback = ((RaycastData*) data)->callback;
void* userdata = ((RaycastData*) data)->userdata;
static void raycastCallback(void* d, dGeomID a, dGeomID b) {
RaycastData* data = d;
if (data->shouldStop) return;
RaycastCallback callback = data->callback;
void* userdata = data->userdata;
Shape* shape = dGeomGetData(b);
if (!shape) {
@ -75,7 +78,9 @@ static void raycastCallback(void* data, dGeomID a, dGeomID b) {
int count = dCollide(a, b, MAX_CONTACTS, &contact->geom, sizeof(dContact));
for (int i = 0; i < count; i++) {
dContactGeom g = contact[i].geom;
callback(shape, g.pos[0], g.pos[1], g.pos[2], g.normal[0], g.normal[1], g.normal[2], userdata);
data->shouldStop = callback(
shape, g.pos[0], g.pos[1], g.pos[2], g.normal[0], g.normal[1], g.normal[2], userdata
);
}
}
@ -83,19 +88,25 @@ typedef struct {
QueryCallback callback;
void* userdata;
bool called;
bool shouldStop;
} QueryData;
static void queryCallback(void* d, dGeomID a, dGeomID b) {
Shape* shape = dGeomGetData(b);
QueryData* data = d;
if (data->shouldStop) return;
Shape* shape = dGeomGetData(b);
if (!shape) {
return;
}
QueryData* data = d;
dContactGeom contact;
if (dCollide(a, b, 1 | CONTACTS_UNIMPORTANT, &contact, sizeof(contact))) {
if (data->callback) data->callback(shape, data->userdata);
if (data->callback) {
data->shouldStop = data->callback(shape, data->userdata);
} else {
data->shouldStop = true;
}
data->called = true;
}
}
@ -298,7 +309,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) {
RaycastData data = { .callback = callback, .userdata = userdata };
RaycastData data = { .callback = callback, .userdata = userdata, .shouldStop = false };
float dx = x2 - x1;
float dy = y2 - y1;
float dz = z2 - z1;
@ -310,7 +321,7 @@ 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) {
QueryData data = { .callback = callback, .userdata = userdata, .called = false };
QueryData data = { .callback = callback, .userdata = userdata, .called = false, .shouldStop = false };
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);
@ -319,7 +330,7 @@ bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCall
}
bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback callback, void* userdata) {
QueryData data = { .callback = callback, .userdata = userdata, .called = false };
QueryData data = { .callback = callback, .userdata = userdata, .called = false, .shouldStop = false };
dGeomID sphere = dCreateSphere(world->space, fabsf(radius));
dGeomSetPosition(sphere, position[0], position[1], position[2]);
dSpaceCollide2(sphere, (dGeomID) world->space, &data, queryCallback);

View file

@ -26,8 +26,8 @@ typedef Joint HingeJoint;
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);
typedef bool (*RaycastCallback)(Shape* shape, float x, float y, float z, float nx, float ny, float nz, void* userdata);
typedef bool (*QueryCallback)(Shape* shape, void* userdata);
bool lovrPhysicsInit(void);
void lovrPhysicsDestroy(void);