@woosh/meep-engine 2.141.0 → 2.142.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/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 +67 -42
- 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 +340 -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/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/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,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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
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
|
+
/**
|
|
28
|
+
* Ray vs a sphere of radius `r` centred at the local origin.
|
|
29
|
+
*
|
|
30
|
+
* @param {Float64Array} outNormal length-3, written on hit
|
|
31
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (local)
|
|
32
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (local, unit)
|
|
33
|
+
* @param {number} tMax
|
|
34
|
+
* @param {number} r sphere radius
|
|
35
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
36
|
+
*/
|
|
37
|
+
export function ray_sphere_local(outNormal, ox, oy, oz, dx, dy, dz, tMax, r) {
|
|
38
|
+
// |o + t·d|² = r², d unit → t² + 2(o·d)t + (|o|² − r²) = 0.
|
|
39
|
+
const b = ox * dx + oy * dy + oz * dz;
|
|
40
|
+
const c = ox * ox + oy * oy + oz * oz - r * r;
|
|
41
|
+
const disc = b * b - c;
|
|
42
|
+
if (disc < 0) return Infinity;
|
|
43
|
+
const sq = Math.sqrt(disc);
|
|
44
|
+
let t = -b - sq; // near root (entry)
|
|
45
|
+
if (t < 0) t = -b + sq; // origin inside the sphere → far root (exit)
|
|
46
|
+
if (t < 0 || t > tMax) return Infinity;
|
|
47
|
+
const inv = 1 / r;
|
|
48
|
+
outNormal[0] = (ox + dx * t) * inv;
|
|
49
|
+
outNormal[1] = (oy + dy * t) * inv;
|
|
50
|
+
outNormal[2] = (oz + dz * t) * inv;
|
|
51
|
+
return t;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Ray vs an axis-aligned box spanning `[-hx,hx] × [-hy,hy] × [-hz,hz]` at the
|
|
56
|
+
* local origin (the canonical pose of {@link BoxShape3D}). Slab method, with
|
|
57
|
+
* the entry (or, origin-inside, exit) face's outward normal.
|
|
58
|
+
*
|
|
59
|
+
* @param {Float64Array} outNormal length-3, written on hit
|
|
60
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (local)
|
|
61
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (local, unit)
|
|
62
|
+
* @param {number} tMax
|
|
63
|
+
* @param {number} hx @param {number} hy @param {number} hz half-extents
|
|
64
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
65
|
+
*/
|
|
66
|
+
export function ray_box_local(outNormal, ox, oy, oz, dx, dy, dz, tMax, hx, hy, hz) {
|
|
67
|
+
let tmin = -Infinity, tmax = Infinity;
|
|
68
|
+
let enterAxis = 0, enterSign = 0, exitAxis = 0, exitSign = 0;
|
|
69
|
+
|
|
70
|
+
// X slab.
|
|
71
|
+
if (dx !== 0) {
|
|
72
|
+
const inv = 1 / dx;
|
|
73
|
+
let tn = (-hx - ox) * inv, tf = (hx - ox) * inv, nsign = -1;
|
|
74
|
+
if (tn > tf) { const tmp = tn; tn = tf; tf = tmp; nsign = 1; }
|
|
75
|
+
if (tn > tmin) { tmin = tn; enterAxis = 0; enterSign = nsign; }
|
|
76
|
+
if (tf < tmax) { tmax = tf; exitAxis = 0; exitSign = -nsign; }
|
|
77
|
+
} else if (ox < -hx || ox > hx) {
|
|
78
|
+
return Infinity;
|
|
79
|
+
}
|
|
80
|
+
// Y slab.
|
|
81
|
+
if (dy !== 0) {
|
|
82
|
+
const inv = 1 / dy;
|
|
83
|
+
let tn = (-hy - oy) * inv, tf = (hy - oy) * inv, nsign = -1;
|
|
84
|
+
if (tn > tf) { const tmp = tn; tn = tf; tf = tmp; nsign = 1; }
|
|
85
|
+
if (tn > tmin) { tmin = tn; enterAxis = 1; enterSign = nsign; }
|
|
86
|
+
if (tf < tmax) { tmax = tf; exitAxis = 1; exitSign = -nsign; }
|
|
87
|
+
} else if (oy < -hy || oy > hy) {
|
|
88
|
+
return Infinity;
|
|
89
|
+
}
|
|
90
|
+
// Z slab.
|
|
91
|
+
if (dz !== 0) {
|
|
92
|
+
const inv = 1 / dz;
|
|
93
|
+
let tn = (-hz - oz) * inv, tf = (hz - oz) * inv, nsign = -1;
|
|
94
|
+
if (tn > tf) { const tmp = tn; tn = tf; tf = tmp; nsign = 1; }
|
|
95
|
+
if (tn > tmin) { tmin = tn; enterAxis = 2; enterSign = nsign; }
|
|
96
|
+
if (tf < tmax) { tmax = tf; exitAxis = 2; exitSign = -nsign; }
|
|
97
|
+
} else if (oz < -hz || oz > hz) {
|
|
98
|
+
return Infinity;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (tmax < tmin || tmax < 0) return Infinity;
|
|
102
|
+
|
|
103
|
+
let t, axis, sign;
|
|
104
|
+
if (tmin >= 0) { t = tmin; axis = enterAxis; sign = enterSign; }
|
|
105
|
+
else { t = tmax; axis = exitAxis; sign = exitSign; } // origin inside the box
|
|
106
|
+
|
|
107
|
+
if (t > tMax) return Infinity;
|
|
108
|
+
outNormal[0] = 0; outNormal[1] = 0; outNormal[2] = 0;
|
|
109
|
+
outNormal[axis] = sign;
|
|
110
|
+
return t;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Ray vs a capsule along the local Y axis: a cylinder of radius `r` over
|
|
115
|
+
* `y ∈ [−hh, hh]` capped by hemispheres of radius `r` at `(0, ±hh, 0)` — the
|
|
116
|
+
* canonical pose of {@link CapsuleShape3D} (`hh = height/2`). Tests the
|
|
117
|
+
* infinite cylinder (clamped to the segment) and the two cap spheres, taking
|
|
118
|
+
* the nearest valid crossing.
|
|
119
|
+
*
|
|
120
|
+
* @param {Float64Array} outNormal length-3, written on hit
|
|
121
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (local)
|
|
122
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (local, unit)
|
|
123
|
+
* @param {number} tMax
|
|
124
|
+
* @param {number} r capsule radius
|
|
125
|
+
* @param {number} hh half-height of the cylindrical section (`height/2`)
|
|
126
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
127
|
+
*/
|
|
128
|
+
export function ray_capsule_local(outNormal, ox, oy, oz, dx, dy, dz, tMax, r, hh) {
|
|
129
|
+
let best = Infinity;
|
|
130
|
+
let nx = 0, ny = 0, nz = 0;
|
|
131
|
+
const r2 = r * r;
|
|
132
|
+
const inv_r = 1 / r;
|
|
133
|
+
|
|
134
|
+
// --- Cylinder side (infinite cylinder about Y, projected to XZ). ---
|
|
135
|
+
const a = dx * dx + dz * dz;
|
|
136
|
+
if (a > 1e-12) {
|
|
137
|
+
const b = ox * dx + oz * dz;
|
|
138
|
+
const c = ox * ox + oz * oz - r2;
|
|
139
|
+
const disc = b * b - a * c;
|
|
140
|
+
if (disc >= 0) {
|
|
141
|
+
const sq = Math.sqrt(disc);
|
|
142
|
+
const inv_a = 1 / a;
|
|
143
|
+
// Both roots; the smaller non-negative one whose hit lies on the
|
|
144
|
+
// cylindrical section is the side contact.
|
|
145
|
+
const roots = (-b - sq) * inv_a;
|
|
146
|
+
const rootf = (-b + sq) * inv_a;
|
|
147
|
+
for (let i = 0; i < 2; i++) {
|
|
148
|
+
const t = i === 0 ? roots : rootf;
|
|
149
|
+
if (t < 0 || t >= best || t > tMax) continue;
|
|
150
|
+
const y = oy + dy * t;
|
|
151
|
+
if (y < -hh || y > hh) continue; // off the cylinder, onto a cap
|
|
152
|
+
best = t;
|
|
153
|
+
const px = ox + dx * t, pz = oz + dz * t;
|
|
154
|
+
nx = px * inv_r; ny = 0; nz = pz * inv_r;
|
|
155
|
+
break; // roots is the nearer; if it qualified we're done
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// --- Cap spheres at (0, ±hh, 0), each valid only on its outer hemisphere. ---
|
|
161
|
+
for (let cap = 0; cap < 2; cap++) {
|
|
162
|
+
const cy = cap === 0 ? hh : -hh;
|
|
163
|
+
const oyc = oy - cy;
|
|
164
|
+
const bb = ox * dx + oyc * dy + oz * dz;
|
|
165
|
+
const cc = ox * ox + oyc * oyc + oz * oz - r2;
|
|
166
|
+
const disc = bb * bb - cc;
|
|
167
|
+
if (disc < 0) continue;
|
|
168
|
+
const sq = Math.sqrt(disc);
|
|
169
|
+
const tn = -bb - sq, tf = -bb + sq;
|
|
170
|
+
for (let i = 0; i < 2; i++) {
|
|
171
|
+
const t = i === 0 ? tn : tf;
|
|
172
|
+
if (t < 0 || t >= best || t > tMax) continue;
|
|
173
|
+
const hy = oy + dy * t;
|
|
174
|
+
// Only the hemisphere beyond the segment end belongs to this cap.
|
|
175
|
+
if (cap === 0 ? hy < hh : hy > -hh) continue;
|
|
176
|
+
best = t;
|
|
177
|
+
nx = (ox + dx * t) * inv_r;
|
|
178
|
+
ny = (hy - cy) * inv_r;
|
|
179
|
+
nz = (oz + dz * t) * inv_r;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (best === Infinity) return Infinity;
|
|
185
|
+
outNormal[0] = nx; outNormal[1] = ny; outNormal[2] = nz;
|
|
186
|
+
return best;
|
|
187
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {AbstractShape3D} shape a concave shape (`is_convex === false`)
|
|
3
|
+
* @param {{x:number,y:number,z:number}} position
|
|
4
|
+
* @param {ArrayLike<number>} rotation body rotation quaternion (x,y,z,w)
|
|
5
|
+
* @param {number} ox @param {number} oy @param {number} oz ray origin (world)
|
|
6
|
+
* @param {number} dx @param {number} dy @param {number} dz ray dir (world, unit)
|
|
7
|
+
* @param {number} tMax
|
|
8
|
+
* @param {Float64Array|Vector3} outNormal world surface normal, written on hit
|
|
9
|
+
* @returns {number} hit distance, or `Infinity` on miss
|
|
10
|
+
*/
|
|
11
|
+
export function refine_ray_concave(shape: AbstractShape3D, position: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
z: number;
|
|
15
|
+
}, rotation: ArrayLike<number>, ox: number, oy: number, oz: number, dx: number, dy: number, dz: number, tMax: number, outNormal: Float64Array | Vector3): number;
|
|
16
|
+
//# sourceMappingURL=refine_ray_concave.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refine_ray_concave.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/refine_ray_concave.js"],"names":[],"mappings":"AAsCA;;;;;;;;;GASG;AACH,qEARW;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,YAC5B,UAAU,MAAM,CAAC,MACjB,MAAM,MAAa,MAAM,MAAa,MAAM,MAC5C,MAAM,MAAa,MAAM,MAAa,MAAM,QAC5C,MAAM,aACN,YAAY,UAAQ,GAClB,MAAM,CAkGlB"}
|