@codexo/exojs-physics 0.15.2 → 0.16.0

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.
Files changed (201) hide show
  1. package/README.md +51 -23
  2. package/dist/esm/Aabb.d.ts +6 -10
  3. package/dist/esm/Aabb.d.ts.map +1 -0
  4. package/dist/esm/Aabb.js +9 -5
  5. package/dist/esm/Aabb.js.map +1 -1
  6. package/dist/esm/Collider.d.ts +62 -10
  7. package/dist/esm/Collider.d.ts.map +1 -0
  8. package/dist/esm/Collider.js +263 -157
  9. package/dist/esm/Collider.js.map +1 -1
  10. package/dist/esm/ContactGraph.d.ts +51 -5
  11. package/dist/esm/ContactGraph.d.ts.map +1 -0
  12. package/dist/esm/ContactGraph.js +282 -223
  13. package/dist/esm/ContactGraph.js.map +1 -1
  14. package/dist/esm/ContactModifier.d.ts +85 -0
  15. package/dist/esm/ContactModifier.d.ts.map +1 -0
  16. package/dist/esm/ContactModifier.js +49 -0
  17. package/dist/esm/ContactModifier.js.map +1 -0
  18. package/dist/esm/PhysicsBody.d.ts +56 -22
  19. package/dist/esm/PhysicsBody.d.ts.map +1 -0
  20. package/dist/esm/PhysicsBody.js +461 -443
  21. package/dist/esm/PhysicsBody.js.map +1 -1
  22. package/dist/esm/PhysicsWorld.d.ts +276 -43
  23. package/dist/esm/PhysicsWorld.d.ts.map +1 -0
  24. package/dist/esm/PhysicsWorld.js +890 -626
  25. package/dist/esm/PhysicsWorld.js.map +1 -1
  26. package/dist/esm/TimeStepper.d.ts +3 -2
  27. package/dist/esm/TimeStepper.d.ts.map +1 -0
  28. package/dist/esm/TimeStepper.js +56 -67
  29. package/dist/esm/TimeStepper.js.map +1 -1
  30. package/dist/esm/backend/NativePhysicsBackend.d.ts +8 -4
  31. package/dist/esm/backend/NativePhysicsBackend.d.ts.map +1 -0
  32. package/dist/esm/backend/NativePhysicsBackend.js +48 -41
  33. package/dist/esm/backend/NativePhysicsBackend.js.map +1 -1
  34. package/dist/esm/backend/PhysicsBackend.d.ts +9 -2
  35. package/dist/esm/backend/PhysicsBackend.d.ts.map +1 -0
  36. package/dist/esm/binding/BindingRegistry.d.ts +25 -4
  37. package/dist/esm/binding/BindingRegistry.d.ts.map +1 -0
  38. package/dist/esm/binding/BindingRegistry.js +70 -36
  39. package/dist/esm/binding/BindingRegistry.js.map +1 -1
  40. package/dist/esm/binding/PhysicsBinding.d.ts +22 -5
  41. package/dist/esm/binding/PhysicsBinding.d.ts.map +1 -0
  42. package/dist/esm/binding/PhysicsBinding.js +46 -21
  43. package/dist/esm/binding/PhysicsBinding.js.map +1 -1
  44. package/dist/esm/broadphase/AabbTreeBroadPhase.d.ts +68 -0
  45. package/dist/esm/broadphase/AabbTreeBroadPhase.d.ts.map +1 -0
  46. package/dist/esm/broadphase/AabbTreeBroadPhase.js +149 -0
  47. package/dist/esm/broadphase/AabbTreeBroadPhase.js.map +1 -0
  48. package/dist/esm/broadphase/BroadPhase.d.ts +7 -4
  49. package/dist/esm/broadphase/BroadPhase.d.ts.map +1 -0
  50. package/dist/esm/broadphase/index.d.ts +2 -1
  51. package/dist/esm/broadphase/index.d.ts.map +1 -0
  52. package/dist/esm/collision/CollisionProxy.d.ts +3 -2
  53. package/dist/esm/collision/CollisionProxy.d.ts.map +1 -0
  54. package/dist/esm/collision/Manifold.d.ts +5 -4
  55. package/dist/esm/collision/Manifold.d.ts.map +1 -0
  56. package/dist/esm/collision/Manifold.js +34 -25
  57. package/dist/esm/collision/Manifold.js.map +1 -1
  58. package/dist/esm/collision/chainAdjacency.d.ts +29 -0
  59. package/dist/esm/collision/chainAdjacency.d.ts.map +1 -0
  60. package/dist/esm/collision/chainAdjacency.js +44 -0
  61. package/dist/esm/collision/chainAdjacency.js.map +1 -0
  62. package/dist/esm/collision/dispatch.d.ts +35 -0
  63. package/dist/esm/collision/dispatch.d.ts.map +1 -0
  64. package/dist/esm/collision/dispatch.js +58 -0
  65. package/dist/esm/collision/dispatch.js.map +1 -0
  66. package/dist/esm/collision/index.d.ts +2 -0
  67. package/dist/esm/collision/index.d.ts.map +1 -0
  68. package/dist/esm/collision/narrowphase.d.ts +5 -2
  69. package/dist/esm/collision/narrowphase.d.ts.map +1 -0
  70. package/dist/esm/collision/narrowphase.js +524 -399
  71. package/dist/esm/collision/narrowphase.js.map +1 -1
  72. package/dist/esm/collision/segments.d.ts +19 -0
  73. package/dist/esm/collision/segments.d.ts.map +1 -0
  74. package/dist/esm/collision/segments.js +36 -0
  75. package/dist/esm/collision/segments.js.map +1 -0
  76. package/dist/esm/collision/sweep.d.ts +35 -0
  77. package/dist/esm/collision/sweep.d.ts.map +1 -0
  78. package/dist/esm/collision/sweep.js +437 -0
  79. package/dist/esm/collision/sweep.js.map +1 -0
  80. package/dist/esm/debug/PhysicsDebugDraw.d.ts +23 -4
  81. package/dist/esm/debug/PhysicsDebugDraw.d.ts.map +1 -0
  82. package/dist/esm/debug/PhysicsDebugDraw.js +230 -188
  83. package/dist/esm/debug/PhysicsDebugDraw.js.map +1 -1
  84. package/dist/esm/debug/index.d.ts +1 -0
  85. package/dist/esm/debug/index.d.ts.map +1 -0
  86. package/dist/esm/debug/index.js +3 -2
  87. package/dist/esm/events.d.ts +1 -0
  88. package/dist/esm/events.d.ts.map +1 -0
  89. package/dist/esm/index.d.ts +1 -0
  90. package/dist/esm/index.d.ts.map +1 -0
  91. package/dist/esm/index.js +24 -19
  92. package/dist/esm/joints/DistanceJoint.d.ts +4 -3
  93. package/dist/esm/joints/DistanceJoint.d.ts.map +1 -0
  94. package/dist/esm/joints/DistanceJoint.js +160 -172
  95. package/dist/esm/joints/DistanceJoint.js.map +1 -1
  96. package/dist/esm/joints/Joint.d.ts +5 -4
  97. package/dist/esm/joints/Joint.d.ts.map +1 -0
  98. package/dist/esm/joints/Joint.js +23 -21
  99. package/dist/esm/joints/Joint.js.map +1 -1
  100. package/dist/esm/joints/MouseJoint.d.ts +8 -7
  101. package/dist/esm/joints/MouseJoint.d.ts.map +1 -0
  102. package/dist/esm/joints/MouseJoint.js +132 -133
  103. package/dist/esm/joints/MouseJoint.js.map +1 -1
  104. package/dist/esm/joints/PrismaticJoint.d.ts +5 -4
  105. package/dist/esm/joints/PrismaticJoint.d.ts.map +1 -0
  106. package/dist/esm/joints/PrismaticJoint.js +211 -240
  107. package/dist/esm/joints/PrismaticJoint.js.map +1 -1
  108. package/dist/esm/joints/RevoluteJoint.d.ts +4 -3
  109. package/dist/esm/joints/RevoluteJoint.d.ts.map +1 -0
  110. package/dist/esm/joints/RevoluteJoint.js +191 -213
  111. package/dist/esm/joints/RevoluteJoint.js.map +1 -1
  112. package/dist/esm/joints/WeldJoint.d.ts +3 -2
  113. package/dist/esm/joints/WeldJoint.d.ts.map +1 -0
  114. package/dist/esm/joints/WeldJoint.js +156 -152
  115. package/dist/esm/joints/WeldJoint.js.map +1 -1
  116. package/dist/esm/joints/WheelJoint.d.ts +4 -3
  117. package/dist/esm/joints/WheelJoint.d.ts.map +1 -0
  118. package/dist/esm/joints/WheelJoint.js +228 -255
  119. package/dist/esm/joints/WheelJoint.js.map +1 -1
  120. package/dist/esm/math.d.ts +6 -9
  121. package/dist/esm/math.d.ts.map +1 -0
  122. package/dist/esm/math.js +37 -39
  123. package/dist/esm/math.js.map +1 -1
  124. package/dist/esm/physicsBuildInfo.d.ts +1 -0
  125. package/dist/esm/physicsBuildInfo.d.ts.map +1 -0
  126. package/dist/esm/physicsBuildInfo.js +6 -4
  127. package/dist/esm/physicsBuildInfo.js.map +1 -1
  128. package/dist/esm/public.d.ts +8 -3
  129. package/dist/esm/public.d.ts.map +1 -0
  130. package/dist/esm/query/QueryEngine.d.ts +56 -12
  131. package/dist/esm/query/QueryEngine.d.ts.map +1 -0
  132. package/dist/esm/query/QueryEngine.js +494 -237
  133. package/dist/esm/query/QueryEngine.js.map +1 -1
  134. package/dist/esm/query/SpatialIndex.d.ts +34 -0
  135. package/dist/esm/query/SpatialIndex.d.ts.map +1 -0
  136. package/dist/esm/shapes/AnyShape.d.ts +9 -4
  137. package/dist/esm/shapes/AnyShape.d.ts.map +1 -0
  138. package/dist/esm/shapes/BoxShape.d.ts +2 -1
  139. package/dist/esm/shapes/BoxShape.d.ts.map +1 -0
  140. package/dist/esm/shapes/BoxShape.js +37 -25
  141. package/dist/esm/shapes/BoxShape.js.map +1 -1
  142. package/dist/esm/shapes/CapsuleShape.d.ts +30 -0
  143. package/dist/esm/shapes/CapsuleShape.d.ts.map +1 -0
  144. package/dist/esm/shapes/CapsuleShape.js +88 -0
  145. package/dist/esm/shapes/CapsuleShape.js.map +1 -0
  146. package/dist/esm/shapes/ChainEdgeShape.d.ts +30 -0
  147. package/dist/esm/shapes/ChainEdgeShape.d.ts.map +1 -0
  148. package/dist/esm/shapes/ChainEdgeShape.js +66 -0
  149. package/dist/esm/shapes/ChainEdgeShape.js.map +1 -0
  150. package/dist/esm/shapes/ChainShape.d.ts +52 -0
  151. package/dist/esm/shapes/ChainShape.d.ts.map +1 -0
  152. package/dist/esm/shapes/ChainShape.js +85 -0
  153. package/dist/esm/shapes/ChainShape.js.map +1 -0
  154. package/dist/esm/shapes/CircleShape.d.ts +3 -4
  155. package/dist/esm/shapes/CircleShape.d.ts.map +1 -0
  156. package/dist/esm/shapes/CircleShape.js +27 -26
  157. package/dist/esm/shapes/CircleShape.js.map +1 -1
  158. package/dist/esm/shapes/PolygonShape.d.ts +7 -8
  159. package/dist/esm/shapes/PolygonShape.d.ts.map +1 -0
  160. package/dist/esm/shapes/PolygonShape.js +131 -162
  161. package/dist/esm/shapes/PolygonShape.js.map +1 -1
  162. package/dist/esm/shapes/SegmentShape.d.ts +31 -0
  163. package/dist/esm/shapes/SegmentShape.d.ts.map +1 -0
  164. package/dist/esm/shapes/SegmentShape.js +62 -0
  165. package/dist/esm/shapes/SegmentShape.js.map +1 -0
  166. package/dist/esm/shapes/Shape.d.ts +28 -17
  167. package/dist/esm/shapes/Shape.d.ts.map +1 -0
  168. package/dist/esm/shapes/Shape.js +12 -13
  169. package/dist/esm/shapes/Shape.js.map +1 -1
  170. package/dist/esm/shapes/convexParts.d.ts +21 -0
  171. package/dist/esm/shapes/convexParts.d.ts.map +1 -0
  172. package/dist/esm/shapes/convexParts.js +26 -0
  173. package/dist/esm/shapes/convexParts.js.map +1 -0
  174. package/dist/esm/shapes/decompose.d.ts +24 -0
  175. package/dist/esm/shapes/decompose.d.ts.map +1 -0
  176. package/dist/esm/shapes/decompose.js +272 -0
  177. package/dist/esm/shapes/decompose.js.map +1 -0
  178. package/dist/esm/shapes/index.d.ts +4 -0
  179. package/dist/esm/shapes/index.d.ts.map +1 -0
  180. package/dist/esm/solver/ContactSolver.d.ts +12 -5
  181. package/dist/esm/solver/ContactSolver.d.ts.map +1 -0
  182. package/dist/esm/solver/ContactSolver.js +425 -471
  183. package/dist/esm/solver/ContactSolver.js.map +1 -1
  184. package/dist/esm/solver/tolerances.d.ts +34 -0
  185. package/dist/esm/solver/tolerances.d.ts.map +1 -0
  186. package/dist/esm/solver/tolerances.js +38 -0
  187. package/dist/esm/solver/tolerances.js.map +1 -0
  188. package/dist/esm/sort.d.ts +5 -4
  189. package/dist/esm/sort.d.ts.map +1 -0
  190. package/dist/esm/sort.js +41 -51
  191. package/dist/esm/sort.js.map +1 -1
  192. package/dist/esm/types.d.ts +4 -8
  193. package/dist/esm/types.d.ts.map +1 -0
  194. package/dist/esm/types.js +15 -17
  195. package/dist/esm/types.js.map +1 -1
  196. package/package.json +6 -6
  197. package/dist/esm/broadphase/SweepAndPrune.d.ts +0 -15
  198. package/dist/esm/broadphase/SweepAndPrune.js +0 -77
  199. package/dist/esm/broadphase/SweepAndPrune.js.map +0 -1
  200. package/dist/esm/debug/index.js.map +0 -1
  201. package/dist/esm/index.js.map +0 -1
@@ -1,259 +1,232 @@
1
- import { applyInverseTransform, applyInverseRotation, applyRotation, applyTransform } from '../math.js';
2
- import { Joint } from './Joint.js';
1
+ import { applyInverseRotation, applyInverseTransform, applyRotation, applyTransform } from "../math.js";
2
+ import { Joint } from "./Joint.js";
3
3
 
4
- /** Reused output sink — physics steps single-threaded, so a shared scratch is safe. */
5
- const scratch = { x: 0, y: 0 };
4
+ //#region src/joints/WheelJoint.ts
5
+ /** Reused output sink - physics steps single-threaded, so a shared scratch is safe. */
6
+ const scratch = {
7
+ x: 0,
8
+ y: 0
9
+ };
6
10
  /**
7
- * A wheel attached to a chassis: free to **spin** (no rotation lock) and sprung
8
- * along a **suspension axis** (a soft spring), but locked **laterally** (it
9
- * cannot slide perpendicular to the axis). Optionally driven by a rotation
10
- * motor and/or bounded by a suspension-travel limit. Used for vehicles. Solved
11
- * in the sub-step loop, warm-started.
12
- */
13
- class WheelJoint extends Joint {
14
- /** Suspension spring frequency in Hz (`0` = rigid axis). */
15
- hertz;
16
- /** Suspension spring damping ratio. */
17
- dampingRatio;
18
- /** When `true`, the motor drives the wheel's spin toward {@link motorSpeed}. */
19
- enableMotor;
20
- /** Target relative angular velocity (rad/s) for the motor. */
21
- motorSpeed;
22
- /** Maximum motor torque. */
23
- maxMotorTorque;
24
- /** When `true`, the axis translation is constrained to `[lowerTranslation, upperTranslation]`. */
25
- enableLimit;
26
- /** Lower suspension-travel limit along the axis. */
27
- lowerTranslation;
28
- /** Upper suspension-travel limit along the axis. */
29
- upperTranslation;
30
- _localAnchorAx;
31
- _localAnchorAy;
32
- _localAnchorBx;
33
- _localAnchorBy;
34
- _localAxisAx;
35
- _localAxisAy;
36
- _axisX = 1;
37
- _axisY = 0;
38
- _perpX = 0;
39
- _perpY = 1;
40
- _a1 = 0;
41
- _a2 = 0;
42
- _s1 = 0;
43
- _s2 = 0;
44
- _perpMass = 0;
45
- _axialMass = 0;
46
- _angularMass = 0;
47
- _springBiasRate = 0;
48
- _springMassScale = 1;
49
- _springImpulseScale = 0;
50
- _cPerp = 0;
51
- _translation = 0;
52
- _h = 0;
53
- _invH = 0;
54
- _perpImpulse = 0;
55
- _springImpulse = 0;
56
- _motorImpulse = 0;
57
- _lowerImpulse = 0;
58
- _upperImpulse = 0;
59
- constructor(options) {
60
- super(options.bodyA, options.bodyB);
61
- applyInverseTransform(options.bodyA.transform, options.anchor.x, options.anchor.y, scratch);
62
- this._localAnchorAx = scratch.x;
63
- this._localAnchorAy = scratch.y;
64
- applyInverseTransform(options.bodyB.transform, options.anchor.x, options.anchor.y, scratch);
65
- this._localAnchorBx = scratch.x;
66
- this._localAnchorBy = scratch.y;
67
- const axisLength = Math.hypot(options.axis.x, options.axis.y);
68
- if (!Number.isFinite(axisLength) || axisLength === 0) {
69
- throw new RangeError(`WheelJoint: axis must be a non-zero finite vector, received (${options.axis.x}, ${options.axis.y}).`);
70
- }
71
- applyInverseRotation(options.bodyA.transform, options.axis.x / axisLength, options.axis.y / axisLength, scratch);
72
- this._localAxisAx = scratch.x;
73
- this._localAxisAy = scratch.y;
74
- this.hertz = options.hertz ?? 0;
75
- this.dampingRatio = options.dampingRatio ?? 1;
76
- this.enableMotor = options.enableMotor ?? false;
77
- this.motorSpeed = options.motorSpeed ?? 0;
78
- this.maxMotorTorque = options.maxMotorTorque ?? 0;
79
- this.enableLimit = options.enableLimit ?? false;
80
- this.lowerTranslation = options.lowerTranslation ?? 0;
81
- this.upperTranslation = options.upperTranslation ?? 0;
82
- }
83
- _prepare(h) {
84
- const bodyA = this.bodyA;
85
- const bodyB = this.bodyB;
86
- this._active = this.enabled && !bodyA.isSleeping && !bodyB.isSleeping && (bodyA.invMass > 0 || bodyB.invMass > 0);
87
- if (!this._active) {
88
- return;
89
- }
90
- applyRotation(bodyA.transform, this._localAxisAx, this._localAxisAy, scratch);
91
- const axisX = scratch.x;
92
- const axisY = scratch.y;
93
- const perpX = -axisY;
94
- const perpY = axisX;
95
- this._axisX = axisX;
96
- this._axisY = axisY;
97
- this._perpX = perpX;
98
- this._perpY = perpY;
99
- applyTransform(bodyA.transform, this._localAnchorAx, this._localAnchorAy, scratch);
100
- const pAx = scratch.x;
101
- const pAy = scratch.y;
102
- applyTransform(bodyB.transform, this._localAnchorBx, this._localAnchorBy, scratch);
103
- const pBx = scratch.x;
104
- const pBy = scratch.y;
105
- const rAx = pAx - bodyA.worldCenterOfMassX;
106
- const rAy = pAy - bodyA.worldCenterOfMassY;
107
- const rBx = pBx - bodyB.worldCenterOfMassX;
108
- const rBy = pBy - bodyB.worldCenterOfMassY;
109
- const dx = pBx - pAx;
110
- const dy = pBy - pAy;
111
- this._a1 = (dx + rAx) * axisY - (dy + rAy) * axisX;
112
- this._a2 = rBx * axisY - rBy * axisX;
113
- this._s1 = (dx + rAx) * perpY - (dy + rAy) * perpX;
114
- this._s2 = rBx * perpY - rBy * perpX;
115
- const mA = bodyA.invMass;
116
- const mB = bodyB.invMass;
117
- const iA = bodyA.invInertia;
118
- const iB = bodyB.invInertia;
119
- const kPerp = mA + mB + iA * this._s1 * this._s1 + iB * this._s2 * this._s2;
120
- this._perpMass = kPerp > 0 ? 1 / kPerp : 0;
121
- const kAxial = mA + mB + iA * this._a1 * this._a1 + iB * this._a2 * this._a2;
122
- this._axialMass = kAxial > 0 ? 1 / kAxial : 0;
123
- this._angularMass = iA + iB > 0 ? 1 / (iA + iB) : 0;
124
- this._cPerp = dx * perpX + dy * perpY;
125
- this._translation = dx * axisX + dy * axisY;
126
- this._h = h;
127
- this._invH = 1 / h;
128
- if (this.hertz > 0) {
129
- const omega = 2 * Math.PI * this.hertz;
130
- const a1 = 2 * this.dampingRatio + h * omega;
131
- const a2 = h * omega * a1;
132
- const a3 = 1 / (1 + a2);
133
- this._springBiasRate = omega / a1;
134
- this._springMassScale = a2 * a3;
135
- this._springImpulseScale = a3;
136
- }
137
- else {
138
- this._springBiasRate = 0.2 / h;
139
- this._springMassScale = 1;
140
- this._springImpulseScale = 0;
141
- }
142
- if (!this.enableMotor) {
143
- this._motorImpulse = 0;
144
- }
145
- if (!this.enableLimit) {
146
- this._lowerImpulse = 0;
147
- this._upperImpulse = 0;
148
- }
149
- }
150
- _warmStart() {
151
- if (!this._active) {
152
- return;
153
- }
154
- const bodyA = this.bodyA;
155
- const bodyB = this.bodyB;
156
- // Rotation motor (angular).
157
- bodyA.angularVelocity -= bodyA.invInertia * this._motorImpulse;
158
- bodyB.angularVelocity += bodyB.invInertia * this._motorImpulse;
159
- this._applyAxial(this._springImpulse + this._lowerImpulse - this._upperImpulse);
160
- this._applyPerp(this._perpImpulse);
161
- }
162
- _solve(useBias) {
163
- if (!this._active) {
164
- return;
165
- }
166
- const bodyA = this.bodyA;
167
- const bodyB = this.bodyB;
168
- // Rotation motor — drives the wheel's spin; rotation is otherwise free.
169
- if (this.enableMotor) {
170
- const cdot = bodyB.angularVelocity - bodyA.angularVelocity - this.motorSpeed;
171
- const max = this.maxMotorTorque * this._h;
172
- const old = this._motorImpulse;
173
- this._motorImpulse = Math.min(max, Math.max(-max, old - this._angularMass * cdot));
174
- const applied = this._motorImpulse - old;
175
- bodyA.angularVelocity -= bodyA.invInertia * applied;
176
- bodyB.angularVelocity += bodyB.invInertia * applied;
177
- }
178
- // Suspension spring along the axis (soft).
179
- const cdotAxis = this._axisVelocity();
180
- const springImpulse = -this._axialMass * this._springMassScale * (cdotAxis + this._springBiasRate * this._translation) - this._springImpulseScale * this._springImpulse;
181
- this._springImpulse += springImpulse;
182
- this._applyAxial(springImpulse);
183
- // Suspension-travel limits along the axis.
184
- if (this.enableLimit) {
185
- // Lower limit (translation ≥ lowerTranslation): positive impulse pushes along +axis.
186
- const cLower = this._translation - this.lowerTranslation;
187
- let biasLower = 0;
188
- if (cLower > 0) {
189
- biasLower = cLower * this._invH;
190
- }
191
- else if (useBias) {
192
- biasLower = 0.2 * this._invH * cLower;
193
- }
194
- const oldLower = this._lowerImpulse;
195
- this._lowerImpulse = Math.max(0, oldLower - this._axialMass * (this._axisVelocity() + biasLower));
196
- this._applyAxial(this._lowerImpulse - oldLower);
197
- // Upper limit (translation ≤ upperTranslation): impulse pushes along −axis.
198
- const cUpper = this.upperTranslation - this._translation;
199
- let biasUpper = 0;
200
- if (cUpper > 0) {
201
- biasUpper = cUpper * this._invH;
202
- }
203
- else if (useBias) {
204
- biasUpper = 0.2 * this._invH * cUpper;
205
- }
206
- const oldUpper = this._upperImpulse;
207
- this._upperImpulse = Math.max(0, oldUpper - this._axialMass * (-this._axisVelocity() + biasUpper));
208
- this._applyAxial(-(this._upperImpulse - oldUpper));
209
- }
210
- // Lateral lock (perpendicular, rigid).
211
- const cdotPerp = this._perpVelocity();
212
- const perpImpulse = -this._perpMass * (cdotPerp + (useBias ? 0.2 * this._invH * this._cPerp : 0));
213
- this._perpImpulse += perpImpulse;
214
- this._applyPerp(perpImpulse);
215
- }
216
- _axisVelocity() {
217
- const bodyA = this.bodyA;
218
- const bodyB = this.bodyB;
219
- return (this._axisX * (bodyB.linearVelocityX - bodyA.linearVelocityX) +
220
- this._axisY * (bodyB.linearVelocityY - bodyA.linearVelocityY) +
221
- this._a2 * bodyB.angularVelocity -
222
- this._a1 * bodyA.angularVelocity);
223
- }
224
- _perpVelocity() {
225
- const bodyA = this.bodyA;
226
- const bodyB = this.bodyB;
227
- return (this._perpX * (bodyB.linearVelocityX - bodyA.linearVelocityX) +
228
- this._perpY * (bodyB.linearVelocityY - bodyA.linearVelocityY) +
229
- this._s2 * bodyB.angularVelocity -
230
- this._s1 * bodyA.angularVelocity);
231
- }
232
- _applyAxial(impulse) {
233
- const bodyA = this.bodyA;
234
- const bodyB = this.bodyB;
235
- const px = impulse * this._axisX;
236
- const py = impulse * this._axisY;
237
- bodyA.linearVelocityX -= bodyA.invMass * px;
238
- bodyA.linearVelocityY -= bodyA.invMass * py;
239
- bodyA.angularVelocity -= bodyA.invInertia * impulse * this._a1;
240
- bodyB.linearVelocityX += bodyB.invMass * px;
241
- bodyB.linearVelocityY += bodyB.invMass * py;
242
- bodyB.angularVelocity += bodyB.invInertia * impulse * this._a2;
243
- }
244
- _applyPerp(impulse) {
245
- const bodyA = this.bodyA;
246
- const bodyB = this.bodyB;
247
- const px = impulse * this._perpX;
248
- const py = impulse * this._perpY;
249
- bodyA.linearVelocityX -= bodyA.invMass * px;
250
- bodyA.linearVelocityY -= bodyA.invMass * py;
251
- bodyA.angularVelocity -= bodyA.invInertia * impulse * this._s1;
252
- bodyB.linearVelocityX += bodyB.invMass * px;
253
- bodyB.linearVelocityY += bodyB.invMass * py;
254
- bodyB.angularVelocity += bodyB.invInertia * impulse * this._s2;
255
- }
256
- }
11
+ * A wheel attached to a chassis: free to **spin** (no rotation lock) and sprung
12
+ * along a **suspension axis** (a soft spring), but locked **laterally** (it
13
+ * cannot slide perpendicular to the axis). Optionally driven by a rotation
14
+ * motor and/or bounded by a suspension-travel limit. Used for vehicles. Solved
15
+ * in the sub-step loop, warm-started.
16
+ */
17
+ var WheelJoint = class extends Joint {
18
+ /** Suspension spring frequency in Hz (`0` = rigid axis). */
19
+ hertz;
20
+ /** Suspension spring damping ratio. */
21
+ dampingRatio;
22
+ /** When `true`, the motor drives the wheel's spin toward {@link motorSpeed}. */
23
+ enableMotor;
24
+ /** Target relative angular velocity (rad/s) for the motor. */
25
+ motorSpeed;
26
+ /** Maximum motor torque. */
27
+ maxMotorTorque;
28
+ /** When `true`, the axis translation is constrained to `[lowerTranslation, upperTranslation]`. */
29
+ enableLimit;
30
+ /** Lower suspension-travel limit along the axis. */
31
+ lowerTranslation;
32
+ /** Upper suspension-travel limit along the axis. */
33
+ upperTranslation;
34
+ _localAnchorAx;
35
+ _localAnchorAy;
36
+ _localAnchorBx;
37
+ _localAnchorBy;
38
+ _localAxisAx;
39
+ _localAxisAy;
40
+ _axisX = 1;
41
+ _axisY = 0;
42
+ _perpX = 0;
43
+ _perpY = 1;
44
+ _a1 = 0;
45
+ _a2 = 0;
46
+ _s1 = 0;
47
+ _s2 = 0;
48
+ _perpMass = 0;
49
+ _axialMass = 0;
50
+ _angularMass = 0;
51
+ _springBiasRate = 0;
52
+ _springMassScale = 1;
53
+ _springImpulseScale = 0;
54
+ _cPerp = 0;
55
+ _translation = 0;
56
+ _h = 0;
57
+ _invH = 0;
58
+ _perpImpulse = 0;
59
+ _springImpulse = 0;
60
+ _motorImpulse = 0;
61
+ _lowerImpulse = 0;
62
+ _upperImpulse = 0;
63
+ constructor(options) {
64
+ super(options.bodyA, options.bodyB);
65
+ applyInverseTransform(options.bodyA.transform, options.anchor.x, options.anchor.y, scratch);
66
+ this._localAnchorAx = scratch.x;
67
+ this._localAnchorAy = scratch.y;
68
+ applyInverseTransform(options.bodyB.transform, options.anchor.x, options.anchor.y, scratch);
69
+ this._localAnchorBx = scratch.x;
70
+ this._localAnchorBy = scratch.y;
71
+ const axisLength = Math.hypot(options.axis.x, options.axis.y);
72
+ if (!Number.isFinite(axisLength) || axisLength === 0) throw new RangeError(`WheelJoint: axis must be a non-zero finite vector, received (${options.axis.x}, ${options.axis.y}).`);
73
+ applyInverseRotation(options.bodyA.transform, options.axis.x / axisLength, options.axis.y / axisLength, scratch);
74
+ this._localAxisAx = scratch.x;
75
+ this._localAxisAy = scratch.y;
76
+ this.hertz = options.hertz ?? 0;
77
+ this.dampingRatio = options.dampingRatio ?? 1;
78
+ this.enableMotor = options.enableMotor ?? false;
79
+ this.motorSpeed = options.motorSpeed ?? 0;
80
+ this.maxMotorTorque = options.maxMotorTorque ?? 0;
81
+ this.enableLimit = options.enableLimit ?? false;
82
+ this.lowerTranslation = options.lowerTranslation ?? 0;
83
+ this.upperTranslation = options.upperTranslation ?? 0;
84
+ }
85
+ _prepare(h) {
86
+ const bodyA = this.bodyA;
87
+ const bodyB = this.bodyB;
88
+ this._active = this.enabled && !bodyA.isSleeping && !bodyB.isSleeping && (bodyA.invMass > 0 || bodyB.invMass > 0);
89
+ if (!this._active) return;
90
+ applyRotation(bodyA.transform, this._localAxisAx, this._localAxisAy, scratch);
91
+ const axisX = scratch.x;
92
+ const axisY = scratch.y;
93
+ const perpX = -axisY;
94
+ const perpY = axisX;
95
+ this._axisX = axisX;
96
+ this._axisY = axisY;
97
+ this._perpX = perpX;
98
+ this._perpY = perpY;
99
+ applyTransform(bodyA.transform, this._localAnchorAx, this._localAnchorAy, scratch);
100
+ const pAx = scratch.x;
101
+ const pAy = scratch.y;
102
+ applyTransform(bodyB.transform, this._localAnchorBx, this._localAnchorBy, scratch);
103
+ const pBx = scratch.x;
104
+ const pBy = scratch.y;
105
+ const rAx = pAx - bodyA.worldCenterOfMassX;
106
+ const rAy = pAy - bodyA.worldCenterOfMassY;
107
+ const rBx = pBx - bodyB.worldCenterOfMassX;
108
+ const rBy = pBy - bodyB.worldCenterOfMassY;
109
+ const dx = pBx - pAx;
110
+ const dy = pBy - pAy;
111
+ this._a1 = (dx + rAx) * axisY - (dy + rAy) * axisX;
112
+ this._a2 = rBx * axisY - rBy * axisX;
113
+ this._s1 = (dx + rAx) * perpY - (dy + rAy) * perpX;
114
+ this._s2 = rBx * perpY - rBy * perpX;
115
+ const mA = bodyA.invMass;
116
+ const mB = bodyB.invMass;
117
+ const iA = bodyA.invInertia;
118
+ const iB = bodyB.invInertia;
119
+ const kPerp = mA + mB + iA * this._s1 * this._s1 + iB * this._s2 * this._s2;
120
+ this._perpMass = kPerp > 0 ? 1 / kPerp : 0;
121
+ const kAxial = mA + mB + iA * this._a1 * this._a1 + iB * this._a2 * this._a2;
122
+ this._axialMass = kAxial > 0 ? 1 / kAxial : 0;
123
+ this._angularMass = iA + iB > 0 ? 1 / (iA + iB) : 0;
124
+ this._cPerp = dx * perpX + dy * perpY;
125
+ this._translation = dx * axisX + dy * axisY;
126
+ this._h = h;
127
+ this._invH = 1 / h;
128
+ if (this.hertz > 0) {
129
+ const omega = 2 * Math.PI * this.hertz;
130
+ const a1 = 2 * this.dampingRatio + h * omega;
131
+ const a2 = h * omega * a1;
132
+ const a3 = 1 / (1 + a2);
133
+ this._springBiasRate = omega / a1;
134
+ this._springMassScale = a2 * a3;
135
+ this._springImpulseScale = a3;
136
+ } else {
137
+ this._springBiasRate = .2 / h;
138
+ this._springMassScale = 1;
139
+ this._springImpulseScale = 0;
140
+ }
141
+ if (!this.enableMotor) this._motorImpulse = 0;
142
+ if (!this.enableLimit) {
143
+ this._lowerImpulse = 0;
144
+ this._upperImpulse = 0;
145
+ }
146
+ }
147
+ _warmStart() {
148
+ if (!this._active) return;
149
+ const bodyA = this.bodyA;
150
+ const bodyB = this.bodyB;
151
+ bodyA.angularVelocity -= bodyA.invInertia * this._motorImpulse;
152
+ bodyB.angularVelocity += bodyB.invInertia * this._motorImpulse;
153
+ this._applyAxial(this._springImpulse + this._lowerImpulse - this._upperImpulse);
154
+ this._applyPerp(this._perpImpulse);
155
+ }
156
+ _solve(useBias) {
157
+ if (!this._active) return;
158
+ const bodyA = this.bodyA;
159
+ const bodyB = this.bodyB;
160
+ if (this.enableMotor) {
161
+ const cdot = bodyB.angularVelocity - bodyA.angularVelocity - this.motorSpeed;
162
+ const max = this.maxMotorTorque * this._h;
163
+ const old = this._motorImpulse;
164
+ this._motorImpulse = Math.min(max, Math.max(-max, old - this._angularMass * cdot));
165
+ const applied = this._motorImpulse - old;
166
+ bodyA.angularVelocity -= bodyA.invInertia * applied;
167
+ bodyB.angularVelocity += bodyB.invInertia * applied;
168
+ }
169
+ const cdotAxis = this._axisVelocity();
170
+ const springImpulse = -this._axialMass * this._springMassScale * (cdotAxis + this._springBiasRate * this._translation) - this._springImpulseScale * this._springImpulse;
171
+ this._springImpulse += springImpulse;
172
+ this._applyAxial(springImpulse);
173
+ if (this.enableLimit) {
174
+ const cLower = this._translation - this.lowerTranslation;
175
+ let biasLower = 0;
176
+ if (cLower > 0) biasLower = cLower * this._invH;
177
+ else if (useBias) biasLower = .2 * this._invH * cLower;
178
+ const oldLower = this._lowerImpulse;
179
+ this._lowerImpulse = Math.max(0, oldLower - this._axialMass * (this._axisVelocity() + biasLower));
180
+ this._applyAxial(this._lowerImpulse - oldLower);
181
+ const cUpper = this.upperTranslation - this._translation;
182
+ let biasUpper = 0;
183
+ if (cUpper > 0) biasUpper = cUpper * this._invH;
184
+ else if (useBias) biasUpper = .2 * this._invH * cUpper;
185
+ const oldUpper = this._upperImpulse;
186
+ this._upperImpulse = Math.max(0, oldUpper - this._axialMass * (-this._axisVelocity() + biasUpper));
187
+ this._applyAxial(-(this._upperImpulse - oldUpper));
188
+ }
189
+ const cdotPerp = this._perpVelocity();
190
+ const perpImpulse = -this._perpMass * (cdotPerp + (useBias ? .2 * this._invH * this._cPerp : 0));
191
+ this._perpImpulse += perpImpulse;
192
+ this._applyPerp(perpImpulse);
193
+ }
194
+ _axisVelocity() {
195
+ const bodyA = this.bodyA;
196
+ const bodyB = this.bodyB;
197
+ return this._axisX * (bodyB.linearVelocityX - bodyA.linearVelocityX) + this._axisY * (bodyB.linearVelocityY - bodyA.linearVelocityY) + this._a2 * bodyB.angularVelocity - this._a1 * bodyA.angularVelocity;
198
+ }
199
+ _perpVelocity() {
200
+ const bodyA = this.bodyA;
201
+ const bodyB = this.bodyB;
202
+ return this._perpX * (bodyB.linearVelocityX - bodyA.linearVelocityX) + this._perpY * (bodyB.linearVelocityY - bodyA.linearVelocityY) + this._s2 * bodyB.angularVelocity - this._s1 * bodyA.angularVelocity;
203
+ }
204
+ _applyAxial(impulse) {
205
+ const bodyA = this.bodyA;
206
+ const bodyB = this.bodyB;
207
+ const px = impulse * this._axisX;
208
+ const py = impulse * this._axisY;
209
+ bodyA.linearVelocityX -= bodyA.invMass * px;
210
+ bodyA.linearVelocityY -= bodyA.invMass * py;
211
+ bodyA.angularVelocity -= bodyA.invInertia * impulse * this._a1;
212
+ bodyB.linearVelocityX += bodyB.invMass * px;
213
+ bodyB.linearVelocityY += bodyB.invMass * py;
214
+ bodyB.angularVelocity += bodyB.invInertia * impulse * this._a2;
215
+ }
216
+ _applyPerp(impulse) {
217
+ const bodyA = this.bodyA;
218
+ const bodyB = this.bodyB;
219
+ const px = impulse * this._perpX;
220
+ const py = impulse * this._perpY;
221
+ bodyA.linearVelocityX -= bodyA.invMass * px;
222
+ bodyA.linearVelocityY -= bodyA.invMass * py;
223
+ bodyA.angularVelocity -= bodyA.invInertia * impulse * this._s1;
224
+ bodyB.linearVelocityX += bodyB.invMass * px;
225
+ bodyB.linearVelocityY += bodyB.invMass * py;
226
+ bodyB.angularVelocity += bodyB.invInertia * impulse * this._s2;
227
+ }
228
+ };
257
229
 
230
+ //#endregion
258
231
  export { WheelJoint };
259
- //# sourceMappingURL=WheelJoint.js.map
232
+ //# sourceMappingURL=WheelJoint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WheelJoint.js","sources":["../../../../src/joints/WheelJoint.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WheelJoint.js","names":[],"sources":["../../../src/joints/WheelJoint.ts"],"sourcesContent":["import type { PointLike } from '@codexo/exojs';\n\nimport { applyInverseRotation, applyInverseTransform, applyRotation, applyTransform } from '../math';\nimport type { PhysicsBody } from '../PhysicsBody';\nimport { Joint } from './Joint';\n\n/** Construction options for a {@link WheelJoint}. */\nexport interface WheelJointOptions {\n /** First body (the chassis). */\n bodyA: PhysicsBody;\n /** Second body (the wheel). */\n bodyB: PhysicsBody;\n /** Shared world-space anchor at creation (the wheel hub). */\n anchor: Readonly<PointLike>;\n /** Suspension axis in world space at creation (normalised internally). */\n axis: Readonly<PointLike>;\n /** Suspension spring frequency in Hz (`0` makes the axis rigid). Default `0`. */\n hertz?: number;\n /** Suspension spring damping ratio. Default `1`. */\n dampingRatio?: number;\n /** Enable the rotation motor (drives the wheel's spin). Default `false`. */\n enableMotor?: boolean;\n /** Target relative angular velocity (rad/s) for the motor. Default `0`. */\n motorSpeed?: number;\n /** Maximum motor torque. Default `0`. */\n maxMotorTorque?: number;\n /** Enable the suspension-travel limit (keeps the axis translation in `[lowerTranslation, upperTranslation]`). Default `false`. */\n enableLimit?: boolean;\n /** Lower suspension-travel limit along the axis (relative to the creation position). Default `0`. */\n lowerTranslation?: number;\n /** Upper suspension-travel limit along the axis. Default `0`. */\n upperTranslation?: number;\n}\n\n/** Reused output sink - physics steps single-threaded, so a shared scratch is safe. */\nconst scratch: PointLike = { x: 0, y: 0 };\n\n/**\n * A wheel attached to a chassis: free to **spin** (no rotation lock) and sprung\n * along a **suspension axis** (a soft spring), but locked **laterally** (it\n * cannot slide perpendicular to the axis). Optionally driven by a rotation\n * motor and/or bounded by a suspension-travel limit. Used for vehicles. Solved\n * in the sub-step loop, warm-started.\n */\nexport class WheelJoint extends Joint {\n /** Suspension spring frequency in Hz (`0` = rigid axis). */\n public hertz: number;\n /** Suspension spring damping ratio. */\n public dampingRatio: number;\n /** When `true`, the motor drives the wheel's spin toward {@link motorSpeed}. */\n public enableMotor: boolean;\n /** Target relative angular velocity (rad/s) for the motor. */\n public motorSpeed: number;\n /** Maximum motor torque. */\n public maxMotorTorque: number;\n /** When `true`, the axis translation is constrained to `[lowerTranslation, upperTranslation]`. */\n public enableLimit: boolean;\n /** Lower suspension-travel limit along the axis. */\n public lowerTranslation: number;\n /** Upper suspension-travel limit along the axis. */\n public upperTranslation: number;\n\n private readonly _localAnchorAx: number;\n private readonly _localAnchorAy: number;\n private readonly _localAnchorBx: number;\n private readonly _localAnchorBy: number;\n private readonly _localAxisAx: number;\n private readonly _localAxisAy: number;\n\n private _axisX = 1;\n private _axisY = 0;\n private _perpX = 0;\n private _perpY = 1;\n private _a1 = 0;\n private _a2 = 0;\n private _s1 = 0;\n private _s2 = 0;\n private _perpMass = 0;\n private _axialMass = 0;\n private _angularMass = 0;\n private _springBiasRate = 0;\n private _springMassScale = 1;\n private _springImpulseScale = 0;\n private _cPerp = 0;\n private _translation = 0;\n private _h = 0;\n private _invH = 0;\n private _perpImpulse = 0;\n private _springImpulse = 0;\n private _motorImpulse = 0;\n private _lowerImpulse = 0;\n private _upperImpulse = 0;\n\n public constructor(options: WheelJointOptions) {\n super(options.bodyA, options.bodyB);\n\n applyInverseTransform(options.bodyA.transform, options.anchor.x, options.anchor.y, scratch);\n this._localAnchorAx = scratch.x;\n this._localAnchorAy = scratch.y;\n applyInverseTransform(options.bodyB.transform, options.anchor.x, options.anchor.y, scratch);\n this._localAnchorBx = scratch.x;\n this._localAnchorBy = scratch.y;\n\n const axisLength = Math.hypot(options.axis.x, options.axis.y);\n\n if (!Number.isFinite(axisLength) || axisLength === 0) {\n throw new RangeError(`WheelJoint: axis must be a non-zero finite vector, received (${options.axis.x}, ${options.axis.y}).`);\n }\n\n applyInverseRotation(options.bodyA.transform, options.axis.x / axisLength, options.axis.y / axisLength, scratch);\n this._localAxisAx = scratch.x;\n this._localAxisAy = scratch.y;\n\n this.hertz = options.hertz ?? 0;\n this.dampingRatio = options.dampingRatio ?? 1;\n this.enableMotor = options.enableMotor ?? false;\n this.motorSpeed = options.motorSpeed ?? 0;\n this.maxMotorTorque = options.maxMotorTorque ?? 0;\n this.enableLimit = options.enableLimit ?? false;\n this.lowerTranslation = options.lowerTranslation ?? 0;\n this.upperTranslation = options.upperTranslation ?? 0;\n }\n\n public override _prepare(h: number): void {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n\n this._active = this.enabled && !bodyA.isSleeping && !bodyB.isSleeping && (bodyA.invMass > 0 || bodyB.invMass > 0);\n\n if (!this._active) {\n return;\n }\n\n applyRotation(bodyA.transform, this._localAxisAx, this._localAxisAy, scratch);\n const axisX = scratch.x;\n const axisY = scratch.y;\n const perpX = -axisY;\n const perpY = axisX;\n\n this._axisX = axisX;\n this._axisY = axisY;\n this._perpX = perpX;\n this._perpY = perpY;\n\n applyTransform(bodyA.transform, this._localAnchorAx, this._localAnchorAy, scratch);\n const pAx = scratch.x;\n const pAy = scratch.y;\n applyTransform(bodyB.transform, this._localAnchorBx, this._localAnchorBy, scratch);\n const pBx = scratch.x;\n const pBy = scratch.y;\n\n const rAx = pAx - bodyA.worldCenterOfMassX;\n const rAy = pAy - bodyA.worldCenterOfMassY;\n const rBx = pBx - bodyB.worldCenterOfMassX;\n const rBy = pBy - bodyB.worldCenterOfMassY;\n const dx = pBx - pAx;\n const dy = pBy - pAy;\n\n this._a1 = (dx + rAx) * axisY - (dy + rAy) * axisX;\n this._a2 = rBx * axisY - rBy * axisX;\n this._s1 = (dx + rAx) * perpY - (dy + rAy) * perpX;\n this._s2 = rBx * perpY - rBy * perpX;\n\n const mA = bodyA.invMass;\n const mB = bodyB.invMass;\n const iA = bodyA.invInertia;\n const iB = bodyB.invInertia;\n\n const kPerp = mA + mB + iA * this._s1 * this._s1 + iB * this._s2 * this._s2;\n this._perpMass = kPerp > 0 ? 1 / kPerp : 0;\n const kAxial = mA + mB + iA * this._a1 * this._a1 + iB * this._a2 * this._a2;\n this._axialMass = kAxial > 0 ? 1 / kAxial : 0;\n this._angularMass = iA + iB > 0 ? 1 / (iA + iB) : 0;\n\n this._cPerp = dx * perpX + dy * perpY;\n this._translation = dx * axisX + dy * axisY;\n this._h = h;\n this._invH = 1 / h;\n\n if (this.hertz > 0) {\n const omega = 2 * Math.PI * this.hertz;\n const a1 = 2 * this.dampingRatio + h * omega;\n const a2 = h * omega * a1;\n const a3 = 1 / (1 + a2);\n\n this._springBiasRate = omega / a1;\n this._springMassScale = a2 * a3;\n this._springImpulseScale = a3;\n } else {\n this._springBiasRate = 0.2 / h;\n this._springMassScale = 1;\n this._springImpulseScale = 0;\n }\n\n if (!this.enableMotor) {\n this._motorImpulse = 0;\n }\n\n if (!this.enableLimit) {\n this._lowerImpulse = 0;\n this._upperImpulse = 0;\n }\n }\n\n public override _warmStart(): void {\n if (!this._active) {\n return;\n }\n\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n\n // Rotation motor (angular).\n bodyA.angularVelocity -= bodyA.invInertia * this._motorImpulse;\n bodyB.angularVelocity += bodyB.invInertia * this._motorImpulse;\n\n this._applyAxial(this._springImpulse + this._lowerImpulse - this._upperImpulse);\n this._applyPerp(this._perpImpulse);\n }\n\n public override _solve(useBias: boolean): void {\n if (!this._active) {\n return;\n }\n\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n\n // Rotation motor - drives the wheel's spin; rotation is otherwise free.\n if (this.enableMotor) {\n const cdot = bodyB.angularVelocity - bodyA.angularVelocity - this.motorSpeed;\n const max = this.maxMotorTorque * this._h;\n const old = this._motorImpulse;\n\n this._motorImpulse = Math.min(max, Math.max(-max, old - this._angularMass * cdot));\n\n const applied = this._motorImpulse - old;\n bodyA.angularVelocity -= bodyA.invInertia * applied;\n bodyB.angularVelocity += bodyB.invInertia * applied;\n }\n\n // Suspension spring along the axis (soft).\n const cdotAxis = this._axisVelocity();\n const springImpulse =\n -this._axialMass * this._springMassScale * (cdotAxis + this._springBiasRate * this._translation) - this._springImpulseScale * this._springImpulse;\n\n this._springImpulse += springImpulse;\n this._applyAxial(springImpulse);\n\n // Suspension-travel limits along the axis.\n if (this.enableLimit) {\n // Lower limit (translation ≥ lowerTranslation): positive impulse pushes along +axis.\n const cLower = this._translation - this.lowerTranslation;\n let biasLower = 0;\n\n if (cLower > 0) {\n biasLower = cLower * this._invH;\n } else if (useBias) {\n biasLower = 0.2 * this._invH * cLower;\n }\n\n const oldLower = this._lowerImpulse;\n this._lowerImpulse = Math.max(0, oldLower - this._axialMass * (this._axisVelocity() + biasLower));\n this._applyAxial(this._lowerImpulse - oldLower);\n\n // Upper limit (translation ≤ upperTranslation): impulse pushes along −axis.\n const cUpper = this.upperTranslation - this._translation;\n let biasUpper = 0;\n\n if (cUpper > 0) {\n biasUpper = cUpper * this._invH;\n } else if (useBias) {\n biasUpper = 0.2 * this._invH * cUpper;\n }\n\n const oldUpper = this._upperImpulse;\n this._upperImpulse = Math.max(0, oldUpper - this._axialMass * (-this._axisVelocity() + biasUpper));\n this._applyAxial(-(this._upperImpulse - oldUpper));\n }\n\n // Lateral lock (perpendicular, rigid).\n const cdotPerp = this._perpVelocity();\n const perpImpulse = -this._perpMass * (cdotPerp + (useBias ? 0.2 * this._invH * this._cPerp : 0));\n\n this._perpImpulse += perpImpulse;\n this._applyPerp(perpImpulse);\n }\n\n private _axisVelocity(): number {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n\n return (\n this._axisX * (bodyB.linearVelocityX - bodyA.linearVelocityX) +\n this._axisY * (bodyB.linearVelocityY - bodyA.linearVelocityY) +\n this._a2 * bodyB.angularVelocity -\n this._a1 * bodyA.angularVelocity\n );\n }\n\n private _perpVelocity(): number {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n\n return (\n this._perpX * (bodyB.linearVelocityX - bodyA.linearVelocityX) +\n this._perpY * (bodyB.linearVelocityY - bodyA.linearVelocityY) +\n this._s2 * bodyB.angularVelocity -\n this._s1 * bodyA.angularVelocity\n );\n }\n\n private _applyAxial(impulse: number): void {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n const px = impulse * this._axisX;\n const py = impulse * this._axisY;\n\n bodyA.linearVelocityX -= bodyA.invMass * px;\n bodyA.linearVelocityY -= bodyA.invMass * py;\n bodyA.angularVelocity -= bodyA.invInertia * impulse * this._a1;\n bodyB.linearVelocityX += bodyB.invMass * px;\n bodyB.linearVelocityY += bodyB.invMass * py;\n bodyB.angularVelocity += bodyB.invInertia * impulse * this._a2;\n }\n\n private _applyPerp(impulse: number): void {\n const bodyA = this.bodyA;\n const bodyB = this.bodyB;\n const px = impulse * this._perpX;\n const py = impulse * this._perpY;\n\n bodyA.linearVelocityX -= bodyA.invMass * px;\n bodyA.linearVelocityY -= bodyA.invMass * py;\n bodyA.angularVelocity -= bodyA.invInertia * impulse * this._s1;\n bodyB.linearVelocityX += bodyB.invMass * px;\n bodyB.linearVelocityY += bodyB.invMass * py;\n bodyB.angularVelocity += bodyB.invInertia * impulse * this._s2;\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,4 @@
1
- /** A mutable two-component output sink used to avoid per-call allocation. */
2
- export interface Mutable2D {
3
- x: number;
4
- y: number;
5
- }
1
+ import type { PointLike } from '@codexo/exojs';
6
2
  /** A rigid 2D transform: translation plus the precomputed sin/cos of `angle`. */
7
3
  export interface Transform {
8
4
  x: number;
@@ -17,16 +13,17 @@ export declare const createTransform: (x?: number, y?: number, angle?: number) =
17
13
  /** Set a transform in place, refreshing sin/cos only when the angle changes. */
18
14
  export declare const setTransform: (transform: Transform, x: number, y: number, angle: number) => Transform;
19
15
  /** Rotate and translate a local point by `transform`, writing into `out`. */
20
- export declare const applyTransform: (transform: Transform, x: number, y: number, out: Mutable2D) => Mutable2D;
16
+ export declare const applyTransform: (transform: Transform, x: number, y: number, out: PointLike) => PointLike;
21
17
  /** Rotate a local direction by `transform` (no translation), writing into `out`. */
22
- export declare const applyRotation: (transform: Transform, x: number, y: number, out: Mutable2D) => Mutable2D;
18
+ export declare const applyRotation: (transform: Transform, x: number, y: number, out: PointLike) => PointLike;
23
19
  /** Map a world point into `transform`'s local frame, writing into `out`. */
24
- export declare const applyInverseTransform: (transform: Transform, x: number, y: number, out: Mutable2D) => Mutable2D;
20
+ export declare const applyInverseTransform: (transform: Transform, x: number, y: number, out: PointLike) => PointLike;
25
21
  /** Map a world direction into `transform`'s local frame, writing into `out`. */
26
- export declare const applyInverseRotation: (transform: Transform, x: number, y: number, out: Mutable2D) => Mutable2D;
22
+ export declare const applyInverseRotation: (transform: Transform, x: number, y: number, out: PointLike) => PointLike;
27
23
  /**
28
24
  * Compose `world = body ∘ local` into `out`. The local transform is expressed
29
25
  * in the body frame (a collider's offset + local rotation); the result is the
30
26
  * collider's world transform.
31
27
  */
32
28
  export declare const composeTransforms: (body: Transform, local: Transform, out: Transform) => Transform;
29
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/math.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,8DAA8D;AAC9D,eAAO,MAAM,eAAe,GAAI,UAAK,EAAE,UAAK,EAAE,cAAS,KAAG,SAMxD,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,YAAY,GAAI,WAAW,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,OAAO,MAAM,KAAG,SAWxF,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,cAAc,GAAI,WAAW,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,KAAK,SAAS,KAAG,SAK3F,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,aAAa,GAAI,WAAW,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,KAAK,SAAS,KAAG,SAK1F,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,GAAI,WAAW,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,KAAK,SAAS,KAAG,SAQlG,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,GAAI,WAAW,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,KAAK,SAAS,KAAG,SAKjG,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,SAAS,EAAE,OAAO,SAAS,EAAE,KAAK,SAAS,KAAG,SAKrF,CAAC"}