Das Submodul zeigte auf GitHub, der eingetragene Stand 028c652 lag aber nur lokal vor: GitHub-Master ac39682 plus Showcase mit Figuren und launch.json. Frische Klone konnten den Controller deshalb nicht laden. Jetzt liegt dieser Stand als normaler Ordner im Repo, ohne Verweis auf GitHub. dist/ und node_modules/ im Controller bleiben ignoriert und werden wie bisher lokal gebaut. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import type { ContactManifold } from "../contacts/ContactManifold";
|
|
import type { ImpulseBody } from "./ImpulseBody";
|
|
import { solveFrictionConstraint, warmStartFriction } from "./frictionConstraint";
|
|
import {
|
|
prepareNormalConstraint,
|
|
solveNormalConstraint,
|
|
warmStartNormal,
|
|
} from "./normalConstraint";
|
|
|
|
/**
|
|
* 共享接触冲量求解器:法向 + 摩擦锥,可选热启动。
|
|
* 人物胶囊不走此核(位置推出);轮悬架 / 轮胎仍在车辆模块。
|
|
*/
|
|
export class ContactImpulseSolver {
|
|
velocityIterations = 8; // 速度迭代次数
|
|
warmStart = true; // 是否复用上一帧冲量做热启动
|
|
|
|
/**
|
|
* 对单个刚体与一组流形做速度级求解。
|
|
* 顺序:准备 bias → 热启动 → 交替解法向 / 摩擦。
|
|
*/
|
|
solveVelocity(
|
|
body: ImpulseBody,
|
|
manifolds: ContactManifold[],
|
|
dt: number,
|
|
): void {
|
|
if (!manifolds.length) return;
|
|
|
|
// 写入弹性与穿透修正用的 biasVelocity
|
|
for (const manifold of manifolds) {
|
|
for (const point of manifold.contacts) {
|
|
prepareNormalConstraint(body, manifold, point, dt);
|
|
}
|
|
}
|
|
|
|
// 先施加缓存冲量,减少 resting 抖动
|
|
if (this.warmStart) {
|
|
for (const manifold of manifolds) {
|
|
for (const point of manifold.contacts) {
|
|
warmStartNormal(body, manifold, point);
|
|
warmStartFriction(body, point);
|
|
}
|
|
}
|
|
}
|
|
|
|
// PGS:每轮先法向后摩擦
|
|
for (let i = 0; i < this.velocityIterations; i++) {
|
|
for (const manifold of manifolds) {
|
|
for (const point of manifold.contacts) {
|
|
solveNormalConstraint(body, manifold, point);
|
|
solveFrictionConstraint(body, manifold, point);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|