mirror of https://github.com/bjornbytes/lovr.git
World:shapecast;
This commit is contained in:
parent
5f6880f8ef
commit
ee76f3418a
|
@ -221,6 +221,28 @@ static int l_lovrWorldRaycast(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrWorldShapecast(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
int index = 2;
|
||||
Shapecast shapecast;
|
||||
shapecast.shape = luax_checktype(L, index++, Shape);
|
||||
index = luax_readvec3(L, index, shapecast.start, NULL);
|
||||
index = luax_readvec3(L, index, shapecast.end, NULL);
|
||||
shapecast.scale = luax_optfloat(L, index++, 1.f);
|
||||
index = luax_readquat(L, index, shapecast.orientation, NULL);
|
||||
if (lua_isnoneornil(L, index)) {
|
||||
CastResult hit;
|
||||
if (lovrWorldShapecast(world, &shapecast, castClosestCallback, &hit)) {
|
||||
return luax_pushcastresult(L, &hit);
|
||||
}
|
||||
} else {
|
||||
luaL_checktype(L, index, LUA_TFUNCTION);
|
||||
lua_settop(L, index);
|
||||
lovrWorldShapecast(world, &shapecast, castCallback, L);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrWorldQueryBox(lua_State* L) {
|
||||
World* world = luax_checktype(L, 1, World);
|
||||
float position[3], size[3];
|
||||
|
@ -396,6 +418,7 @@ const luaL_Reg lovrWorld[] = {
|
|||
{ "getJoints", l_lovrWorldGetJoints },
|
||||
{ "update", l_lovrWorldUpdate },
|
||||
{ "raycast", l_lovrWorldRaycast },
|
||||
{ "shapecast", l_lovrWorldShapecast },
|
||||
{ "queryBox", l_lovrWorldQueryBox },
|
||||
{ "querySphere", l_lovrWorldQuerySphere },
|
||||
{ "getGravity", l_lovrWorldGetGravity },
|
||||
|
|
|
@ -47,6 +47,14 @@ typedef struct {
|
|||
float end[3];
|
||||
} Raycast;
|
||||
|
||||
typedef struct {
|
||||
Shape* shape;
|
||||
float start[3];
|
||||
float end[3];
|
||||
float scale;
|
||||
float orientation[4];
|
||||
} Shapecast;
|
||||
|
||||
typedef struct {
|
||||
Collider* collider;
|
||||
Shape* shape;
|
||||
|
@ -67,6 +75,7 @@ Collider* lovrWorldGetColliders(World* world, Collider* collider);
|
|||
Joint* lovrWorldGetJoints(World* world, Joint* joint);
|
||||
void lovrWorldUpdate(World* world, float dt);
|
||||
bool lovrWorldRaycast(World* world, Raycast* raycast, CastCallback* callback, void* userdata);
|
||||
bool lovrWorldShapecast(World* world, Shapecast* shapecast, CastCallback* 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);
|
||||
void lovrWorldGetGravity(World* world, float gravity[3]);
|
||||
|
|
|
@ -188,13 +188,14 @@ void lovrWorldUpdate(World* world, float dt) {
|
|||
typedef struct {
|
||||
World* world;
|
||||
Raycast* raycast;
|
||||
Shapecast* shapecast;
|
||||
CastCallback* callback;
|
||||
void* userdata;
|
||||
} RaycastContext;
|
||||
} CastContext;
|
||||
|
||||
static float raycastCallback(void* arg, JPH_RayCastResult* result) {
|
||||
RaycastContext* ctx = arg;
|
||||
CastResult hit;
|
||||
CastContext* ctx = arg;
|
||||
Raycast* raycast = ctx->raycast;
|
||||
hit.collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(ctx->world->bodies, result->bodyID);
|
||||
hit.shape = subshapeToShape(hit.collider, result->subShapeID2);
|
||||
|
@ -218,7 +219,7 @@ bool lovrWorldRaycast(World* world, Raycast* raycast, CastCallback* callback, vo
|
|||
JPH_RVec3* origin = vec3_toJolt(raycast->start);
|
||||
JPH_Vec3* direction = vec3_toJolt(dir);
|
||||
|
||||
RaycastContext context = {
|
||||
CastContext context = {
|
||||
.world = world,
|
||||
.raycast = raycast,
|
||||
.callback = callback,
|
||||
|
@ -228,27 +229,64 @@ bool lovrWorldRaycast(World* world, Raycast* raycast, CastCallback* callback, vo
|
|||
return JPH_NarrowPhaseQuery_CastRay2(query, origin, direction, raycastCallback, &context, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static float shapecastCallback(void* arg, JPH_ShapeCastResult* result) {
|
||||
CastResult hit;
|
||||
CastContext* ctx = arg;
|
||||
Shapecast* shapecast = ctx->shapecast;
|
||||
hit.collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(ctx->world->bodies, result->bodyID2);
|
||||
hit.shape = subshapeToShape(hit.collider, result->subShapeID2);
|
||||
vec3_fromJolt(hit.position, &result->contactPointOn2);
|
||||
JPH_Vec3 normal;
|
||||
JPH_Body_GetWorldSpaceSurfaceNormal(hit.collider->body, result->subShapeID2, &result->contactPointOn2, &normal);
|
||||
vec3_fromJolt(hit.normal, &normal);
|
||||
hit.fraction = result->fraction;
|
||||
return ctx->callback(ctx->userdata, &hit);
|
||||
}
|
||||
|
||||
bool lovrWorldShapecast(World* world, Shapecast* shapecast, CastCallback callback, void* userdata) {
|
||||
const JPH_NarrowPhaseQuery* query = JPH_PhysicsSystem_GetNarrowPhaseQueryNoLock(world->system);
|
||||
|
||||
JPH_Shape* shape = shapecast->shape->shape;
|
||||
|
||||
JPH_Vec3 centerOfMass;
|
||||
JPH_Shape_GetCenterOfMass(shape, ¢erOfMass);
|
||||
|
||||
JPH_RMatrix4x4 transform;
|
||||
mat4_fromPose(&transform.m11, shapecast->start, shapecast->orientation);
|
||||
mat4_translate(&transform.m11, centerOfMass.x, centerOfMass.y, centerOfMass.z);
|
||||
mat4_scale(&transform.m11, shapecast->scale, shapecast->scale, shapecast->scale); // TODO does this work, or should we use scale arg?
|
||||
|
||||
float dir[3];
|
||||
vec3_init(dir, shapecast->end);
|
||||
vec3_sub(dir, shapecast->start);
|
||||
JPH_Vec3* direction = vec3_toJolt(dir);
|
||||
JPH_RVec3 offset = { 0.f, 0.f, 0.f };
|
||||
|
||||
CastContext context = {
|
||||
.world = world,
|
||||
.shapecast = shapecast,
|
||||
.callback = callback,
|
||||
.userdata = userdata
|
||||
};
|
||||
|
||||
return JPH_NarrowPhaseQuery_CastShape(query, shape, &transform, direction, &offset, shapecastCallback, &context, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
World* world;
|
||||
QueryCallback* callback;
|
||||
void* userdata;
|
||||
} QueryInfo;
|
||||
} QueryContext;
|
||||
|
||||
static void queryCallback(void* arg, JPH_BodyID id) {
|
||||
QueryInfo* query = arg;
|
||||
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(query->world->bodies, id);
|
||||
if (query->callback) query->callback(query->userdata, collider);
|
||||
QueryContext* ctx = arg;
|
||||
Collider* collider = (Collider*) (uintptr_t) JPH_BodyInterface_GetUserData(ctx->world->bodies, id);
|
||||
if (ctx->callback) ctx->callback(ctx->userdata, collider);
|
||||
}
|
||||
|
||||
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback* callback, void* userdata) {
|
||||
const JPH_BroadPhaseQuery* query = JPH_PhysicsSystem_GetBroadPhaseQuery(world->system);
|
||||
|
||||
QueryInfo info = {
|
||||
.world = world,
|
||||
.callback = callback,
|
||||
.userdata = userdata
|
||||
};
|
||||
|
||||
JPH_AABox box;
|
||||
box.min.x = position[0] - size[0] * .5f;
|
||||
box.min.y = position[1] - size[1] * .5f;
|
||||
|
@ -256,19 +294,26 @@ bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCall
|
|||
box.max.x = position[0] + size[0] * .5f;
|
||||
box.max.y = position[1] + size[1] * .5f;
|
||||
box.max.z = position[2] + size[2] * .5f;
|
||||
return JPH_BroadPhaseQuery_CollideAABox(query, &box, queryCallback, &info, NULL, NULL);
|
||||
}
|
||||
|
||||
bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback* callback, void* userdata) {
|
||||
const JPH_BroadPhaseQuery* query = JPH_PhysicsSystem_GetBroadPhaseQuery(world->system);
|
||||
|
||||
QueryInfo info = {
|
||||
QueryContext context = {
|
||||
.world = world,
|
||||
.callback = callback,
|
||||
.userdata = userdata
|
||||
};
|
||||
|
||||
return JPH_BroadPhaseQuery_CollideSphere(query, vec3_toJolt(position), radius, queryCallback, &info, NULL, NULL);
|
||||
return JPH_BroadPhaseQuery_CollideAABox(query, &box, queryCallback, &context, NULL, NULL);
|
||||
}
|
||||
|
||||
bool lovrWorldQuerySphere(World* world, float position[3], float radius, QueryCallback* callback, void* userdata) {
|
||||
const JPH_BroadPhaseQuery* query = JPH_PhysicsSystem_GetBroadPhaseQuery(world->system);
|
||||
|
||||
QueryContext context = {
|
||||
.world = world,
|
||||
.callback = callback,
|
||||
.userdata = userdata
|
||||
};
|
||||
|
||||
return JPH_BroadPhaseQuery_CollideSphere(query, vec3_toJolt(position), radius, queryCallback, &context, NULL, NULL);
|
||||
}
|
||||
|
||||
void lovrWorldGetGravity(World* world, float gravity[3]) {
|
||||
|
|
|
@ -299,6 +299,10 @@ bool lovrWorldRaycast(World* world, Raycast* raycast, CastCallback* callback, vo
|
|||
return false;
|
||||
}
|
||||
|
||||
bool lovrWorldShapecast(World* world, Shapecast* shapecast, CastCallback* callback, void* userdata) {
|
||||
lovrThrow("NYI");
|
||||
}
|
||||
|
||||
bool lovrWorldQueryBox(World* world, float position[3], float size[3], QueryCallback* callback, void* userdata) {
|
||||
QueryData data = { .callback = callback, .userdata = userdata, .called = false, .shouldStop = false };
|
||||
dGeomID box = dCreateBox(world->space, fabsf(size[0]), fabsf(size[1]), fabsf(size[2]));
|
||||
|
|
Loading…
Reference in New Issue