Skip to content

Commit

Permalink
Add World:rayCastAny and World:rayCastClosest.
Browse files Browse the repository at this point in the history
They return hit position, normal, and ray fraction (if there is a hit), and also take an optional fixture category bitmask parameter.
  • Loading branch information
slime73 committed Oct 2, 2023
1 parent c3847d5 commit 28a898d
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 7 deletions.
72 changes: 72 additions & 0 deletions src/modules/physics/box2d/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,30 @@ float World::RayCastCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &po
return 0;
}

World::RayCastOneCallback::RayCastOneCallback(uint16 categoryMask, bool any)
: hit(false)
, hitPoint()
, hitNormal()
, hitFraction(1.0f)
, categoryMask(categoryMask)
, any(any)
{
}

float World::RayCastOneCallback::ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction)
{
if (categoryMask != 0xFFFF && (categoryMask & fixture->GetFilterData().categoryBits) == 0)
return -1;

hit = true;
hitPoint = point;
hitNormal = normal;
hitFraction = fraction;

// Returning the fraction makes sure it doesn't process anything farther away in subsequent iterations.
return any ? 0 : fraction;
}

void World::SayGoodbye(b2Fixture *fixture)
{
Fixture *f = (Fixture *)(fixture->GetUserData().pointer);
Expand Down Expand Up @@ -612,6 +636,54 @@ int World::rayCast(lua_State *L)
return 0;
}

int World::rayCastAny(lua_State *L)
{
float x1 = (float)luaL_checknumber(L, 1);
float y1 = (float)luaL_checknumber(L, 2);
float x2 = (float)luaL_checknumber(L, 3);
float y2 = (float)luaL_checknumber(L, 4);
uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF);
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
RayCastOneCallback raycast(categoryMaskBits, true);
world->RayCast(&raycast, v1, v2);
if (raycast.hit)
{
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
lua_pushnumber(L, hitPoint.x);
lua_pushnumber(L, hitPoint.y);
lua_pushnumber(L, raycast.hitNormal.x);
lua_pushnumber(L, raycast.hitNormal.y);
lua_pushnumber(L, raycast.hitFraction);
return 5;
}
return 0;
}

int World::rayCastClosest(lua_State *L)
{
float x1 = (float)luaL_checknumber(L, 1);
float y1 = (float)luaL_checknumber(L, 2);
float x2 = (float)luaL_checknumber(L, 3);
float y2 = (float)luaL_checknumber(L, 4);
uint16 categoryMaskBits = (uint16)luaL_optinteger(L, 5, 0xFFFF);
b2Vec2 v1 = Physics::scaleDown(b2Vec2(x1, y1));
b2Vec2 v2 = Physics::scaleDown(b2Vec2(x2, y2));
RayCastOneCallback raycast(categoryMaskBits, false);
world->RayCast(&raycast, v1, v2);
if (raycast.hit)
{
b2Vec2 hitPoint = Physics::scaleUp(raycast.hitPoint);
lua_pushnumber(L, hitPoint.x);
lua_pushnumber(L, hitPoint.y);
lua_pushnumber(L, raycast.hitNormal.x);
lua_pushnumber(L, raycast.hitNormal.y);
lua_pushnumber(L, raycast.hitFraction);
return 5;
}
return 0;
}

void World::destroy()
{
if (world == nullptr)
Expand Down
32 changes: 26 additions & 6 deletions src/modules/physics/box2d/World.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ class World : public Object, public b2ContactListener, public b2ContactFilter, p
{
public:
QueryCallback(World *world, lua_State *L, int idx);
~QueryCallback();
virtual bool ReportFixture(b2Fixture *fixture);
virtual ~QueryCallback();
bool ReportFixture(b2Fixture *fixture) override;
private:
World *world;
lua_State *L;
Expand All @@ -107,8 +107,8 @@ class World : public Object, public b2ContactListener, public b2ContactFilter, p
{
public:
CollectCallback(World *world, lua_State *L);
~CollectCallback();
virtual bool ReportFixture(b2Fixture *fixture);
virtual ~CollectCallback();
bool ReportFixture(b2Fixture *fixture) override;
private:
World *world;
lua_State *L;
Expand All @@ -119,15 +119,32 @@ class World : public Object, public b2ContactListener, public b2ContactFilter, p
{
public:
RayCastCallback(World *world, lua_State *L, int idx);
~RayCastCallback();
virtual float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction);
virtual ~RayCastCallback();
float ReportFixture(b2Fixture *fixture, const b2Vec2 &point, const b2Vec2 &normal, float fraction) override;
private:
World *world;
lua_State *L;
int funcidx;
int userargs;
};

class RayCastOneCallback : public b2RayCastCallback
{
public:
RayCastOneCallback(uint16 categoryMask, bool any);
virtual ~RayCastOneCallback() {};
float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override;

bool hit;
b2Vec2 hitPoint;
b2Vec2 hitNormal;
float hitFraction;

private:
uint16 categoryMask;
bool any;
};

/**
* Creates a new world.
**/
Expand Down Expand Up @@ -298,6 +315,9 @@ class World : public Object, public b2ContactListener, public b2ContactFilter, p
**/
int rayCast(lua_State *L);

int rayCastAny(lua_State *L);
int rayCastClosest(lua_State *L);

/**
* Destroy this world.
**/
Expand Down
22 changes: 21 additions & 1 deletion src/modules/physics/box2d/wrap_World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ int w_World_queryFixturesInArea(lua_State *L)
return t->queryFixturesInArea(L);
}

int w_World_queryBoundingBox(lua_State* L)
int w_World_queryBoundingBox(lua_State *L)
{
luax_markdeprecated(L, 1, "World:queryBoundingBox", API_METHOD, DEPRECATED_RENAMED, "World:queryFixturesInArea");
return w_World_queryFixturesInArea(L);
Expand All @@ -209,6 +209,24 @@ int w_World_rayCast(lua_State *L)
return ret;
}

int w_World_rayCastAny(lua_State *L)
{
World *t = luax_checkworld(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->rayCastAny(L); });
return ret;
}

int w_World_rayCastClosest(lua_State *L)
{
World *t = luax_checkworld(L, 1);
lua_remove(L, 1);
int ret = 0;
luax_catchexcept(L, [&]() { ret = t->rayCastClosest(L); });
return ret;
}

int w_World_destroy(lua_State *L)
{
World *t = luax_checkworld(L, 1);
Expand Down Expand Up @@ -245,6 +263,8 @@ static const luaL_Reg w_World_functions[] =
{ "queryFixturesInArea", w_World_queryFixturesInArea },
{ "getFixturesInArea", w_World_getFixturesInArea },
{ "rayCast", w_World_rayCast },
{ "rayCastAny", w_World_rayCastAny },
{ "rayCastClosest", w_World_rayCastClosest },
{ "destroy", w_World_destroy },
{ "isDestroyed", w_World_isDestroyed },

Expand Down

0 comments on commit 28a898d

Please sign in to comment.