@woosh/meep-engine 2.141.0 → 2.143.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.
- package/package.json +1 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +1 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.js +1 -1
- package/src/core/geom/3d/shape/SphereShape3D.d.ts +47 -0
- package/src/core/geom/3d/shape/SphereShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/SphereShape3D.js +127 -0
- package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +30 -18
- package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnitSphereShape3D.js +44 -92
- package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
- package/src/core/geom/3d/shape/json/shape_to_type.js +4 -2
- package/src/core/geom/3d/shape/json/type_adapters.d.ts +12 -3
- package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
- package/src/core/geom/3d/shape/json/type_adapters.js +16 -4
- package/src/core/geom/3d/shape/util/shape_to_visual_entity.js +2 -2
- package/src/engine/control/first-person/DESIGN_COLLISION.md +255 -0
- package/src/engine/control/first-person/prototype_first_person_controller.js +5 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +70 -43
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.d.ts +12 -22
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.js +345 -186
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.d.ts +44 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.d.ts.map +1 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.js +151 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/generateHilbertNoiseTexture.d.ts +14 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/generateHilbertNoiseTexture.d.ts.map +1 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/generateHilbertNoiseTexture.js +78 -0
- package/src/engine/physics/PLAN.md +705 -578
- package/src/engine/physics/REVIEW_003.md +166 -0
- package/src/engine/physics/constraint/solve_constraints.d.ts +24 -2
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +402 -165
- package/src/engine/physics/ecs/Joint.d.ts +115 -0
- package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
- package/src/engine/physics/ecs/Joint.js +168 -0
- package/src/engine/physics/ecs/JointSerializationAdapter.d.ts +29 -0
- package/src/engine/physics/ecs/JointSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/ecs/JointSerializationAdapter.js +72 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +20 -13
- package/src/engine/physics/narrowphase/ray_shapes.d.ts +66 -0
- package/src/engine/physics/narrowphase/ray_shapes.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/ray_shapes.js +187 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +16 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.js +145 -0
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +39 -0
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/refine_ray_hit.js +78 -0
- package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +8 -7
- package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/sphere_sphere_contact.js +8 -7
- package/src/engine/physics/queries/raycast.d.ts +11 -9
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +108 -159
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts +114 -0
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -0
- package/src/engine/physics/vehicle/RaycastVehicle.js +333 -0
|
@@ -82,6 +82,18 @@ export class Joint {
|
|
|
82
82
|
* @type {Uint8Array}
|
|
83
83
|
*/
|
|
84
84
|
readonly dofMode: Uint8Array;
|
|
85
|
+
/**
|
|
86
|
+
* How the three angular DOF positions are measured. `false` (default) uses
|
|
87
|
+
* the per-axis small-angle rotation vector — exact at the rest pose and
|
|
88
|
+
* cheap, correct for welds, hinges, and modest angular limits. `true`
|
|
89
|
+
* switches to the **swing-twist** decomposition: angular X is the *twist*
|
|
90
|
+
* (rotation about the bone / X axis) and angular Y/Z are the *swing* (tilt
|
|
91
|
+
* off it), each measured as an exact angle. Use it for wide cone-twist
|
|
92
|
+
* range-of-motion (ragdoll shoulders) where the small-angle measure
|
|
93
|
+
* under-reports large angles. See {@link asConeTwist}.
|
|
94
|
+
* @type {boolean}
|
|
95
|
+
*/
|
|
96
|
+
swingTwist: boolean;
|
|
85
97
|
/**
|
|
86
98
|
* Lower / upper bounds per DOF, used by {@link DofMode.LIMITED}. Linear in
|
|
87
99
|
* metres, angular in radians. (Reserved — consumed once the LIMITED mode
|
|
@@ -165,6 +177,109 @@ export class Joint {
|
|
|
165
177
|
* @returns {Joint} this
|
|
166
178
|
*/
|
|
167
179
|
asPrismatic(freeLinearAxis?: number): Joint;
|
|
180
|
+
/**
|
|
181
|
+
* Configure as a cone-twist (ragdoll) joint: a ball-socket point (3 linear
|
|
182
|
+
* locked) whose angular motion is a limited **twist** about the bone (frame
|
|
183
|
+
* X) and a limited **swing** cone off it (frame Y / Z). Enables
|
|
184
|
+
* {@link swingTwist} so the limits are measured as exact angles, holding
|
|
185
|
+
* accurately at the wide ranges ragdoll shoulders need.
|
|
186
|
+
*
|
|
187
|
+
* Orient {@link localBasisA} / {@link localBasisB} so frame X runs along the
|
|
188
|
+
* bone. The swing cone is box-shaped: independent Y and Z half-angles
|
|
189
|
+
* (`swingLimitZ` defaults to `swingLimitY` for a circular cone).
|
|
190
|
+
*
|
|
191
|
+
* @param {number} twistLower @param {number} twistUpper twist bounds, rad.
|
|
192
|
+
* @param {number} swingLimitY swing half-angle about frame Y, rad.
|
|
193
|
+
* @param {number} [swingLimitZ] swing half-angle about frame Z, rad
|
|
194
|
+
* (defaults to `swingLimitY`).
|
|
195
|
+
* @returns {Joint} this
|
|
196
|
+
*/
|
|
197
|
+
asConeTwist(twistLower: number, twistUpper: number, swingLimitY: number, swingLimitZ?: number): Joint;
|
|
198
|
+
/**
|
|
199
|
+
* Limit a linear DOF to a travel range along its frame axis (slider
|
|
200
|
+
* end-stops): the DOF slides freely within `[lower, upper]` metres and is
|
|
201
|
+
* resisted at the stops. Sets {@link DofMode.LIMITED} on that axis.
|
|
202
|
+
*
|
|
203
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
204
|
+
* @param {number} lower @param {number} upper travel bounds in metres
|
|
205
|
+
* (signed anchor-A offset from anchor-B along the frame axis).
|
|
206
|
+
* @returns {Joint} this
|
|
207
|
+
*/
|
|
208
|
+
setLinearLimit(axis: number, lower: number, upper: number): Joint;
|
|
209
|
+
/**
|
|
210
|
+
* Limit an angular DOF to a rotation range about its frame axis (joint
|
|
211
|
+
* range-of-motion): free within `[lower, upper]` radians, resisted at the
|
|
212
|
+
* stops. Sets {@link DofMode.LIMITED} on that angular axis.
|
|
213
|
+
*
|
|
214
|
+
* The angular position is a first-order (small-angle) measure, so the
|
|
215
|
+
* effective stop is accurate for modest ranges (hinge / slider end-stops)
|
|
216
|
+
* but under-reports large angles — wide cones (ragdoll shoulders) want the
|
|
217
|
+
* swing-twist decomposition (already available as
|
|
218
|
+
* `Quaternion.computeSwingAndTwist` / `computeTwistAngle`). See the solver
|
|
219
|
+
* module docs.
|
|
220
|
+
*
|
|
221
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
222
|
+
* @param {number} lower @param {number} upper rotation bounds in radians.
|
|
223
|
+
* @returns {Joint} this
|
|
224
|
+
*/
|
|
225
|
+
setAngularLimit(axis: number, lower: number, upper: number): Joint;
|
|
226
|
+
/**
|
|
227
|
+
* Drive a linear DOF at a target speed along its frame axis (piston,
|
|
228
|
+
* conveyor, powered slider). A force-limited velocity servo: it pulls the
|
|
229
|
+
* relative velocity toward `targetVelocity` as hard as `maxForce` allows.
|
|
230
|
+
* Sets {@link DofMode.MOTOR} on that axis.
|
|
231
|
+
*
|
|
232
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
233
|
+
* @param {number} targetVelocity desired relative anchor speed of A w.r.t.
|
|
234
|
+
* B along the frame axis, m/s (sign convention A − B).
|
|
235
|
+
* @param {number} maxForce force budget in newtons (`Infinity` for an
|
|
236
|
+
* ideal velocity drive; `0` makes the motor inert).
|
|
237
|
+
* @returns {Joint} this
|
|
238
|
+
*/
|
|
239
|
+
setLinearMotor(axis: number, targetVelocity: number, maxForce: number): Joint;
|
|
240
|
+
/**
|
|
241
|
+
* Drive an angular DOF at a target rate about its frame axis (wheel drive,
|
|
242
|
+
* powered hinge / door, turntable). A force-(torque-)limited velocity servo
|
|
243
|
+
* pulling the relative angular velocity toward `targetVelocity`. Sets
|
|
244
|
+
* {@link DofMode.MOTOR} on that angular axis.
|
|
245
|
+
*
|
|
246
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
247
|
+
* @param {number} targetVelocity desired relative angular rate of B w.r.t.
|
|
248
|
+
* A about the frame axis, rad/s (sign convention B − A — so for a
|
|
249
|
+
* world-anchored motor a positive target spins body A negatively about
|
|
250
|
+
* the axis).
|
|
251
|
+
* @param {number} maxForce torque budget in newton-metres (`Infinity` for
|
|
252
|
+
* an ideal drive; `0` makes the motor inert).
|
|
253
|
+
* @returns {Joint} this
|
|
254
|
+
*/
|
|
255
|
+
setAngularMotor(axis: number, targetVelocity: number, maxForce: number): Joint;
|
|
256
|
+
/**
|
|
257
|
+
* Make a linear DOF a compliant spring along its frame axis (suspension,
|
|
258
|
+
* bungee, soft-return slider). The spring drives the DOF toward its zero
|
|
259
|
+
* (the rest pose — place the anchors / basis so the relaxed position is
|
|
260
|
+
* `C·axis = 0`) with stiffness and damping, yielding under load rather than
|
|
261
|
+
* holding rigid. Sets {@link DofMode.SPRING} on that axis.
|
|
262
|
+
*
|
|
263
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
264
|
+
* @param {number} stiffness spring constant `k`, N/m (0 ⇒ pure damper).
|
|
265
|
+
* @param {number} damping damping coefficient `c`, N·s/m (0 ⇒ undamped).
|
|
266
|
+
* @returns {Joint} this
|
|
267
|
+
*/
|
|
268
|
+
setLinearSpring(axis: number, stiffness: number, damping: number): Joint;
|
|
269
|
+
/**
|
|
270
|
+
* Make an angular DOF a compliant torsional spring about its frame axis
|
|
271
|
+
* (soft-return hinge, sway bar, soft ragdoll joint). Drives the relative
|
|
272
|
+
* rotation about the axis toward zero with stiffness and damping. Sets
|
|
273
|
+
* {@link DofMode.SPRING} on that angular axis. Uses the small-angle measure
|
|
274
|
+
* (see the solver module docs), so it is for modest ranges.
|
|
275
|
+
*
|
|
276
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
277
|
+
* @param {number} stiffness torsional spring constant `k`, N·m/rad
|
|
278
|
+
* (0 ⇒ pure damper).
|
|
279
|
+
* @param {number} damping torsional damping, N·m·s/rad (0 ⇒ undamped).
|
|
280
|
+
* @returns {Joint} this
|
|
281
|
+
*/
|
|
282
|
+
setAngularSpring(axis: number, stiffness: number, damping: number): Joint;
|
|
168
283
|
/**
|
|
169
284
|
* @readonly
|
|
170
285
|
* @type {boolean}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Joint.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/Joint.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,gCAFU,MAAM,CAEoB;AAEpC;;;;GAIG;AACH,0BAFU,MAAM,CAEc;AAE9B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAEI;;;OAGG;IACH,SAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,SAFU,MAAM,CAEM;IAEtB;;;;OAIG;IACH,uBAFU,OAAO,CAEmB;IAEpC;;;;;OAKG;IACH,uBAFU,OAAO,CAEmB;IAEpC;;;;;;;;;OASG;IACH,sBAFU,UAAU,CAEW;IAE/B;;;;;;;OAOG;IACH,sBAFU,UAAU,CAEW;IAE/B;;;;;OAKG;IACH,kBAFU,UAAU,CAKjB;IAEH;;;;;;OAMG;IACH,wBAFU,YAAY,CAEc;IACpC,qCAAqC;IACrC,wBADqB,YAAY,CACG;IAEpC;;;;;OAKG;IACH,uBAFU,YAAY,CAEa;IACnC,qCAAqC;IACrC,qBADqB,YAAY,CACA;IAEjC;;;;;OAKG;IACH,iCAFU,YAAY,CAEuB;IAC7C,qCAAqC;IACrC,2BADqB,YAAY,CACM;IAEvC;;;;;OAKG;IACH,qBAFU,YAAY,CAEW;IAEjC;;;OAGG;IACH,UAFU,MAAM,CAEF;IACd;;;OAGG;IACH,UAFU,MAAM,CAEO;IACvB;;;OAGG;IACH,UAFU,MAAM,CAEa;IAE7B;;;;;OAKG;IACH,gBAFa,KAAK,CAUjB;IAED;;;;OAIG;IACH,UAFa,KAAK,CAKjB;IAED;;;;;;;;OAQG;IACH,0BAJW,MAAM,GAEJ,KAAK,CAWjB;IAED;;;;;;;;OAQG;IACH,6BAJW,MAAM,GAEJ,KAAK,CAWjB;IASL;;;OAGG;IACH,kBAFU,OAAO,CAEM;CAZtB;;kBAIS,MAAM;;
|
|
1
|
+
{"version":3,"file":"Joint.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/Joint.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,gCAFU,MAAM,CAEoB;AAEpC;;;;GAIG;AACH,0BAFU,MAAM,CAEc;AAE9B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAEI;;;OAGG;IACH,SAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,SAFU,MAAM,CAEM;IAEtB;;;;OAIG;IACH,uBAFU,OAAO,CAEmB;IAEpC;;;;;OAKG;IACH,uBAFU,OAAO,CAEmB;IAEpC;;;;;;;;;OASG;IACH,sBAFU,UAAU,CAEW;IAE/B;;;;;;;OAOG;IACH,sBAFU,UAAU,CAEW;IAE/B;;;;;OAKG;IACH,kBAFU,UAAU,CAKjB;IAEH;;;;;;;;;;OAUG;IACH,YAFU,OAAO,CAEE;IAEnB;;;;;;OAMG;IACH,wBAFU,YAAY,CAEc;IACpC,qCAAqC;IACrC,wBADqB,YAAY,CACG;IAEpC;;;;;OAKG;IACH,uBAFU,YAAY,CAEa;IACnC,qCAAqC;IACrC,qBADqB,YAAY,CACA;IAEjC;;;;;OAKG;IACH,iCAFU,YAAY,CAEuB;IAC7C,qCAAqC;IACrC,2BADqB,YAAY,CACM;IAEvC;;;;;OAKG;IACH,qBAFU,YAAY,CAEW;IAEjC;;;OAGG;IACH,UAFU,MAAM,CAEF;IACd;;;OAGG;IACH,UAFU,MAAM,CAEO;IACvB;;;OAGG;IACH,UAFU,MAAM,CAEa;IAE7B;;;;;OAKG;IACH,gBAFa,KAAK,CAUjB;IAED;;;;OAIG;IACH,UAFa,KAAK,CAKjB;IAED;;;;;;;;OAQG;IACH,0BAJW,MAAM,GAEJ,KAAK,CAWjB;IAED;;;;;;;;OAQG;IACH,6BAJW,MAAM,GAEJ,KAAK,CAWjB;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,wBANW,MAAM,cAAqB,MAAM,eACjC,MAAM,gBACN,MAAM,GAEJ,KAAK,CAiBjB;IAED;;;;;;;;;OASG;IACH,qBALW,MAAM,SACN,MAAM,SAAgB,MAAM,GAE1B,KAAK,CAOjB;IAED;;;;;;;;;;;;;;;OAeG;IACH,sBAJW,MAAM,SACN,MAAM,SAAgB,MAAM,GAC1B,KAAK,CAOjB;IAED;;;;;;;;;;;;OAYG;IACH,qBAPW,MAAM,kBACN,MAAM,YAEN,MAAM,GAEJ,KAAK,CAOjB;IAED;;;;;;;;;;;;;;OAcG;IACH,sBATW,MAAM,kBACN,MAAM,YAIN,MAAM,GAEJ,KAAK,CAOjB;IAED;;;;;;;;;;;OAWG;IACH,sBALW,MAAM,aACN,MAAM,WACN,MAAM,GACJ,KAAK,CAOjB;IAED;;;;;;;;;;;;OAYG;IACH,uBANW,MAAM,aACN,MAAM,WAEN,MAAM,GACJ,KAAK,CAOjB;IASL;;;OAGG;IACH,kBAFU,OAAO,CAEM;CAZtB;;kBAIS,MAAM;;oBAzYI,+BAA+B;uBAC5B,kCAAkC"}
|
|
@@ -99,6 +99,19 @@ export class Joint {
|
|
|
99
99
|
DofMode.FREE, DofMode.FREE, DofMode.FREE,
|
|
100
100
|
]);
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* How the three angular DOF positions are measured. `false` (default) uses
|
|
104
|
+
* the per-axis small-angle rotation vector — exact at the rest pose and
|
|
105
|
+
* cheap, correct for welds, hinges, and modest angular limits. `true`
|
|
106
|
+
* switches to the **swing-twist** decomposition: angular X is the *twist*
|
|
107
|
+
* (rotation about the bone / X axis) and angular Y/Z are the *swing* (tilt
|
|
108
|
+
* off it), each measured as an exact angle. Use it for wide cone-twist
|
|
109
|
+
* range-of-motion (ragdoll shoulders) where the small-angle measure
|
|
110
|
+
* under-reports large angles. See {@link asConeTwist}.
|
|
111
|
+
* @type {boolean}
|
|
112
|
+
*/
|
|
113
|
+
swingTwist = false;
|
|
114
|
+
|
|
102
115
|
/**
|
|
103
116
|
* Lower / upper bounds per DOF, used by {@link DofMode.LIMITED}. Linear in
|
|
104
117
|
* metres, angular in radians. (Reserved — consumed once the LIMITED mode
|
|
@@ -219,6 +232,161 @@ export class Joint {
|
|
|
219
232
|
this.dofMode[5] = DofMode.LOCKED;
|
|
220
233
|
return this;
|
|
221
234
|
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Configure as a cone-twist (ragdoll) joint: a ball-socket point (3 linear
|
|
238
|
+
* locked) whose angular motion is a limited **twist** about the bone (frame
|
|
239
|
+
* X) and a limited **swing** cone off it (frame Y / Z). Enables
|
|
240
|
+
* {@link swingTwist} so the limits are measured as exact angles, holding
|
|
241
|
+
* accurately at the wide ranges ragdoll shoulders need.
|
|
242
|
+
*
|
|
243
|
+
* Orient {@link localBasisA} / {@link localBasisB} so frame X runs along the
|
|
244
|
+
* bone. The swing cone is box-shaped: independent Y and Z half-angles
|
|
245
|
+
* (`swingLimitZ` defaults to `swingLimitY` for a circular cone).
|
|
246
|
+
*
|
|
247
|
+
* @param {number} twistLower @param {number} twistUpper twist bounds, rad.
|
|
248
|
+
* @param {number} swingLimitY swing half-angle about frame Y, rad.
|
|
249
|
+
* @param {number} [swingLimitZ] swing half-angle about frame Z, rad
|
|
250
|
+
* (defaults to `swingLimitY`).
|
|
251
|
+
* @returns {Joint} this
|
|
252
|
+
*/
|
|
253
|
+
asConeTwist(twistLower, twistUpper, swingLimitY, swingLimitZ = swingLimitY) {
|
|
254
|
+
this.dofMode[0] = DofMode.LOCKED;
|
|
255
|
+
this.dofMode[1] = DofMode.LOCKED;
|
|
256
|
+
this.dofMode[2] = DofMode.LOCKED;
|
|
257
|
+
this.swingTwist = true;
|
|
258
|
+
this.dofMode[3] = DofMode.LIMITED;
|
|
259
|
+
this.dofLowerLimit[3] = twistLower;
|
|
260
|
+
this.dofUpperLimit[3] = twistUpper;
|
|
261
|
+
this.dofMode[4] = DofMode.LIMITED;
|
|
262
|
+
this.dofLowerLimit[4] = -swingLimitY;
|
|
263
|
+
this.dofUpperLimit[4] = swingLimitY;
|
|
264
|
+
this.dofMode[5] = DofMode.LIMITED;
|
|
265
|
+
this.dofLowerLimit[5] = -swingLimitZ;
|
|
266
|
+
this.dofUpperLimit[5] = swingLimitZ;
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Limit a linear DOF to a travel range along its frame axis (slider
|
|
272
|
+
* end-stops): the DOF slides freely within `[lower, upper]` metres and is
|
|
273
|
+
* resisted at the stops. Sets {@link DofMode.LIMITED} on that axis.
|
|
274
|
+
*
|
|
275
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
276
|
+
* @param {number} lower @param {number} upper travel bounds in metres
|
|
277
|
+
* (signed anchor-A offset from anchor-B along the frame axis).
|
|
278
|
+
* @returns {Joint} this
|
|
279
|
+
*/
|
|
280
|
+
setLinearLimit(axis, lower, upper) {
|
|
281
|
+
this.dofMode[axis] = DofMode.LIMITED;
|
|
282
|
+
this.dofLowerLimit[axis] = lower;
|
|
283
|
+
this.dofUpperLimit[axis] = upper;
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Limit an angular DOF to a rotation range about its frame axis (joint
|
|
289
|
+
* range-of-motion): free within `[lower, upper]` radians, resisted at the
|
|
290
|
+
* stops. Sets {@link DofMode.LIMITED} on that angular axis.
|
|
291
|
+
*
|
|
292
|
+
* The angular position is a first-order (small-angle) measure, so the
|
|
293
|
+
* effective stop is accurate for modest ranges (hinge / slider end-stops)
|
|
294
|
+
* but under-reports large angles — wide cones (ragdoll shoulders) want the
|
|
295
|
+
* swing-twist decomposition (already available as
|
|
296
|
+
* `Quaternion.computeSwingAndTwist` / `computeTwistAngle`). See the solver
|
|
297
|
+
* module docs.
|
|
298
|
+
*
|
|
299
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
300
|
+
* @param {number} lower @param {number} upper rotation bounds in radians.
|
|
301
|
+
* @returns {Joint} this
|
|
302
|
+
*/
|
|
303
|
+
setAngularLimit(axis, lower, upper) {
|
|
304
|
+
this.dofMode[3 + axis] = DofMode.LIMITED;
|
|
305
|
+
this.dofLowerLimit[3 + axis] = lower;
|
|
306
|
+
this.dofUpperLimit[3 + axis] = upper;
|
|
307
|
+
return this;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Drive a linear DOF at a target speed along its frame axis (piston,
|
|
312
|
+
* conveyor, powered slider). A force-limited velocity servo: it pulls the
|
|
313
|
+
* relative velocity toward `targetVelocity` as hard as `maxForce` allows.
|
|
314
|
+
* Sets {@link DofMode.MOTOR} on that axis.
|
|
315
|
+
*
|
|
316
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
317
|
+
* @param {number} targetVelocity desired relative anchor speed of A w.r.t.
|
|
318
|
+
* B along the frame axis, m/s (sign convention A − B).
|
|
319
|
+
* @param {number} maxForce force budget in newtons (`Infinity` for an
|
|
320
|
+
* ideal velocity drive; `0` makes the motor inert).
|
|
321
|
+
* @returns {Joint} this
|
|
322
|
+
*/
|
|
323
|
+
setLinearMotor(axis, targetVelocity, maxForce) {
|
|
324
|
+
this.dofMode[axis] = DofMode.MOTOR;
|
|
325
|
+
this.dofMotorTargetVelocity[axis] = targetVelocity;
|
|
326
|
+
this.dofMotorMaxForce[axis] = maxForce;
|
|
327
|
+
return this;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Drive an angular DOF at a target rate about its frame axis (wheel drive,
|
|
332
|
+
* powered hinge / door, turntable). A force-(torque-)limited velocity servo
|
|
333
|
+
* pulling the relative angular velocity toward `targetVelocity`. Sets
|
|
334
|
+
* {@link DofMode.MOTOR} on that angular axis.
|
|
335
|
+
*
|
|
336
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
337
|
+
* @param {number} targetVelocity desired relative angular rate of B w.r.t.
|
|
338
|
+
* A about the frame axis, rad/s (sign convention B − A — so for a
|
|
339
|
+
* world-anchored motor a positive target spins body A negatively about
|
|
340
|
+
* the axis).
|
|
341
|
+
* @param {number} maxForce torque budget in newton-metres (`Infinity` for
|
|
342
|
+
* an ideal drive; `0` makes the motor inert).
|
|
343
|
+
* @returns {Joint} this
|
|
344
|
+
*/
|
|
345
|
+
setAngularMotor(axis, targetVelocity, maxForce) {
|
|
346
|
+
this.dofMode[3 + axis] = DofMode.MOTOR;
|
|
347
|
+
this.dofMotorTargetVelocity[3 + axis] = targetVelocity;
|
|
348
|
+
this.dofMotorMaxForce[3 + axis] = maxForce;
|
|
349
|
+
return this;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Make a linear DOF a compliant spring along its frame axis (suspension,
|
|
354
|
+
* bungee, soft-return slider). The spring drives the DOF toward its zero
|
|
355
|
+
* (the rest pose — place the anchors / basis so the relaxed position is
|
|
356
|
+
* `C·axis = 0`) with stiffness and damping, yielding under load rather than
|
|
357
|
+
* holding rigid. Sets {@link DofMode.SPRING} on that axis.
|
|
358
|
+
*
|
|
359
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
360
|
+
* @param {number} stiffness spring constant `k`, N/m (0 ⇒ pure damper).
|
|
361
|
+
* @param {number} damping damping coefficient `c`, N·s/m (0 ⇒ undamped).
|
|
362
|
+
* @returns {Joint} this
|
|
363
|
+
*/
|
|
364
|
+
setLinearSpring(axis, stiffness, damping) {
|
|
365
|
+
this.dofMode[axis] = DofMode.SPRING;
|
|
366
|
+
this.dofStiffness[axis] = stiffness;
|
|
367
|
+
this.dofDamping[axis] = damping;
|
|
368
|
+
return this;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Make an angular DOF a compliant torsional spring about its frame axis
|
|
373
|
+
* (soft-return hinge, sway bar, soft ragdoll joint). Drives the relative
|
|
374
|
+
* rotation about the axis toward zero with stiffness and damping. Sets
|
|
375
|
+
* {@link DofMode.SPRING} on that angular axis. Uses the small-angle measure
|
|
376
|
+
* (see the solver module docs), so it is for modest ranges.
|
|
377
|
+
*
|
|
378
|
+
* @param {number} axis frame axis: 0 = x, 1 = y, 2 = z.
|
|
379
|
+
* @param {number} stiffness torsional spring constant `k`, N·m/rad
|
|
380
|
+
* (0 ⇒ pure damper).
|
|
381
|
+
* @param {number} damping torsional damping, N·m·s/rad (0 ⇒ undamped).
|
|
382
|
+
* @returns {Joint} this
|
|
383
|
+
*/
|
|
384
|
+
setAngularSpring(axis, stiffness, damping) {
|
|
385
|
+
this.dofMode[3 + axis] = DofMode.SPRING;
|
|
386
|
+
this.dofStiffness[3 + axis] = stiffness;
|
|
387
|
+
this.dofDamping[3 + axis] = damping;
|
|
388
|
+
return this;
|
|
389
|
+
}
|
|
222
390
|
}
|
|
223
391
|
|
|
224
392
|
/**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary serialization for {@link Joint}.
|
|
3
|
+
*
|
|
4
|
+
* Writes the configurable / persistent fields: the two anchor entities, the
|
|
5
|
+
* local anchor points and basis frames, and the per-DOF mode + limit / spring /
|
|
6
|
+
* motor config. Transient runtime state owned by the {@link PhysicsSystem} —
|
|
7
|
+
* the warm-start accumulator (`dofImpulse`) and the resolved `_bodyIdA` /
|
|
8
|
+
* `_bodyIdB` / `_jointId` — is deliberately excluded; it is recomputed on
|
|
9
|
+
* `link_joint`, and serialising it would tie the stream to a particular world
|
|
10
|
+
* instance.
|
|
11
|
+
*/
|
|
12
|
+
export class JointSerializationAdapter extends BinaryClassSerializationAdapter<any> {
|
|
13
|
+
constructor();
|
|
14
|
+
klass: typeof Joint;
|
|
15
|
+
version: number;
|
|
16
|
+
/**
|
|
17
|
+
* @param {BinaryBuffer} buffer
|
|
18
|
+
* @param {Joint} value
|
|
19
|
+
*/
|
|
20
|
+
serialize(buffer: BinaryBuffer, value: Joint): void;
|
|
21
|
+
/**
|
|
22
|
+
* @param {BinaryBuffer} buffer
|
|
23
|
+
* @param {Joint} value
|
|
24
|
+
*/
|
|
25
|
+
deserialize(buffer: BinaryBuffer, value: Joint): void;
|
|
26
|
+
}
|
|
27
|
+
import { BinaryClassSerializationAdapter } from "../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
|
|
28
|
+
import { Joint } from "./Joint.js";
|
|
29
|
+
//# sourceMappingURL=JointSerializationAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JointSerializationAdapter.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/JointSerializationAdapter.js"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH;;IAEI,oBAAc;IACd,gBAAY;IAEZ;;;OAGG;IACH,uCAFW,KAAK,QAwBf;IAED;;;OAGG;IACH,yCAFW,KAAK,QAqBf;CACJ;gDAvE+C,6DAA6D;sBACvF,YAAY"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { BinaryClassSerializationAdapter } from "../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
|
|
2
|
+
import { Joint } from "./Joint.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Binary serialization for {@link Joint}.
|
|
6
|
+
*
|
|
7
|
+
* Writes the configurable / persistent fields: the two anchor entities, the
|
|
8
|
+
* local anchor points and basis frames, and the per-DOF mode + limit / spring /
|
|
9
|
+
* motor config. Transient runtime state owned by the {@link PhysicsSystem} —
|
|
10
|
+
* the warm-start accumulator (`dofImpulse`) and the resolved `_bodyIdA` /
|
|
11
|
+
* `_bodyIdB` / `_jointId` — is deliberately excluded; it is recomputed on
|
|
12
|
+
* `link_joint`, and serialising it would tie the stream to a particular world
|
|
13
|
+
* instance.
|
|
14
|
+
*/
|
|
15
|
+
export class JointSerializationAdapter extends BinaryClassSerializationAdapter {
|
|
16
|
+
|
|
17
|
+
klass = Joint;
|
|
18
|
+
version = 0;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {BinaryBuffer} buffer
|
|
22
|
+
* @param {Joint} value
|
|
23
|
+
*/
|
|
24
|
+
serialize(buffer, value) {
|
|
25
|
+
// Anchor entities — entityB may be JOINT_WORLD (−1), so signed.
|
|
26
|
+
buffer.writeInt32(value.entityA);
|
|
27
|
+
buffer.writeInt32(value.entityB);
|
|
28
|
+
|
|
29
|
+
const la = value.localAnchorA, lb = value.localAnchorB;
|
|
30
|
+
buffer.writeFloat64(la.x); buffer.writeFloat64(la.y); buffer.writeFloat64(la.z);
|
|
31
|
+
buffer.writeFloat64(lb.x); buffer.writeFloat64(lb.y); buffer.writeFloat64(lb.z);
|
|
32
|
+
|
|
33
|
+
const ba = value.localBasisA, bb = value.localBasisB;
|
|
34
|
+
buffer.writeFloat64(ba[0]); buffer.writeFloat64(ba[1]); buffer.writeFloat64(ba[2]); buffer.writeFloat64(ba[3]);
|
|
35
|
+
buffer.writeFloat64(bb[0]); buffer.writeFloat64(bb[1]); buffer.writeFloat64(bb[2]); buffer.writeFloat64(bb[3]);
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < 6; i++) buffer.writeUint8(value.dofMode[i]);
|
|
38
|
+
for (let i = 0; i < 6; i++) buffer.writeFloat64(value.dofLowerLimit[i]);
|
|
39
|
+
for (let i = 0; i < 6; i++) buffer.writeFloat64(value.dofUpperLimit[i]);
|
|
40
|
+
for (let i = 0; i < 6; i++) buffer.writeFloat64(value.dofStiffness[i]);
|
|
41
|
+
for (let i = 0; i < 6; i++) buffer.writeFloat64(value.dofDamping[i]);
|
|
42
|
+
for (let i = 0; i < 6; i++) buffer.writeFloat64(value.dofMotorTargetVelocity[i]);
|
|
43
|
+
for (let i = 0; i < 6; i++) buffer.writeFloat64(value.dofMotorMaxForce[i]);
|
|
44
|
+
|
|
45
|
+
buffer.writeUint8(value.swingTwist ? 1 : 0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {BinaryBuffer} buffer
|
|
50
|
+
* @param {Joint} value
|
|
51
|
+
*/
|
|
52
|
+
deserialize(buffer, value) {
|
|
53
|
+
value.entityA = buffer.readInt32();
|
|
54
|
+
value.entityB = buffer.readInt32();
|
|
55
|
+
|
|
56
|
+
value.localAnchorA.set(buffer.readFloat64(), buffer.readFloat64(), buffer.readFloat64());
|
|
57
|
+
value.localAnchorB.set(buffer.readFloat64(), buffer.readFloat64(), buffer.readFloat64());
|
|
58
|
+
|
|
59
|
+
value.localBasisA.set(buffer.readFloat64(), buffer.readFloat64(), buffer.readFloat64(), buffer.readFloat64());
|
|
60
|
+
value.localBasisB.set(buffer.readFloat64(), buffer.readFloat64(), buffer.readFloat64(), buffer.readFloat64());
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < 6; i++) value.dofMode[i] = buffer.readUint8();
|
|
63
|
+
for (let i = 0; i < 6; i++) value.dofLowerLimit[i] = buffer.readFloat64();
|
|
64
|
+
for (let i = 0; i < 6; i++) value.dofUpperLimit[i] = buffer.readFloat64();
|
|
65
|
+
for (let i = 0; i < 6; i++) value.dofStiffness[i] = buffer.readFloat64();
|
|
66
|
+
for (let i = 0; i < 6; i++) value.dofDamping[i] = buffer.readFloat64();
|
|
67
|
+
for (let i = 0; i < 6; i++) value.dofMotorTargetVelocity[i] = buffer.readFloat64();
|
|
68
|
+
for (let i = 0; i < 6; i++) value.dofMotorMaxForce[i] = buffer.readFloat64();
|
|
69
|
+
|
|
70
|
+
value.swingTwist = buffer.readUint8() !== 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"narrowphase_step.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/narrowphase_step.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"narrowphase_step.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/narrowphase_step.js"],"names":[],"mappings":"AAovCA;;;;;;;;;;;GAWG;AACH,uFALW,MAAM,MAAM;IAAC,QAAQ,WAAW;IAAC,SAAS,YAAW;CAAC,CAAC,CAAC,QAyJlE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,uEAJW,MAAM,UACN,MAAM;IAAC,QAAQ,WAAW;IAAC,SAAS,YAAW;CAAC,CAAC,UACjD,MAAM;IAAC,QAAQ,WAAW;IAAC,SAAS,YAAW;CAAC,CAAC,QAiD3D"}
|
|
@@ -358,8 +358,10 @@ function dispatch_pair(count, colA, trA, colB, trB, gjk_axis_buf = null, gjk_axi
|
|
|
358
358
|
const shapeA = colA.shape;
|
|
359
359
|
const shapeB = colB.shape;
|
|
360
360
|
|
|
361
|
-
|
|
362
|
-
|
|
361
|
+
// isSphereShape3D covers both UnitSphereShape3D (fixed radius 1) and
|
|
362
|
+
// SphereShape3D (arbitrary radius). Both expose `radius`.
|
|
363
|
+
const isSphereA = shapeA.isSphereShape3D === true;
|
|
364
|
+
const isSphereB = shapeB.isSphereShape3D === true;
|
|
363
365
|
// isBoxShape3D covers both UnitCubeShape3D (fixed 0.5) and BoxShape3D
|
|
364
366
|
// (arbitrary half-extents). Both expose `half_extents` as a Vector3.
|
|
365
367
|
const isBoxA = shapeA.isBoxShape3D === true;
|
|
@@ -369,12 +371,13 @@ function dispatch_pair(count, colA, trA, colB, trB, gjk_axis_buf = null, gjk_axi
|
|
|
369
371
|
|
|
370
372
|
// sphere-sphere
|
|
371
373
|
if (isSphereA && isSphereB) {
|
|
374
|
+
const ra = shapeA.radius, rb = shapeB.radius;
|
|
372
375
|
|
|
373
376
|
const ok = sphere_sphere_contact(
|
|
374
377
|
sphere_result,
|
|
375
378
|
trA.position.x, trA.position.y, trA.position.z,
|
|
376
379
|
trB.position.x, trB.position.y, trB.position.z,
|
|
377
|
-
|
|
380
|
+
ra, rb
|
|
378
381
|
);
|
|
379
382
|
|
|
380
383
|
if (!ok) return count;
|
|
@@ -383,23 +386,25 @@ function dispatch_pair(count, colA, trA, colB, trB, gjk_axis_buf = null, gjk_axi
|
|
|
383
386
|
|
|
384
387
|
// Sphere-sphere produces exactly one contact per pair; fid = 1
|
|
385
388
|
// identifies it as a real feature (distinguishes from "no info" = 0)
|
|
386
|
-
// and is trivially stable across frames.
|
|
389
|
+
// and is trivially stable across frames. Witnesses are the surface
|
|
390
|
+
// points along the (unit) normal, scaled by each sphere's radius.
|
|
387
391
|
return append_contact(count,
|
|
388
|
-
trA.position.x - nx, trA.position.y - ny, trA.position.z - nz,
|
|
389
|
-
trB.position.x + nx, trB.position.y + ny, trB.position.z + nz,
|
|
392
|
+
trA.position.x - nx * ra, trA.position.y - ny * ra, trA.position.z - nz * ra,
|
|
393
|
+
trB.position.x + nx * rb, trB.position.y + ny * rb, trB.position.z + nz * rb,
|
|
390
394
|
nx, ny, nz, sphere_result[3], 1);
|
|
391
395
|
}
|
|
392
396
|
|
|
393
397
|
// sphere ↔ box
|
|
394
398
|
if ((isSphereA && isBoxB) || (isBoxA && isSphereB)) {
|
|
395
|
-
const sphereTr
|
|
399
|
+
const sphereTr = isSphereA ? trA : trB;
|
|
400
|
+
const sphereShape = isSphereA ? shapeA : shapeB;
|
|
396
401
|
const boxTr = isSphereA ? trB : trA;
|
|
397
402
|
const boxShape = isSphereA ? shapeB : shapeA;
|
|
398
403
|
const bh = boxShape.half_extents;
|
|
399
404
|
|
|
400
405
|
const ok = sphere_box_contact(
|
|
401
406
|
closed_form_result,
|
|
402
|
-
sphereTr.position.x, sphereTr.position.y, sphereTr.position.z,
|
|
407
|
+
sphereTr.position.x, sphereTr.position.y, sphereTr.position.z, sphereShape.radius,
|
|
403
408
|
boxTr.position.x, boxTr.position.y, boxTr.position.z,
|
|
404
409
|
boxTr.rotation.x, boxTr.rotation.y, boxTr.rotation.z, boxTr.rotation.w,
|
|
405
410
|
bh.x, bh.y, bh.z
|
|
@@ -491,12 +496,13 @@ function dispatch_pair(count, colA, trA, colB, trB, gjk_axis_buf = null, gjk_axi
|
|
|
491
496
|
const capsuleTr = isCapsuleA ? trA : trB;
|
|
492
497
|
const capsuleShape = isCapsuleA ? colA.shape : colB.shape;
|
|
493
498
|
const sphereTr = isCapsuleA ? trB : trA;
|
|
499
|
+
const sphereShape = isCapsuleA ? colB.shape : colA.shape;
|
|
494
500
|
const ok = capsule_sphere_contact(
|
|
495
501
|
closed_form_result,
|
|
496
502
|
capsuleTr.position.x, capsuleTr.position.y, capsuleTr.position.z,
|
|
497
503
|
capsuleTr.rotation.x, capsuleTr.rotation.y, capsuleTr.rotation.z, capsuleTr.rotation.w,
|
|
498
504
|
capsuleShape.radius, capsuleShape.height * 0.5,
|
|
499
|
-
sphereTr.position.x, sphereTr.position.y, sphereTr.position.z,
|
|
505
|
+
sphereTr.position.x, sphereTr.position.y, sphereTr.position.z, sphereShape.radius
|
|
500
506
|
);
|
|
501
507
|
if (!ok) return count;
|
|
502
508
|
let nx = closed_form_result[0], ny = closed_form_result[1], nz = closed_form_result[2];
|
|
@@ -639,14 +645,15 @@ function dispatch_pair(count, colA, trA, colB, trB, gjk_axis_buf = null, gjk_axi
|
|
|
639
645
|
const c_pos_y = concave_tr.position.y;
|
|
640
646
|
const c_pos_z = concave_tr.position.z;
|
|
641
647
|
|
|
642
|
-
// Sphere fast-path: when the convex side is a
|
|
643
|
-
//
|
|
648
|
+
// Sphere fast-path: when the convex side is a sphere we bypass GJK+EPA
|
|
649
|
+
// entirely per triangle and use the closed-form
|
|
644
650
|
// {@link sphere_triangle_contact}. This avoids the EPA precision
|
|
645
651
|
// wall on Triangle3D (whose support function is degenerate along
|
|
646
652
|
// the face normal — all 3 vertices project to the same value),
|
|
647
653
|
// which was producing noisy depths at small penetrations and
|
|
648
654
|
// letting dropped spheres tunnel through heightmaps / meshes.
|
|
649
|
-
const isSphereConvex = convex_col.shape.
|
|
655
|
+
const isSphereConvex = convex_col.shape.isSphereShape3D === true;
|
|
656
|
+
const sphere_radius = isSphereConvex ? convex_col.shape.radius : 0;
|
|
650
657
|
|
|
651
658
|
// Box fast-path: closed-form {@link box_triangle_contact} via SAT
|
|
652
659
|
// over 13 axes + polygon clipping for face-vs-face contacts.
|
|
@@ -743,7 +750,7 @@ function dispatch_pair(count, colA, trA, colB, trB, gjk_axis_buf = null, gjk_axi
|
|
|
743
750
|
|
|
744
751
|
const ok = sphere_triangle_contact(
|
|
745
752
|
sphere_triangle_result,
|
|
746
|
-
convex_wx, convex_wy, convex_wz,
|
|
753
|
+
convex_wx, convex_wy, convex_wz, sphere_radius,
|
|
747
754
|
ax_w, ay_w, az_w,
|
|
748
755
|
bx_w, by_w, bz_w,
|
|
749
756
|
cx_w, cy_w, cz_w
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # Local-frame ray ↔ primitive intersections (raycast narrowphase)
|
|
3
|
+
*
|
|
4
|
+
* Each function intersects a ray, **expressed in the shape's local frame**,
|
|
5
|
+
* against a canonical primitive at the origin (sphere at the origin; box
|
|
6
|
+
* axis-aligned spanning `[-h, +h]`; capsule along the local Y axis). They
|
|
7
|
+
* return the hit distance `t` along the ray (`Infinity` on a miss) and write
|
|
8
|
+
* the **local** outward surface normal (unit) into `outNormal[0..2]`.
|
|
9
|
+
*
|
|
10
|
+
* The ray-narrowphase dispatch transforms the world ray into the body's local
|
|
11
|
+
* frame once (rotate by the inverse body rotation — a unit direction stays
|
|
12
|
+
* unit, so `t` is preserved), calls the matching primitive, then rotates the
|
|
13
|
+
* returned local normal back to world. Keeping the primitives canonical lets
|
|
14
|
+
* the box and capsule tests be axis-aligned (cheap slab / cylinder math) and
|
|
15
|
+
* shares a single transform across them.
|
|
16
|
+
*
|
|
17
|
+
* Conventions:
|
|
18
|
+
* - the ray direction is unit length (the caller guarantees it);
|
|
19
|
+
* - the first surface crossing at or after the origin within `tMax` is
|
|
20
|
+
* returned; a ray starting inside the shape returns its exit crossing;
|
|
21
|
+
* - the normal is the geometric outward surface normal at the hit.
|
|
22
|
+
*
|
|
23
|
+
* @author Alex Goldring
|
|
24
|
+
* @copyright Company Named Limited (c) 2026
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Ray vs a sphere of radius `r` centred at the local origin.
|
|
28
|
+
*
|
|
29
|
+
* @param {Float64Array} outNormal length-3, written on hit
|
|
30
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (local)
|
|
31
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (local, unit)
|
|
32
|
+
* @param {number} tMax
|
|
33
|
+
* @param {number} r sphere radius
|
|
34
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
35
|
+
*/
|
|
36
|
+
export function ray_sphere_local(outNormal: Float64Array, ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, tMax: number, r: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Ray vs an axis-aligned box spanning `[-hx,hx] × [-hy,hy] × [-hz,hz]` at the
|
|
39
|
+
* local origin (the canonical pose of {@link BoxShape3D}). Slab method, with
|
|
40
|
+
* the entry (or, origin-inside, exit) face's outward normal.
|
|
41
|
+
*
|
|
42
|
+
* @param {Float64Array} outNormal length-3, written on hit
|
|
43
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (local)
|
|
44
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (local, unit)
|
|
45
|
+
* @param {number} tMax
|
|
46
|
+
* @param {number} hx @param {number} hy @param {number} hz half-extents
|
|
47
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
48
|
+
*/
|
|
49
|
+
export function ray_box_local(outNormal: Float64Array, ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, tMax: number, hx: number, hy: number, hz: number): number;
|
|
50
|
+
/**
|
|
51
|
+
* Ray vs a capsule along the local Y axis: a cylinder of radius `r` over
|
|
52
|
+
* `y ∈ [−hh, hh]` capped by hemispheres of radius `r` at `(0, ±hh, 0)` — the
|
|
53
|
+
* canonical pose of {@link CapsuleShape3D} (`hh = height/2`). Tests the
|
|
54
|
+
* infinite cylinder (clamped to the segment) and the two cap spheres, taking
|
|
55
|
+
* the nearest valid crossing.
|
|
56
|
+
*
|
|
57
|
+
* @param {Float64Array} outNormal length-3, written on hit
|
|
58
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (local)
|
|
59
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (local, unit)
|
|
60
|
+
* @param {number} tMax
|
|
61
|
+
* @param {number} r capsule radius
|
|
62
|
+
* @param {number} hh half-height of the cylindrical section (`height/2`)
|
|
63
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
64
|
+
*/
|
|
65
|
+
export function ray_capsule_local(outNormal: Float64Array, ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, tMax: number, r: number, hh: number): number;
|
|
66
|
+
//# sourceMappingURL=ray_shapes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ray_shapes.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/ray_shapes.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;GASG;AACH,4CAPW,YAAY,MACZ,MAAM,MAAa,MAAM,MAAa,MAAM,MAC5C,MAAM,MAAa,MAAM,MAAa,MAAM,QAC5C,MAAM,KACN,MAAM,GACJ,MAAM,CAiBlB;AAED;;;;;;;;;;;GAWG;AACH,yCAPW,YAAY,MACZ,MAAM,MAAa,MAAM,MAAa,MAAM,MAC5C,MAAM,MAAa,MAAM,MAAa,MAAM,QAC5C,MAAM,MACN,MAAM,MAAa,MAAM,MAAa,MAAM,GAC1C,MAAM,CA+ClB;AAED;;;;;;;;;;;;;;GAcG;AACH,6CARW,YAAY,MACZ,MAAM,MAAa,MAAM,MAAa,MAAM,MAC5C,MAAM,MAAa,MAAM,MAAa,MAAM,QAC5C,MAAM,KACN,MAAM,MACN,MAAM,GACJ,MAAM,CA6DlB"}
|