@react-three/rapier 1.4.0 → 2.0.0-canary.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/dist/declarations/src/components/AnyCollider.d.ts +16 -16
- package/dist/declarations/src/components/InstancedRigidBodies.d.ts +6 -5
- package/dist/declarations/src/components/MeshCollider.d.ts +2 -2
- package/dist/declarations/src/components/Physics.d.ts +14 -10
- package/dist/declarations/src/components/RigidBody.d.ts +9 -11
- package/dist/declarations/src/hooks/hooks.d.ts +4 -4
- package/dist/declarations/src/hooks/joints.d.ts +2 -2
- package/dist/declarations/src/index.d.ts +15 -15
- package/dist/declarations/src/types.d.ts +54 -66
- package/dist/react-three-rapier.cjs.d.ts +1 -0
- package/dist/react-three-rapier.cjs.dev.js +402 -516
- package/dist/react-three-rapier.cjs.prod.js +402 -516
- package/dist/react-three-rapier.esm.js +403 -517
- package/package.json +15 -19
- package/readme.md +0 -2
- package/dist/declarations/src/components/Debug.d.ts +0 -2
- package/dist/declarations/src/components/FrameStepper.d.ts +0 -9
- package/dist/declarations/src/hooks/use-forwarded-ref.d.ts +0 -2
- package/dist/declarations/src/hooks/use-imperative-instance.d.ts +0 -5
- package/dist/declarations/src/utils/shared-objects.d.ts +0 -9
- package/dist/declarations/src/utils/singleton-proxy.d.ts +0 -11
- package/dist/declarations/src/utils/utils-collider.d.ts +0 -83
- package/dist/declarations/src/utils/utils-physics.d.ts +0 -1
- package/dist/declarations/src/utils/utils-rigidbody.d.ts +0 -24
- package/dist/declarations/src/utils/utils.d.ts +0 -14
@@ -1,50 +1,56 @@
|
|
1
1
|
import { Vector3 as Vector3$1, Quaternion as Quaternion$1, ActiveEvents, ColliderDesc, EventQueue, RigidBodyDesc } from '@dimforge/rapier3d-compat';
|
2
2
|
export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
|
3
3
|
import { useFrame, useThree } from '@react-three/fiber';
|
4
|
-
import React, { useRef, useEffect, memo, useMemo, useContext, useState, createContext, useCallback,
|
4
|
+
import React, { useRef, useEffect, memo, useMemo, useContext, useState, createContext, useCallback, Fragment } from 'react';
|
5
5
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, BufferAttribute, MathUtils, DynamicDrawUsage } from 'three';
|
6
6
|
import { suspend } from 'suspend-react';
|
7
7
|
import { mergeVertices } from 'three-stdlib';
|
8
8
|
|
9
|
-
function
|
10
|
-
if (
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
});
|
17
|
-
} else {
|
18
|
-
obj[key] = value;
|
9
|
+
function _toPrimitive(t, r) {
|
10
|
+
if ("object" != typeof t || !t) return t;
|
11
|
+
var e = t[Symbol.toPrimitive];
|
12
|
+
if (void 0 !== e) {
|
13
|
+
var i = e.call(t, r || "default");
|
14
|
+
if ("object" != typeof i) return i;
|
15
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
19
16
|
}
|
17
|
+
return ("string" === r ? String : Number)(t);
|
18
|
+
}
|
20
19
|
|
21
|
-
|
20
|
+
function _toPropertyKey(t) {
|
21
|
+
var i = _toPrimitive(t, "string");
|
22
|
+
return "symbol" == typeof i ? i : i + "";
|
22
23
|
}
|
23
24
|
|
24
|
-
function
|
25
|
-
|
25
|
+
function _defineProperty(e, r, t) {
|
26
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
27
|
+
value: t,
|
28
|
+
enumerable: !0,
|
29
|
+
configurable: !0,
|
30
|
+
writable: !0
|
31
|
+
}) : e[r] = t, e;
|
32
|
+
}
|
26
33
|
|
34
|
+
function ownKeys(e, r) {
|
35
|
+
var t = Object.keys(e);
|
27
36
|
if (Object.getOwnPropertySymbols) {
|
28
|
-
var
|
29
|
-
|
30
|
-
return Object.getOwnPropertyDescriptor(
|
31
|
-
})),
|
37
|
+
var o = Object.getOwnPropertySymbols(e);
|
38
|
+
r && (o = o.filter(function (r) {
|
39
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
40
|
+
})), t.push.apply(t, o);
|
32
41
|
}
|
33
|
-
|
34
|
-
return keys;
|
42
|
+
return t;
|
35
43
|
}
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
44
|
+
function _objectSpread2(e) {
|
45
|
+
for (var r = 1; r < arguments.length; r++) {
|
46
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
47
|
+
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
|
48
|
+
_defineProperty(e, r, t[r]);
|
49
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
50
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
44
51
|
});
|
45
52
|
}
|
46
|
-
|
47
|
-
return target;
|
53
|
+
return e;
|
48
54
|
}
|
49
55
|
|
50
56
|
const _quaternion = new Quaternion();
|
@@ -92,41 +98,33 @@ const rigidBodyTypeMap = {
|
|
92
98
|
const rigidBodyTypeFromString = type => rigidBodyTypeMap[type];
|
93
99
|
const scaleVertices = (vertices, scale) => {
|
94
100
|
const scaledVerts = Array.from(vertices);
|
95
|
-
|
96
101
|
for (let i = 0; i < vertices.length / 3; i++) {
|
97
102
|
scaledVerts[i * 3] *= scale.x;
|
98
103
|
scaledVerts[i * 3 + 1] *= scale.y;
|
99
104
|
scaledVerts[i * 3 + 2] *= scale.z;
|
100
105
|
}
|
101
|
-
|
102
106
|
return scaledVerts;
|
103
107
|
};
|
104
108
|
const vectorToTuple = v => {
|
105
109
|
if (!v) return [0];
|
106
|
-
|
107
110
|
if (v instanceof Quaternion) {
|
108
111
|
return [v.x, v.y, v.z, v.w];
|
109
112
|
}
|
110
|
-
|
111
113
|
if (v instanceof Vector3 || v instanceof Euler) {
|
112
114
|
return [v.x, v.y, v.z];
|
113
115
|
}
|
114
|
-
|
115
116
|
if (Array.isArray(v)) {
|
116
117
|
return v;
|
117
118
|
}
|
118
|
-
|
119
119
|
return [v];
|
120
120
|
};
|
121
121
|
function useConst(initialValue) {
|
122
|
-
const ref = useRef();
|
123
|
-
|
122
|
+
const ref = useRef(undefined);
|
124
123
|
if (ref.current === undefined) {
|
125
124
|
ref.current = {
|
126
125
|
value: typeof initialValue === "function" ? initialValue() : initialValue
|
127
126
|
};
|
128
127
|
}
|
129
|
-
|
130
128
|
return ref.current.value;
|
131
129
|
}
|
132
130
|
|
@@ -145,7 +143,6 @@ const useRaf = callback => {
|
|
145
143
|
cb.current(delta / 1000);
|
146
144
|
lastFrame.current = now;
|
147
145
|
};
|
148
|
-
|
149
146
|
raf.current = requestAnimationFrame(loop);
|
150
147
|
return () => cancelAnimationFrame(raf.current);
|
151
148
|
}, []);
|
@@ -160,7 +157,6 @@ const UseFrameStepper = ({
|
|
160
157
|
}, updatePriority);
|
161
158
|
return null;
|
162
159
|
};
|
163
|
-
|
164
160
|
const RafStepper = ({
|
165
161
|
onStep
|
166
162
|
}) => {
|
@@ -169,7 +165,6 @@ const RafStepper = ({
|
|
169
165
|
});
|
170
166
|
return null;
|
171
167
|
};
|
172
|
-
|
173
168
|
const FrameStepper = ({
|
174
169
|
onStep,
|
175
170
|
type,
|
@@ -182,98 +177,80 @@ const FrameStepper = ({
|
|
182
177
|
updatePriority: updatePriority
|
183
178
|
});
|
184
179
|
};
|
185
|
-
|
186
180
|
var FrameStepper$1 = /*#__PURE__*/memo(FrameStepper);
|
187
181
|
|
188
|
-
function _objectWithoutPropertiesLoose(
|
189
|
-
if (
|
190
|
-
var
|
191
|
-
var
|
192
|
-
|
193
|
-
|
194
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
195
|
-
key = sourceKeys[i];
|
196
|
-
if (excluded.indexOf(key) >= 0) continue;
|
197
|
-
target[key] = source[key];
|
182
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
183
|
+
if (null == r) return {};
|
184
|
+
var t = {};
|
185
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
186
|
+
if (-1 !== e.indexOf(n)) continue;
|
187
|
+
t[n] = r[n];
|
198
188
|
}
|
199
|
-
|
200
|
-
return target;
|
189
|
+
return t;
|
201
190
|
}
|
202
191
|
|
203
|
-
function _objectWithoutProperties(
|
204
|
-
if (
|
205
|
-
var
|
206
|
-
|
207
|
-
|
192
|
+
function _objectWithoutProperties(e, t) {
|
193
|
+
if (null == e) return {};
|
194
|
+
var o,
|
195
|
+
r,
|
196
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
208
197
|
if (Object.getOwnPropertySymbols) {
|
209
|
-
var
|
210
|
-
|
211
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
212
|
-
key = sourceSymbolKeys[i];
|
213
|
-
if (excluded.indexOf(key) >= 0) continue;
|
214
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
215
|
-
target[key] = source[key];
|
216
|
-
}
|
198
|
+
var n = Object.getOwnPropertySymbols(e);
|
199
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
217
200
|
}
|
218
|
-
|
219
|
-
return target;
|
201
|
+
return i;
|
220
202
|
}
|
221
203
|
|
222
|
-
const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale", "softCcdPrediction"];
|
204
|
+
const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale", "softCcdPrediction", "ref"];
|
223
205
|
const scaleColliderArgs = (shape, args, scale) => {
|
224
|
-
const newArgs = args.slice();
|
206
|
+
const newArgs = args.slice();
|
225
207
|
|
208
|
+
// Heightfield uses a vector
|
226
209
|
if (shape === "heightfield") {
|
227
210
|
const s = newArgs[3];
|
228
211
|
s.x *= scale.x;
|
229
212
|
s.x *= scale.y;
|
230
213
|
s.x *= scale.z;
|
231
214
|
return newArgs;
|
232
|
-
}
|
233
|
-
|
215
|
+
}
|
234
216
|
|
217
|
+
// Trimesh and convex scale the vertices
|
235
218
|
if (shape === "trimesh" || shape === "convexHull") {
|
236
219
|
newArgs[0] = scaleVertices(newArgs[0], scale);
|
237
220
|
return newArgs;
|
238
|
-
}
|
239
|
-
|
221
|
+
}
|
240
222
|
|
223
|
+
// Prepfill with some extra
|
241
224
|
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
242
225
|
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
243
226
|
};
|
244
227
|
const createColliderFromOptions = (options, world, scale, getRigidBody) => {
|
245
|
-
const scaledArgs = scaleColliderArgs(options.shape, options.args, scale);
|
246
|
-
|
228
|
+
const scaledArgs = scaleColliderArgs(options.shape, options.args, scale);
|
229
|
+
// @ts-ignore
|
247
230
|
const desc = ColliderDesc[options.shape](...scaledArgs);
|
248
231
|
return world.createCollider(desc, getRigidBody === null || getRigidBody === void 0 ? void 0 : getRigidBody());
|
249
232
|
};
|
250
233
|
const immutableColliderOptions = ["shape", "args"];
|
251
234
|
const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
|
252
|
-
|
253
235
|
const setColliderMassOptions = (collider, options) => {
|
254
236
|
if (options.density !== undefined) {
|
255
237
|
if (options.mass !== undefined || options.massProperties !== undefined) {
|
256
238
|
throw new Error(massPropertiesConflictError);
|
257
239
|
}
|
258
|
-
|
259
240
|
collider.setDensity(options.density);
|
260
241
|
return;
|
261
242
|
}
|
262
|
-
|
263
243
|
if (options.mass !== undefined) {
|
264
244
|
if (options.massProperties !== undefined) {
|
265
245
|
throw new Error(massPropertiesConflictError);
|
266
246
|
}
|
267
|
-
|
268
247
|
collider.setMass(options.mass);
|
269
248
|
return;
|
270
249
|
}
|
271
|
-
|
272
250
|
if (options.massProperties !== undefined) {
|
273
251
|
collider.setMassProperties(options.massProperties.mass, options.massProperties.centerOfMass, options.massProperties.principalAngularInertia, options.massProperties.angularInertiaLocalFrame);
|
274
252
|
}
|
275
253
|
};
|
276
|
-
|
277
254
|
const mutableColliderOptions = {
|
278
255
|
sensor: (collider, value) => {
|
279
256
|
collider.setSensor(value);
|
@@ -311,23 +288,17 @@ const mutableColliderOptions = {
|
|
311
288
|
const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
|
312
289
|
const setColliderOptions = (collider, options, states) => {
|
313
290
|
const state = states.get(collider.handle);
|
314
|
-
|
315
291
|
if (state) {
|
316
292
|
var _state$worldParent;
|
317
|
-
|
318
293
|
// Update collider position based on the object's position
|
319
294
|
const parentWorldScale = state.object.parent.getWorldScale(_vector3);
|
320
295
|
const parentInvertedWorldMatrix = (_state$worldParent = state.worldParent) === null || _state$worldParent === void 0 ? void 0 : _state$worldParent.matrixWorld.clone().invert();
|
321
296
|
state.object.updateWorldMatrix(true, false);
|
322
|
-
|
323
297
|
_matrix4.copy(state.object.matrixWorld);
|
324
|
-
|
325
298
|
if (parentInvertedWorldMatrix) {
|
326
299
|
_matrix4.premultiply(parentInvertedWorldMatrix);
|
327
300
|
}
|
328
|
-
|
329
301
|
_matrix4.decompose(_position, _rotation, _scale);
|
330
|
-
|
331
302
|
if (collider.parent()) {
|
332
303
|
collider.setTranslationWrtParent({
|
333
304
|
x: _position.x * parentWorldScale.x,
|
@@ -343,16 +314,17 @@ const setColliderOptions = (collider, options, states) => {
|
|
343
314
|
});
|
344
315
|
collider.setRotation(_rotation);
|
345
316
|
}
|
346
|
-
|
347
317
|
mutableColliderOptionKeys.forEach(key => {
|
348
318
|
if (key in options) {
|
349
319
|
const option = options[key];
|
350
|
-
mutableColliderOptions[key](collider,
|
320
|
+
mutableColliderOptions[key](collider,
|
321
|
+
// @ts-ignore Option does not want to fit into the function, but it will
|
351
322
|
option, options);
|
352
323
|
}
|
353
|
-
});
|
354
|
-
// are exclusive.
|
324
|
+
});
|
355
325
|
|
326
|
+
// handle mass separately, because the assignments
|
327
|
+
// are exclusive.
|
356
328
|
setColliderMassOptions(collider, options);
|
357
329
|
}
|
358
330
|
};
|
@@ -366,7 +338,6 @@ const useUpdateColliderOptions = (getCollider, props, states) => {
|
|
366
338
|
setColliderOptions(collider, props, states);
|
367
339
|
}, [...mutablePropsAsFlatArray, getCollider]);
|
368
340
|
};
|
369
|
-
|
370
341
|
const isChildOfMeshCollider = child => {
|
371
342
|
let flag = false;
|
372
343
|
child.traverseAncestors(a => {
|
@@ -374,7 +345,6 @@ const isChildOfMeshCollider = child => {
|
|
374
345
|
});
|
375
346
|
return flag;
|
376
347
|
};
|
377
|
-
|
378
348
|
const createColliderState = (collider, object, rigidBodyObject) => {
|
379
349
|
return {
|
380
350
|
collider,
|
@@ -396,16 +366,13 @@ const createColliderPropsFromChildren = ({
|
|
396
366
|
const childColliderProps = [];
|
397
367
|
object.updateWorldMatrix(true, false);
|
398
368
|
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
399
|
-
|
400
369
|
const colliderFromChild = child => {
|
401
370
|
if ("isMesh" in child) {
|
402
371
|
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
403
372
|
const worldScale = child.getWorldScale(_scale);
|
404
373
|
const shape = autoColliderMap[options.colliders || "cuboid"];
|
405
374
|
child.updateWorldMatrix(true, false);
|
406
|
-
|
407
375
|
_matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
|
408
|
-
|
409
376
|
const rotationEuler = new Euler().setFromQuaternion(_rotation, "XYZ");
|
410
377
|
const {
|
411
378
|
geometry
|
@@ -414,7 +381,6 @@ const createColliderPropsFromChildren = ({
|
|
414
381
|
args,
|
415
382
|
offset
|
416
383
|
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
417
|
-
|
418
384
|
const colliderProps = _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(options)), {}, {
|
419
385
|
args: args,
|
420
386
|
shape: shape,
|
@@ -422,17 +388,14 @@ const createColliderPropsFromChildren = ({
|
|
422
388
|
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
423
389
|
scale: [worldScale.x, worldScale.y, worldScale.z]
|
424
390
|
});
|
425
|
-
|
426
391
|
childColliderProps.push(colliderProps);
|
427
392
|
}
|
428
393
|
};
|
429
|
-
|
430
394
|
if (options.includeInvisible) {
|
431
395
|
object.traverse(colliderFromChild);
|
432
396
|
} else {
|
433
397
|
object.traverseVisible(colliderFromChild);
|
434
398
|
}
|
435
|
-
|
436
399
|
return childColliderProps;
|
437
400
|
};
|
438
401
|
const getColliderArgsFromGeometry = (geometry, colliders) => {
|
@@ -449,7 +412,6 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
449
412
|
offset: boundingBox.getCenter(new Vector3())
|
450
413
|
};
|
451
414
|
}
|
452
|
-
|
453
415
|
case "ball":
|
454
416
|
{
|
455
417
|
geometry.computeBoundingSphere();
|
@@ -462,18 +424,15 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
462
424
|
offset: boundingSphere.center
|
463
425
|
};
|
464
426
|
}
|
465
|
-
|
466
427
|
case "trimesh":
|
467
428
|
{
|
468
429
|
var _clonedGeometry$index;
|
469
|
-
|
470
430
|
const clonedGeometry = geometry.index ? geometry.clone() : mergeVertices(geometry);
|
471
431
|
return {
|
472
432
|
args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
|
473
433
|
offset: new Vector3()
|
474
434
|
};
|
475
435
|
}
|
476
|
-
|
477
436
|
case "hull":
|
478
437
|
{
|
479
438
|
const g = geometry.clone();
|
@@ -483,7 +442,6 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
483
442
|
};
|
484
443
|
}
|
485
444
|
}
|
486
|
-
|
487
445
|
return {
|
488
446
|
args: [],
|
489
447
|
offset: new Vector3()
|
@@ -509,7 +467,6 @@ activeEvents = {}) => {
|
|
509
467
|
} = props;
|
510
468
|
useEffect(() => {
|
511
469
|
const collider = getCollider();
|
512
|
-
|
513
470
|
if (collider) {
|
514
471
|
const {
|
515
472
|
collision: collisionEventsActive,
|
@@ -517,7 +474,6 @@ activeEvents = {}) => {
|
|
517
474
|
} = getActiveCollisionEventsFromProps(props);
|
518
475
|
const hasCollisionEvent = collisionEventsActive || activeEvents.collision;
|
519
476
|
const hasContactForceEvent = contactForceEventsActive || activeEvents.contactForce;
|
520
|
-
|
521
477
|
if (hasCollisionEvent && hasContactForceEvent) {
|
522
478
|
collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS | ActiveEvents.CONTACT_FORCE_EVENTS);
|
523
479
|
} else if (hasCollisionEvent) {
|
@@ -525,7 +481,6 @@ activeEvents = {}) => {
|
|
525
481
|
} else if (hasContactForceEvent) {
|
526
482
|
collider.setActiveEvents(ActiveEvents.CONTACT_FORCE_EVENTS);
|
527
483
|
}
|
528
|
-
|
529
484
|
events.set(collider.handle, {
|
530
485
|
onCollisionEnter,
|
531
486
|
onCollisionExit,
|
@@ -534,7 +489,6 @@ activeEvents = {}) => {
|
|
534
489
|
onContactForce
|
535
490
|
});
|
536
491
|
}
|
537
|
-
|
538
492
|
return () => {
|
539
493
|
if (collider) {
|
540
494
|
events.delete(collider.handle);
|
@@ -544,34 +498,33 @@ activeEvents = {}) => {
|
|
544
498
|
};
|
545
499
|
const cleanRigidBodyPropsForCollider = (props = {}) => {
|
546
500
|
const rest = _objectWithoutProperties(props, _excluded$2);
|
547
|
-
|
548
501
|
return rest;
|
549
502
|
};
|
550
503
|
|
504
|
+
// Utils
|
551
505
|
const useMutableCallback = fn => {
|
552
506
|
const ref = useRef(fn);
|
553
507
|
useEffect(() => {
|
554
508
|
ref.current = fn;
|
555
509
|
}, [fn]);
|
556
510
|
return ref;
|
557
|
-
};
|
511
|
+
};
|
558
512
|
|
513
|
+
// External hooks
|
559
514
|
/**
|
560
515
|
* Exposes the Rapier context, and world
|
561
516
|
* @category Hooks
|
562
517
|
*/
|
563
|
-
|
564
|
-
|
565
518
|
const useRapier = () => {
|
566
519
|
const rapier = useContext(rapierContext);
|
567
520
|
if (!rapier) throw new Error("react-three-rapier: useRapier must be used within <Physics />!");
|
568
521
|
return rapier;
|
569
522
|
};
|
523
|
+
|
570
524
|
/**
|
571
525
|
* Registers a callback to be called before the physics step
|
572
526
|
* @category Hooks
|
573
527
|
*/
|
574
|
-
|
575
528
|
const useBeforePhysicsStep = callback => {
|
576
529
|
const {
|
577
530
|
beforeStepCallbacks
|
@@ -584,11 +537,11 @@ const useBeforePhysicsStep = callback => {
|
|
584
537
|
};
|
585
538
|
}, []);
|
586
539
|
};
|
540
|
+
|
587
541
|
/**
|
588
542
|
* Registers a callback to be called after the physics step
|
589
543
|
* @category Hooks
|
590
544
|
*/
|
591
|
-
|
592
545
|
const useAfterPhysicsStep = callback => {
|
593
546
|
const {
|
594
547
|
afterStepCallbacks
|
@@ -600,17 +553,16 @@ const useAfterPhysicsStep = callback => {
|
|
600
553
|
afterStepCallbacks.delete(ref);
|
601
554
|
};
|
602
555
|
}, []);
|
603
|
-
};
|
556
|
+
};
|
604
557
|
|
558
|
+
// Internal hooks
|
605
559
|
/**
|
606
560
|
* @internal
|
607
561
|
*/
|
608
|
-
|
609
562
|
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
610
563
|
const [colliderProps, setColliderProps] = useState([]);
|
611
564
|
useEffect(() => {
|
612
565
|
const object = ref.current;
|
613
|
-
|
614
566
|
if (object && options.colliders !== false) {
|
615
567
|
setColliderProps(createColliderPropsFromChildren({
|
616
568
|
object: ref.current,
|
@@ -656,33 +608,26 @@ const createSingletonProxy = createInstance => {
|
|
656
608
|
if (!instance) {
|
657
609
|
instance = createInstance();
|
658
610
|
}
|
659
|
-
|
660
611
|
return Reflect.get(instance, prop);
|
661
612
|
},
|
662
|
-
|
663
613
|
set(target, prop, value) {
|
664
614
|
if (!instance) {
|
665
615
|
instance = createInstance();
|
666
616
|
}
|
667
|
-
|
668
617
|
return Reflect.set(instance, prop, value);
|
669
618
|
}
|
670
|
-
|
671
619
|
};
|
672
620
|
const proxy = new Proxy({}, handler);
|
673
|
-
|
674
621
|
const reset = () => {
|
675
622
|
instance = undefined;
|
676
623
|
};
|
677
|
-
|
678
624
|
const set = newInstance => {
|
679
625
|
instance = newInstance;
|
680
626
|
};
|
627
|
+
|
681
628
|
/**
|
682
629
|
* Return the proxy and a reset function
|
683
630
|
*/
|
684
|
-
|
685
|
-
|
686
631
|
return {
|
687
632
|
proxy,
|
688
633
|
reset,
|
@@ -691,10 +636,8 @@ const createSingletonProxy = createInstance => {
|
|
691
636
|
};
|
692
637
|
|
693
638
|
const rapierContext = /*#__PURE__*/createContext(undefined);
|
694
|
-
|
695
639
|
const getCollisionPayloadFromSource = (target, other) => {
|
696
640
|
var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
|
697
|
-
|
698
641
|
return {
|
699
642
|
target: {
|
700
643
|
rigidBody: target.rigidBody.object,
|
@@ -714,13 +657,11 @@ const getCollisionPayloadFromSource = (target, other) => {
|
|
714
657
|
rigidBodyObject: (_other$rigidBody$stat2 = other.rigidBody.state) === null || _other$rigidBody$stat2 === void 0 ? void 0 : _other$rigidBody$stat2.object
|
715
658
|
};
|
716
659
|
};
|
717
|
-
|
718
660
|
const importRapier = async () => {
|
719
661
|
let r = await import('@dimforge/rapier3d-compat');
|
720
662
|
await r.init();
|
721
663
|
return r;
|
722
664
|
};
|
723
|
-
|
724
665
|
/**
|
725
666
|
* The main physics component used to create a physics world.
|
726
667
|
* @category Components
|
@@ -743,7 +684,7 @@ const Physics = props => {
|
|
743
684
|
numInternalPgsIterations = 1,
|
744
685
|
minIslandSize = 128,
|
745
686
|
maxCcdSubsteps = 1,
|
746
|
-
|
687
|
+
contactNaturalFrequency = 30,
|
747
688
|
lengthUnit = 1
|
748
689
|
} = props;
|
749
690
|
const rapier = suspend(importRapier, ["@react-thee/rapier", importRapier]);
|
@@ -757,12 +698,12 @@ const Physics = props => {
|
|
757
698
|
const eventQueue = useConst(() => new EventQueue(false));
|
758
699
|
const beforeStepCallbacks = useConst(() => new Set());
|
759
700
|
const afterStepCallbacks = useConst(() => new Set());
|
701
|
+
|
760
702
|
/**
|
761
703
|
* Initiate the world
|
762
704
|
* This creates a singleton proxy, so that the world is only created when
|
763
705
|
* something within it is accessed.
|
764
706
|
*/
|
765
|
-
|
766
707
|
const {
|
767
708
|
proxy: worldProxy,
|
768
709
|
reset: resetWorldProxy,
|
@@ -773,8 +714,9 @@ const Physics = props => {
|
|
773
714
|
worldProxy.free();
|
774
715
|
resetWorldProxy();
|
775
716
|
};
|
776
|
-
}, []);
|
717
|
+
}, []);
|
777
718
|
|
719
|
+
// Update mutable props
|
778
720
|
useEffect(() => {
|
779
721
|
worldProxy.gravity = vector3ToRapierVector(gravity);
|
780
722
|
worldProxy.integrationParameters.numSolverIterations = numSolverIterations;
|
@@ -784,12 +726,11 @@ const Physics = props => {
|
|
784
726
|
worldProxy.integrationParameters.minIslandSize = minIslandSize;
|
785
727
|
worldProxy.integrationParameters.maxCcdSubsteps = maxCcdSubsteps;
|
786
728
|
worldProxy.integrationParameters.normalizedPredictionDistance = predictionDistance;
|
787
|
-
worldProxy.integrationParameters.erp = erp;
|
788
729
|
worldProxy.lengthUnit = lengthUnit;
|
789
|
-
|
730
|
+
worldProxy.integrationParameters.contact_natural_frequency = contactNaturalFrequency;
|
731
|
+
}, [worldProxy, ...gravity, numSolverIterations, numAdditionalFrictionIterations, numInternalPgsIterations, allowedLinearError, minIslandSize, maxCcdSubsteps, predictionDistance, lengthUnit, contactNaturalFrequency]);
|
790
732
|
const getSourceFromColliderHandle = useCallback(handle => {
|
791
733
|
var _collider$parent;
|
792
|
-
|
793
734
|
const collider = worldProxy.getCollider(handle);
|
794
735
|
const colEvents = colliderEvents.get(handle);
|
795
736
|
const colliderState = colliderStates.get(handle);
|
@@ -817,37 +758,36 @@ const Physics = props => {
|
|
817
758
|
});
|
818
759
|
const step = useCallback(dt => {
|
819
760
|
const world = worldProxy;
|
761
|
+
|
820
762
|
/* Check if the timestep is supposed to be variable. We'll do this here
|
821
763
|
once so we don't have to string-check every frame. */
|
822
|
-
|
823
764
|
const timeStepVariable = timeStep === "vary";
|
765
|
+
|
824
766
|
/**
|
825
767
|
* Fixed timeStep simulation progression
|
826
768
|
* @see https://gafferongames.com/post/fix_your_timestep/
|
827
769
|
*/
|
828
770
|
|
829
771
|
const clampedDelta = MathUtils.clamp(dt, 0, 0.5);
|
830
|
-
|
831
772
|
const stepWorld = delta => {
|
832
773
|
// Trigger beforeStep callbacks
|
833
774
|
beforeStepCallbacks.forEach(callback => {
|
834
775
|
callback.current(world);
|
835
776
|
});
|
836
777
|
world.timestep = delta;
|
837
|
-
world.step(eventQueue);
|
778
|
+
world.step(eventQueue);
|
838
779
|
|
780
|
+
// Trigger afterStep callbacks
|
839
781
|
afterStepCallbacks.forEach(callback => {
|
840
782
|
callback.current(world);
|
841
783
|
});
|
842
784
|
};
|
843
|
-
|
844
785
|
if (timeStepVariable) {
|
845
786
|
stepWorld(clampedDelta);
|
846
787
|
} else {
|
847
788
|
// don't step time forwards if paused
|
848
789
|
// Increase accumulator
|
849
790
|
steppingState.accumulator += clampedDelta;
|
850
|
-
|
851
791
|
while (steppingState.accumulator >= timeStep) {
|
852
792
|
// Set up previous state
|
853
793
|
// needed for accurate interpolations if the world steps more than once
|
@@ -860,57 +800,48 @@ const Physics = props => {
|
|
860
800
|
};
|
861
801
|
});
|
862
802
|
}
|
863
|
-
|
864
803
|
stepWorld(timeStep);
|
865
804
|
steppingState.accumulator -= timeStep;
|
866
805
|
}
|
867
806
|
}
|
807
|
+
const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep;
|
868
808
|
|
869
|
-
|
870
|
-
|
809
|
+
// Update meshes
|
871
810
|
rigidBodyStates.forEach((state, handle) => {
|
872
811
|
const rigidBody = world.getRigidBody(handle);
|
873
812
|
const events = rigidBodyEvents.get(handle);
|
874
|
-
|
875
813
|
if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
|
876
814
|
if (rigidBody.isSleeping() && !state.isSleeping) {
|
877
815
|
var _events$onSleep;
|
878
|
-
|
879
816
|
events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
|
880
817
|
}
|
881
|
-
|
882
818
|
if (!rigidBody.isSleeping() && state.isSleeping) {
|
883
819
|
var _events$onWake;
|
884
|
-
|
885
820
|
events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
|
886
821
|
}
|
887
|
-
|
888
822
|
state.isSleeping = rigidBody.isSleeping();
|
889
823
|
}
|
890
|
-
|
891
824
|
if (!rigidBody || rigidBody.isSleeping() && !("isInstancedMesh" in state.object) || !state.setMatrix) {
|
892
825
|
return;
|
893
|
-
}
|
894
|
-
|
826
|
+
}
|
895
827
|
|
828
|
+
// New states
|
896
829
|
let t = rigidBody.translation();
|
897
830
|
let r = rigidBody.rotation();
|
898
831
|
let previousState = steppingState.previousState[handle];
|
899
|
-
|
900
832
|
if (previousState) {
|
901
833
|
// Get previous simulated world position
|
902
|
-
_matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
903
|
-
|
834
|
+
_matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
904
835
|
|
836
|
+
// Apply previous tick position
|
905
837
|
if (state.meshType == "mesh") {
|
906
838
|
state.object.position.copy(_position);
|
907
839
|
state.object.quaternion.copy(_rotation);
|
908
840
|
}
|
909
|
-
}
|
910
|
-
|
841
|
+
}
|
911
842
|
|
843
|
+
// Get new position
|
912
844
|
_matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
913
|
-
|
914
845
|
if (state.meshType == "instancedMesh") {
|
915
846
|
state.setMatrix(_matrix4);
|
916
847
|
} else {
|
@@ -921,19 +852,17 @@ const Physics = props => {
|
|
921
852
|
});
|
922
853
|
eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
923
854
|
const source1 = getSourceFromColliderHandle(handle1);
|
924
|
-
const source2 = getSourceFromColliderHandle(handle2);
|
855
|
+
const source2 = getSourceFromColliderHandle(handle2);
|
925
856
|
|
857
|
+
// Collision Events
|
926
858
|
if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
|
927
859
|
return;
|
928
860
|
}
|
929
|
-
|
930
861
|
const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
|
931
862
|
const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
|
932
|
-
|
933
863
|
if (started) {
|
934
864
|
world.contactPair(source1.collider.object, source2.collider.object, (manifold, flipped) => {
|
935
865
|
var _source1$rigidBody$ev, _source1$rigidBody$ev2, _source2$rigidBody$ev, _source2$rigidBody$ev2, _source1$collider$eve, _source1$collider$eve2, _source2$collider$eve, _source2$collider$eve2;
|
936
|
-
|
937
866
|
/* RigidBody events */
|
938
867
|
(_source1$rigidBody$ev = source1.rigidBody.events) === null || _source1$rigidBody$ev === void 0 ? void 0 : (_source1$rigidBody$ev2 = _source1$rigidBody$ev.onCollisionEnter) === null || _source1$rigidBody$ev2 === void 0 ? void 0 : _source1$rigidBody$ev2.call(_source1$rigidBody$ev, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
|
939
868
|
manifold,
|
@@ -943,8 +872,8 @@ const Physics = props => {
|
|
943
872
|
manifold,
|
944
873
|
flipped
|
945
874
|
}));
|
946
|
-
/* Collider events */
|
947
875
|
|
876
|
+
/* Collider events */
|
948
877
|
(_source1$collider$eve = source1.collider.events) === null || _source1$collider$eve === void 0 ? void 0 : (_source1$collider$eve2 = _source1$collider$eve.onCollisionEnter) === null || _source1$collider$eve2 === void 0 ? void 0 : _source1$collider$eve2.call(_source1$collider$eve, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
|
949
878
|
manifold,
|
950
879
|
flipped
|
@@ -956,18 +885,16 @@ const Physics = props => {
|
|
956
885
|
});
|
957
886
|
} else {
|
958
887
|
var _source1$rigidBody$ev3, _source1$rigidBody$ev4, _source2$rigidBody$ev3, _source2$rigidBody$ev4, _source1$collider$eve3, _source1$collider$eve4, _source2$collider$eve3, _source2$collider$eve4;
|
959
|
-
|
960
888
|
(_source1$rigidBody$ev3 = source1.rigidBody.events) === null || _source1$rigidBody$ev3 === void 0 ? void 0 : (_source1$rigidBody$ev4 = _source1$rigidBody$ev3.onCollisionExit) === null || _source1$rigidBody$ev4 === void 0 ? void 0 : _source1$rigidBody$ev4.call(_source1$rigidBody$ev3, collisionPayload1);
|
961
889
|
(_source2$rigidBody$ev3 = source2.rigidBody.events) === null || _source2$rigidBody$ev3 === void 0 ? void 0 : (_source2$rigidBody$ev4 = _source2$rigidBody$ev3.onCollisionExit) === null || _source2$rigidBody$ev4 === void 0 ? void 0 : _source2$rigidBody$ev4.call(_source2$rigidBody$ev3, collisionPayload2);
|
962
890
|
(_source1$collider$eve3 = source1.collider.events) === null || _source1$collider$eve3 === void 0 ? void 0 : (_source1$collider$eve4 = _source1$collider$eve3.onCollisionExit) === null || _source1$collider$eve4 === void 0 ? void 0 : _source1$collider$eve4.call(_source1$collider$eve3, collisionPayload1);
|
963
891
|
(_source2$collider$eve3 = source2.collider.events) === null || _source2$collider$eve3 === void 0 ? void 0 : (_source2$collider$eve4 = _source2$collider$eve3.onCollisionExit) === null || _source2$collider$eve4 === void 0 ? void 0 : _source2$collider$eve4.call(_source2$collider$eve3, collisionPayload2);
|
964
|
-
}
|
965
|
-
|
892
|
+
}
|
966
893
|
|
894
|
+
// Sensor Intersections
|
967
895
|
if (started) {
|
968
896
|
if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
|
969
897
|
var _source1$rigidBody$ev5, _source1$rigidBody$ev6, _source2$rigidBody$ev5, _source2$rigidBody$ev6, _source1$collider$eve5, _source1$collider$eve6, _source2$collider$eve5, _source2$collider$eve6;
|
970
|
-
|
971
898
|
(_source1$rigidBody$ev5 = source1.rigidBody.events) === null || _source1$rigidBody$ev5 === void 0 ? void 0 : (_source1$rigidBody$ev6 = _source1$rigidBody$ev5.onIntersectionEnter) === null || _source1$rigidBody$ev6 === void 0 ? void 0 : _source1$rigidBody$ev6.call(_source1$rigidBody$ev5, collisionPayload1);
|
972
899
|
(_source2$rigidBody$ev5 = source2.rigidBody.events) === null || _source2$rigidBody$ev5 === void 0 ? void 0 : (_source2$rigidBody$ev6 = _source2$rigidBody$ev5.onIntersectionEnter) === null || _source2$rigidBody$ev6 === void 0 ? void 0 : _source2$rigidBody$ev6.call(_source2$rigidBody$ev5, collisionPayload2);
|
973
900
|
(_source1$collider$eve5 = source1.collider.events) === null || _source1$collider$eve5 === void 0 ? void 0 : (_source1$collider$eve6 = _source1$collider$eve5.onIntersectionEnter) === null || _source1$collider$eve6 === void 0 ? void 0 : _source1$collider$eve6.call(_source1$collider$eve5, collisionPayload1);
|
@@ -975,7 +902,6 @@ const Physics = props => {
|
|
975
902
|
}
|
976
903
|
} else {
|
977
904
|
var _source1$rigidBody$ev7, _source1$rigidBody$ev8, _source2$rigidBody$ev7, _source2$rigidBody$ev8, _source1$collider$eve7, _source1$collider$eve8, _source2$collider$eve7, _source2$collider$eve8;
|
978
|
-
|
979
905
|
(_source1$rigidBody$ev7 = source1.rigidBody.events) === null || _source1$rigidBody$ev7 === void 0 ? void 0 : (_source1$rigidBody$ev8 = _source1$rigidBody$ev7.onIntersectionExit) === null || _source1$rigidBody$ev8 === void 0 ? void 0 : _source1$rigidBody$ev8.call(_source1$rigidBody$ev7, collisionPayload1);
|
980
906
|
(_source2$rigidBody$ev7 = source2.rigidBody.events) === null || _source2$rigidBody$ev7 === void 0 ? void 0 : (_source2$rigidBody$ev8 = _source2$rigidBody$ev7.onIntersectionExit) === null || _source2$rigidBody$ev8 === void 0 ? void 0 : _source2$rigidBody$ev8.call(_source2$rigidBody$ev7, collisionPayload2);
|
981
907
|
(_source1$collider$eve7 = source1.collider.events) === null || _source1$collider$eve7 === void 0 ? void 0 : (_source1$collider$eve8 = _source1$collider$eve7.onIntersectionExit) === null || _source1$collider$eve8 === void 0 ? void 0 : _source1$collider$eve8.call(_source1$collider$eve7, collisionPayload1);
|
@@ -984,14 +910,13 @@ const Physics = props => {
|
|
984
910
|
});
|
985
911
|
eventQueue.drainContactForceEvents(event => {
|
986
912
|
var _source1$rigidBody$ev9, _source1$rigidBody$ev10, _source2$rigidBody$ev9, _source2$rigidBody$ev10, _source1$collider$eve9, _source1$collider$eve10, _source2$collider$eve9, _source2$collider$eve10;
|
987
|
-
|
988
913
|
const source1 = getSourceFromColliderHandle(event.collider1());
|
989
|
-
const source2 = getSourceFromColliderHandle(event.collider2());
|
914
|
+
const source2 = getSourceFromColliderHandle(event.collider2());
|
990
915
|
|
916
|
+
// Collision Events
|
991
917
|
if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
|
992
918
|
return;
|
993
919
|
}
|
994
|
-
|
995
920
|
const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
|
996
921
|
const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
|
997
922
|
(_source1$rigidBody$ev9 = source1.rigidBody.events) === null || _source1$rigidBody$ev9 === void 0 ? void 0 : (_source1$rigidBody$ev10 = _source1$rigidBody$ev9.onContactForce) === null || _source1$rigidBody$ev10 === void 0 ? void 0 : _source1$rigidBody$ev10.call(_source1$rigidBody$ev9, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
|
@@ -1058,41 +983,44 @@ const Physics = props => {
|
|
1058
983
|
};
|
1059
984
|
|
1060
985
|
function _extends() {
|
1061
|
-
_extends = Object.assign ? Object.assign.bind() : function (
|
1062
|
-
for (var
|
1063
|
-
var
|
1064
|
-
|
1065
|
-
for (var key in source) {
|
1066
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
1067
|
-
target[key] = source[key];
|
1068
|
-
}
|
1069
|
-
}
|
986
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
987
|
+
for (var e = 1; e < arguments.length; e++) {
|
988
|
+
var t = arguments[e];
|
989
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
1070
990
|
}
|
1071
|
-
|
1072
|
-
|
1073
|
-
};
|
1074
|
-
return _extends.apply(this, arguments);
|
991
|
+
return n;
|
992
|
+
}, _extends.apply(null, arguments);
|
1075
993
|
}
|
1076
994
|
|
995
|
+
// Need to catch the case where forwardedRef is a function... how to do that?
|
996
|
+
const useForwardedRef = (forwardedRef, defaultValue = null) => {
|
997
|
+
const innerRef = useRef(defaultValue);
|
998
|
+
|
999
|
+
// Update the forwarded ref when the inner ref changes
|
1000
|
+
if (forwardedRef && typeof forwardedRef !== "function") {
|
1001
|
+
if (!forwardedRef.current) {
|
1002
|
+
forwardedRef.current = innerRef.current;
|
1003
|
+
}
|
1004
|
+
return forwardedRef;
|
1005
|
+
}
|
1006
|
+
return innerRef;
|
1007
|
+
};
|
1008
|
+
|
1077
1009
|
/**
|
1078
1010
|
* Initiate an instance and return a safe getter
|
1079
1011
|
*/
|
1080
|
-
|
1081
1012
|
const useImperativeInstance = (createFn, destroyFn, dependencyList) => {
|
1082
|
-
const ref = useRef();
|
1013
|
+
const ref = useRef(undefined);
|
1083
1014
|
const getInstance = useCallback(() => {
|
1084
1015
|
if (!ref.current) {
|
1085
1016
|
ref.current = createFn();
|
1086
1017
|
}
|
1087
|
-
|
1088
1018
|
return ref.current;
|
1089
1019
|
}, dependencyList);
|
1090
1020
|
useEffect(() => {
|
1091
1021
|
// Save the destroy function and instance
|
1092
1022
|
const instance = getInstance();
|
1093
|
-
|
1094
1023
|
const destroy = () => destroyFn(instance);
|
1095
|
-
|
1096
1024
|
return () => {
|
1097
1025
|
destroy();
|
1098
1026
|
ref.current = undefined;
|
@@ -1101,102 +1029,238 @@ const useImperativeInstance = (createFn, destroyFn, dependencyList) => {
|
|
1101
1029
|
return getInstance;
|
1102
1030
|
};
|
1103
1031
|
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
const vec3 = ({
|
1110
|
-
x,
|
1111
|
-
y,
|
1112
|
-
z
|
1113
|
-
} = {
|
1114
|
-
x: 0,
|
1115
|
-
y: 0,
|
1116
|
-
z: 0
|
1117
|
-
}) => {
|
1118
|
-
return new Vector3(x, y, z);
|
1119
|
-
};
|
1120
|
-
/**
|
1121
|
-
* Takes an object resembling a Quaternion and returs a Three.Quaternion
|
1122
|
-
* @category Math helpers
|
1123
|
-
*/
|
1032
|
+
const rigidBodyDescFromOptions = options => {
|
1033
|
+
var _options$canSleep;
|
1034
|
+
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
1035
|
+
const desc = new RigidBodyDesc(type);
|
1124
1036
|
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
z,
|
1129
|
-
w
|
1130
|
-
} = {
|
1131
|
-
x: 0,
|
1132
|
-
y: 0,
|
1133
|
-
z: 0,
|
1134
|
-
w: 1
|
1135
|
-
}) => {
|
1136
|
-
return new Quaternion(x, y, z, w);
|
1037
|
+
// Apply immutable options
|
1038
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
1039
|
+
return desc;
|
1137
1040
|
};
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
y,
|
1146
|
-
z
|
1147
|
-
} = {
|
1148
|
-
x: 0,
|
1149
|
-
y: 0,
|
1150
|
-
z: 0
|
1041
|
+
const createRigidBodyState = ({
|
1042
|
+
rigidBody,
|
1043
|
+
object,
|
1044
|
+
setMatrix,
|
1045
|
+
getMatrix,
|
1046
|
+
worldScale,
|
1047
|
+
meshType: _meshType = "mesh"
|
1151
1048
|
}) => {
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
return innerRef;
|
1049
|
+
object.updateWorldMatrix(true, false);
|
1050
|
+
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
1051
|
+
return {
|
1052
|
+
object,
|
1053
|
+
rigidBody,
|
1054
|
+
invertedWorldMatrix,
|
1055
|
+
setMatrix: setMatrix ? setMatrix : matrix => {
|
1056
|
+
object.matrix.copy(matrix);
|
1057
|
+
},
|
1058
|
+
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
1059
|
+
scale: worldScale || object.getWorldScale(_scale).clone(),
|
1060
|
+
isSleeping: false,
|
1061
|
+
meshType: _meshType
|
1062
|
+
};
|
1167
1063
|
};
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
}
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1064
|
+
const immutableRigidBodyOptions = ["args", "colliders", "canSleep"];
|
1065
|
+
const mutableRigidBodyOptions = {
|
1066
|
+
gravityScale: (rb, value) => {
|
1067
|
+
rb.setGravityScale(value, true);
|
1068
|
+
},
|
1069
|
+
additionalSolverIterations(rb, value) {
|
1070
|
+
rb.setAdditionalSolverIterations(value);
|
1071
|
+
},
|
1072
|
+
linearDamping: (rb, value) => {
|
1073
|
+
rb.setLinearDamping(value);
|
1074
|
+
},
|
1075
|
+
angularDamping: (rb, value) => {
|
1076
|
+
rb.setAngularDamping(value);
|
1077
|
+
},
|
1078
|
+
dominanceGroup: (rb, value) => {
|
1079
|
+
rb.setDominanceGroup(value);
|
1080
|
+
},
|
1081
|
+
enabledRotations: (rb, [x, y, z]) => {
|
1082
|
+
rb.setEnabledRotations(x, y, z, true);
|
1083
|
+
},
|
1084
|
+
enabledTranslations: (rb, [x, y, z]) => {
|
1085
|
+
rb.setEnabledTranslations(x, y, z, true);
|
1086
|
+
},
|
1087
|
+
lockRotations: (rb, value) => {
|
1088
|
+
rb.lockRotations(value, true);
|
1089
|
+
},
|
1090
|
+
lockTranslations: (rb, value) => {
|
1091
|
+
rb.lockTranslations(value, true);
|
1092
|
+
},
|
1093
|
+
angularVelocity: (rb, [x, y, z]) => {
|
1094
|
+
rb.setAngvel({
|
1095
|
+
x,
|
1096
|
+
y,
|
1097
|
+
z
|
1098
|
+
}, true);
|
1099
|
+
},
|
1100
|
+
linearVelocity: (rb, [x, y, z]) => {
|
1101
|
+
rb.setLinvel({
|
1102
|
+
x,
|
1103
|
+
y,
|
1104
|
+
z
|
1105
|
+
}, true);
|
1106
|
+
},
|
1107
|
+
ccd: (rb, value) => {
|
1108
|
+
rb.enableCcd(value);
|
1109
|
+
},
|
1110
|
+
softCcdPrediction: (rb, value) => {
|
1111
|
+
rb.setSoftCcdPrediction(value);
|
1112
|
+
},
|
1113
|
+
userData: (rb, value) => {
|
1114
|
+
rb.userData = value;
|
1115
|
+
},
|
1116
|
+
type(rb, value) {
|
1117
|
+
rb.setBodyType(rigidBodyTypeFromString(value), true);
|
1118
|
+
},
|
1119
|
+
position: () => {},
|
1120
|
+
rotation: () => {},
|
1121
|
+
quaternion: () => {},
|
1122
|
+
scale: () => {}
|
1123
|
+
};
|
1124
|
+
const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
|
1125
|
+
const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
|
1126
|
+
if (!rigidBody) {
|
1127
|
+
return;
|
1128
|
+
}
|
1129
|
+
const state = states.get(rigidBody.handle);
|
1130
|
+
if (state) {
|
1131
|
+
if (updateTranslations) {
|
1132
|
+
state.object.updateWorldMatrix(true, false);
|
1133
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
1134
|
+
rigidBody.setTranslation(_position, false);
|
1135
|
+
rigidBody.setRotation(_rotation, false);
|
1136
|
+
}
|
1137
|
+
mutableRigidBodyOptionKeys.forEach(key => {
|
1138
|
+
if (key in options) {
|
1139
|
+
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
1140
|
+
}
|
1141
|
+
});
|
1142
|
+
}
|
1143
|
+
};
|
1144
|
+
const useUpdateRigidBodyOptions = (getRigidBody, props, states, updateTranslations = true) => {
|
1145
|
+
// TODO: Improve this, split each prop into its own effect
|
1146
|
+
const mutablePropsAsFlatArray = useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
1147
|
+
return vectorToTuple(props[key]);
|
1148
|
+
}), [props]);
|
1149
|
+
useEffect(() => {
|
1150
|
+
const rigidBody = getRigidBody();
|
1151
|
+
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
1152
|
+
}, mutablePropsAsFlatArray);
|
1153
|
+
};
|
1154
|
+
const useRigidBodyEvents = (getRigidBody, props, events) => {
|
1155
|
+
const {
|
1156
|
+
onWake,
|
1157
|
+
onSleep,
|
1158
|
+
onCollisionEnter,
|
1159
|
+
onCollisionExit,
|
1160
|
+
onIntersectionEnter,
|
1161
|
+
onIntersectionExit,
|
1162
|
+
onContactForce
|
1163
|
+
} = props;
|
1164
|
+
const eventHandlers = {
|
1165
|
+
onWake,
|
1166
|
+
onSleep,
|
1167
|
+
onCollisionEnter,
|
1168
|
+
onCollisionExit,
|
1169
|
+
onIntersectionEnter,
|
1170
|
+
onIntersectionExit,
|
1171
|
+
onContactForce
|
1172
|
+
};
|
1173
|
+
useEffect(() => {
|
1174
|
+
const rigidBody = getRigidBody();
|
1175
|
+
events.set(rigidBody.handle, eventHandlers);
|
1176
|
+
return () => {
|
1177
|
+
events.delete(rigidBody.handle);
|
1178
|
+
};
|
1179
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
1180
|
+
};
|
1181
|
+
|
1182
|
+
/**
|
1183
|
+
* Takes an object resembling a Vector3 and returs a Three.Vector3
|
1184
|
+
* @category Math helpers
|
1185
|
+
*/
|
1186
|
+
const vec3 = ({
|
1187
|
+
x,
|
1188
|
+
y,
|
1189
|
+
z
|
1190
|
+
} = {
|
1191
|
+
x: 0,
|
1192
|
+
y: 0,
|
1193
|
+
z: 0
|
1194
|
+
}) => {
|
1195
|
+
return new Vector3(x, y, z);
|
1196
|
+
};
|
1197
|
+
|
1198
|
+
/**
|
1199
|
+
* Takes an object resembling a Quaternion and returs a Three.Quaternion
|
1200
|
+
* @category Math helpers
|
1201
|
+
*/
|
1202
|
+
const quat = ({
|
1203
|
+
x,
|
1204
|
+
y,
|
1205
|
+
z,
|
1206
|
+
w
|
1207
|
+
} = {
|
1208
|
+
x: 0,
|
1209
|
+
y: 0,
|
1210
|
+
z: 0,
|
1211
|
+
w: 1
|
1212
|
+
}) => {
|
1213
|
+
return new Quaternion(x, y, z, w);
|
1214
|
+
};
|
1215
|
+
|
1216
|
+
/**
|
1217
|
+
* Takes an object resembling an Euler and returs a Three.Euler
|
1218
|
+
* @category Math helpers
|
1219
|
+
*/
|
1220
|
+
const euler = ({
|
1221
|
+
x,
|
1222
|
+
y,
|
1223
|
+
z
|
1224
|
+
} = {
|
1225
|
+
x: 0,
|
1226
|
+
y: 0,
|
1227
|
+
z: 0
|
1228
|
+
}) => {
|
1229
|
+
return new Euler(x, y, z);
|
1230
|
+
};
|
1231
|
+
|
1232
|
+
/**
|
1233
|
+
* A collider is a shape that can be attached to a rigid body to define its physical properties.
|
1234
|
+
* @internal
|
1235
|
+
*/
|
1236
|
+
const AnyCollider = /*#__PURE__*/memo(props => {
|
1237
|
+
const {
|
1238
|
+
children,
|
1239
|
+
position,
|
1240
|
+
rotation,
|
1241
|
+
quaternion,
|
1242
|
+
scale,
|
1243
|
+
name
|
1244
|
+
} = props;
|
1245
|
+
const {
|
1246
|
+
world,
|
1247
|
+
colliderEvents,
|
1248
|
+
colliderStates
|
1249
|
+
} = useRapier();
|
1250
|
+
const rigidBodyContext = useRigidBodyContext();
|
1251
|
+
const colliderRef = useForwardedRef(props.ref);
|
1252
|
+
const objectRef = useRef(null);
|
1253
|
+
|
1254
|
+
// We spread the props out here to make sure that the ref is updated when the props change.
|
1255
|
+
const immutablePropArray = immutableColliderOptions.flatMap(key =>
|
1256
|
+
// Array.isArray(props[key]) ? [...props[key]] : props[key]
|
1257
|
+
Array.isArray(props[key]) ? props[key] : [props[key]]);
|
1258
|
+
const getInstance = useImperativeInstance(() => {
|
1259
|
+
const worldScale = objectRef.current.getWorldScale(vec3());
|
1260
|
+
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
|
1261
|
+
if (typeof props.ref == "function") {
|
1262
|
+
props.ref(collider);
|
1263
|
+
}
|
1200
1264
|
colliderRef.current = collider;
|
1201
1265
|
return collider;
|
1202
1266
|
}, collider => {
|
@@ -1224,8 +1288,7 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
|
|
1224
1288
|
ref: objectRef,
|
1225
1289
|
name: name
|
1226
1290
|
}, children);
|
1227
|
-
})
|
1228
|
-
|
1291
|
+
});
|
1229
1292
|
/**
|
1230
1293
|
* A cuboid collider shape
|
1231
1294
|
* @category Colliders
|
@@ -1237,7 +1300,6 @@ const CuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1237
1300
|
}));
|
1238
1301
|
});
|
1239
1302
|
CuboidCollider.displayName = "CuboidCollider";
|
1240
|
-
|
1241
1303
|
/**
|
1242
1304
|
* A round cuboid collider shape
|
1243
1305
|
* @category Colliders
|
@@ -1247,7 +1309,6 @@ const RoundCuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__P
|
|
1247
1309
|
ref: ref
|
1248
1310
|
})));
|
1249
1311
|
RoundCuboidCollider.displayName = "RoundCuboidCollider";
|
1250
|
-
|
1251
1312
|
/**
|
1252
1313
|
* A ball collider shape
|
1253
1314
|
* @category Colliders
|
@@ -1257,7 +1318,6 @@ const BallCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/
|
|
1257
1318
|
ref: ref
|
1258
1319
|
})));
|
1259
1320
|
BallCollider.displayName = "BallCollider";
|
1260
|
-
|
1261
1321
|
/**
|
1262
1322
|
* A capsule collider shape
|
1263
1323
|
* @category Colliders
|
@@ -1267,7 +1327,6 @@ const CapsuleCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE_
|
|
1267
1327
|
ref: ref
|
1268
1328
|
})));
|
1269
1329
|
CapsuleCollider.displayName = "CapsuleCollider";
|
1270
|
-
|
1271
1330
|
/**
|
1272
1331
|
* A heightfield collider shape
|
1273
1332
|
* @category Colliders
|
@@ -1277,7 +1336,6 @@ const HeightfieldCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__P
|
|
1277
1336
|
ref: ref
|
1278
1337
|
})));
|
1279
1338
|
HeightfieldCollider.displayName = "HeightfieldCollider";
|
1280
|
-
|
1281
1339
|
/**
|
1282
1340
|
* A trimesh collider shape
|
1283
1341
|
* @category Colliders
|
@@ -1287,7 +1345,6 @@ const TrimeshCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE_
|
|
1287
1345
|
ref: ref
|
1288
1346
|
})));
|
1289
1347
|
TrimeshCollider.displayName = "TrimeshCollider";
|
1290
|
-
|
1291
1348
|
/**
|
1292
1349
|
* A cone collider shape
|
1293
1350
|
* @category Colliders
|
@@ -1297,7 +1354,6 @@ const ConeCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/
|
|
1297
1354
|
ref: ref
|
1298
1355
|
})));
|
1299
1356
|
ConeCollider.displayName = "ConeCollider";
|
1300
|
-
|
1301
1357
|
/**
|
1302
1358
|
* A round cylinder collider shape
|
1303
1359
|
* @category Colliders
|
@@ -1307,7 +1363,6 @@ const RoundConeCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PUR
|
|
1307
1363
|
ref: ref
|
1308
1364
|
})));
|
1309
1365
|
RoundConeCollider.displayName = "RoundConeCollider";
|
1310
|
-
|
1311
1366
|
/**
|
1312
1367
|
* A cylinder collider shape
|
1313
1368
|
* @category Colliders
|
@@ -1317,7 +1372,6 @@ const CylinderCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE
|
|
1317
1372
|
ref: ref
|
1318
1373
|
})));
|
1319
1374
|
CylinderCollider.displayName = "CylinderCollider";
|
1320
|
-
|
1321
1375
|
/**
|
1322
1376
|
* A round cylinder collider shape
|
1323
1377
|
* @category Colliders
|
@@ -1327,7 +1381,6 @@ const RoundCylinderCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#_
|
|
1327
1381
|
ref: ref
|
1328
1382
|
})));
|
1329
1383
|
CylinderCollider.displayName = "RoundCylinderCollider";
|
1330
|
-
|
1331
1384
|
/**
|
1332
1385
|
* A convex hull collider shape
|
1333
1386
|
* @category Colliders
|
@@ -1338,187 +1391,27 @@ const ConvexHullCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PU
|
|
1338
1391
|
})));
|
1339
1392
|
ConvexHullCollider.displayName = "ConvexHullCollider";
|
1340
1393
|
|
1341
|
-
const
|
1342
|
-
var _options$canSleep;
|
1343
|
-
|
1344
|
-
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
1345
|
-
const desc = new RigidBodyDesc(type); // Apply immutable options
|
1346
|
-
|
1347
|
-
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
1348
|
-
return desc;
|
1349
|
-
};
|
1350
|
-
const createRigidBodyState = ({
|
1351
|
-
rigidBody,
|
1352
|
-
object,
|
1353
|
-
setMatrix,
|
1354
|
-
getMatrix,
|
1355
|
-
worldScale,
|
1356
|
-
meshType: _meshType = "mesh"
|
1357
|
-
}) => {
|
1358
|
-
object.updateWorldMatrix(true, false);
|
1359
|
-
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
1360
|
-
return {
|
1361
|
-
object,
|
1362
|
-
rigidBody,
|
1363
|
-
invertedWorldMatrix,
|
1364
|
-
setMatrix: setMatrix ? setMatrix : matrix => {
|
1365
|
-
object.matrix.copy(matrix);
|
1366
|
-
},
|
1367
|
-
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
1368
|
-
scale: worldScale || object.getWorldScale(_scale).clone(),
|
1369
|
-
isSleeping: false,
|
1370
|
-
meshType: _meshType
|
1371
|
-
};
|
1372
|
-
};
|
1373
|
-
const immutableRigidBodyOptions = ["args", "colliders", "canSleep"];
|
1374
|
-
const mutableRigidBodyOptions = {
|
1375
|
-
gravityScale: (rb, value) => {
|
1376
|
-
rb.setGravityScale(value, true);
|
1377
|
-
},
|
1378
|
-
|
1379
|
-
additionalSolverIterations(rb, value) {
|
1380
|
-
rb.setAdditionalSolverIterations(value);
|
1381
|
-
},
|
1382
|
-
|
1383
|
-
linearDamping: (rb, value) => {
|
1384
|
-
rb.setLinearDamping(value);
|
1385
|
-
},
|
1386
|
-
angularDamping: (rb, value) => {
|
1387
|
-
rb.setAngularDamping(value);
|
1388
|
-
},
|
1389
|
-
dominanceGroup: (rb, value) => {
|
1390
|
-
rb.setDominanceGroup(value);
|
1391
|
-
},
|
1392
|
-
enabledRotations: (rb, [x, y, z]) => {
|
1393
|
-
rb.setEnabledRotations(x, y, z, true);
|
1394
|
-
},
|
1395
|
-
enabledTranslations: (rb, [x, y, z]) => {
|
1396
|
-
rb.setEnabledTranslations(x, y, z, true);
|
1397
|
-
},
|
1398
|
-
lockRotations: (rb, value) => {
|
1399
|
-
rb.lockRotations(value, true);
|
1400
|
-
},
|
1401
|
-
lockTranslations: (rb, value) => {
|
1402
|
-
rb.lockTranslations(value, true);
|
1403
|
-
},
|
1404
|
-
angularVelocity: (rb, [x, y, z]) => {
|
1405
|
-
rb.setAngvel({
|
1406
|
-
x,
|
1407
|
-
y,
|
1408
|
-
z
|
1409
|
-
}, true);
|
1410
|
-
},
|
1411
|
-
linearVelocity: (rb, [x, y, z]) => {
|
1412
|
-
rb.setLinvel({
|
1413
|
-
x,
|
1414
|
-
y,
|
1415
|
-
z
|
1416
|
-
}, true);
|
1417
|
-
},
|
1418
|
-
ccd: (rb, value) => {
|
1419
|
-
rb.enableCcd(value);
|
1420
|
-
},
|
1421
|
-
softCcdPrediction: (rb, value) => {
|
1422
|
-
rb.setSoftCcdPrediction(value);
|
1423
|
-
},
|
1424
|
-
userData: (rb, value) => {
|
1425
|
-
rb.userData = value;
|
1426
|
-
},
|
1427
|
-
|
1428
|
-
type(rb, value) {
|
1429
|
-
rb.setBodyType(rigidBodyTypeFromString(value), true);
|
1430
|
-
},
|
1431
|
-
|
1432
|
-
position: () => {},
|
1433
|
-
rotation: () => {},
|
1434
|
-
quaternion: () => {},
|
1435
|
-
scale: () => {}
|
1436
|
-
};
|
1437
|
-
const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
|
1438
|
-
const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
|
1439
|
-
if (!rigidBody) {
|
1440
|
-
return;
|
1441
|
-
}
|
1442
|
-
|
1443
|
-
const state = states.get(rigidBody.handle);
|
1444
|
-
|
1445
|
-
if (state) {
|
1446
|
-
if (updateTranslations) {
|
1447
|
-
state.object.updateWorldMatrix(true, false);
|
1448
|
-
|
1449
|
-
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
1450
|
-
|
1451
|
-
rigidBody.setTranslation(_position, false);
|
1452
|
-
rigidBody.setRotation(_rotation, false);
|
1453
|
-
}
|
1454
|
-
|
1455
|
-
mutableRigidBodyOptionKeys.forEach(key => {
|
1456
|
-
if (key in options) {
|
1457
|
-
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
1458
|
-
}
|
1459
|
-
});
|
1460
|
-
}
|
1461
|
-
};
|
1462
|
-
const useUpdateRigidBodyOptions = (getRigidBody, props, states, updateTranslations = true) => {
|
1463
|
-
// TODO: Improve this, split each prop into its own effect
|
1464
|
-
const mutablePropsAsFlatArray = useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
1465
|
-
return vectorToTuple(props[key]);
|
1466
|
-
}), [props]);
|
1467
|
-
useEffect(() => {
|
1468
|
-
const rigidBody = getRigidBody();
|
1469
|
-
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
1470
|
-
}, mutablePropsAsFlatArray);
|
1471
|
-
};
|
1472
|
-
const useRigidBodyEvents = (getRigidBody, props, events) => {
|
1473
|
-
const {
|
1474
|
-
onWake,
|
1475
|
-
onSleep,
|
1476
|
-
onCollisionEnter,
|
1477
|
-
onCollisionExit,
|
1478
|
-
onIntersectionEnter,
|
1479
|
-
onIntersectionExit,
|
1480
|
-
onContactForce
|
1481
|
-
} = props;
|
1482
|
-
const eventHandlers = {
|
1483
|
-
onWake,
|
1484
|
-
onSleep,
|
1485
|
-
onCollisionEnter,
|
1486
|
-
onCollisionExit,
|
1487
|
-
onIntersectionEnter,
|
1488
|
-
onIntersectionExit,
|
1489
|
-
onContactForce
|
1490
|
-
};
|
1491
|
-
useEffect(() => {
|
1492
|
-
const rigidBody = getRigidBody();
|
1493
|
-
events.set(rigidBody.handle, eventHandlers);
|
1494
|
-
return () => {
|
1495
|
-
events.delete(rigidBody.handle);
|
1496
|
-
};
|
1497
|
-
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
1498
|
-
};
|
1499
|
-
|
1500
|
-
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
|
1394
|
+
const _excluded$1 = ["ref", "children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
|
1501
1395
|
const RigidBodyContext = /*#__PURE__*/createContext(undefined);
|
1502
1396
|
const useRigidBodyContext = () => useContext(RigidBodyContext);
|
1503
|
-
|
1504
1397
|
/**
|
1505
1398
|
* A rigid body is a physical object that can be simulated by the physics engine.
|
1506
1399
|
* @category Components
|
1507
1400
|
*/
|
1508
|
-
const RigidBody = /*#__PURE__*/memo(
|
1401
|
+
const RigidBody = /*#__PURE__*/memo(props => {
|
1509
1402
|
const {
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1403
|
+
ref,
|
1404
|
+
children,
|
1405
|
+
type,
|
1406
|
+
position,
|
1407
|
+
rotation,
|
1408
|
+
scale,
|
1409
|
+
quaternion,
|
1410
|
+
transformState
|
1411
|
+
} = props,
|
1412
|
+
objectProps = _objectWithoutProperties(props, _excluded$1);
|
1520
1413
|
const objectRef = useRef(null);
|
1521
|
-
const rigidBodyRef = useForwardedRef(
|
1414
|
+
const rigidBodyRef = useForwardedRef(ref);
|
1522
1415
|
const {
|
1523
1416
|
world,
|
1524
1417
|
rigidBodyStates,
|
@@ -1533,24 +1426,24 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
|
|
1533
1426
|
const immutablePropArray = immutableRigidBodyOptions.flatMap(key => {
|
1534
1427
|
return Array.isArray(mergedOptions[key]) ? [...mergedOptions[key]] : mergedOptions[key];
|
1535
1428
|
});
|
1536
|
-
const childColliderProps = useChildColliderProps(objectRef, mergedOptions);
|
1429
|
+
const childColliderProps = useChildColliderProps(objectRef, mergedOptions);
|
1537
1430
|
|
1431
|
+
// Provide a way to eagerly create rigidbody
|
1538
1432
|
const getRigidBody = useImperativeInstance(() => {
|
1539
1433
|
const desc = rigidBodyDescFromOptions(mergedOptions);
|
1540
1434
|
const rigidBody = world.createRigidBody(desc);
|
1541
|
-
|
1542
|
-
|
1543
|
-
forwardedRef(rigidBody);
|
1435
|
+
if (typeof ref === "function") {
|
1436
|
+
ref(rigidBody);
|
1544
1437
|
}
|
1545
|
-
|
1546
1438
|
rigidBodyRef.current = rigidBody;
|
1547
1439
|
return rigidBody;
|
1548
1440
|
}, rigidBody => {
|
1549
1441
|
if (world.getRigidBody(rigidBody.handle)) {
|
1550
1442
|
world.removeRigidBody(rigidBody);
|
1551
1443
|
}
|
1552
|
-
}, immutablePropArray);
|
1444
|
+
}, immutablePropArray);
|
1553
1445
|
|
1446
|
+
// Only provide a object state after the ref has been set
|
1554
1447
|
useEffect(() => {
|
1555
1448
|
const rigidBody = getRigidBody();
|
1556
1449
|
const state = createRigidBodyState({
|
@@ -1583,7 +1476,7 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
|
|
1583
1476
|
}), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
|
1584
1477
|
key: index
|
1585
1478
|
}, colliderProps)))));
|
1586
|
-
})
|
1479
|
+
});
|
1587
1480
|
RigidBody.displayName = "RigidBody";
|
1588
1481
|
|
1589
1482
|
/**
|
@@ -1620,52 +1513,52 @@ const MeshCollider = /*#__PURE__*/memo(props => {
|
|
1620
1513
|
});
|
1621
1514
|
MeshCollider.displayName = "MeshCollider";
|
1622
1515
|
|
1623
|
-
const _excluded = ["
|
1624
|
-
|
1625
|
-
|
1516
|
+
const _excluded = ["ref"],
|
1517
|
+
_excluded2 = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
|
1518
|
+
const InstancedRigidBodies = /*#__PURE__*/memo(_ref => {
|
1519
|
+
let {
|
1520
|
+
ref
|
1521
|
+
} = _ref,
|
1522
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
1523
|
+
const rigidBodiesRef = useForwardedRef(ref, []);
|
1626
1524
|
const objectRef = useRef(null);
|
1627
1525
|
const instanceWrapperRef = useRef(null);
|
1628
|
-
|
1629
1526
|
const {
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1527
|
+
// instanced props
|
1528
|
+
children,
|
1529
|
+
instances,
|
1530
|
+
colliderNodes = [],
|
1531
|
+
// wrapper object props
|
1532
|
+
position,
|
1533
|
+
rotation,
|
1534
|
+
quaternion,
|
1535
|
+
scale
|
1536
|
+
|
1537
|
+
// rigid body specific props, and r3f-object props
|
1538
|
+
} = props,
|
1539
|
+
rigidBodyProps = _objectWithoutProperties(props, _excluded2);
|
1642
1540
|
const childColliderProps = useChildColliderProps(objectRef, _objectSpread2(_objectSpread2({}, props), {}, {
|
1643
1541
|
children: undefined
|
1644
1542
|
}));
|
1645
|
-
|
1646
1543
|
const getInstancedMesh = () => {
|
1647
1544
|
const firstChild = instanceWrapperRef.current.children[0];
|
1648
|
-
|
1649
1545
|
if (firstChild && "isInstancedMesh" in firstChild) {
|
1650
1546
|
return firstChild;
|
1651
1547
|
}
|
1652
|
-
|
1653
1548
|
return undefined;
|
1654
1549
|
};
|
1655
|
-
|
1656
1550
|
useEffect(() => {
|
1657
1551
|
const instancedMesh = getInstancedMesh();
|
1658
|
-
|
1659
1552
|
if (instancedMesh) {
|
1660
1553
|
instancedMesh.instanceMatrix.setUsage(DynamicDrawUsage);
|
1661
1554
|
} else {
|
1662
1555
|
console.warn("InstancedRigidBodies expects exactly one child, which must be an InstancedMesh");
|
1663
1556
|
}
|
1664
|
-
}, []);
|
1557
|
+
}, []);
|
1665
1558
|
|
1559
|
+
// Update the RigidBodyStates whenever the instances change
|
1666
1560
|
const applyInstancedState = (state, index) => {
|
1667
1561
|
const instancedMesh = getInstancedMesh();
|
1668
|
-
|
1669
1562
|
if (instancedMesh) {
|
1670
1563
|
return _objectSpread2(_objectSpread2({}, state), {}, {
|
1671
1564
|
getMatrix: matrix => {
|
@@ -1679,10 +1572,8 @@ const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props,
|
|
1679
1572
|
meshType: "instancedMesh"
|
1680
1573
|
});
|
1681
1574
|
}
|
1682
|
-
|
1683
1575
|
return state;
|
1684
1576
|
};
|
1685
|
-
|
1686
1577
|
return /*#__PURE__*/React.createElement("object3D", _extends({
|
1687
1578
|
ref: objectRef
|
1688
1579
|
}, rigidBodyProps, {
|
@@ -1693,25 +1584,26 @@ const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props,
|
|
1693
1584
|
}), /*#__PURE__*/React.createElement("object3D", {
|
1694
1585
|
ref: instanceWrapperRef
|
1695
1586
|
}, children), instances === null || instances === void 0 ? void 0 : instances.map((instance, index) => /*#__PURE__*/React.createElement(RigidBody, _extends({}, rigidBodyProps, instance, {
|
1696
|
-
ref: body =>
|
1587
|
+
ref: body => {
|
1588
|
+
rigidBodiesRef.current[index] = body;
|
1589
|
+
},
|
1697
1590
|
transformState: state => applyInstancedState(state, index)
|
1698
1591
|
}), /*#__PURE__*/React.createElement(React.Fragment, null, colliderNodes.map((node, index) => /*#__PURE__*/React.createElement(Fragment, {
|
1699
1592
|
key: index
|
1700
1593
|
}, node)), childColliderProps.map((colliderProps, colliderIndex) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
|
1701
1594
|
key: colliderIndex
|
1702
1595
|
}, colliderProps)))))));
|
1703
|
-
})
|
1596
|
+
});
|
1704
1597
|
InstancedRigidBodies.displayName = "InstancedRigidBodies";
|
1705
1598
|
|
1706
1599
|
/**
|
1707
1600
|
* @internal
|
1708
1601
|
*/
|
1709
|
-
|
1710
1602
|
const useImpulseJoint = (body1, body2, params) => {
|
1711
1603
|
const {
|
1712
1604
|
world
|
1713
1605
|
} = useRapier();
|
1714
|
-
const jointRef = useRef();
|
1606
|
+
const jointRef = useRef(undefined);
|
1715
1607
|
useImperativeInstance(() => {
|
1716
1608
|
if (body1.current && body2.current) {
|
1717
1609
|
const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
|
@@ -1721,7 +1613,6 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1721
1613
|
}, joint => {
|
1722
1614
|
if (joint) {
|
1723
1615
|
jointRef.current = undefined;
|
1724
|
-
|
1725
1616
|
if (world.getImpulseJoint(joint.handle)) {
|
1726
1617
|
world.removeImpulseJoint(joint, true);
|
1727
1618
|
}
|
@@ -1729,6 +1620,7 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1729
1620
|
}, []);
|
1730
1621
|
return jointRef;
|
1731
1622
|
};
|
1623
|
+
|
1732
1624
|
/**
|
1733
1625
|
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
1734
1626
|
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
@@ -1736,13 +1628,13 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1736
1628
|
*
|
1737
1629
|
* @category Hooks - Joints
|
1738
1630
|
*/
|
1739
|
-
|
1740
1631
|
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
1741
1632
|
const {
|
1742
1633
|
rapier
|
1743
1634
|
} = useRapier();
|
1744
1635
|
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vector3ToRapierVector(body1Anchor), quaternionToRapierQuaternion(body1LocalFrame), vector3ToRapierVector(body2Anchor), quaternionToRapierQuaternion(body2LocalFrame)));
|
1745
1636
|
};
|
1637
|
+
|
1746
1638
|
/**
|
1747
1639
|
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
1748
1640
|
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
@@ -1751,13 +1643,13 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
|
|
1751
1643
|
*
|
1752
1644
|
* @category Hooks - Joints
|
1753
1645
|
*/
|
1754
|
-
|
1755
1646
|
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
1756
1647
|
const {
|
1757
1648
|
rapier
|
1758
1649
|
} = useRapier();
|
1759
1650
|
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vector3ToRapierVector(body1Anchor), vector3ToRapierVector(body2Anchor)));
|
1760
1651
|
};
|
1652
|
+
|
1761
1653
|
/**
|
1762
1654
|
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
1763
1655
|
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
@@ -1765,20 +1657,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
1765
1657
|
*
|
1766
1658
|
* @category Hooks - Joints
|
1767
1659
|
*/
|
1768
|
-
|
1769
1660
|
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
1770
1661
|
const {
|
1771
1662
|
rapier
|
1772
1663
|
} = useRapier();
|
1773
1664
|
const params = rapier.JointData.revolute(vector3ToRapierVector(body1Anchor), vector3ToRapierVector(body2Anchor), vector3ToRapierVector(axis));
|
1774
|
-
|
1775
1665
|
if (limits) {
|
1776
1666
|
params.limitsEnabled = true;
|
1777
1667
|
params.limits = limits;
|
1778
1668
|
}
|
1779
|
-
|
1780
1669
|
return useImpulseJoint(body1, body2, params);
|
1781
1670
|
};
|
1671
|
+
|
1782
1672
|
/**
|
1783
1673
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
1784
1674
|
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
@@ -1786,25 +1676,22 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]
|
|
1786
1676
|
*
|
1787
1677
|
* @category Hooks - Joints
|
1788
1678
|
*/
|
1789
|
-
|
1790
1679
|
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
1791
1680
|
const {
|
1792
1681
|
rapier
|
1793
1682
|
} = useRapier();
|
1794
1683
|
const params = rapier.JointData.prismatic(vector3ToRapierVector(body1Anchor), vector3ToRapierVector(body2Anchor), vector3ToRapierVector(axis));
|
1795
|
-
|
1796
1684
|
if (limits) {
|
1797
1685
|
params.limitsEnabled = true;
|
1798
1686
|
params.limits = limits;
|
1799
1687
|
}
|
1800
|
-
|
1801
1688
|
return useImpulseJoint(body1, body2, params);
|
1802
1689
|
};
|
1690
|
+
|
1803
1691
|
/**
|
1804
1692
|
* The rope joint limits the max distance between two bodies.
|
1805
1693
|
* @category Hooks - Joints
|
1806
1694
|
*/
|
1807
|
-
|
1808
1695
|
const useRopeJoint = (body1, body2, [body1Anchor, body2Anchor, length]) => {
|
1809
1696
|
const {
|
1810
1697
|
rapier
|
@@ -1814,11 +1701,11 @@ const useRopeJoint = (body1, body2, [body1Anchor, body2Anchor, length]) => {
|
|
1814
1701
|
const params = rapier.JointData.rope(length, vBody1Anchor, vBody2Anchor);
|
1815
1702
|
return useImpulseJoint(body1, body2, params);
|
1816
1703
|
};
|
1704
|
+
|
1817
1705
|
/**
|
1818
1706
|
* The spring joint applies a force proportional to the distance between two objects.
|
1819
1707
|
* @category Hooks - Joints
|
1820
1708
|
*/
|
1821
|
-
|
1822
1709
|
const useSpringJoint = (body1, body2, [body1Anchor, body2Anchor, restLength, stiffness, damping]) => {
|
1823
1710
|
const {
|
1824
1711
|
rapier
|
@@ -1862,7 +1749,6 @@ const useSpringJoint = (body1, body2, [body1Anchor, body2Anchor, restLength, sti
|
|
1862
1749
|
* @returns An InteractionGroup bitmask.
|
1863
1750
|
*/
|
1864
1751
|
const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
|
1865
|
-
|
1866
1752
|
const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
|
1867
1753
|
|
1868
1754
|
export { AnyCollider, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundConeCollider, RoundCuboidCollider, RoundCylinderCollider, TrimeshCollider, euler, interactionGroups, quat, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRopeJoint, useSphericalJoint, useSpringJoint, vec3 };
|