From b407b709d4cd87b445545c98a52ae86b8ba6d44c Mon Sep 17 00:00:00 2001 From: Erin Catto Date: Mon, 29 Jul 2024 22:26:31 -0700 Subject: [PATCH] Hull validation (#178) sample UI clean up for #172 --- include/box2d/collision.h | 2 ++ samples/sample_benchmark.cpp | 32 +++++++++++-------- samples/sample_bodies.cpp | 15 +++++---- samples/sample_collision.cpp | 59 ++++++++++++++++++---------------- samples/sample_continuous.cpp | 12 ++++--- samples/sample_events.cpp | 6 ++-- samples/sample_geometry.cpp | 27 ++++++++++++++-- samples/sample_joints.cpp | 60 +++++++++++++++++++---------------- samples/sample_robustness.cpp | 8 +++-- samples/sample_shapes.cpp | 6 ++-- samples/sample_stacking.cpp | 2 +- src/geometry.c | 16 ++++++++-- 12 files changed, 149 insertions(+), 96 deletions(-) diff --git a/include/box2d/collision.h b/include/box2d/collision.h index 618d0f8d..0dc83764 100644 --- a/include/box2d/collision.h +++ b/include/box2d/collision.h @@ -175,9 +175,11 @@ typedef struct b2SmoothSegment B2_API bool b2IsValidRay(const b2RayCastInput* input); /// Make a convex polygon from a convex hull. This will assert if the hull is not valid. +/// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull B2_API b2Polygon b2MakePolygon(const b2Hull* hull, float radius); /// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid. +/// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull B2_API b2Polygon b2MakeOffsetPolygon(const b2Hull* hull, float radius, b2Transform transform); /// Make a square polygon, bypassing the need for a convex hull. diff --git a/samples/sample_benchmark.cpp b/samples/sample_benchmark.cpp index 8632d8b7..2e01372b 100644 --- a/samples/sample_benchmark.cpp +++ b/samples/sample_benchmark.cpp @@ -254,10 +254,10 @@ class BenchmarkBarrel : public Sample void UpdateUI() override { - float height = 100.0f; + float height = 80.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Stacks", nullptr, ImGuiWindowFlags_NoResize); + ImGui::SetNextWindowSize(ImVec2(220.0f, height)); + ImGui::Begin("Benchmark: Barrel", nullptr, ImGuiWindowFlags_NoResize); bool changed = false; const char* shapeTypes[] = {"Circle", "Capsule", "Mix", "Compound", "Human"}; @@ -372,10 +372,11 @@ class BenchmarkTumbler : public Sample void UpdateUI() override { - float height = 100.0f; + float height = 60.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Tumbler", nullptr, ImGuiWindowFlags_NoResize); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); + ImGui::Begin("Benchmark: Tumbler", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(120.0f); if (ImGui::SliderFloat("Speed", &m_motorSpeed, 0.0f, 100.0f, "%.f")) { @@ -387,6 +388,7 @@ class BenchmarkTumbler : public Sample } } + ImGui::PopItemWidth(); ImGui::End(); } @@ -515,10 +517,11 @@ class BenchmarkManyTumblers : public Sample void UpdateUI() override { - float height = 120.0f; + float height = 110.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Many Tumblers", nullptr, ImGuiWindowFlags_NoResize); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); + ImGui::Begin("Benchmark: Many Tumblers", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); bool changed = false; changed = changed || ImGui::SliderInt("Row Count", &m_rowCount, 1, 32); @@ -538,6 +541,7 @@ class BenchmarkManyTumblers : public Sample } } + ImGui::PopItemWidth(); ImGui::End(); } @@ -770,8 +774,9 @@ class BenchmarkManyPyramids : public Sample { float height = 160.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Stacks", nullptr, ImGuiWindowFlags_NoResize); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); + ImGui::Begin("Benchmark: Many Pyramids", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); bool changed = false; changed = changed || ImGui::SliderInt("Row Count", &m_rowCount, 1, 32); @@ -786,6 +791,7 @@ class BenchmarkManyPyramids : public Sample CreateScene(); } + ImGui::PopItemWidth(); ImGui::End(); } @@ -1152,10 +1158,10 @@ class BenchmarkJointGrid : public Sample void UpdateUI() override { - float height = 100.0f; + float height = 60.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Joint Grid", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Benchmark: Joint Grid", nullptr, ImGuiWindowFlags_NoResize); if (ImGui::SliderFloat("gravity", &m_gravity, 0.0f, 20.0f, "%.1f")) { diff --git a/samples/sample_bodies.cpp b/samples/sample_bodies.cpp index 69ddc480..2fe1a58a 100644 --- a/samples/sample_bodies.cpp +++ b/samples/sample_bodies.cpp @@ -185,10 +185,10 @@ class BodyType : public Sample void UpdateUI() override { - float height = 150.0f; + float height = 140.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::SetNextWindowSize(ImVec2(180.0f, height)); + ImGui::Begin("Body Type", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); if (ImGui::RadioButton("Static", m_type == b2_staticBody)) { @@ -525,11 +525,10 @@ class Weeble : public Sample void UpdateUI() override { - float height = 160.0f; + float height = 120.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); ImGui::Begin("Weeble", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); - if (ImGui::Button("Teleport")) { b2Body_SetTransform(m_weebleId, {0.0f, 5.0f}, 0.95 * b2_pi); @@ -539,9 +538,11 @@ class Weeble : public Sample { b2World_Explode(m_worldId, m_explosionPosition, m_explosionRadius, m_explosionMagnitude); } + ImGui::PushItemWidth(100.0f); ImGui::SliderFloat("Magnitude", &m_explosionMagnitude, -100.0f, 100.0f, "%.1f"); + ImGui::PopItemWidth(); ImGui::End(); } @@ -679,7 +680,7 @@ class Sleep : public Sample ImGui::SetNextWindowSize(ImVec2(240.0f, height)); ImGui::Begin("Sleep", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); - ImGui::PushItemWidth(140.0f); + ImGui::PushItemWidth(120.0f); ImGui::Text("Pendulum Tuning"); diff --git a/samples/sample_collision.cpp b/samples/sample_collision.cpp index dc633ee3..0b9b34f9 100644 --- a/samples/sample_collision.cpp +++ b/samples/sample_collision.cpp @@ -569,11 +569,13 @@ class DynamicTree : public Sample void UpdateUI() override { - float height = 340.0f; + float height = 320.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); + + ImGui::Begin("Dynamic Tree", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); - ImGui::Begin("Tree Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); bool changed = false; if (ImGui::SliderInt("rows", &m_rowCount, 0, 1000, "%d")) @@ -632,6 +634,7 @@ class DynamicTree : public Sample ImGui::Text("mouse button 1: ray cast"); ImGui::Text("mouse button 1 + shift: query"); + ImGui::PopItemWidth(); ImGui::End(); if (changed) @@ -910,17 +913,14 @@ class RayCast : public Sample { float height = 230.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); - ImGui::Begin("RayCast Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::Begin("Ray-cast", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); - if (ImGui::SliderFloat("x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f")) - { - } + ImGui::PushItemWidth(100.0f); - if (ImGui::SliderFloat("y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f")) - { - } + ImGui::SliderFloat("x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f"); + ImGui::SliderFloat("y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f"); if (ImGui::SliderFloat("angle", &m_angle, -b2_pi, b2_pi, "%.2f")) { @@ -931,9 +931,8 @@ class RayCast : public Sample //{ // } - if (ImGui::Checkbox("show fraction", &m_showFraction)) - { - } + ImGui::Checkbox("show fraction", &m_showFraction); + if (ImGui::Button("Reset")) { @@ -947,6 +946,8 @@ class RayCast : public Sample ImGui::Text("mouse btn 1 + shft: translate"); ImGui::Text("mouse btn 1 + ctrl: rotate"); + ImGui::PopItemWidth(); + ImGui::End(); } @@ -1566,9 +1567,9 @@ class RayCastWorld : public Sample { float height = 300.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); - ImGui::Begin("Options", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::Begin("Ray-cast World", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); ImGui::Checkbox("Simple", &m_simple); @@ -2051,9 +2052,9 @@ class OverlapWorld : public Sample { float height = 330.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(140.0f, height)); - ImGui::Begin("Options", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::Begin("Overlap World", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); if (ImGui::Button("Polygon 1")) Create(0); @@ -2256,7 +2257,7 @@ class Manifold : public Sample ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Manifold Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::Begin("Manifold", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); ImGui::SliderFloat("x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f"); ImGui::SliderFloat("y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f"); @@ -2907,11 +2908,12 @@ class SmoothManifold : public Sample void UpdateUI() override { - float height = 270.0f; + float height = 290.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(180.0f, height)); ImGui::Begin("Smooth Manifold", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); { const char* shapeTypes[] = {"Circle", "Box"}; @@ -2920,18 +2922,18 @@ class SmoothManifold : public Sample m_shapeType = ShapeType(shapeType); } - ImGui::SliderFloat("x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f"); - ImGui::SliderFloat("y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f"); + ImGui::SliderFloat("x Offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f"); + ImGui::SliderFloat("y Offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f"); - if (ImGui::SliderFloat("angle", &m_angle, -b2_pi, b2_pi, "%.2f")) + if (ImGui::SliderFloat("Angle", &m_angle, -b2_pi, b2_pi, "%.2f")) { m_transform.q = b2MakeRot(m_angle); } - ImGui::SliderFloat("round", &m_round, 0.0f, 0.4f, "%.1f"); - ImGui::Checkbox("show ids", &m_showIds); - ImGui::Checkbox("show separation", &m_showSeparation); - ImGui::Checkbox("show anchors", &m_showAnchors); + ImGui::SliderFloat("Round", &m_round, 0.0f, 0.4f, "%.1f"); + ImGui::Checkbox("Show Ids", &m_showIds); + ImGui::Checkbox("Show Separation", &m_showSeparation); + ImGui::Checkbox("Show Anchors", &m_showAnchors); if (ImGui::Button("Reset")) { @@ -2944,6 +2946,7 @@ class SmoothManifold : public Sample ImGui::Text("mouse button 1: drag"); ImGui::Text("mouse button 1 + shift: rotate"); + ImGui::PopItemWidth(); ImGui::End(); } diff --git a/samples/sample_continuous.cpp b/samples/sample_continuous.cpp index a4948df8..06b6dac7 100644 --- a/samples/sample_continuous.cpp +++ b/samples/sample_continuous.cpp @@ -340,11 +340,11 @@ class SkinnyBox : public Sample void UpdateUI() override { - float height = 130.0f; + float height = 110.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(140.0f, height)); - ImGui::Begin("Options", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Skinny Box", nullptr, ImGuiWindowFlags_NoResize); ImGui::Checkbox("Capsule", &m_capsule); @@ -603,11 +603,12 @@ class GhostCollision : public Sample void UpdateUI() override { - float height = 160.0f; + float height = 140.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(180.0f, height)); ImGui::Begin("Ghost Collision", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); if (ImGui::Checkbox("Chain", &m_useChain)) { @@ -649,6 +650,7 @@ class GhostCollision : public Sample Launch(); } + ImGui::PopItemWidth(); ImGui::End(); } diff --git a/samples/sample_events.cpp b/samples/sample_events.cpp index ffbb45b8..605dec2b 100644 --- a/samples/sample_events.cpp +++ b/samples/sample_events.cpp @@ -221,9 +221,9 @@ class SensorEvent : public Sample void UpdateUI() override { - float height = 100.0f; + float height = 90.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(140.0f, height)); ImGui::Begin("Sensor Event", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); @@ -445,7 +445,7 @@ class ContactEvent : public Sample ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Sample Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + ImGui::Begin("Contact Event", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); ImGui::SliderFloat("force", &m_force, 100.0f, 500.0f, "%.1f"); diff --git a/samples/sample_geometry.cpp b/samples/sample_geometry.cpp index b290accc..0c352604 100644 --- a/samples/sample_geometry.cpp +++ b/samples/sample_geometry.cpp @@ -44,6 +44,24 @@ class ConvexHull : public Sample m_points[6] = {3.73758054f, -1.11098099f }; m_points[7] = {1.33504069f, -4.43795443f }; + m_count = e_count; +#elif 0 + m_points[0] = {-0.328125, 0.179688}; + m_points[1] = {-0.203125, 0.304688}; + m_points[2] = {0.171875, 0.304688}; + m_points[3] = {0.359375, 0.117188}; + m_points[4] = {0.359375, -0.195313}; + m_points[5] = {0.234375, -0.320313}; + m_points[6] = {-0.265625, -0.257813}; + m_points[7] = {-0.328125, -0.132813}; + + b2Hull hull = b2ComputeHull(m_points, 8); + bool valid = b2ValidateHull(&hull); + if (valid == false) + { + assert(valid); + } + m_count = e_count; #else @@ -53,7 +71,7 @@ class ConvexHull : public Sample b2Vec2 lowerBound = {-4.0f, -4.0f}; b2Vec2 upperBound = {4.0f, 4.0f}; - for (int32_t i = 0; i < e_count; ++i) + for (int i = 0; i < e_count; ++i) { float x = 10.0f * RandomFloat(); float y = 10.0f * RandomFloat(); @@ -85,6 +103,9 @@ class ConvexHull : public Sample case GLFW_KEY_G: Generate(); break; + + default: + break; } } @@ -103,7 +124,7 @@ class ConvexHull : public Sample { #if 1 // defect hunting - for (int32_t i = 0; i < 10000; ++i) + for (int i = 0; i < 10000; ++i) { Generate(); hull = b2ComputeHull(m_points, m_count); @@ -125,7 +146,7 @@ class ConvexHull : public Sample // performance Generate(); b2Timer timer; - for (int32_t i = 0; i < 1000000; ++i) + for (int i = 0; i < 1000000; ++i) { hull = b2ComputeHull(m_points, m_count); } diff --git a/samples/sample_joints.cpp b/samples/sample_joints.cpp index ea375c79..b265939b 100644 --- a/samples/sample_joints.cpp +++ b/samples/sample_joints.cpp @@ -113,13 +113,14 @@ class DistanceJoint : public Sample void UpdateUI() override { - float height = 220.0f; + float height = 140.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(180.0f, height)); ImGui::Begin("Distance Joint", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); - if (ImGui::SliderFloat("length", &m_length, 0.1f, 4.0f, "%3.1f")) + if (ImGui::SliderFloat("Length", &m_length, 0.1f, 4.0f, "%3.1f")) { for (int i = 0; i < m_count; ++i) { @@ -128,7 +129,7 @@ class DistanceJoint : public Sample } } - if (ImGui::Checkbox("spring", &m_enableSpring)) + if (ImGui::Checkbox("Spring", &m_enableSpring)) { for (int i = 0; i < m_count; ++i) { @@ -139,7 +140,7 @@ class DistanceJoint : public Sample if (m_enableSpring) { - if (ImGui::SliderFloat("hertz", &m_hertz, 0.0f, 15.0f, "%3.1f")) + if (ImGui::SliderFloat("Hertz", &m_hertz, 0.0f, 15.0f, "%3.1f")) { for (int i = 0; i < m_count; ++i) { @@ -148,7 +149,7 @@ class DistanceJoint : public Sample } } - if (ImGui::SliderFloat("damping", &m_dampingRatio, 0.0f, 4.0f, "%3.1f")) + if (ImGui::SliderFloat("Damping", &m_dampingRatio, 0.0f, 4.0f, "%3.1f")) { for (int i = 0; i < m_count; ++i) { @@ -158,7 +159,7 @@ class DistanceJoint : public Sample } } - if (ImGui::Checkbox("limit", &m_enableLimit)) + if (ImGui::Checkbox("Limit", &m_enableLimit)) { for (int i = 0; i < m_count; ++i) { @@ -169,7 +170,7 @@ class DistanceJoint : public Sample if (m_enableLimit) { - if (ImGui::SliderFloat("min length", &m_minLength, 0.1f, 4.0f, "%3.1f")) + if (ImGui::SliderFloat("Min Length", &m_minLength, 0.1f, 4.0f, "%3.1f")) { for (int i = 0; i < m_count; ++i) { @@ -178,7 +179,7 @@ class DistanceJoint : public Sample } } - if (ImGui::SliderFloat("max length", &m_maxLength, 0.1f, 4.0f, "%3.1f")) + if (ImGui::SliderFloat("Max Length", &m_maxLength, 0.1f, 4.0f, "%3.1f")) { for (int i = 0; i < m_count; ++i) { @@ -189,11 +190,12 @@ class DistanceJoint : public Sample } int count = m_count; - if (ImGui::SliderInt("count", &count, 1, e_maxCount)) + if (ImGui::SliderInt("Count", &count, 1, e_maxCount)) { CreateScene(count); } + ImGui::PopItemWidth(); ImGui::End(); } @@ -613,7 +615,7 @@ class PrismaticJoint : public Sample ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Prismatic Joint", nullptr, ImGuiWindowFlags_NoResize); if (ImGui::Checkbox("Limit", &m_enableLimit)) { @@ -950,7 +952,7 @@ class Bridge : public Sample } } - if (ImGui::SliderFloat("gravity scale", &m_gravityScale, -1.0f, 1.0f, "%.1f")) + if (ImGui::SliderFloat("Gravity scale", &m_gravityScale, -1.0f, 1.0f, "%.1f")) { for (int i = 0; i < e_count; ++i) { @@ -1058,7 +1060,7 @@ class BallAndChain : public Sample ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Options", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Ball and Chain", nullptr, ImGuiWindowFlags_NoResize); bool updateFriction = ImGui::SliderFloat("Joint Friction", &m_frictionTorque, 0.0f, 1000.0f, "%2.f"); if (updateFriction) @@ -1160,8 +1162,9 @@ class Cantilever : public Sample ImGui::SetNextWindowSize(ImVec2(240.0f, height)); ImGui::Begin("Cantilever", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); - if (ImGui::SliderFloat("linear Hertz", &m_linearHertz, 0.0f, 20.0f, "%.0f")) + if (ImGui::SliderFloat("Linear Hertz", &m_linearHertz, 0.0f, 20.0f, "%.0f")) { for (int i = 0; i < e_count; ++i) { @@ -1169,7 +1172,7 @@ class Cantilever : public Sample } } - if (ImGui::SliderFloat("linear damping ratio", &m_linearDampingRatio, 0.0f, 10.0f, "%.1f")) + if (ImGui::SliderFloat("Linear Damping Ratio", &m_linearDampingRatio, 0.0f, 10.0f, "%.1f")) { for (int i = 0; i < e_count; ++i) { @@ -1177,7 +1180,7 @@ class Cantilever : public Sample } } - if (ImGui::SliderFloat("angular Hertz", &m_angularHertz, 0.0f, 20.0f, "%.0f")) + if (ImGui::SliderFloat("Angular Hertz", &m_angularHertz, 0.0f, 20.0f, "%.0f")) { for (int i = 0; i < e_count; ++i) { @@ -1185,7 +1188,7 @@ class Cantilever : public Sample } } - if (ImGui::SliderFloat("angular damping ratio", &m_angularDampingRatio, 0.0f, 10.0f, "%.1f")) + if (ImGui::SliderFloat("Angular Damping Ratio", &m_angularDampingRatio, 0.0f, 10.0f, "%.1f")) { for (int i = 0; i < e_count; ++i) { @@ -1193,7 +1196,7 @@ class Cantilever : public Sample } } - if (ImGui::Checkbox("collide connected", &m_collideConnected)) + if (ImGui::Checkbox("Collide Connected", &m_collideConnected)) { for (int i = 0; i < e_count; ++i) { @@ -1201,7 +1204,7 @@ class Cantilever : public Sample } } - if (ImGui::SliderFloat("gravity scale", &m_gravityScale, -1.0f, 1.0f, "%.1f")) + if (ImGui::SliderFloat("Gravity Scale", &m_gravityScale, -1.0f, 1.0f, "%.1f")) { for (int i = 0; i < e_count; ++i) { @@ -1209,6 +1212,7 @@ class Cantilever : public Sample } } + ImGui::PopItemWidth(); ImGui::End(); } @@ -1444,11 +1448,11 @@ class FixedRotation : public Sample { float height = 60.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(180.0f, height)); ImGui::Begin("Fixed Rotation", nullptr, ImGuiWindowFlags_NoResize); - if (ImGui::Checkbox("fixed rotation", &m_fixedRotation)) + if (ImGui::Checkbox("Fixed Rotation", &m_fixedRotation)) { for (int i = 0; i < e_count; ++i) { @@ -1662,7 +1666,7 @@ class BreakableJoint : public Sample ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Reaction Force", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Breakable Joint", nullptr, ImGuiWindowFlags_NoResize); ImGui::SliderFloat("break force", &m_breakForce, 0.0f, 10000.0f, "%.1f"); @@ -2019,27 +2023,27 @@ class Driving : public Sample { float height = 140.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(200.0f, height)); - ImGui::Begin("Car", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Driving", nullptr, ImGuiWindowFlags_NoResize); ImGui::PushItemWidth(100.0f); - if (ImGui::SliderFloat("spring Hertz", &m_hertz, 0.0f, 20.0f, "%.0f")) + if (ImGui::SliderFloat("Spring Hertz", &m_hertz, 0.0f, 20.0f, "%.0f")) { m_car.SetHertz(m_hertz); } - if (ImGui::SliderFloat("damping ratio", &m_dampingRatio, 0.0f, 10.0f, "%.1f")) + if (ImGui::SliderFloat("Damping Ratio", &m_dampingRatio, 0.0f, 10.0f, "%.1f")) { m_car.SetDampingRadio(m_dampingRatio); } - if (ImGui::SliderFloat("speed", &m_speed, 0.0f, 50.0f, "%.0f")) + if (ImGui::SliderFloat("Speed", &m_speed, 0.0f, 50.0f, "%.0f")) { m_car.SetSpeed(m_throttle * m_speed); } - if (ImGui::SliderFloat("torque", &m_torque, 0.0f, 5.0f, "%.1f")) + if (ImGui::SliderFloat("Torque", &m_torque, 0.0f, 5.0f, "%.1f")) { m_car.SetTorque(m_torque); } diff --git a/samples/sample_robustness.cpp b/samples/sample_robustness.cpp index 0991d499..b008dfc7 100644 --- a/samples/sample_robustness.cpp +++ b/samples/sample_robustness.cpp @@ -219,11 +219,12 @@ class OverlapRecovery : public Sample void UpdateUI() override { - float height = 220.0f; + float height = 210.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(220.0f, height)); - ImGui::Begin("Stacks", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Overlap Recovery", nullptr, ImGuiWindowFlags_NoResize); + ImGui::PushItemWidth(100.0f); bool changed = false; changed = changed || ImGui::SliderFloat("Extent", &m_extent, 0.1f, 1.0f, "%.1f"); @@ -239,6 +240,7 @@ class OverlapRecovery : public Sample CreateScene(); } + ImGui::PopItemWidth(); ImGui::End(); } diff --git a/samples/sample_shapes.cpp b/samples/sample_shapes.cpp index 2c01ffe5..b2fcf914 100644 --- a/samples/sample_shapes.cpp +++ b/samples/sample_shapes.cpp @@ -153,11 +153,11 @@ class ChainShape : public Sample void UpdateUI() override { - float height = 125.0f; + float height = 135.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Options", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Chain Shape", nullptr, ImGuiWindowFlags_NoResize); const char* shapeTypes[] = {"Circle", "Capsule", "Box"}; int shapeType = int(m_shapeType); @@ -383,7 +383,7 @@ class CompoundShapes : public Sample { float height = 100.0f; ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); - ImGui::SetNextWindowSize(ImVec2(240.0f, height)); + ImGui::SetNextWindowSize(ImVec2(180.0f, height)); ImGui::Begin("Compound Shapes", nullptr, ImGuiWindowFlags_NoResize); diff --git a/samples/sample_stacking.cpp b/samples/sample_stacking.cpp index c96d7049..1344de7e 100644 --- a/samples/sample_stacking.cpp +++ b/samples/sample_stacking.cpp @@ -323,7 +323,7 @@ class VerticalStack : public Sample ImGui::SetNextWindowPos(ImVec2(10.0f, g_camera.m_height - height - 50.0f), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(240.0f, height)); - ImGui::Begin("Stacks", nullptr, ImGuiWindowFlags_NoResize); + ImGui::Begin("Vertical Stack", nullptr, ImGuiWindowFlags_NoResize); ImGui::PushItemWidth(120.0f); diff --git a/src/geometry.c b/src/geometry.c index 8d52b35d..173e6776 100644 --- a/src/geometry.c +++ b/src/geometry.c @@ -56,7 +56,13 @@ static b2Vec2 b2ComputePolygonCentroid(const b2Vec2* vertices, int32_t count) b2Polygon b2MakePolygon(const b2Hull* hull, float radius) { - B2_ASSERT(hull->count >= 3); + B2_ASSERT(b2ValidateHull(hull)); + + if (hull->count < 3) + { + // Handle a bad hull when assertions are disabled + return b2MakeSquare(0.5f); + } b2Polygon shape = {0}; shape.count = hull->count; @@ -85,7 +91,13 @@ b2Polygon b2MakePolygon(const b2Hull* hull, float radius) b2Polygon b2MakeOffsetPolygon(const b2Hull* hull, float radius, b2Transform transform) { - B2_ASSERT(hull->count >= 3); + B2_ASSERT(b2ValidateHull(hull)); + + if (hull->count < 3) + { + // Handle a bad hull when assertions are disabled + return b2MakeSquare(0.5f); + } b2Polygon shape = {0}; shape.count = hull->count;