diff --git a/engine/src/physics/solver/penetration_constraint/plugin.cpp b/engine/src/physics/solver/penetration_constraint/plugin.cpp index f169b0b427..2dd6c6e662 100644 --- a/engine/src/physics/solver/penetration_constraint/plugin.cpp +++ b/engine/src/physics/solver/penetration_constraint/plugin.cpp @@ -14,6 +14,7 @@ using namespace cubos::engine; CUBOS_DEFINE_TAG(cubos::engine::addPenetrationConstraintTag); +CUBOS_DEFINE_TAG(cubos::engine::penetrationConstraintWarmStartTag); CUBOS_DEFINE_TAG(cubos::engine::penetrationConstraintSolveTag); CUBOS_DEFINE_TAG(cubos::engine::penetrationConstraintSolveRelaxTag); CUBOS_DEFINE_TAG(cubos::engine::penetrationConstraintRestitutionTag); @@ -230,11 +231,68 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) cubos.relation(); cubos.tag(addPenetrationConstraintTag); + cubos.tag(penetrationConstraintWarmStartTag); cubos.tag(penetrationConstraintSolveTag); cubos.tag(penetrationConstraintSolveRelaxTag); cubos.tag(penetrationConstraintRestitutionTag); cubos.tag(penetrationConstraintCleanTag); + cubos.system("warm start") + .tagged(penetrationConstraintWarmStartTag) + .after(addPenetrationConstraintTag) + .before(penetrationConstraintSolveTag) + .tagged(fixedSubstepTag) + .call([](Query + query) { + for (auto [ent1, mass1, inertia1, rotation1, correction1, velocity1, angVelocity1, constraint, ent2, mass2, + inertia2, rotation2, correction2, velocity2, angVelocity2] : query) + { + glm::vec3 v1 = velocity1.vec; + glm::vec3 v2 = velocity2.vec; + + glm::vec3 w1 = angVelocity1.vec; + glm::vec3 w2 = angVelocity2.vec; + + glm::vec3 tangent1; + glm::vec3 tangent2; + if (ent1 != constraint.entity) + { + getTangents(v2, v1, constraint.normal, tangent1, tangent2); + } + else + { + getTangents(v1, v2, constraint.normal, tangent1, tangent2); + } + + for (PenetrationConstraintPointData& contactPoint : constraint.points) + { + glm::vec3 r1 = contactPoint.fixedAnchor1; + glm::vec3 r2 = contactPoint.fixedAnchor2; + + /// TODO: replace this number by a warmStartCoefficient + glm::vec3 p = 1.0F * (contactPoint.normalImpulse * constraint.normal) + + (contactPoint.frictionImpulse1 * tangent1) + + (contactPoint.frictionImpulse2 * tangent2); + if (ent1 != constraint.entity) + { + p *= -1.0F; + } + + v1 -= p * mass1.inverseMass; + w1 -= inertia1.inverseInertia * glm::cross(r1, p); + v2 += p * mass2.inverseMass; + w2 += inertia2.inverseInertia * glm::cross(r2, p); + } + + velocity1.vec = v1; + angVelocity1.vec = w1; + velocity2.vec = v2; + angVelocity2.vec = w2; + } + }); + cubos.system("solve contacts bias") .tagged(penetrationConstraintSolveTag) .tagged(physicsSolveContactTag) @@ -353,10 +411,9 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) { auto pointData = PenetrationConstraintPointData{}; - /// TODO: when we have warm-start change this - pointData.normalImpulse = 0.0F; - pointData.frictionImpulse1 = 0.0F; - pointData.frictionImpulse2 = 0.0F; + pointData.normalImpulse = point.normalImpulse; + pointData.frictionImpulse1 = point.frictionImpulse1; + pointData.frictionImpulse2 = point.frictionImpulse2; pointData.localAnchor1 = point.localOn1 - centerOfMass1.vec; pointData.localAnchor2 = point.localOn2 - centerOfMass2.vec; @@ -441,6 +498,29 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) } }); + /// TODO: create tag for this + cubos.system("store impulses and clean penetration constraint pairs") + .tagged(physicsFinalizePositionTag) + .call([](Commands cmds, Query cQuery, + Query pQuery) { + for (auto [entity, constraint, other] : cQuery) + { + if (auto match = pQuery.pin(0, entity).pin(1, other).first()) + { + auto [entity, manifold, other] = *match; + // CUBOS_DEBUG("msize: {}, csize: {}", manifold.points.size(), constraint.points.size()); + for (int i = 0; i < manifold.points.size(); i++) + { + manifold.points[i].normalImpulse = constraint.points[i].normalImpulse; + manifold.points[i].frictionImpulse1 = constraint.points[i].frictionImpulse1; + manifold.points[i].frictionImpulse2 = constraint.points[i].frictionImpulse2; + } + } + cmds.unrelate(entity, other); + } + }); + + /* cubos.system("clean penetration constraint pairs") .tagged(penetrationConstraintCleanTag) .before(addPenetrationConstraintTag) @@ -451,4 +531,5 @@ void cubos::engine::penetrationConstraintPlugin(Cubos& cubos) cmds.unrelate(entity, other); } }); + */ } diff --git a/engine/src/physics/solver/penetration_constraint/plugin.hpp b/engine/src/physics/solver/penetration_constraint/plugin.hpp index a0b23aaf9e..275781ba3b 100644 --- a/engine/src/physics/solver/penetration_constraint/plugin.hpp +++ b/engine/src/physics/solver/penetration_constraint/plugin.hpp @@ -14,6 +14,7 @@ namespace cubos::engine /// @brief Adds solver for penetration constraint. extern Tag addPenetrationConstraintTag; + extern Tag penetrationConstraintWarmStartTag; extern Tag penetrationConstraintCleanTag; extern Tag penetrationConstraintSolveTag; extern Tag penetrationConstraintRestitutionTag;