The two contact force directions, side by side

One vertex P of the upper sheet, two triangles of the lower sheet seen edge-on (the one below P and its neighbour), the stored division plane of each pair, and the same motion of P in both panels. Left: the force along the plane normal n. Right: the force along the closest-point direction d. Drag the slider or press play. 中文:左边是沿分割平面法线 n 推,右边是沿最近点方向 d 推,同一个顶点同一段运动。

The words

Pthe vertex we look at (upper sheet).
witness wthe point of the triangle closest to P. Nothing more. The gap of the pair is measured between P and w. 中文:witness 就是三角形上离 P 最近的那个点。
division plane, normal nthe certified separator stored for the pair: the triangle is entirely on one side, P on the other. The truncation keeps the anchor from crossing it. n is fixed between two commits.
dthe unit vector from w to P, the closest-point direction. It changes whenever P or the triangle moves.
gap along nn · (P − w): how far P is from w measured along n (the design's constraint).
gap along d|P − w|: the plain distance (what I had switched to).
t = 0.00

Why the direction is not a free choice. The ALM row carries one multiplier λ for one constraint C(x) ≥ 0, and its force is λ times the gradient of that constraint. With the design's constraint C = n·(P − w) the gradient on P is n, so the force is along the plane normal. With C = |P − w| the gradient is d, so the force is along the closest-point direction. Picking the direction means picking the constraint. The division plane is what the truncation certifies, so the row that belongs to it pushes along n. That is what the code does again since dd26a7264.

Why the planes are tilted, and why that is right