Box2D-0.1.0.0: upstream/src/mover.c
// SPDX-FileCopyrightText: 2025 Erin Catto
// SPDX-License-Identifier: MIT
#include "box2d/collision.h"
#include "box2d/constants.h"
b2PlaneSolverResult b2SolvePlanes( b2Vec2 targetDelta, b2CollisionPlane* planes, int count )
{
for ( int i = 0; i < count; ++i )
{
planes[i].push = 0.0f;
}
b2Vec2 delta = targetDelta;
float tolerance = B2_LINEAR_SLOP;
int iteration;
for ( iteration = 0; iteration < 20; ++iteration )
{
float totalPush = 0.0f;
for ( int planeIndex = 0; planeIndex < count; ++planeIndex )
{
b2CollisionPlane* plane = planes + planeIndex;
// Add slop to prevent jitter
float separation = b2PlaneSeparation( plane->plane, delta ) + B2_LINEAR_SLOP;
// if (separation > 0.0f)
//{
// continue;
// }
float push = -separation;
// Clamp accumulated push
float accumulatedPush = plane->push;
plane->push = b2ClampFloat( plane->push + push, 0.0f, plane->pushLimit );
push = plane->push - accumulatedPush;
delta = b2MulAdd( delta, push, plane->plane.normal );
// Track maximum push for convergence
totalPush += b2AbsFloat( push );
}
if ( totalPush < tolerance )
{
break;
}
}
return (b2PlaneSolverResult){
.delta = delta,
.iterationCount = iteration,
};
}
b2Vec2 b2ClipVector( b2Vec2 vector, const b2CollisionPlane* planes, int count )
{
b2Vec2 v = vector;
for ( int planeIndex = 0; planeIndex < count; ++planeIndex )
{
const b2CollisionPlane* plane = planes + planeIndex;
if ( plane->push == 0.0f || plane->clipVelocity == false )
{
continue;
}
v = b2MulSub( v, b2MinFloat( 0.0f, b2Dot( v, plane->plane.normal ) ), plane->plane.normal );
}
return v;
}