Skip to content

Commit

Permalink
feat(engine): added resource to easily configure magic numbers in solver
Browse files Browse the repository at this point in the history
  • Loading branch information
GCeSilva committed Nov 24, 2024
1 parent ce15432 commit 9dab08d
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 28 deletions.
2 changes: 2 additions & 0 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include "physics_constants_integration.hpp"

#include <cubos/core/ecs/reflection.hpp>
#include <cubos/core/reflection/external/primitives.hpp>

CUBOS_REFLECT_IMPL(cubos::engine::PhysicsConstantsIntegration)

Check warning on line 6 in engine/src/physics/solver/integration/physics_constants_integration.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/integration/physics_constants_integration.cpp#L6

Added line #L6 was not covered by tests
{
return core::ecs::TypeBuilder<PhysicsConstantsIntegration>("cubos::engine::PhysicsConstantsIntegration")
.withField("minInvMass", &PhysicsConstantsIntegration::minInvMass)
.withField("minInvInertia", &PhysicsConstantsIntegration::minInvInertia)
.build();

Check warning on line 11 in engine/src/physics/solver/integration/physics_constants_integration.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/integration/physics_constants_integration.cpp#L8-L11

Added lines #L8 - L11 were not covered by tests
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// @file
/// @brief Resource @ref cubos::engine::PhysicsConstantsIntegration.
/// @ingroup physics-plugin

#pragma once

#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>

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
21 changes: 13 additions & 8 deletions engine/src/physics/solver/integration/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)
cubos.depends(physicsPlugin);
cubos.depends(physicsSolverPlugin);

cubos.resource<PhysicsConstantsIntegration>();

Check warning on line 25 in engine/src/physics/solver/integration/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/integration/plugin.cpp#L25

Added line #L25 was not covered by tests

cubos.tag(physicsApplyImpulsesTag);
cubos.tag(physicsClearForcesTag).after(physicsFinalizePositionTag).tagged(fixedStepTag);

Expand Down Expand Up @@ -54,13 +56,14 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)
.call([](Query<Velocity&, AngularVelocity&, const Force&, const Torque&, const Mass&, const Inertia&,
const Rotation&>
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;
}
Expand All @@ -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;
}
Expand All @@ -97,21 +100,22 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)
.call([](Query<AccumulatedCorrection&, Rotation&, const Velocity&, const AngularVelocity&, const Mass&,
const Inertia&>
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;
}

correction.position += velocity.vec * subDeltaTime;

// Rotation
if (inertia.inverseInertia == glm::mat3(0.0F))
if (inertia.inverseInertia == glm::mat3(physicsConstants.minInvInertia))
{
continue;
}
Expand All @@ -124,10 +128,11 @@ void cubos::engine::physicsIntegrationPlugin(Cubos& cubos)

cubos.system("finalize position")
.tagged(physicsFinalizePositionTag)
.call([](Query<Position&, AccumulatedCorrection&, const Mass&> query) {
.call([](Query<Position&, AccumulatedCorrection&, const Mass&> query,

Check warning on line 131 in engine/src/physics/solver/integration/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/integration/plugin.cpp#L131

Added line #L131 was not covered by tests
const PhysicsConstantsIntegration& physicsConstants) {
for (auto [position, correction, mass] : query)
{
if (mass.inverseMass <= 0.0F)
if (mass.inverseMass <= physicsConstants.minInvMass)
{
continue;
}
Expand Down
6 changes: 6 additions & 0 deletions engine/src/physics/solver/integration/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@

#include <cubos/engine/prelude.hpp>

#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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "physics_constants_pc.hpp"

#include <cubos/core/ecs/reflection.hpp>
#include <cubos/core/reflection/external/primitives.hpp>

CUBOS_REFLECT_IMPL(cubos::engine::PhysicsConstantsPC)

Check warning on line 6 in engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp#L6

Added line #L6 was not covered by tests
{
return core::ecs::TypeBuilder<PhysicsConstantsPC>("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();

Check warning on line 17 in engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/physics_constants_pc.cpp#L8-L17

Added lines #L8 - L17 were not covered by tests
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/// @file
/// @brief Resource @ref cubos::engine::PhysicsConstantsPC.
/// @ingroup physics-plugin

#pragma once

#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/api.hpp>

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
50 changes: 30 additions & 20 deletions engine/src/physics/solver/penetration_constraint/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Check warning on line 124 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L124

Added line #L124 was not covered by tests
massScale = constraint.massCoefficient;
impulseScale = constraint.impulseCoefficient;
}
Expand Down Expand Up @@ -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);

Check warning on line 165 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L165

Added line #L165 was not covered by tests
}
else
{
getTangents(v1, v2, constraint.normal, tangent1, tangent2);
getTangents(v1, v2, constraint.normal, tangent1, tangent2, physicsConstants);

Check warning on line 169 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L169

Added line #L169 was not covered by tests
}

// Friction
Expand Down Expand Up @@ -229,6 +230,8 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos)

cubos.relation<PenetrationConstraint>();

cubos.resource<PhysicsConstantsPC>();

Check warning on line 233 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L233

Added line #L233 was not covered by tests

cubos.tag(addPenetrationConstraintTag);
cubos.tag(penetrationConstraintSolveTag);
cubos.tag(penetrationConstraintSolveRelaxTag);
Expand All @@ -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);
});

Check warning on line 251 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L250-L251

Added lines #L250 - L251 were not covered by tests

cubos.system("solve contacts no bias")
.tagged(penetrationConstraintSolveRelaxTag)
Expand All @@ -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);
});

Check warning on line 263 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L262-L263

Added lines #L262 - L263 were not covered by tests

cubos.system("add restitution")
.tagged(penetrationConstraintRestitutionTag)
Expand All @@ -263,11 +270,12 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos)
.call([](Query<Entity, const Mass&, const Inertia&, AccumulatedCorrection&, Velocity&, AngularVelocity&,
PenetrationConstraint&, Entity, const Mass&, const Inertia&, AccumulatedCorrection&, Velocity&,
AngularVelocity&>
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;
}
Expand All @@ -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)

Check warning on line 291 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L291

Added line #L291 was not covered by tests
{
continue;
}
Expand Down Expand Up @@ -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));

Check warning on line 345 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L345

Added line #L345 was not covered by tests

for (auto [ent1, mass1, inertia1, centerOfMass1, rotation1, velocity1, angVelocity1, material1, manifold,
ent2, mass2, inertia2, centerOfMass2, rotation2, velocity2, angVelocity2, material2] : query)
Expand All @@ -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);

Check warning on line 354 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L354

Added line #L354 was not covered by tests
}
else
{
getTangents(velocity1.vec, velocity2.vec, manifold.normal, tangent1, tangent2);
getTangents(velocity1.vec, velocity2.vec, manifold.normal, tangent1, tangent2, physicsConstants);

Check warning on line 358 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L358

Added line #L358 was not covered by tests
}

std::vector<PenetrationConstraintPointData> points;
Expand Down Expand Up @@ -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;

Check warning on line 399 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L399

Added line #L399 was not covered by tests

// friction mass
glm::vec3 rt11 = glm::cross(r1, tangent1);
Expand All @@ -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;

Check warning on line 420 in engine/src/physics/solver/penetration_constraint/plugin.cpp

View check run for this annotation

Codecov / codecov/patch

engine/src/physics/solver/penetration_constraint/plugin.cpp#L419-L420

Added lines #L419 - L420 were not covered by tests

points.push_back(pointData);
}
Expand Down
5 changes: 5 additions & 0 deletions engine/src/physics/solver/penetration_constraint/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
#include <cubos/engine/prelude.hpp>

#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;
Expand Down

0 comments on commit 9dab08d

Please sign in to comment.