Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix shape cast initial overlap and tolerance #125

Merged
merged 2 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 94 additions & 23 deletions samples/sample_collision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1598,14 +1598,14 @@ class RayCastWorld : public Sample
{
const char* castTypes[] = {"Ray", "Circle", "Capsule", "Polygon"};
int castType = int(m_castType);
if (ImGui::Combo("Cast Type", &castType, castTypes, IM_ARRAYSIZE(castTypes)))
if (ImGui::Combo("Type", &castType, castTypes, IM_ARRAYSIZE(castTypes)))
{
m_castType = CastType(castType);
}

if (m_castType != e_rayCast)
{
ImGui::SliderFloat("radius", &m_castRadius, 0.0f, 2.0f, "%.1f");
ImGui::SliderFloat("Radius", &m_castRadius, 0.0f, 2.0f, "%.1f");
}

const char* modes[] = {"Any", "Closest", "Multiple", "Sorted"};
Expand Down Expand Up @@ -3274,10 +3274,11 @@ class ShapeCast : public Sample
if (settings.restart == false)
{
g_camera.m_center = {-1.5f, 1.0f};
g_camera.m_zoom = 0.12f;
g_camera.m_zoom = 0.2f;
}

#if 1
// box swept against a triangle
m_vAs[0] = {-0.5f, 1.0f};
m_vAs[1] = {0.5f, 1.0f};
m_vAs[2] = {0.0f, 0.0f};
Expand All @@ -3297,53 +3298,99 @@ class ShapeCast : public Sample
m_transformB.q = b2Rot_identity;
m_translationB = {8.0f, 0.0f};
#elif 0
m_vAs[0].Set(0.0f, 0.0f);
// A point swept against a box
m_vAs[0] = {-0.5f, -0.5f};
m_vAs[1] = {0.5f, -0.5f};
m_vAs[2] = {0.5f, 0.5f};
m_vAs[3] = {-0.5f, 0.5f};
m_countA = 4;
m_radiusA = 0.0f;

m_vBs[0] = {0.0f, 0.0f};
m_countB = 1;
m_radiusB = 0.0f;

m_transformA.p = {0.0f, 0.0f};
m_transformA.q = b2Rot_identity;
m_transformB.p = {-1.0f, 0.0f};
m_transformB.q = b2Rot_identity;
m_translationB = {1.0f, 0.0f};
#elif 0
m_vAs[0] = {0.0f, 0.0f};
m_countA = 1;
m_radiusA = 0.5f;

m_vBs[0].Set(0.0f, 0.0f);
m_vBs[0] = {0.0f, 0.0f};
m_countB = 1;
m_radiusB = 0.5f;

m_transformA.p.Set(0.0f, 0.25f);
m_transformA.q.SetIdentity();
m_transformB.p.Set(-4.0f, 0.0f);
m_transformB.q.SetIdentity();
m_translationB.Set(8.0f, 0.0f);
m_transformA.p = {0.0f, 0.25f};
m_transformA.q = b2Rot_identity;
m_transformB.p = {-4.0f, 0.0f};
m_transformB.q = b2Rot_identity;
m_translationB = {8.0f, 0.0f};
#else
m_vAs[0].Set(0.0f, 0.0f);
m_vAs[1].Set(2.0f, 0.0f);
m_vAs[0] = {0.0f, 0.0f};
m_vAs[1] = {2.0f, 0.0f};
m_countA = 2;
m_radiusA = b2_polygonRadius;
m_radiusA = 0.0f;

m_vBs[0].Set(0.0f, 0.0f);
m_vBs[0] = {0.0f, 0.0f};
m_countB = 1;
m_radiusB = 0.25f;

// Initial overlap
m_transformA.p.Set(0.0f, 0.0f);
m_transformA.q.SetIdentity();
m_transformB.p.Set(-0.244360745f, 0.05999358f);
m_transformB.q.SetIdentity();
m_translationB.Set(0.0f, 0.0399999991f);
m_transformA.p = b2Vec2_zero;
m_transformA.q = b2Rot_identity;
m_transformB.p = {-0.244360745f, 0.05999358f};
m_transformB.q = b2Rot_identity;
m_translationB = {0.0f, 0.0399999991f};
#endif

m_rayDrag = false;
}

static Sample* Create(Settings& settings)
{
return new ShapeCast(settings);
}

void MouseDown(b2Vec2 p, int button, int mods) override
{
if (button == GLFW_MOUSE_BUTTON_1)
{
m_transformB.p = p;
m_rayDrag = true;
}
}

void MouseUp(b2Vec2, int button) override
{
if (button == GLFW_MOUSE_BUTTON_1)
{
m_rayDrag = false;
}
}

void MouseMove(b2Vec2 p) override
{
if (m_rayDrag)
{
m_translationB = b2Sub(p, m_transformB.p);
}
}

void Step(Settings& settings) override
{
Sample::Step(settings);

b2ShapeCastPairInput input;
b2ShapeCastPairInput input = {0};
input.proxyA = b2MakeProxy(m_vAs, m_countA, m_radiusA);
input.proxyB = b2MakeProxy(m_vBs, m_countB, m_radiusB);
input.transformA = m_transformA;
input.transformB = m_transformB;
input.translationB = m_translationB;
input.maxFraction = 1.0f;

b2CastOutput output = b2ShapeCast(&input);

Expand Down Expand Up @@ -3374,7 +3421,14 @@ class ShapeCast : public Sample

if (m_countA == 1)
{
g_draw.DrawCircle(vertices[0], m_radiusA, {0.9f, 0.9f, 0.9f, 1.0f});
if (m_radiusA > 0.0f)
{
g_draw.DrawCircle(vertices[0], m_radiusA, {0.9f, 0.9f, 0.9f, 1.0f});
}
else
{
g_draw.DrawPoint(vertices[0], 5.0f, {0.9f, 0.9f, 0.9f, 1.0f});
}
}
else
{
Expand All @@ -3388,7 +3442,14 @@ class ShapeCast : public Sample

if (m_countB == 1)
{
g_draw.DrawCircle(vertices[0], m_radiusB, {0.5f, 0.9f, 0.5f, 1.0f});
if (m_radiusB > 0.0f)
{
g_draw.DrawCircle(vertices[0], m_radiusB, {0.5f, 0.9f, 0.5f, 1.0f});
}
else
{
g_draw.DrawPoint(vertices[0], 5.0f, {0.5f, 0.9f, 0.5f, 1.0f});
}
}
else
{
Expand All @@ -3402,7 +3463,14 @@ class ShapeCast : public Sample

if (m_countB == 1)
{
g_draw.DrawCircle(vertices[0], m_radiusB, {0.5f, 0.7f, 0.9f, 1.0f});
if (m_radiusB > 0.0f)
{
g_draw.DrawCircle(vertices[0], m_radiusB, {0.5f, 0.7f, 0.9f, 1.0f});
}
else
{
g_draw.DrawPoint(vertices[0], 5.0f, {0.5f, 0.7f, 0.9f, 1.0f});
}
}
else
{
Expand All @@ -3416,6 +3484,8 @@ class ShapeCast : public Sample
b2Vec2 p2 = b2MulAdd(p1, 1.0f, output.normal);
g_draw.DrawSegment(p1, p2, {0.9f, 0.3f, 0.3f, 1.0f});
}

g_draw.DrawSegment(m_transformB.p, b2Add(m_transformB.p, m_translationB), {0.9f, 0.9f, 0.9f, 1.0f});
}

b2Vec2 m_vAs[b2_maxPolygonVertices];
Expand All @@ -3429,6 +3499,7 @@ class ShapeCast : public Sample
b2Transform m_transformA;
b2Transform m_transformB;
b2Vec2 m_translationB;
bool m_rayDrag;
};

static int sampleShapeCast = RegisterSample("Collision", "Shape Cast", ShapeCast::Create);
Expand Down
48 changes: 48 additions & 0 deletions samples/sample_continuous.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,51 @@ class GhostCollision : public Sample
};

static int sampleGhostCollision = RegisterSample("Continuous", "Ghost Collision", GhostCollision::Create);

// Speculative collision failure case suggested by Dirk Gregorius
class SpeculativeFail : public Sample
{
public:
SpeculativeFail(Settings& settings)
: Sample(settings)
{
if (settings.restart == false)
{
g_camera.m_center = {1.0f, 5.0f};
g_camera.m_zoom = 0.25f;
}

{
b2BodyDef bodyDef = b2DefaultBodyDef();
b2BodyId groundId = b2CreateBody(m_worldId, &bodyDef);

b2ShapeDef shapeDef = b2DefaultShapeDef();
b2Segment segment = {{-10.0f, 0.0f}, {10.0f, 0.0f}};
b2CreateSegmentShape(groundId, &shapeDef, &segment);

b2Vec2 points[5] = {{-2.0f, 4.0f}, {2.0f, 4.0f}, {2.0f, 4.1f}, {-0.5f, 4.2f}, {-2.0f, 4.2f}};
b2Hull hull = b2ComputeHull(points, 5);
b2Polygon poly = b2MakePolygon(&hull, 0.0f);
b2CreatePolygonShape(groundId, &shapeDef, &poly);
}

{
b2BodyDef bodyDef = b2DefaultBodyDef();
bodyDef.type = b2_dynamicBody;
bodyDef.position = {0.0f, 8.0f};
bodyDef.linearVelocity = {0.0f, -100.0f};
b2BodyId bodyId = b2CreateBody(m_worldId, &bodyDef);

b2ShapeDef shapeDef = b2DefaultShapeDef();
b2Polygon box = b2MakeBox(2.0f, 0.05f);
b2CreatePolygonShape(bodyId, &shapeDef, &box);
}
}

static Sample* Create(Settings& settings)
{
return new SpeculativeFail(settings);
}
};

static int sampleSpeculativeFail = RegisterSample("Continuous", "Speculative Fail", SpeculativeFail::Create);
Loading
Loading