reze-engine 0.35.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/engine.js +2 -2
- package/dist/model.d.ts +0 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -16
- package/dist/physics/contact.d.ts +12 -3
- package/dist/physics/contact.d.ts.map +1 -1
- package/dist/physics/contact.js +5 -2
- package/dist/physics/manifold.d.ts +32 -11
- package/dist/physics/manifold.d.ts.map +1 -1
- package/dist/physics/manifold.js +137 -57
- package/dist/physics/solver.d.ts +7 -1
- package/dist/physics/solver.d.ts.map +1 -1
- package/dist/physics/solver.js +536 -182
- package/dist/physics/world.d.ts +2 -0
- package/dist/physics/world.d.ts.map +1 -1
- package/dist/physics/world.js +16 -43
- package/package.json +1 -1
- package/src/engine.ts +2 -2
- package/src/model.ts +0 -20
- package/src/physics/contact.ts +17 -7
- package/src/physics/manifold.ts +151 -0
- package/src/physics/solver.ts +520 -184
- package/src/physics/world.ts +17 -43
package/src/physics/world.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { Vec3 } from "../math"
|
|
|
2
2
|
import type { RigidBodyStore } from "./body"
|
|
3
3
|
import { RigidbodyType } from "./types"
|
|
4
4
|
import type { SixDofSpringConstraint } from "./constraint"
|
|
5
|
-
import { solveConstraints, type SolverCache } from "./solver"
|
|
5
|
+
import { solveConstraints, saveContactImpulses, applySplitImpulsePush, type SolverCache } from "./solver"
|
|
6
|
+
import { ManifoldCache } from "./manifold"
|
|
6
7
|
import { findContacts, type ContactPool } from "./contact"
|
|
7
8
|
|
|
8
9
|
// World step: predict velocities → collide → solve → position correction →
|
|
@@ -38,6 +39,9 @@ export class World {
|
|
|
38
39
|
readonly gravity: Vec3
|
|
39
40
|
solverIterations = 10
|
|
40
41
|
|
|
42
|
+
/** Per-pair contact impulse history behind warm starting. */
|
|
43
|
+
private manifolds = new ManifoldCache()
|
|
44
|
+
|
|
41
45
|
// Per-body damping factors pow(1−damping, dt), cached because damping and
|
|
42
46
|
// the fixed dt never change — two Math.pow per body per substep otherwise.
|
|
43
47
|
private dampCacheDt = -1
|
|
@@ -166,50 +170,20 @@ export class World {
|
|
|
166
170
|
|
|
167
171
|
// 3. Solve joint + contact constraints (velocity-only).
|
|
168
172
|
if (constraints.length > 0 || contacts.count > 0) {
|
|
169
|
-
solveConstraints(store, constraints, cache, contacts, dt, this.solverIterations)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// it because it doesn't go through the velocity channel. Inverse-mass
|
|
175
|
-
// weighted so a kinematic body stays put and only the dynamic one
|
|
176
|
-
// translates.
|
|
177
|
-
// Softer and later than a rigid-body engine would use, deliberately. MMD
|
|
178
|
-
// cloth is a dense chain of small bodies resting on the character, and
|
|
179
|
-
// aggressive penetration recovery feeds those contacts energy that the
|
|
180
|
-
// joint springs hand straight back — the tips never settle. Measured on a
|
|
181
|
-
// 688-body model: resting peak velocity 1.79 → 1.10, and 12.9 → 6.6 under
|
|
182
|
-
// an idle animation, for a slop of two hundredths of a unit (under 2 mm at
|
|
183
|
-
// MMD scale) that no eye finds.
|
|
184
|
-
const POS_CORRECTION_FACTOR = 0.15
|
|
185
|
-
const POS_SLOP = 0.02
|
|
186
|
-
for (let ci = 0; ci < contacts.count; ci++) {
|
|
187
|
-
const c = contacts.get(ci)
|
|
188
|
-
if (c.depth <= POS_SLOP) continue
|
|
189
|
-
const imA = invMass[c.bodyA]
|
|
190
|
-
const imB = invMass[c.bodyB]
|
|
191
|
-
const total = imA + imB
|
|
192
|
-
if (total <= 0) continue
|
|
193
|
-
const correction = (c.depth - POS_SLOP) * POS_CORRECTION_FACTOR
|
|
194
|
-
const dx = correction * c.nx
|
|
195
|
-
const dy = correction * c.ny
|
|
196
|
-
const dz = correction * c.nz
|
|
197
|
-
const ai = c.bodyA * 3
|
|
198
|
-
const bi = c.bodyB * 3
|
|
199
|
-
if (imA > 0) {
|
|
200
|
-
const fA = imA / total
|
|
201
|
-
pos[ai + 0] -= dx * fA
|
|
202
|
-
pos[ai + 1] -= dy * fA
|
|
203
|
-
pos[ai + 2] -= dz * fA
|
|
204
|
-
}
|
|
205
|
-
if (imB > 0) {
|
|
206
|
-
const fB = imB / total
|
|
207
|
-
pos[bi + 0] += dx * fB
|
|
208
|
-
pos[bi + 1] += dy * fB
|
|
209
|
-
pos[bi + 2] += dz * fB
|
|
210
|
-
}
|
|
173
|
+
solveConstraints(store, constraints, cache, contacts, dt, this.solverIterations, this.manifolds)
|
|
174
|
+
applySplitImpulsePush(store, dt)
|
|
175
|
+
saveContactImpulses(store, contacts, this.manifolds)
|
|
176
|
+
} else {
|
|
177
|
+
this.manifolds.clear()
|
|
211
178
|
}
|
|
212
179
|
|
|
180
|
+
// 4. Penetration recovery happens in the contact velocity row (Baumgarte,
|
|
181
|
+
// CONTACT_ERP), not here. Bullet 2.75 — the build MMD's physics runs —
|
|
182
|
+
// defaults m_splitImpulse to false and folds positionalError straight
|
|
183
|
+
// into m_rhs, so a separate position-translation pass is a divergence
|
|
184
|
+
// from what PMX rigs are authored against. It also could not be made to
|
|
185
|
+
// behave: every contact translated the body by its own full share, so a
|
|
186
|
+
// panel carrying dozens of rows was shoved out dozens of times.
|
|
213
187
|
// 5. Integrate. Cap angular velocity at π/2 per step — a high-impulse
|
|
214
188
|
// contact spike on a low-inertia body would otherwise spin past π
|
|
215
189
|
// in one step and trash the quaternion integration. Linear velocity
|