diff --git a/app/test_scenarios.cpp b/app/test_scenarios.cpp index 9c28393..2329db8 100644 --- a/app/test_scenarios.cpp +++ b/app/test_scenarios.cpp @@ -11,6 +11,20 @@ #define M_PI 3.14159265358979323846 #endif +std::vector chapters = {"Kinematics", "Laws of Motion", "Collision", "Rotation", "Fluids", "Thermal Properties"}; +std::unordered_map> testmap; + +void InitializeTestMap() +{ + testmap["Kinematics"] = {TestCase::ProjectMotion, TestCase::RelativeVelocity}; + testmap["Laws of Motion"] = {TestCase::NewtonThirdLaw}; + testmap["Collision"] = {TestCase::PerfectElasticCollision, TestCase::PerfectInelasticCollision, TestCase::Collision}; + testmap["Rotation"] = {TestCase::BoxToppleOnRamp, TestCase::SphereToppleOnRamp, TestCase::CollisionCauseTopple}; + testmap["Fluids"] = {TestCase::BuoyancyTest}; + testmap["Thermal Properties"] = {}; +} + + namespace { BoxCollider g_floor(Vec3(100.0f, 0.1f, 100.0f)); @@ -117,6 +131,92 @@ namespace return Camera(); } + Camera spawn_relative_velocity(PhysicsWorld &world) +{ + + + const float y = 0.5f; + + Vec3 pos1(-8.0f, y, 0.0f); + Vec3 pos2(8.0f, y, 0.0f); + + Vec3 vel1(15.0f, 0.0f, 0.0f); + Vec3 vel2(5.0f, 0.0f, 0.0f); + + Rigidbody b1(pos1, vel1, &g_small_sphere, 1.0f); + Rigidbody b2(pos2, vel2, &g_small_sphere, 1.0f); + + b1.restitution = 0.0f; + b2.restitution = 0.0f; + b1.friction = 0.0f; + b2.friction = 0.0f; + + world.addBody(b1); + world.addBody(b2); + + return Camera().setPosition(glm::vec3(0.0f, 3.0f, 20.0f)); +} + + Camera spawn_newton_third_law(PhysicsWorld &world) +{ + + + const float y = 0.5f; + Vec3 pos1(-10.0f, y, 0.0f); + Vec3 vel1(12.0f, 0.0f, 0.0f); + Rigidbody light_body(pos1, vel1, &g_small_sphere, 0.5f); + + Vec3 pos2(10.0f, y, 0.0f); + Vec3 vel2(-6.0f, 0.0f, 0.0f); + Rigidbody heavy_body(pos2, vel2, &g_big_sphere, 2.0f); + light_body.restitution = 1.0f; + heavy_body.restitution = 1.0f; + light_body.friction = 0.0f; + heavy_body.friction = 0.0f; + + world.addBody(light_body); + world.addBody(heavy_body); + return Camera().setPosition(glm::vec3(0.0f, 3.0f, 25.0f)); +} + + Camera spawn_box_topple_on_ramp(PhysicsWorld &world) +{ + + world.addBody(Rigidbody(Vec3(0.0f, 0.0f, 0.0f), Vec3(), &g_steep_ramp, 0.0f)); + Rigidbody toppling_box(Vec3(0.0f, 4.0f, 0.0f), Vec3(), &g_wide_box, 1.5f); + toppling_box.friction = 0.3f; + toppling_box.restitution = 0.4f; + world.addBody(toppling_box); + + return Camera().setPosition(glm::vec3(8.0f, 6.0f, 20.0f)); +} + + Camera spawn_sphere_topple_on_ramp(PhysicsWorld &world) +{ + world.addBody(Rigidbody(Vec3(0.0f, 0.0f, 0.0f), Vec3(), &g_steep_ramp, 0.0f)); + Rigidbody rolling_sphere(Vec3(0.0f, 4.0f, 0.0f), Vec3(), &g_big_sphere, 1.2f); + rolling_sphere.friction = 0.2f; + rolling_sphere.restitution = 0.6f; + world.addBody(rolling_sphere); + + return Camera().setPosition(glm::vec3(8.0f, 6.0f, 20.0f)); +} + + Camera spawn_collision_cause_topple(PhysicsWorld &world) +{ world.addBody(Rigidbody(Vec3(0.0f, 0.0f, 0.0f), Vec3(), &g_gentle_ramp, 0.0f)); + + Rigidbody moving_box(Vec3(-8.0f, 6.0f, 0.0f), Vec3(8.0f, 0.0f, 0.0f), &g_small_box, 2.0f); + moving_box.friction = 0.1f; + moving_box.restitution = 0.5f; + world.addBody(moving_box); + Rigidbody target_sphere(Vec3(4.0f, 1.0f, 0.0f), Vec3(), &g_small_sphere, 1.0f); + target_sphere.friction = 0.2f; + target_sphere.restitution = 0.7f; + world.addBody(target_sphere); + + return Camera().setPosition(glm::vec3(0.0f, 4.0f, 20.0f)); +} + void add_floor(PhysicsWorld &world) { // Keep floor top at y=0 so scenario bodies spawn above, not inside. @@ -664,6 +764,16 @@ Camera LoadSingleTestScenario(PhysicsWorld &world, TestCase test_case) case TestCase::RollingFriction: spawn_sphere_rolling(world); return Camera().setPosition(glm::vec3(-1.0f, 5.0f, 26.0f)); + case TestCase::RelativeVelocity: + return spawn_relative_velocity(world); + case TestCase::NewtonThirdLaw: + return spawn_newton_third_law(world); + case TestCase::BoxToppleOnRamp: + return spawn_box_topple_on_ramp(world); + case TestCase::SphereToppleOnRamp: + return spawn_sphere_topple_on_ramp(world); + case TestCase::CollisionCauseTopple: + return spawn_collision_cause_topple(world); case TestCase::BuoyancyTest: world.enable_buoyancy = true; world.water_fluid = Fluid(2.0f, 2.0f, 0.3f); diff --git a/app/test_scenarios.hpp b/app/test_scenarios.hpp index 63b6447..c736e61 100644 --- a/app/test_scenarios.hpp +++ b/app/test_scenarios.hpp @@ -1,5 +1,8 @@ #pragma once #include "../renderer/camera.hpp" +#include +#include +#include class PhysicsWorld; enum class TestCase @@ -17,7 +20,16 @@ enum class TestCase CornerCollision, RollingFriction, BuoyancyTest, - HeatTransferDemo + HeatTransferDemo, + RelativeVelocity, + NewtonThirdLaw, + BoxToppleOnRamp, + SphereToppleOnRamp, + CollisionCauseTopple }; +extern std::vector chapters; +extern std::unordered_map> testmap; + +void InitializeTestMap(); Camera LoadSingleTestScenario(PhysicsWorld &world, TestCase test_case); diff --git a/renderer/window.cpp b/renderer/window.cpp index 398e9a5..324202a 100644 --- a/renderer/window.cpp +++ b/renderer/window.cpp @@ -39,7 +39,12 @@ namespace TestCase::CornerCollision, TestCase::RollingFriction, TestCase::BuoyancyTest, - TestCase::HeatTransferDemo + TestCase::HeatTransferDemo, + TestCase::RelativeVelocity, + TestCase::NewtonThirdLaw, + TestCase::BoxToppleOnRamp, + TestCase::SphereToppleOnRamp, + TestCase::CollisionCauseTopple }; constexpr const char *kTestCaseNames[] = { @@ -56,7 +61,12 @@ namespace "Corner Collision Torque", "Rolling vs Sliding", "Buoyancy Test", - "Heat Transfer Lab" + "Heat Transfer Lab", + "Relative Velocity", + "Newton's Third Law", + "Box Topple on Ramp", + "Sphere Topple on Ramp", + "Collision Cause Topple" }; constexpr const char *kTestCaseDescriptions[] = { @@ -73,10 +83,17 @@ namespace "Corner-to-corner impacts show how contact point offsets create torque.", "Contrast high-friction rolling with sliding motion on ramps and flats.", "Observe how buoyant forces affect floating objects in simulated fluids.", - "Watch boxes and spheres equalize heat via conduction and radiation with temperature-driven colors." + "Watch boxes and spheres equalize heat via conduction and radiation with temperature-driven colors.", + "", + "", + "", + "", + "" }; + + constexpr const char *kGravityPresetNames[] = { "Mercury (3.70 m/s^2)", "Venus (8.87 m/s^2)", @@ -119,6 +136,9 @@ static void ShowTooltip(const char *text) void CreateWindow(PhysicsWorld &world) { + // Initialize test scenario mapping + InitializeTestMap(); + // Initialize and configure GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);