From 9dab08dd5241552baebe1ef0dc1c6db41dff33bc Mon Sep 17 00:00:00 2001 From: GCeSilva Date: Thu, 21 Nov 2024 17:22:46 +0000 Subject: [PATCH] feat(engine): added resource to easily configure magic numbers in solver --- engine/CMakeLists.txt | 2 + .../physics_constants_integration.cpp | 12 +++++ .../physics_constants_integration.hpp | 24 +++++++++ .../src/physics/solver/integration/plugin.cpp | 21 +++++--- .../src/physics/solver/integration/plugin.hpp | 6 +++ .../physics_constants_pc.cpp | 18 +++++++ .../physics_constants_pc.hpp | 36 +++++++++++++ .../solver/penetration_constraint/plugin.cpp | 50 +++++++++++-------- .../solver/penetration_constraint/plugin.hpp | 5 ++ 9 files changed, 146 insertions(+), 28 deletions(-) create mode 100644 engine/src/physics/solver/integration/physics_constants_integration.cpp create mode 100644 engine/src/physics/solver/integration/physics_constants_integration.hpp create mode 100644 engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp create mode 100644 engine/src/physics/solver/penetration_constraint/physics_constants_pc.hpp diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 9a40651a12..23ce5b1976 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -90,9 +90,11 @@ set(CUBOS_ENGINE_SOURCE "src/physics/solver/plugin.cpp" "src/physics/constraints/penetration_constraint.cpp" "src/physics/solver/penetration_constraint/plugin.cpp" + "src/physics/solver/penetration_constraint/physics_constants_pc.cpp" "src/physics/fixed_substep/plugin.cpp" "src/physics/fixed_substep/substeps.cpp" "src/physics/solver/integration/plugin.cpp" + "src/physics/solver/integration/physics_constants_integration.cpp" "src/input/plugin.cpp" "src/input/input.cpp" diff --git a/engine/src/physics/solver/integration/physics_constants_integration.cpp b/engine/src/physics/solver/integration/physics_constants_integration.cpp new file mode 100644 index 0000000000..4d3ef84691 --- /dev/null +++ b/engine/src/physics/solver/integration/physics_constants_integration.cpp @@ -0,0 +1,12 @@ +#include "physics_constants_integration.hpp" + +#include +#include + +CUBOS_REFLECT_IMPL(cubos::engine::PhysicsConstantsIntegration) +{ + return core::ecs::TypeBuilder("cubos::engine::PhysicsConstantsIntegration") + .withField("minInvMass", &PhysicsConstantsIntegration::minInvMass) + .withField("minInvInertia", &PhysicsConstantsIntegration::minInvInertia) + .build(); +} \ No newline at end of file diff --git a/engine/src/physics/solver/integration/physics_constants_integration.hpp b/engine/src/physics/solver/integration/physics_constants_integration.hpp new file mode 100644 index 0000000000..363ddf3518 --- /dev/null +++ b/engine/src/physics/solver/integration/physics_constants_integration.hpp @@ -0,0 +1,24 @@ +/// @file +/// @brief Resource @ref cubos::engine::PhysicsConstantsIntegration. +/// @ingroup physics-plugin + +#pragma once + +#include + +#include + +namespace cubos::engine +{ + /// @brief Resource which allows configuration over constants in the integration plugin. + /// @ingroup physics-plugin + struct PhysicsConstantsIntegration + { + CUBOS_REFLECT; + + float minInvMass = 0.0F; + + float minInvInertia = 0.0F; + }; + +} // namespace cubos::engine diff --git a/engine/src/physics/solver/integration/plugin.cpp b/engine/src/physics/solver/integration/plugin.cpp index 456b129e7e..53e30b49d4 100644 --- a/engine/src/physics/solver/integration/plugin.cpp +++ b/engine/src/physics/solver/integration/plugin.cpp @@ -22,6 +22,8 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos) cubos.depends(physicsPlugin); cubos.depends(physicsSolverPlugin); + cubos.resource(); + cubos.tag(physicsApplyImpulsesTag); cubos.tag(physicsClearForcesTag).after(physicsFinalizePositionTag).tagged(fixedStepTag); @@ -54,13 +56,14 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos) .call([](Query query, - const Damping& damping, const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps) { + const Damping& damping, const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, + const PhysicsConstantsIntegration& physicsConstants) { float subDeltaTime = fixedDeltaTime.value / (float)substeps.value; for (auto [velocity, angVelocity, force, torque, mass, inertia, rotation] : query) { // Linear velocity - if (mass.inverseMass <= 0.0F) + if (mass.inverseMass <= physicsConstants.minInvMass) { continue; } @@ -74,7 +77,7 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos) velocity.vec += deltaLinearVelocity; // Angular velocity - if (inertia.inverseInertia == glm::mat3(0.0F)) + if (inertia.inverseInertia == glm::mat3(physicsConstants.minInvInertia)) { continue; } @@ -97,13 +100,14 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos) .call([](Query query, - const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps) { + const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, + const PhysicsConstantsIntegration& physicsConstants) { float subDeltaTime = fixedDeltaTime.value / (float)substeps.value; for (auto [correction, rotation, velocity, angVelocity, mass, inertia] : query) { // Position - if (mass.inverseMass <= 0.0F) + if (mass.inverseMass <= physicsConstants.minInvMass) { continue; } @@ -111,7 +115,7 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos) correction.position += velocity.vec * subDeltaTime; // Rotation - if (inertia.inverseInertia == glm::mat3(0.0F)) + if (inertia.inverseInertia == glm::mat3(physicsConstants.minInvInertia)) { continue; } @@ -124,10 +128,11 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos) cubos.system("finalize position") .tagged(physicsFinalizePositionTag) - .call([](Query query) { + .call([](Query query, + const PhysicsConstantsIntegration& physicsConstants) { for (auto [position, correction, mass] : query) { - if (mass.inverseMass <= 0.0F) + if (mass.inverseMass <= physicsConstants.minInvMass) { continue; } diff --git a/engine/src/physics/solver/integration/plugin.hpp b/engine/src/physics/solver/integration/plugin.hpp index fed889de76..53e7bc2420 100644 --- a/engine/src/physics/solver/integration/plugin.hpp +++ b/engine/src/physics/solver/integration/plugin.hpp @@ -6,10 +6,16 @@ #include +#include "physics_constants_integration.hpp" + namespace cubos::engine { /// @ingroup physics-solver-plugin /// @brief Adds velocity and position integration. + /// + /// ## Resources + /// - @ref PhysicsConstantsIntegration - holds constants for integration plugin. + /// extern Tag physicsApplyImpulsesTag; extern Tag physicsClearForcesTag; diff --git a/engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp b/engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp new file mode 100644 index 0000000000..57e8906e98 --- /dev/null +++ b/engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp @@ -0,0 +1,18 @@ +#include "physics_constants_pc.hpp" + +#include +#include + +CUBOS_REFLECT_IMPL(cubos::engine::PhysicsConstantsPC) +{ + return core::ecs::TypeBuilder("cubos::engine::PhysicsConstantsPC") + .withField("maxBias", &PhysicsConstantsPC::maxBias) + .withField("minContactHertz", &PhysicsConstantsPC::minContactHertz) + .withField("minKNormal", &PhysicsConstantsPC::minKNormal) + .withField("minKFriction", &PhysicsConstantsPC::minKFriction) + .withField("minTangentLenSq", &PhysicsConstantsPC::minTangentLenSq) + .withField("minRestitution", &PhysicsConstantsPC::minRestitution) + .withField("minNormalSpeed", &PhysicsConstantsPC::minNormalSpeed) + .withField("minNormalImpulse", &PhysicsConstantsPC::minNormalImpulse) + .build(); +} \ No newline at end of file diff --git a/engine/src/physics/solver/penetration_constraint/physics_constants_pc.hpp b/engine/src/physics/solver/penetration_constraint/physics_constants_pc.hpp new file mode 100644 index 0000000000..43b978e831 --- /dev/null +++ b/engine/src/physics/solver/penetration_constraint/physics_constants_pc.hpp @@ -0,0 +1,36 @@ +/// @file +/// @brief Resource @ref cubos::engine::PhysicsConstantsPC. +/// @ingroup physics-plugin + +#pragma once + +#include + +#include + +namespace cubos::engine +{ + /// @brief Resource which allows configuration over magic numbers in the solver plugin. + /// @ingroup physics-plugin + struct PhysicsConstantsPC + { + CUBOS_REFLECT; + + float maxBias = -4.0F; + + float minContactHertz = 30.0F; + + float minKNormal = 0.0F; + + float minKFriction = 0.0F; + + float minTangentLenSq = 1e-6F * 1e-6F; + + float minRestitution = 0.0F; + + float minNormalSpeed = -0.01F; + + float minNormalImpulse = 0.0F; + }; + +} // namespace cubos::engine diff --git a/engine/src/physics/solver/penetration_constraint/plugin.cpp b/engine/src/physics/solver/penetration_constraint/plugin.cpp index f169b0b427..ba57ed5026 100644 --- a/engine/src/physics/solver/penetration_constraint/plugin.cpp +++ b/engine/src/physics/solver/penetration_constraint/plugin.cpp @@ -34,14 +34,14 @@ static void getPlaneSpace(const glm::vec3& n, glm::vec3& tangent1, glm::vec3& ta } static void getTangents(const glm::vec3& velocity1, const glm::vec3& velocity2, const glm::vec3& n, glm::vec3& tangent1, - glm::vec3& tangent2) + glm::vec3& tangent2, const PhysicsConstantsPC& physicsConstants) { // Use linear relative velocity for determining tangents. glm::vec3 linearVr = velocity2 - velocity1; tangent1 = linearVr - glm::dot(linearVr, n) * n; float tangentLenSq = glm::length2(tangent1); - if (tangentLenSq > 1e-6 * 1e-6) /// TODO: check this + if (tangentLenSq > physicsConstants.minTangentLenSq) /// TODO: check this { tangent1 = glm::normalize(tangent1); tangent2 = glm::cross(n, tangent1); @@ -82,7 +82,8 @@ static void solvePenetrationConstraint( PenetrationConstraint&, Entity, const Mass&, const Inertia&, const Rotation&, AccumulatedCorrection&, Velocity&, AngularVelocity&> query, - const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, const bool useBias) + const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, const PhysicsConstantsPC& physicsConstants, + const bool useBias) { for (auto [ent1, mass1, inertia1, rotation1, correction1, velocity1, angVelocity1, constraint, ent2, mass2, inertia2, rotation2, correction2, velocity2, angVelocity2] : query) @@ -120,7 +121,7 @@ static void solvePenetrationConstraint( } else if (useBias) { - bias = glm::max(constraint.biasCoefficient * separation, -4.0F); + bias = glm::max(constraint.biasCoefficient * separation, physicsConstants.maxBias); massScale = constraint.massCoefficient; impulseScale = constraint.impulseCoefficient; } @@ -161,11 +162,11 @@ static void solvePenetrationConstraint( glm::vec3 tangent2; if (ent1 != constraint.entity) { - getTangents(v2, v1, constraint.normal, tangent1, tangent2); + getTangents(v2, v1, constraint.normal, tangent1, tangent2, physicsConstants); } else { - getTangents(v1, v2, constraint.normal, tangent1, tangent2); + getTangents(v1, v2, constraint.normal, tangent1, tangent2, physicsConstants); } // Friction @@ -229,6 +230,8 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) cubos.relation(); + cubos.resource(); + cubos.tag(addPenetrationConstraintTag); cubos.tag(penetrationConstraintSolveTag); cubos.tag(penetrationConstraintSolveRelaxTag); @@ -242,8 +245,10 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) AngularVelocity&, PenetrationConstraint&, Entity, const Mass&, const Inertia&, const Rotation&, AccumulatedCorrection&, Velocity&, AngularVelocity&> query, - const FixedDeltaTime& fixedDeltaTime, - const Substeps& substeps) { solvePenetrationConstraint(query, fixedDeltaTime, substeps, true); }); + const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, + const PhysicsConstantsPC& physicsConstants) { + solvePenetrationConstraint(query, fixedDeltaTime, substeps, physicsConstants, true); + }); cubos.system("solve contacts no bias") .tagged(penetrationConstraintSolveRelaxTag) @@ -252,8 +257,10 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) AngularVelocity&, PenetrationConstraint&, Entity, const Mass&, const Inertia&, const Rotation&, AccumulatedCorrection&, Velocity&, AngularVelocity&> query, - const FixedDeltaTime& fixedDeltaTime, - const Substeps& substeps) { solvePenetrationConstraint(query, fixedDeltaTime, substeps, false); }); + const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, + const PhysicsConstantsPC& physicsConstants) { + solvePenetrationConstraint(query, fixedDeltaTime, substeps, physicsConstants, false); + }); cubos.system("add restitution") .tagged(penetrationConstraintRestitutionTag) @@ -263,11 +270,12 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) .call([](Query - query) { + query, + const PhysicsConstantsPC& physicsConstants) { for (auto [ent1, mass1, inertia1, correction1, velocity1, angVelocity1, constraint, ent2, mass2, inertia2, correction2, velocity2, angVelocity2] : query) { - if (constraint.restitution == 0.0F) + if (constraint.restitution == physicsConstants.minRestitution) { continue; } @@ -279,7 +287,8 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) for (auto point : constraint.points) { - if (point.normalSpeed > -0.01F || point.normalImpulse == 0.0F) + if (point.normalSpeed > physicsConstants.minNormalSpeed || + point.normalImpulse == physicsConstants.minNormalImpulse) { continue; } @@ -330,9 +339,10 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) const Inertia&, const CenterOfMass&, const Rotation&, const Velocity&, const AngularVelocity&, const PhysicsMaterial&> query, - const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps) { + const FixedDeltaTime& fixedDeltaTime, const Substeps& substeps, + const PhysicsConstantsPC& physicsConstants) { float subDeltaTime = fixedDeltaTime.value / (float)substeps.value; - float contactHertz = glm::min(30.0F, 0.25F * (1.0F / subDeltaTime)); + float contactHertz = glm::min(physicsConstants.minContactHertz, 0.25F * (1.0F / subDeltaTime)); for (auto [ent1, mass1, inertia1, centerOfMass1, rotation1, velocity1, angVelocity1, material1, manifold, ent2, mass2, inertia2, centerOfMass2, rotation2, velocity2, angVelocity2, material2] : query) @@ -341,11 +351,11 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) glm::vec3 tangent2; if (ent1 != manifold.entity) { - getTangents(velocity2.vec, velocity1.vec, manifold.normal, tangent1, tangent2); + getTangents(velocity2.vec, velocity1.vec, manifold.normal, tangent1, tangent2, physicsConstants); } else { - getTangents(velocity1.vec, velocity2.vec, manifold.normal, tangent1, tangent2); + getTangents(velocity1.vec, velocity2.vec, manifold.normal, tangent1, tangent2, physicsConstants); } std::vector points; @@ -386,7 +396,7 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) float kNormal = mass1.inverseMass + mass2.inverseMass + glm::dot(inertia1.inverseInertia * rn1, rn1) + glm::dot(inertia2.inverseInertia * rn2, rn2); - pointData.normalMass = kNormal > 0.0F ? 1.0F / kNormal : 0.0F; + pointData.normalMass = kNormal > physicsConstants.minKNormal ? 1.0F / kNormal : 0.0F; // friction mass glm::vec3 rt11 = glm::cross(r1, tangent1); @@ -406,8 +416,8 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) mass1.inverseMass + mass2.inverseMass + glm::dot(i1Rt21, rt21) + glm::dot(i2Rt22, rt22); /// TODO: these could be an array in the point - pointData.frictionMass1 = kFriction1 > 0.0F ? 1.0F / kFriction1 : 0.0F; - pointData.frictionMass2 = kFriction2 > 0.0F ? 1.0F / kFriction2 : 0.0F; + pointData.frictionMass1 = kFriction1 > physicsConstants.minKFriction ? 1.0F / kFriction1 : 0.0F; + pointData.frictionMass2 = kFriction2 > physicsConstants.minKFriction ? 1.0F / kFriction2 : 0.0F; points.push_back(pointData); } diff --git a/engine/src/physics/solver/penetration_constraint/plugin.hpp b/engine/src/physics/solver/penetration_constraint/plugin.hpp index a0b23aaf9e..8ed54a5b33 100644 --- a/engine/src/physics/solver/penetration_constraint/plugin.hpp +++ b/engine/src/physics/solver/penetration_constraint/plugin.hpp @@ -7,11 +7,16 @@ #include #include "../../constraints/penetration_constraint.hpp" +#include "physics_constants_pc.hpp" namespace cubos::engine { /// @ingroup physics-solver-plugin /// @brief Adds solver for penetration constraint. + /// + /// ## Resources + /// - @ref PhysicsConstantsPC - holds constants for penetration constraint plugin. + /// extern Tag addPenetrationConstraintTag; extern Tag penetrationConstraintCleanTag;