@react-three/rapier 0.9.0 → 0.10.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/Attractor.d.ts +51 -0
- package/dist/declarations/src/MeshCollider.d.ts +4 -1
- package/dist/declarations/src/Physics.d.ts +33 -4
- package/dist/declarations/src/index.d.ts +2 -1
- package/dist/declarations/src/{bitmasks.d.ts → interaction-groups.d.ts} +0 -0
- package/dist/declarations/src/types.d.ts +20 -6
- package/dist/react-three-rapier.cjs.dev.js +1055 -917
- package/dist/react-three-rapier.cjs.prod.js +1055 -917
- package/dist/react-three-rapier.esm.js +1059 -922
- package/package.json +1 -1
- package/readme.md +112 -47
@@ -31,6 +31,47 @@ function _interopNamespace(e) {
|
|
31
31
|
|
32
32
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
33
33
|
|
34
|
+
function _defineProperty(obj, key, value) {
|
35
|
+
if (key in obj) {
|
36
|
+
Object.defineProperty(obj, key, {
|
37
|
+
value: value,
|
38
|
+
enumerable: true,
|
39
|
+
configurable: true,
|
40
|
+
writable: true
|
41
|
+
});
|
42
|
+
} else {
|
43
|
+
obj[key] = value;
|
44
|
+
}
|
45
|
+
|
46
|
+
return obj;
|
47
|
+
}
|
48
|
+
|
49
|
+
function ownKeys(object, enumerableOnly) {
|
50
|
+
var keys = Object.keys(object);
|
51
|
+
|
52
|
+
if (Object.getOwnPropertySymbols) {
|
53
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
54
|
+
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
55
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
56
|
+
})), keys.push.apply(keys, symbols);
|
57
|
+
}
|
58
|
+
|
59
|
+
return keys;
|
60
|
+
}
|
61
|
+
|
62
|
+
function _objectSpread2(target) {
|
63
|
+
for (var i = 1; i < arguments.length; i++) {
|
64
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
65
|
+
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
|
66
|
+
_defineProperty(target, key, source[key]);
|
67
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
|
68
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
69
|
+
});
|
70
|
+
}
|
71
|
+
|
72
|
+
return target;
|
73
|
+
}
|
74
|
+
|
34
75
|
const _quaternion = new three.Quaternion();
|
35
76
|
new three.Euler();
|
36
77
|
const _vector3 = new three.Vector3();
|
@@ -238,1055 +279,1070 @@ const createJointApi = ref => {
|
|
238
279
|
};
|
239
280
|
};
|
240
281
|
|
241
|
-
const
|
282
|
+
const scaleColliderArgs = (shape, args, scale) => {
|
283
|
+
const newArgs = args.slice(); // Heightfield uses a vector
|
242
284
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
285
|
+
if (shape === "heightfield") {
|
286
|
+
const s = newArgs[3];
|
287
|
+
s.x *= scale.x;
|
288
|
+
s.x *= scale.y;
|
289
|
+
s.x *= scale.z;
|
290
|
+
return newArgs;
|
291
|
+
} // Trimesh and convex scale the vertices
|
248
292
|
|
249
|
-
const Physics = ({
|
250
|
-
colliders: _colliders = "cuboid",
|
251
|
-
gravity: _gravity = [0, -9.81, 0],
|
252
|
-
children,
|
253
|
-
timeStep: _timeStep = 1 / 60,
|
254
|
-
paused: _paused = false,
|
255
|
-
updatePriority,
|
256
|
-
interpolate: _interpolate = true
|
257
|
-
}) => {
|
258
|
-
const rapier = useAsset.useAsset(importRapier);
|
259
|
-
const worldRef = React.useRef();
|
260
|
-
const getWorldRef = React.useRef(() => {
|
261
|
-
if (!worldRef.current) {
|
262
|
-
const world = new rapier.World(vectorArrayToVector3(_gravity));
|
263
|
-
worldRef.current = world;
|
264
|
-
}
|
265
293
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
const [rigidBodyEvents] = React.useState(() => new Map());
|
271
|
-
const [colliderEvents] = React.useState(() => new Map());
|
272
|
-
const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
|
294
|
+
if (shape === "trimesh" || shape === "convexHull") {
|
295
|
+
newArgs[0] = scaleVertices(newArgs[0], scale);
|
296
|
+
return newArgs;
|
297
|
+
} // Prepfill with some extra
|
273
298
|
|
274
|
-
React.useEffect(() => {
|
275
|
-
const world = getWorldRef.current();
|
276
|
-
return () => {
|
277
|
-
if (world) {
|
278
|
-
world.free();
|
279
|
-
worldRef.current = undefined;
|
280
|
-
}
|
281
|
-
};
|
282
|
-
}, []); // Update gravity
|
283
299
|
|
284
|
-
|
285
|
-
|
300
|
+
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
301
|
+
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
302
|
+
};
|
303
|
+
const createColliderFromOptions = (options, world, scale, rigidBody) => {
|
304
|
+
const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
|
286
305
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
const [steppingState] = React.useState({
|
292
|
-
previousState: {},
|
293
|
-
accumulator: 0
|
294
|
-
});
|
295
|
-
/* Check if the timestep is supposed to be variable. We'll do this here
|
296
|
-
once so we don't have to string-check every frame. */
|
306
|
+
const desc = rapier3dCompat.ColliderDesc[options.shape](...scaledArgs);
|
307
|
+
return world.createCollider(desc, rigidBody);
|
308
|
+
};
|
309
|
+
const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
|
297
310
|
|
298
|
-
|
299
|
-
|
300
|
-
|
311
|
+
const setColliderMassOptions = (collider, options) => {
|
312
|
+
if (options.density !== undefined) {
|
313
|
+
if (options.mass !== undefined || options.massProperties !== undefined) {
|
314
|
+
throw new Error(massPropertiesConflictError);
|
315
|
+
}
|
301
316
|
|
302
|
-
|
303
|
-
|
317
|
+
collider.setDensity(options.density);
|
318
|
+
return;
|
319
|
+
}
|
304
320
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
|
309
|
-
const rigidBody = rigidBodyHandle ? world.getRigidBody(rigidBodyHandle) : undefined;
|
310
|
-
const rbEvents = rigidBody && rigidBodyHandle ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
|
311
|
-
const rigidBodyState = rigidBodyHandle ? rigidBodyStates.get(rigidBodyHandle) : undefined;
|
312
|
-
return {
|
313
|
-
collider: {
|
314
|
-
object: collider,
|
315
|
-
events: colEvents,
|
316
|
-
state: colliderState
|
317
|
-
},
|
318
|
-
rigidBody: {
|
319
|
-
object: rigidBody,
|
320
|
-
events: rbEvents,
|
321
|
-
state: rigidBodyState
|
322
|
-
}
|
323
|
-
};
|
321
|
+
if (options.mass !== undefined) {
|
322
|
+
if (options.massProperties !== undefined) {
|
323
|
+
throw new Error(massPropertiesConflictError);
|
324
324
|
}
|
325
|
-
}, []);
|
326
|
-
fiber.useFrame((_, dt) => {
|
327
|
-
const world = worldRef.current;
|
328
|
-
if (!world) return;
|
329
|
-
/**
|
330
|
-
* Fixed timeStep simulation progression
|
331
|
-
* @see https://gafferongames.com/post/fix_your_timestep/
|
332
|
-
*/
|
333
325
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
world.timestep = clampedDelta;
|
338
|
-
if (!_paused) world.step(eventQueue);
|
339
|
-
} else {
|
340
|
-
world.timestep = _timeStep; // don't step time forwards if paused
|
341
|
-
// Increase accumulator
|
326
|
+
collider.setMass(options.mass);
|
327
|
+
return;
|
328
|
+
}
|
342
329
|
|
343
|
-
|
330
|
+
if (options.massProperties !== undefined) {
|
331
|
+
collider.setMassProperties(options.massProperties.mass, options.massProperties.centerOfMass, options.massProperties.principalAngularInertia, options.massProperties.angularInertiaLocalFrame);
|
332
|
+
}
|
333
|
+
};
|
344
334
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
335
|
+
const mutableColliderOptions = {
|
336
|
+
sensor: (collider, value) => {
|
337
|
+
collider.setSensor(value);
|
338
|
+
},
|
339
|
+
collisionGroups: (collider, value) => {
|
340
|
+
collider.setCollisionGroups(value);
|
341
|
+
},
|
342
|
+
solverGroups: (collider, value) => {
|
343
|
+
collider.setSolverGroups(value);
|
344
|
+
},
|
345
|
+
friction: (collider, value) => {
|
346
|
+
collider.setFriction(value);
|
347
|
+
},
|
348
|
+
frictionCombineRule: (collider, value) => {
|
349
|
+
collider.setFrictionCombineRule(value);
|
350
|
+
},
|
351
|
+
restitution: (collider, value) => {
|
352
|
+
collider.setRestitution(value);
|
353
|
+
},
|
354
|
+
restitutionCombineRule: (collider, value) => {
|
355
|
+
collider.setRestitutionCombineRule(value);
|
356
|
+
},
|
357
|
+
// To make sure the options all mutalbe options are listed
|
358
|
+
quaternion: () => {},
|
359
|
+
position: () => {},
|
360
|
+
rotation: () => {},
|
361
|
+
scale: () => {}
|
362
|
+
};
|
363
|
+
const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
|
364
|
+
const setColliderOptions = (collider, options, states) => {
|
365
|
+
const state = states.get(collider.handle);
|
364
366
|
|
365
|
-
|
367
|
+
if (state) {
|
368
|
+
var _state$worldParent;
|
366
369
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
+
// Update collider position based on the object's position
|
371
|
+
const parentWorldScale = state.object.parent.getWorldScale(_vector3);
|
372
|
+
const parentInvertedWorldMatrix = (_state$worldParent = state.worldParent) === null || _state$worldParent === void 0 ? void 0 : _state$worldParent.matrixWorld.clone().invert();
|
373
|
+
state.object.updateWorldMatrix(true, false);
|
370
374
|
|
371
|
-
|
372
|
-
if (rigidBody.isSleeping() && !state.isSleeping) {
|
373
|
-
var _events$onSleep;
|
375
|
+
_matrix4.copy(state.object.matrixWorld);
|
374
376
|
|
375
|
-
|
376
|
-
|
377
|
+
if (parentInvertedWorldMatrix) {
|
378
|
+
_matrix4.premultiply(parentInvertedWorldMatrix);
|
379
|
+
}
|
377
380
|
|
378
|
-
|
379
|
-
var _events$onWake;
|
381
|
+
_matrix4.decompose(_position, _rotation, _scale);
|
380
382
|
|
381
|
-
|
382
|
-
|
383
|
+
if (collider.parent()) {
|
384
|
+
collider.setTranslationWrtParent({
|
385
|
+
x: _position.x * parentWorldScale.x,
|
386
|
+
y: _position.y * parentWorldScale.y,
|
387
|
+
z: _position.z * parentWorldScale.z
|
388
|
+
});
|
389
|
+
collider.setRotationWrtParent(_rotation);
|
390
|
+
} else {
|
391
|
+
collider.setTranslation({
|
392
|
+
x: _position.x * parentWorldScale.x,
|
393
|
+
y: _position.y * parentWorldScale.y,
|
394
|
+
z: _position.z * parentWorldScale.z
|
395
|
+
});
|
396
|
+
collider.setRotation(_rotation);
|
397
|
+
}
|
383
398
|
|
384
|
-
|
399
|
+
mutableColliderOptionKeys.forEach(key => {
|
400
|
+
if (key in options) {
|
401
|
+
const option = options[key];
|
402
|
+
mutableColliderOptions[key](collider, // @ts-ignore Option does not want to fit into the function, but it will
|
403
|
+
option, options);
|
385
404
|
}
|
405
|
+
}); // handle mass separately, because the assignments
|
406
|
+
// are exclusive.
|
386
407
|
|
387
|
-
|
388
|
-
|
389
|
-
|
408
|
+
setColliderMassOptions(collider, options);
|
409
|
+
}
|
410
|
+
};
|
411
|
+
const useUpdateColliderOptions = (collidersRef, props, states) => {
|
412
|
+
// TODO: Improve this, split each prop into its own effect
|
413
|
+
const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
|
414
|
+
return vectorToTuple(props[key]);
|
415
|
+
}), [props]);
|
416
|
+
React.useEffect(() => {
|
417
|
+
collidersRef.current.forEach(collider => {
|
418
|
+
setColliderOptions(collider, props, states);
|
419
|
+
});
|
420
|
+
}, mutablePropsAsFlatArray);
|
421
|
+
};
|
390
422
|
|
391
|
-
|
392
|
-
|
393
|
-
|
423
|
+
const isChildOfMeshCollider = child => {
|
424
|
+
let flag = false;
|
425
|
+
child.traverseAncestors(a => {
|
426
|
+
if (a.userData.r3RapierType === "MeshCollider") flag = true;
|
427
|
+
});
|
428
|
+
return flag;
|
429
|
+
};
|
394
430
|
|
395
|
-
|
396
|
-
|
397
|
-
|
431
|
+
const createColliderState = (collider, object, rigidBodyObject) => {
|
432
|
+
return {
|
433
|
+
collider,
|
434
|
+
worldParent: rigidBodyObject || undefined,
|
435
|
+
object
|
436
|
+
};
|
437
|
+
};
|
438
|
+
const autoColliderMap = {
|
439
|
+
cuboid: "cuboid",
|
440
|
+
ball: "ball",
|
441
|
+
hull: "convexHull",
|
442
|
+
trimesh: "trimesh"
|
443
|
+
};
|
444
|
+
const createColliderPropsFromChildren = ({
|
445
|
+
object,
|
446
|
+
ignoreMeshColliders: _ignoreMeshColliders = true,
|
447
|
+
options
|
448
|
+
}) => {
|
449
|
+
const colliderProps = [];
|
450
|
+
object.updateWorldMatrix(true, false);
|
451
|
+
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
398
452
|
|
453
|
+
const colliderFromChild = child => {
|
454
|
+
if ("isMesh" in child) {
|
455
|
+
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
456
|
+
const worldScale = child.getWorldScale(_scale);
|
457
|
+
const shape = autoColliderMap[options.colliders || "cuboid"];
|
458
|
+
child.updateWorldMatrix(true, false);
|
399
459
|
|
400
|
-
|
401
|
-
state.object.position.copy(_position);
|
402
|
-
state.object.quaternion.copy(_rotation);
|
403
|
-
}
|
404
|
-
} // Get new position
|
460
|
+
_matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
|
405
461
|
|
462
|
+
const rotationEuler = new three.Euler().setFromQuaternion(_rotation, "XYZ");
|
463
|
+
const {
|
464
|
+
geometry
|
465
|
+
} = child;
|
466
|
+
const {
|
467
|
+
args,
|
468
|
+
offset
|
469
|
+
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
470
|
+
colliderProps.push(_objectSpread2(_objectSpread2({}, options), {}, {
|
471
|
+
args: args,
|
472
|
+
shape: shape,
|
473
|
+
rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
|
474
|
+
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
475
|
+
scale: [worldScale.x, worldScale.y, worldScale.z]
|
476
|
+
}));
|
477
|
+
}
|
478
|
+
};
|
406
479
|
|
407
|
-
|
480
|
+
if (options.includeInvisible) {
|
481
|
+
object.traverse(colliderFromChild);
|
482
|
+
} else {
|
483
|
+
object.traverseVisible(colliderFromChild);
|
484
|
+
}
|
408
485
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
486
|
+
return colliderProps;
|
487
|
+
};
|
488
|
+
const getColliderArgsFromGeometry = (geometry, colliders) => {
|
489
|
+
switch (colliders) {
|
490
|
+
case "cuboid":
|
491
|
+
{
|
492
|
+
geometry.computeBoundingBox();
|
493
|
+
const {
|
494
|
+
boundingBox
|
495
|
+
} = geometry;
|
496
|
+
const size = boundingBox.getSize(new three.Vector3());
|
497
|
+
return {
|
498
|
+
args: [size.x / 2, size.y / 2, size.z / 2],
|
499
|
+
offset: boundingBox.getCenter(new three.Vector3())
|
500
|
+
};
|
416
501
|
}
|
417
|
-
});
|
418
|
-
eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
419
|
-
const source1 = getSourceFromColliderHandle(handle1);
|
420
|
-
const source2 = getSourceFromColliderHandle(handle2); // Collision Events
|
421
502
|
|
422
|
-
|
423
|
-
|
503
|
+
case "ball":
|
504
|
+
{
|
505
|
+
geometry.computeBoundingSphere();
|
506
|
+
const {
|
507
|
+
boundingSphere
|
508
|
+
} = geometry;
|
509
|
+
const radius = boundingSphere.radius;
|
510
|
+
return {
|
511
|
+
args: [radius],
|
512
|
+
offset: boundingSphere.center
|
513
|
+
};
|
424
514
|
}
|
425
515
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
/* RigidBody events */
|
431
|
-
(_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, {
|
432
|
-
rigidBody: source2.rigidBody.object,
|
433
|
-
collider: source2.collider.object,
|
434
|
-
colliderObject: (_source2$collider$sta = source2.collider.state) === null || _source2$collider$sta === void 0 ? void 0 : _source2$collider$sta.object,
|
435
|
-
rigidBodyObject: (_source2$rigidBody$st = source2.rigidBody.state) === null || _source2$rigidBody$st === void 0 ? void 0 : _source2$rigidBody$st.object,
|
436
|
-
manifold,
|
437
|
-
flipped
|
438
|
-
});
|
439
|
-
(_source2$rigidBody$ev = source2.rigidBody.events) === null || _source2$rigidBody$ev === void 0 ? void 0 : (_source2$rigidBody$ev2 = _source2$rigidBody$ev.onCollisionEnter) === null || _source2$rigidBody$ev2 === void 0 ? void 0 : _source2$rigidBody$ev2.call(_source2$rigidBody$ev, {
|
440
|
-
rigidBody: source1.rigidBody.object,
|
441
|
-
collider: source1.collider.object,
|
442
|
-
colliderObject: (_source1$collider$sta = source1.collider.state) === null || _source1$collider$sta === void 0 ? void 0 : _source1$collider$sta.object,
|
443
|
-
rigidBodyObject: (_source1$rigidBody$st = source1.rigidBody.state) === null || _source1$rigidBody$st === void 0 ? void 0 : _source1$rigidBody$st.object,
|
444
|
-
manifold,
|
445
|
-
flipped
|
446
|
-
});
|
447
|
-
/* Collider events */
|
448
|
-
|
449
|
-
(_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, {
|
450
|
-
rigidBody: source2.rigidBody.object,
|
451
|
-
collider: source2.collider.object,
|
452
|
-
colliderObject: (_source2$collider$sta2 = source2.collider.state) === null || _source2$collider$sta2 === void 0 ? void 0 : _source2$collider$sta2.object,
|
453
|
-
rigidBodyObject: (_source2$rigidBody$st2 = source2.rigidBody.state) === null || _source2$rigidBody$st2 === void 0 ? void 0 : _source2$rigidBody$st2.object,
|
454
|
-
manifold,
|
455
|
-
flipped
|
456
|
-
});
|
457
|
-
(_source2$collider$eve = source2.collider.events) === null || _source2$collider$eve === void 0 ? void 0 : (_source2$collider$eve2 = _source2$collider$eve.onCollisionEnter) === null || _source2$collider$eve2 === void 0 ? void 0 : _source2$collider$eve2.call(_source2$collider$eve, {
|
458
|
-
rigidBody: source1.rigidBody.object,
|
459
|
-
collider: source1.collider.object,
|
460
|
-
colliderObject: (_source1$collider$sta2 = source1.collider.state) === null || _source1$collider$sta2 === void 0 ? void 0 : _source1$collider$sta2.object,
|
461
|
-
rigidBodyObject: (_source1$rigidBody$st2 = source1.rigidBody.state) === null || _source1$rigidBody$st2 === void 0 ? void 0 : _source1$rigidBody$st2.object,
|
462
|
-
manifold,
|
463
|
-
flipped
|
464
|
-
});
|
465
|
-
});
|
466
|
-
} else {
|
467
|
-
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;
|
468
|
-
|
469
|
-
(_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, {
|
470
|
-
rigidBody: source2.rigidBody.object,
|
471
|
-
collider: source2.collider.object
|
472
|
-
});
|
473
|
-
(_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, {
|
474
|
-
rigidBody: source1.rigidBody.object,
|
475
|
-
collider: source1.collider.object
|
476
|
-
});
|
477
|
-
(_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, {
|
478
|
-
rigidBody: source2.rigidBody.object,
|
479
|
-
collider: source2.collider.object
|
480
|
-
});
|
481
|
-
(_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, {
|
482
|
-
rigidBody: source1.rigidBody.object,
|
483
|
-
collider: source1.collider.object
|
484
|
-
});
|
485
|
-
} // Sensor Intersections
|
486
|
-
|
487
|
-
|
488
|
-
if (started) {
|
489
|
-
if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
|
490
|
-
var _source1$rigidBody$ev5, _source1$rigidBody$ev6, _source2$collider$sta3, _source2$rigidBody$st3, _source2$rigidBody$ev5, _source2$rigidBody$ev6, _source1$collider$sta3, _source1$rigidBody$st3, _source1$collider$eve5, _source1$collider$eve6, _source2$collider$sta4, _source2$rigidBody$st4, _source2$collider$eve5, _source2$collider$eve6, _source1$collider$sta4, _source1$rigidBody$st4;
|
491
|
-
|
492
|
-
(_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, {
|
493
|
-
rigidBody: source2.rigidBody.object,
|
494
|
-
collider: source2.collider.object,
|
495
|
-
colliderObject: (_source2$collider$sta3 = source2.collider.state) === null || _source2$collider$sta3 === void 0 ? void 0 : _source2$collider$sta3.object,
|
496
|
-
rigidBodyObject: (_source2$rigidBody$st3 = source2.rigidBody.state) === null || _source2$rigidBody$st3 === void 0 ? void 0 : _source2$rigidBody$st3.object
|
497
|
-
});
|
498
|
-
(_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, {
|
499
|
-
rigidBody: source1.rigidBody.object,
|
500
|
-
collider: source1.collider.object,
|
501
|
-
colliderObject: (_source1$collider$sta3 = source1.collider.state) === null || _source1$collider$sta3 === void 0 ? void 0 : _source1$collider$sta3.object,
|
502
|
-
rigidBodyObject: (_source1$rigidBody$st3 = source1.rigidBody.state) === null || _source1$rigidBody$st3 === void 0 ? void 0 : _source1$rigidBody$st3.object
|
503
|
-
});
|
504
|
-
(_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, {
|
505
|
-
rigidBody: source2.rigidBody.object,
|
506
|
-
collider: source2.collider.object,
|
507
|
-
colliderObject: (_source2$collider$sta4 = source2.collider.state) === null || _source2$collider$sta4 === void 0 ? void 0 : _source2$collider$sta4.object,
|
508
|
-
rigidBodyObject: (_source2$rigidBody$st4 = source2.rigidBody.state) === null || _source2$rigidBody$st4 === void 0 ? void 0 : _source2$rigidBody$st4.object
|
509
|
-
});
|
510
|
-
(_source2$collider$eve5 = source2.collider.events) === null || _source2$collider$eve5 === void 0 ? void 0 : (_source2$collider$eve6 = _source2$collider$eve5.onIntersectionEnter) === null || _source2$collider$eve6 === void 0 ? void 0 : _source2$collider$eve6.call(_source2$collider$eve5, {
|
511
|
-
rigidBody: source1.rigidBody.object,
|
512
|
-
collider: source1.collider.object,
|
513
|
-
colliderObject: (_source1$collider$sta4 = source1.collider.state) === null || _source1$collider$sta4 === void 0 ? void 0 : _source1$collider$sta4.object,
|
514
|
-
rigidBodyObject: (_source1$rigidBody$st4 = source1.rigidBody.state) === null || _source1$rigidBody$st4 === void 0 ? void 0 : _source1$rigidBody$st4.object
|
515
|
-
});
|
516
|
-
}
|
517
|
-
} else {
|
518
|
-
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;
|
516
|
+
case "trimesh":
|
517
|
+
{
|
518
|
+
var _clonedGeometry$index;
|
519
519
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
rigidBody: source1.rigidBody.object,
|
526
|
-
collider: source1.collider.object
|
527
|
-
});
|
528
|
-
(_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, {
|
529
|
-
rigidBody: source2.rigidBody.object,
|
530
|
-
collider: source2.collider.object
|
531
|
-
});
|
532
|
-
(_source2$collider$eve7 = source2.collider.events) === null || _source2$collider$eve7 === void 0 ? void 0 : (_source2$collider$eve8 = _source2$collider$eve7.onIntersectionExit) === null || _source2$collider$eve8 === void 0 ? void 0 : _source2$collider$eve8.call(_source2$collider$eve7, {
|
533
|
-
rigidBody: source1.rigidBody.object,
|
534
|
-
collider: source1.collider.object
|
535
|
-
});
|
520
|
+
const clonedGeometry = geometry.index ? geometry.clone() : threeStdlib.mergeVertices(geometry);
|
521
|
+
return {
|
522
|
+
args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
|
523
|
+
offset: new three.Vector3()
|
524
|
+
};
|
536
525
|
}
|
537
|
-
});
|
538
|
-
eventQueue.drainContactForceEvents(event => {
|
539
|
-
var _source1$rigidBody$ev9, _source1$rigidBody$ev10, _source2$collider$sta5, _source2$rigidBody$st5, _source2$rigidBody$ev9, _source2$rigidBody$ev10, _source1$collider$sta5, _source1$rigidBody$st5, _source1$collider$eve9, _source1$collider$eve10, _source2$collider$sta6, _source2$rigidBody$st6, _source2$collider$eve9, _source2$collider$eve10, _source1$collider$sta6, _source1$rigidBody$st6;
|
540
|
-
|
541
|
-
const source1 = getSourceFromColliderHandle(event.collider1());
|
542
|
-
const source2 = getSourceFromColliderHandle(event.collider2()); // Collision Events
|
543
526
|
|
544
|
-
|
545
|
-
|
527
|
+
case "hull":
|
528
|
+
{
|
529
|
+
const g = geometry.clone();
|
530
|
+
return {
|
531
|
+
args: [g.attributes.position.array],
|
532
|
+
offset: new three.Vector3()
|
533
|
+
};
|
546
534
|
}
|
535
|
+
}
|
547
536
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
rigidBodyObject: (_source2$rigidBody$st5 = source2.rigidBody.state) === null || _source2$rigidBody$st5 === void 0 ? void 0 : _source2$rigidBody$st5.object,
|
553
|
-
totalForce: event.totalForce(),
|
554
|
-
totalForceMagnitude: event.totalForceMagnitude(),
|
555
|
-
maxForceDirection: event.maxForceDirection(),
|
556
|
-
maxForceMagnitude: event.maxForceMagnitude()
|
557
|
-
});
|
558
|
-
(_source2$rigidBody$ev9 = source2.rigidBody.events) === null || _source2$rigidBody$ev9 === void 0 ? void 0 : (_source2$rigidBody$ev10 = _source2$rigidBody$ev9.onContactForce) === null || _source2$rigidBody$ev10 === void 0 ? void 0 : _source2$rigidBody$ev10.call(_source2$rigidBody$ev9, {
|
559
|
-
rigidBody: source1.rigidBody.object,
|
560
|
-
collider: source1.collider.object,
|
561
|
-
colliderObject: (_source1$collider$sta5 = source1.collider.state) === null || _source1$collider$sta5 === void 0 ? void 0 : _source1$collider$sta5.object,
|
562
|
-
rigidBodyObject: (_source1$rigidBody$st5 = source1.rigidBody.state) === null || _source1$rigidBody$st5 === void 0 ? void 0 : _source1$rigidBody$st5.object,
|
563
|
-
totalForce: event.totalForce(),
|
564
|
-
totalForceMagnitude: event.totalForceMagnitude(),
|
565
|
-
maxForceDirection: event.maxForceDirection(),
|
566
|
-
maxForceMagnitude: event.maxForceMagnitude()
|
567
|
-
});
|
568
|
-
(_source1$collider$eve9 = source1.collider.events) === null || _source1$collider$eve9 === void 0 ? void 0 : (_source1$collider$eve10 = _source1$collider$eve9.onContactForce) === null || _source1$collider$eve10 === void 0 ? void 0 : _source1$collider$eve10.call(_source1$collider$eve9, {
|
569
|
-
rigidBody: source2.rigidBody.object,
|
570
|
-
collider: source2.collider.object,
|
571
|
-
colliderObject: (_source2$collider$sta6 = source2.collider.state) === null || _source2$collider$sta6 === void 0 ? void 0 : _source2$collider$sta6.object,
|
572
|
-
rigidBodyObject: (_source2$rigidBody$st6 = source2.rigidBody.state) === null || _source2$rigidBody$st6 === void 0 ? void 0 : _source2$rigidBody$st6.object,
|
573
|
-
totalForce: event.totalForce(),
|
574
|
-
totalForceMagnitude: event.totalForceMagnitude(),
|
575
|
-
maxForceDirection: event.maxForceDirection(),
|
576
|
-
maxForceMagnitude: event.maxForceMagnitude()
|
577
|
-
});
|
578
|
-
(_source2$collider$eve9 = source2.collider.events) === null || _source2$collider$eve9 === void 0 ? void 0 : (_source2$collider$eve10 = _source2$collider$eve9.onContactForce) === null || _source2$collider$eve10 === void 0 ? void 0 : _source2$collider$eve10.call(_source2$collider$eve9, {
|
579
|
-
rigidBody: source1.rigidBody.object,
|
580
|
-
collider: source1.collider.object,
|
581
|
-
colliderObject: (_source1$collider$sta6 = source1.collider.state) === null || _source1$collider$sta6 === void 0 ? void 0 : _source1$collider$sta6.object,
|
582
|
-
rigidBodyObject: (_source1$rigidBody$st6 = source1.rigidBody.state) === null || _source1$rigidBody$st6 === void 0 ? void 0 : _source1$rigidBody$st6.object,
|
583
|
-
totalForce: event.totalForce(),
|
584
|
-
totalForceMagnitude: event.totalForceMagnitude(),
|
585
|
-
maxForceDirection: event.maxForceDirection(),
|
586
|
-
maxForceMagnitude: event.maxForceMagnitude()
|
587
|
-
});
|
588
|
-
});
|
589
|
-
}, updatePriority);
|
590
|
-
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
591
|
-
const context = React.useMemo(() => ({
|
592
|
-
rapier,
|
593
|
-
world: api,
|
594
|
-
physicsOptions: {
|
595
|
-
colliders: _colliders,
|
596
|
-
gravity: _gravity
|
597
|
-
},
|
598
|
-
rigidBodyStates,
|
599
|
-
colliderStates,
|
600
|
-
rigidBodyEvents,
|
601
|
-
colliderEvents,
|
602
|
-
isPaused: _paused
|
603
|
-
}), [_paused]);
|
604
|
-
return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
|
605
|
-
value: context
|
606
|
-
}, children);
|
537
|
+
return {
|
538
|
+
args: [],
|
539
|
+
offset: new three.Vector3()
|
540
|
+
};
|
607
541
|
};
|
542
|
+
const useColliderEvents = (collidersRef, props, events) => {
|
543
|
+
const {
|
544
|
+
onCollisionEnter,
|
545
|
+
onCollisionExit,
|
546
|
+
onIntersectionEnter,
|
547
|
+
onIntersectionExit,
|
548
|
+
onContactForce
|
549
|
+
} = props;
|
550
|
+
React.useEffect(() => {
|
551
|
+
var _collidersRef$current;
|
608
552
|
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
var source = arguments[i];
|
553
|
+
(_collidersRef$current = collidersRef.current) === null || _collidersRef$current === void 0 ? void 0 : _collidersRef$current.forEach(collider => {
|
554
|
+
const hasCollisionEvent = !!(onCollisionEnter || onCollisionExit || onIntersectionEnter || onIntersectionExit);
|
555
|
+
const hasContactForceEvent = !!onContactForce;
|
613
556
|
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
557
|
+
if (hasCollisionEvent && hasContactForceEvent) {
|
558
|
+
collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS | rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
|
559
|
+
} else if (hasCollisionEvent) {
|
560
|
+
collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
|
561
|
+
} else if (hasContactForceEvent) {
|
562
|
+
collider.setActiveEvents(rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
|
618
563
|
}
|
619
|
-
}
|
620
564
|
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
565
|
+
events.set(collider.handle, {
|
566
|
+
onCollisionEnter,
|
567
|
+
onCollisionExit,
|
568
|
+
onIntersectionEnter,
|
569
|
+
onIntersectionExit,
|
570
|
+
onContactForce
|
571
|
+
});
|
572
|
+
});
|
573
|
+
return () => {
|
574
|
+
var _collidersRef$current2;
|
625
575
|
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
var sourceKeys = Object.keys(source);
|
630
|
-
var key, i;
|
631
|
-
|
632
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
633
|
-
key = sourceKeys[i];
|
634
|
-
if (excluded.indexOf(key) >= 0) continue;
|
635
|
-
target[key] = source[key];
|
636
|
-
}
|
637
|
-
|
638
|
-
return target;
|
639
|
-
}
|
640
|
-
|
641
|
-
function _objectWithoutProperties(source, excluded) {
|
642
|
-
if (source == null) return {};
|
643
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
644
|
-
var key, i;
|
645
|
-
|
646
|
-
if (Object.getOwnPropertySymbols) {
|
647
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
648
|
-
|
649
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
650
|
-
key = sourceSymbolKeys[i];
|
651
|
-
if (excluded.indexOf(key) >= 0) continue;
|
652
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
653
|
-
target[key] = source[key];
|
654
|
-
}
|
655
|
-
}
|
656
|
-
|
657
|
-
return target;
|
658
|
-
}
|
659
|
-
|
660
|
-
function _defineProperty(obj, key, value) {
|
661
|
-
if (key in obj) {
|
662
|
-
Object.defineProperty(obj, key, {
|
663
|
-
value: value,
|
664
|
-
enumerable: true,
|
665
|
-
configurable: true,
|
666
|
-
writable: true
|
667
|
-
});
|
668
|
-
} else {
|
669
|
-
obj[key] = value;
|
670
|
-
}
|
671
|
-
|
672
|
-
return obj;
|
673
|
-
}
|
674
|
-
|
675
|
-
function ownKeys(object, enumerableOnly) {
|
676
|
-
var keys = Object.keys(object);
|
677
|
-
|
678
|
-
if (Object.getOwnPropertySymbols) {
|
679
|
-
var symbols = Object.getOwnPropertySymbols(object);
|
680
|
-
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
681
|
-
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
682
|
-
})), keys.push.apply(keys, symbols);
|
683
|
-
}
|
684
|
-
|
685
|
-
return keys;
|
686
|
-
}
|
687
|
-
|
688
|
-
function _objectSpread2(target) {
|
689
|
-
for (var i = 1; i < arguments.length; i++) {
|
690
|
-
var source = null != arguments[i] ? arguments[i] : {};
|
691
|
-
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
|
692
|
-
_defineProperty(target, key, source[key]);
|
693
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
|
694
|
-
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
695
|
-
});
|
696
|
-
}
|
697
|
-
|
698
|
-
return target;
|
699
|
-
}
|
700
|
-
|
701
|
-
const scaleColliderArgs = (shape, args, scale) => {
|
702
|
-
const newArgs = args.slice(); // Heightfield uses a vector
|
703
|
-
|
704
|
-
if (shape === "heightfield") {
|
705
|
-
const s = newArgs[3];
|
706
|
-
s.x *= scale.x;
|
707
|
-
s.x *= scale.y;
|
708
|
-
s.x *= scale.z;
|
709
|
-
return newArgs;
|
710
|
-
} // Trimesh and convex scale the vertices
|
711
|
-
|
712
|
-
|
713
|
-
if (shape === "trimesh" || shape === "convexHull") {
|
714
|
-
newArgs[0] = scaleVertices(newArgs[0], scale);
|
715
|
-
return newArgs;
|
716
|
-
} // Prepfill with some extra
|
717
|
-
|
718
|
-
|
719
|
-
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
720
|
-
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
576
|
+
(_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
|
577
|
+
};
|
578
|
+
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
721
579
|
};
|
722
|
-
const createColliderFromOptions = (options, world, scale, rigidBody) => {
|
723
|
-
const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
|
724
580
|
|
725
|
-
|
726
|
-
|
581
|
+
const rigidBodyDescFromOptions = options => {
|
582
|
+
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
583
|
+
const desc = new rapier3dCompat.RigidBodyDesc(type);
|
584
|
+
return desc;
|
727
585
|
};
|
728
|
-
const
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
}
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
}
|
748
|
-
|
749
|
-
if (options.massProperties !== undefined) {
|
750
|
-
collider.setMassProperties(options.massProperties.mass, options.massProperties.centerOfMass, options.massProperties.principalAngularInertia, options.massProperties.angularInertiaLocalFrame);
|
751
|
-
}
|
586
|
+
const createRigidBodyState = ({
|
587
|
+
rigidBody,
|
588
|
+
object,
|
589
|
+
setMatrix,
|
590
|
+
getMatrix,
|
591
|
+
worldScale
|
592
|
+
}) => {
|
593
|
+
object.updateWorldMatrix(true, false);
|
594
|
+
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
595
|
+
return {
|
596
|
+
object,
|
597
|
+
rigidBody,
|
598
|
+
invertedWorldMatrix,
|
599
|
+
setMatrix: setMatrix ? setMatrix : matrix => {
|
600
|
+
object.matrix.copy(matrix);
|
601
|
+
},
|
602
|
+
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
603
|
+
scale: worldScale || object.getWorldScale(_scale).clone(),
|
604
|
+
isSleeping: false
|
605
|
+
};
|
752
606
|
};
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
collider.setSensor(value);
|
607
|
+
const mutableRigidBodyOptions = {
|
608
|
+
gravityScale: (rb, value) => {
|
609
|
+
rb.setGravityScale(value, true);
|
757
610
|
},
|
758
|
-
|
759
|
-
|
611
|
+
linearDamping: (rb, value) => {
|
612
|
+
rb.setLinearDamping(value);
|
760
613
|
},
|
761
|
-
|
762
|
-
|
614
|
+
angularDamping: (rb, value) => {
|
615
|
+
rb.setAngularDamping(value);
|
763
616
|
},
|
764
|
-
|
765
|
-
|
617
|
+
enabledRotations: (rb, [x, y, z]) => {
|
618
|
+
rb.setEnabledRotations(x, y, z, true);
|
766
619
|
},
|
767
|
-
|
768
|
-
|
620
|
+
enabledTranslations: (rb, [x, y, z]) => {
|
621
|
+
rb.setEnabledTranslations(x, y, z, true);
|
769
622
|
},
|
770
|
-
|
771
|
-
|
623
|
+
angularVelocity: (rb, [x, y, z]) => {
|
624
|
+
rb.setAngvel({
|
625
|
+
x,
|
626
|
+
y,
|
627
|
+
z
|
628
|
+
}, true);
|
772
629
|
},
|
773
|
-
|
774
|
-
|
630
|
+
linearVelocity: (rb, [x, y, z]) => {
|
631
|
+
rb.setLinvel({
|
632
|
+
x,
|
633
|
+
y,
|
634
|
+
z
|
635
|
+
}, true);
|
636
|
+
},
|
637
|
+
ccd: (rb, value) => {
|
638
|
+
rb.enableCcd(value);
|
639
|
+
},
|
640
|
+
userData: (rb, value) => {
|
641
|
+
rb.userData = value;
|
775
642
|
},
|
776
|
-
// To make sure the options all mutalbe options are listed
|
777
|
-
quaternion: () => {},
|
778
643
|
position: () => {},
|
779
644
|
rotation: () => {},
|
645
|
+
quaternion: () => {},
|
780
646
|
scale: () => {}
|
781
647
|
};
|
782
|
-
const
|
783
|
-
const
|
784
|
-
|
648
|
+
const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
|
649
|
+
const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
|
650
|
+
if (!rigidBody) {
|
651
|
+
return;
|
652
|
+
}
|
653
|
+
|
654
|
+
const state = states.get(rigidBody.handle);
|
785
655
|
|
786
656
|
if (state) {
|
787
|
-
|
788
|
-
|
789
|
-
state.object.updateWorldMatrix(true, false);
|
657
|
+
if (updateTranslations) {
|
658
|
+
state.object.updateWorldMatrix(true, false);
|
790
659
|
|
791
|
-
|
660
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
792
661
|
|
793
|
-
|
794
|
-
|
795
|
-
x: _position.x * parentWorldScale.x,
|
796
|
-
y: _position.y * parentWorldScale.y,
|
797
|
-
z: _position.z * parentWorldScale.z
|
798
|
-
});
|
799
|
-
collider.setRotationWrtParent(_rotation);
|
800
|
-
} else {
|
801
|
-
collider.setTranslation({
|
802
|
-
x: _position.x * parentWorldScale.x,
|
803
|
-
y: _position.y * parentWorldScale.y,
|
804
|
-
z: _position.z * parentWorldScale.z
|
805
|
-
});
|
806
|
-
collider.setRotation(_rotation);
|
662
|
+
rigidBody.setTranslation(_position, false);
|
663
|
+
rigidBody.setRotation(_rotation, false);
|
807
664
|
}
|
808
665
|
|
809
|
-
|
666
|
+
mutableRigidBodyOptionKeys.forEach(key => {
|
810
667
|
if (key in options) {
|
811
|
-
|
812
|
-
mutableColliderOptions[key](collider, // @ts-ignore Option does not want to fit into the function, but it will
|
813
|
-
option, options);
|
668
|
+
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
814
669
|
}
|
815
|
-
});
|
816
|
-
// are exclusive.
|
817
|
-
|
818
|
-
setColliderMassOptions(collider, options);
|
670
|
+
});
|
819
671
|
}
|
820
672
|
};
|
821
|
-
const
|
673
|
+
const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
|
822
674
|
// TODO: Improve this, split each prop into its own effect
|
823
|
-
const mutablePropsAsFlatArray = React.useMemo(() =>
|
675
|
+
const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
824
676
|
return vectorToTuple(props[key]);
|
825
677
|
}), [props]);
|
826
678
|
React.useEffect(() => {
|
827
|
-
|
828
|
-
|
829
|
-
|
679
|
+
if (Array.isArray(rigidBodyRef.current)) {
|
680
|
+
for (const rigidBody of rigidBodyRef.current) {
|
681
|
+
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
682
|
+
}
|
683
|
+
} else if (rigidBodyRef.current) {
|
684
|
+
setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
|
685
|
+
}
|
830
686
|
}, mutablePropsAsFlatArray);
|
831
687
|
};
|
832
|
-
|
833
|
-
const
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
const
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
688
|
+
const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
689
|
+
const {
|
690
|
+
onWake,
|
691
|
+
onSleep,
|
692
|
+
onCollisionEnter,
|
693
|
+
onCollisionExit,
|
694
|
+
onIntersectionEnter,
|
695
|
+
onIntersectionExit
|
696
|
+
} = props;
|
697
|
+
const eventHandlers = {
|
698
|
+
onWake,
|
699
|
+
onSleep,
|
700
|
+
onCollisionEnter,
|
701
|
+
onCollisionExit,
|
702
|
+
onIntersectionEnter,
|
703
|
+
onIntersectionExit
|
846
704
|
};
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
object,
|
856
|
-
ignoreMeshColliders: _ignoreMeshColliders = true,
|
857
|
-
options
|
858
|
-
}) => {
|
859
|
-
const colliderProps = [];
|
860
|
-
object.updateWorldMatrix(true, false);
|
861
|
-
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
705
|
+
React.useEffect(() => {
|
706
|
+
if (Array.isArray(rigidBodyRef.current)) {
|
707
|
+
for (const rigidBody of rigidBodyRef.current) {
|
708
|
+
events.set(rigidBody.handle, eventHandlers);
|
709
|
+
}
|
710
|
+
} else if (rigidBodyRef.current) {
|
711
|
+
events.set(rigidBodyRef.current.handle, eventHandlers);
|
712
|
+
}
|
862
713
|
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
714
|
+
return () => {
|
715
|
+
if (Array.isArray(rigidBodyRef.current)) {
|
716
|
+
for (const rigidBody of rigidBodyRef.current) {
|
717
|
+
events.delete(rigidBody.handle);
|
718
|
+
}
|
719
|
+
} else if (rigidBodyRef.current) {
|
720
|
+
events.delete(rigidBodyRef.current.handle);
|
721
|
+
}
|
722
|
+
};
|
723
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
724
|
+
};
|
869
725
|
|
870
|
-
|
726
|
+
const useRapier = () => {
|
727
|
+
return React.useContext(RapierContext);
|
728
|
+
};
|
729
|
+
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
730
|
+
const [colliderProps, setColliderProps] = React.useState([]);
|
731
|
+
React.useEffect(() => {
|
732
|
+
const object = ref.current;
|
871
733
|
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
args,
|
878
|
-
offset
|
879
|
-
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
880
|
-
colliderProps.push(_objectSpread2(_objectSpread2({}, options), {}, {
|
881
|
-
args: args,
|
882
|
-
shape: shape,
|
883
|
-
rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
|
884
|
-
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
885
|
-
scale: [worldScale.x, worldScale.y, worldScale.z]
|
734
|
+
if (object && options.colliders !== false) {
|
735
|
+
setColliderProps(createColliderPropsFromChildren({
|
736
|
+
object: ref.current,
|
737
|
+
options,
|
738
|
+
ignoreMeshColliders
|
886
739
|
}));
|
887
740
|
}
|
888
|
-
};
|
889
|
-
|
890
|
-
if (options.includeInvisible) {
|
891
|
-
object.traverse(colliderFromChild);
|
892
|
-
} else {
|
893
|
-
object.traverseVisible(colliderFromChild);
|
894
|
-
}
|
895
|
-
|
741
|
+
}, [options.colliders]);
|
896
742
|
return colliderProps;
|
897
743
|
};
|
898
|
-
const
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
744
|
+
const useRigidBody = (options = {}) => {
|
745
|
+
const {
|
746
|
+
world,
|
747
|
+
rigidBodyStates,
|
748
|
+
physicsOptions,
|
749
|
+
rigidBodyEvents
|
750
|
+
} = useRapier();
|
751
|
+
const ref = React.useRef();
|
752
|
+
const mergedOptions = React.useMemo(() => {
|
753
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
|
754
|
+
children: undefined
|
755
|
+
});
|
756
|
+
}, [physicsOptions, options]);
|
757
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
|
912
758
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
return {
|
921
|
-
args: [radius],
|
922
|
-
offset: boundingSphere.center
|
923
|
-
};
|
924
|
-
}
|
759
|
+
const rigidBodyRef = React.useRef();
|
760
|
+
const getRigidBodyRef = React.useRef(() => {
|
761
|
+
if (!rigidBodyRef.current) {
|
762
|
+
const desc = rigidBodyDescFromOptions(options);
|
763
|
+
const rigidBody = world.createRigidBody(desc);
|
764
|
+
rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
|
765
|
+
}
|
925
766
|
|
926
|
-
|
927
|
-
|
928
|
-
var _clonedGeometry$index;
|
767
|
+
return rigidBodyRef.current;
|
768
|
+
}); // Setup
|
929
769
|
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
offset: new three.Vector3()
|
934
|
-
};
|
935
|
-
}
|
770
|
+
React.useEffect(() => {
|
771
|
+
const rigidBody = getRigidBodyRef.current();
|
772
|
+
rigidBodyRef.current = rigidBody;
|
936
773
|
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
return {
|
941
|
-
args: [g.attributes.position.array],
|
942
|
-
offset: new three.Vector3()
|
943
|
-
};
|
944
|
-
}
|
945
|
-
}
|
774
|
+
if (!ref.current) {
|
775
|
+
ref.current = new three.Object3D();
|
776
|
+
}
|
946
777
|
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
778
|
+
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
779
|
+
rigidBody,
|
780
|
+
object: ref.current
|
781
|
+
}));
|
782
|
+
return () => {
|
783
|
+
world.removeRigidBody(rigidBody);
|
784
|
+
rigidBodyStates.delete(rigidBody.handle);
|
785
|
+
rigidBodyRef.current = undefined;
|
786
|
+
};
|
787
|
+
}, []);
|
788
|
+
useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
|
789
|
+
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
790
|
+
const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
791
|
+
return [ref, api, childColliderProps];
|
792
|
+
}; // Joints
|
962
793
|
|
963
|
-
|
964
|
-
|
965
|
-
|
794
|
+
const useImpulseJoint = (body1, body2, params) => {
|
795
|
+
const {
|
796
|
+
world
|
797
|
+
} = useRapier();
|
798
|
+
const jointRef = React.useRef();
|
799
|
+
const getJointRef = React.useRef(() => {
|
800
|
+
if (!jointRef.current) {
|
801
|
+
let rb1;
|
802
|
+
let rb2;
|
966
803
|
|
967
|
-
if (
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
collider.setActiveEvents(rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
|
804
|
+
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
805
|
+
rb1 = world.getRigidBody(body1.current.handle);
|
806
|
+
rb2 = world.getRigidBody(body2.current.handle);
|
807
|
+
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
808
|
+
jointRef.current = newJoint;
|
973
809
|
}
|
810
|
+
}
|
974
811
|
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
onIntersectionExit,
|
980
|
-
onContactForce
|
981
|
-
});
|
982
|
-
});
|
812
|
+
return jointRef.current;
|
813
|
+
});
|
814
|
+
React.useEffect(() => {
|
815
|
+
const joint = getJointRef.current();
|
983
816
|
return () => {
|
984
|
-
|
985
|
-
|
986
|
-
|
817
|
+
if (joint) {
|
818
|
+
world.removeImpulseJoint(joint);
|
819
|
+
jointRef.current = undefined;
|
820
|
+
}
|
987
821
|
};
|
988
|
-
}, [
|
822
|
+
}, []);
|
823
|
+
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
824
|
+
return api;
|
989
825
|
};
|
826
|
+
/**
|
827
|
+
*
|
828
|
+
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
829
|
+
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
830
|
+
* The fixed-joint makes these frames coincide in world-space.
|
831
|
+
*/
|
990
832
|
|
991
|
-
const
|
992
|
-
const
|
993
|
-
|
994
|
-
|
833
|
+
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
834
|
+
const {
|
835
|
+
rapier
|
836
|
+
} = useRapier();
|
837
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
|
838
|
+
w: 1
|
839
|
+
}), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
|
840
|
+
w: 1
|
841
|
+
})));
|
995
842
|
};
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
const
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
invertedWorldMatrix,
|
1009
|
-
setMatrix: setMatrix ? setMatrix : matrix => {
|
1010
|
-
object.matrix.copy(matrix);
|
1011
|
-
},
|
1012
|
-
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
1013
|
-
scale: worldScale || object.getWorldScale(_scale).clone(),
|
1014
|
-
isSleeping: false
|
1015
|
-
};
|
843
|
+
/**
|
844
|
+
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
845
|
+
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
846
|
+
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
847
|
+
* points that need to coincide on the local-space of each rigid-body.
|
848
|
+
*/
|
849
|
+
|
850
|
+
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
851
|
+
const {
|
852
|
+
rapier
|
853
|
+
} = useRapier();
|
854
|
+
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
1016
855
|
};
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
}
|
1027
|
-
|
1028
|
-
rb.setEnabledRotations(x, y, z, true);
|
1029
|
-
},
|
1030
|
-
enabledTranslations: (rb, [x, y, z]) => {
|
1031
|
-
rb.setEnabledTranslations(x, y, z, true);
|
1032
|
-
},
|
1033
|
-
angularVelocity: (rb, [x, y, z]) => {
|
1034
|
-
rb.setAngvel({
|
1035
|
-
x,
|
1036
|
-
y,
|
1037
|
-
z
|
1038
|
-
}, true);
|
1039
|
-
},
|
1040
|
-
linearVelocity: (rb, [x, y, z]) => {
|
1041
|
-
rb.setLinvel({
|
1042
|
-
x,
|
1043
|
-
y,
|
1044
|
-
z
|
1045
|
-
}, true);
|
1046
|
-
},
|
1047
|
-
ccd: (rb, value) => {
|
1048
|
-
rb.enableCcd(value);
|
1049
|
-
},
|
1050
|
-
userData: (rb, value) => {
|
1051
|
-
rb.userData = value;
|
1052
|
-
},
|
1053
|
-
position: () => {},
|
1054
|
-
rotation: () => {},
|
1055
|
-
quaternion: () => {},
|
1056
|
-
scale: () => {}
|
856
|
+
/**
|
857
|
+
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
858
|
+
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
859
|
+
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
860
|
+
*/
|
861
|
+
|
862
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
863
|
+
const {
|
864
|
+
rapier
|
865
|
+
} = useRapier();
|
866
|
+
return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
1057
867
|
};
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
868
|
+
/**
|
869
|
+
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
870
|
+
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
871
|
+
* local tangent axis can be specified for each rigid-body.
|
872
|
+
*/
|
1063
873
|
|
1064
|
-
|
874
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
875
|
+
const {
|
876
|
+
rapier
|
877
|
+
} = useRapier();
|
878
|
+
return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
879
|
+
};
|
1065
880
|
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
881
|
+
const calcForceByType = {
|
882
|
+
static: (s, m2, r, d, G) => s,
|
883
|
+
linear: (s, m2, r, d, G) => s * (d / r),
|
884
|
+
newtonian: (s, m2, r, d, G) => G * s * m2 / Math.pow(d, 2)
|
885
|
+
};
|
886
|
+
const applyAttractorForceOnRigidBody = (rigidBody, {
|
887
|
+
object,
|
888
|
+
strength,
|
889
|
+
range,
|
890
|
+
gravitationalConstant,
|
891
|
+
collisionGroups,
|
892
|
+
type
|
893
|
+
}) => {
|
894
|
+
const rbPosition = rigidBody.translation();
|
895
|
+
|
896
|
+
_position.set(rbPosition.x, rbPosition.y, rbPosition.z);
|
897
|
+
|
898
|
+
const worldPosition = object.getWorldPosition(new three.Vector3());
|
899
|
+
const distance = worldPosition.distanceTo(_position);
|
900
|
+
|
901
|
+
if (distance < range) {
|
902
|
+
let force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant); // Prevent wild forces when Attractors collide
|
1069
903
|
|
1070
|
-
|
904
|
+
force = force === Infinity ? strength : force; // Naively test if the rigidBody contains a collider in one of the collision groups
|
1071
905
|
|
1072
|
-
|
1073
|
-
rigidBody.setRotation(_rotation, false);
|
1074
|
-
}
|
906
|
+
let isRigidBodyInCollisionGroup = collisionGroups === undefined ? true : false;
|
1075
907
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
1086
|
-
return vectorToTuple(props[key]);
|
1087
|
-
}), [props]);
|
1088
|
-
React.useEffect(() => {
|
1089
|
-
if (Array.isArray(rigidBodyRef.current)) {
|
1090
|
-
for (const rigidBody of rigidBodyRef.current) {
|
1091
|
-
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
908
|
+
if (collisionGroups !== undefined) {
|
909
|
+
for (let i = 0; i < rigidBody.numColliders(); i++) {
|
910
|
+
const collider = rigidBody.collider(i);
|
911
|
+
const colliderCollisionGroups = collider.collisionGroups();
|
912
|
+
|
913
|
+
if ((collisionGroups >> 16 & colliderCollisionGroups) != 0 && (colliderCollisionGroups >> 16 & collisionGroups) != 0) {
|
914
|
+
isRigidBodyInCollisionGroup = true;
|
915
|
+
break;
|
916
|
+
}
|
1092
917
|
}
|
1093
|
-
} else if (rigidBodyRef.current) {
|
1094
|
-
setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
|
1095
918
|
}
|
1096
|
-
|
919
|
+
|
920
|
+
if (isRigidBodyInCollisionGroup) {
|
921
|
+
_vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);
|
922
|
+
|
923
|
+
rigidBody.applyImpulse(_vector3, true);
|
924
|
+
}
|
925
|
+
}
|
1097
926
|
};
|
1098
|
-
const
|
927
|
+
const Attractor = /*#__PURE__*/React.memo(props => {
|
1099
928
|
const {
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
929
|
+
position = [0, 0, 0],
|
930
|
+
strength = 1,
|
931
|
+
range = 10,
|
932
|
+
type = "static",
|
933
|
+
gravitationalConstant = 6.673e-11,
|
934
|
+
collisionGroups
|
1106
935
|
} = props;
|
1107
|
-
const
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
onCollisionExit,
|
1112
|
-
onIntersectionEnter,
|
1113
|
-
onIntersectionExit
|
1114
|
-
};
|
936
|
+
const {
|
937
|
+
attractorStates
|
938
|
+
} = useRapier();
|
939
|
+
const object = React.useRef(null);
|
1115
940
|
React.useEffect(() => {
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
941
|
+
var _object$current;
|
942
|
+
|
943
|
+
let uuid = ((_object$current = object.current) === null || _object$current === void 0 ? void 0 : _object$current.uuid) || "_";
|
944
|
+
|
945
|
+
if (object.current) {
|
946
|
+
attractorStates.set(uuid, {
|
947
|
+
object: object.current,
|
948
|
+
strength,
|
949
|
+
range,
|
950
|
+
type,
|
951
|
+
gravitationalConstant,
|
952
|
+
collisionGroups
|
953
|
+
});
|
1122
954
|
}
|
1123
955
|
|
1124
956
|
return () => {
|
1125
|
-
|
1126
|
-
for (const rigidBody of rigidBodyRef.current) {
|
1127
|
-
events.delete(rigidBody.handle);
|
1128
|
-
}
|
1129
|
-
} else if (rigidBodyRef.current) {
|
1130
|
-
events.delete(rigidBodyRef.current.handle);
|
1131
|
-
}
|
957
|
+
attractorStates.delete(uuid);
|
1132
958
|
};
|
1133
|
-
}, [
|
959
|
+
}, [props]);
|
960
|
+
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
961
|
+
ref: object,
|
962
|
+
position: position
|
963
|
+
});
|
964
|
+
});
|
965
|
+
|
966
|
+
const RapierContext = /*#__PURE__*/React.createContext(undefined);
|
967
|
+
|
968
|
+
const getCollisionPayloadFromSource = (target, other) => {
|
969
|
+
var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
|
970
|
+
|
971
|
+
return {
|
972
|
+
target: {
|
973
|
+
rigidBody: target.rigidBody.object,
|
974
|
+
collider: target.collider.object,
|
975
|
+
colliderObject: (_target$collider$stat = target.collider.state) === null || _target$collider$stat === void 0 ? void 0 : _target$collider$stat.object,
|
976
|
+
rigidBodyObject: (_target$rigidBody$sta = target.rigidBody.state) === null || _target$rigidBody$sta === void 0 ? void 0 : _target$rigidBody$sta.object
|
977
|
+
},
|
978
|
+
other: {
|
979
|
+
rigidBody: other.rigidBody.object,
|
980
|
+
collider: other.collider.object,
|
981
|
+
colliderObject: (_other$collider$state = other.collider.state) === null || _other$collider$state === void 0 ? void 0 : _other$collider$state.object,
|
982
|
+
rigidBodyObject: (_other$rigidBody$stat = other.rigidBody.state) === null || _other$rigidBody$stat === void 0 ? void 0 : _other$rigidBody$stat.object
|
983
|
+
},
|
984
|
+
rigidBody: other.rigidBody.object,
|
985
|
+
collider: other.collider.object,
|
986
|
+
colliderObject: (_other$collider$state2 = other.collider.state) === null || _other$collider$state2 === void 0 ? void 0 : _other$collider$state2.object,
|
987
|
+
rigidBodyObject: (_other$rigidBody$stat2 = other.rigidBody.state) === null || _other$rigidBody$stat2 === void 0 ? void 0 : _other$rigidBody$stat2.object
|
988
|
+
};
|
1134
989
|
};
|
1135
990
|
|
1136
|
-
const
|
1137
|
-
|
991
|
+
const importRapier = async () => {
|
992
|
+
let r = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@dimforge/rapier3d-compat')); });
|
993
|
+
await r.init();
|
994
|
+
return r;
|
1138
995
|
};
|
1139
|
-
|
1140
|
-
|
996
|
+
|
997
|
+
const Physics = ({
|
998
|
+
colliders: _colliders = "cuboid",
|
999
|
+
gravity: _gravity = [0, -9.81, 0],
|
1000
|
+
children,
|
1001
|
+
timeStep: _timeStep = 1 / 60,
|
1002
|
+
paused: _paused = false,
|
1003
|
+
updatePriority,
|
1004
|
+
interpolate: _interpolate = true
|
1005
|
+
}) => {
|
1006
|
+
const rapier = useAsset.useAsset(importRapier);
|
1007
|
+
const worldRef = React.useRef();
|
1008
|
+
const getWorldRef = React.useRef(() => {
|
1009
|
+
if (!worldRef.current) {
|
1010
|
+
const world = new rapier.World(vectorArrayToVector3(_gravity));
|
1011
|
+
worldRef.current = world;
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
return worldRef.current;
|
1015
|
+
});
|
1016
|
+
const [rigidBodyStates] = React.useState(() => new Map());
|
1017
|
+
const [colliderStates] = React.useState(() => new Map());
|
1018
|
+
const [rigidBodyEvents] = React.useState(() => new Map());
|
1019
|
+
const [colliderEvents] = React.useState(() => new Map());
|
1020
|
+
const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false));
|
1021
|
+
const [attractorStates] = React.useState(() => new Map()); // Init world
|
1022
|
+
|
1141
1023
|
React.useEffect(() => {
|
1142
|
-
const
|
1024
|
+
const world = getWorldRef.current();
|
1025
|
+
return () => {
|
1026
|
+
if (world) {
|
1027
|
+
world.free();
|
1028
|
+
worldRef.current = undefined;
|
1029
|
+
}
|
1030
|
+
};
|
1031
|
+
}, []); // Update gravity
|
1143
1032
|
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
}));
|
1033
|
+
React.useEffect(() => {
|
1034
|
+
const world = worldRef.current;
|
1035
|
+
|
1036
|
+
if (world) {
|
1037
|
+
world.gravity = vectorArrayToVector3(_gravity);
|
1150
1038
|
}
|
1151
|
-
}, [
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1039
|
+
}, [_gravity]);
|
1040
|
+
const getSourceFromColliderHandle = React.useCallback(handle => {
|
1041
|
+
const world = worldRef.current;
|
1042
|
+
|
1043
|
+
if (world) {
|
1044
|
+
var _collider$parent;
|
1045
|
+
|
1046
|
+
const collider = world.getCollider(handle);
|
1047
|
+
const colEvents = colliderEvents.get(handle);
|
1048
|
+
const colliderState = colliderStates.get(handle);
|
1049
|
+
const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
|
1050
|
+
const rigidBody = rigidBodyHandle !== undefined ? world.getRigidBody(rigidBodyHandle) : undefined;
|
1051
|
+
const rbEvents = rigidBody && rigidBodyHandle !== undefined ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
|
1052
|
+
const rigidBodyState = rigidBodyHandle !== undefined ? rigidBodyStates.get(rigidBodyHandle) : undefined;
|
1053
|
+
const source = {
|
1054
|
+
collider: {
|
1055
|
+
object: collider,
|
1056
|
+
events: colEvents,
|
1057
|
+
state: colliderState
|
1058
|
+
},
|
1059
|
+
rigidBody: {
|
1060
|
+
object: rigidBody,
|
1061
|
+
events: rbEvents,
|
1062
|
+
state: rigidBodyState
|
1063
|
+
}
|
1064
|
+
};
|
1065
|
+
return source;
|
1066
|
+
}
|
1067
|
+
}, []);
|
1068
|
+
const [steppingState] = React.useState({
|
1069
|
+
previousState: {},
|
1070
|
+
accumulator: 0
|
1071
|
+
});
|
1072
|
+
const step = React.useCallback(dt => {
|
1073
|
+
const world = worldRef.current;
|
1074
|
+
if (!world) return;
|
1075
|
+
/* Check if the timestep is supposed to be variable. We'll do this here
|
1076
|
+
once so we don't have to string-check every frame. */
|
1077
|
+
|
1078
|
+
const timeStepVariable = _timeStep === "vary";
|
1079
|
+
/**
|
1080
|
+
* Fixed timeStep simulation progression
|
1081
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
1082
|
+
*/
|
1083
|
+
|
1084
|
+
const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
|
1085
|
+
|
1086
|
+
if (timeStepVariable) {
|
1087
|
+
world.timestep = clampedDelta;
|
1088
|
+
world.step(eventQueue);
|
1089
|
+
} else {
|
1090
|
+
world.timestep = _timeStep; // don't step time forwards if paused
|
1091
|
+
// Increase accumulator
|
1092
|
+
|
1093
|
+
steppingState.accumulator += clampedDelta;
|
1094
|
+
|
1095
|
+
while (steppingState.accumulator >= _timeStep) {
|
1096
|
+
world.forEachRigidBody(body => {
|
1097
|
+
// Set up previous state
|
1098
|
+
// needed for accurate interpolations if the world steps more than once
|
1099
|
+
if (_interpolate) {
|
1100
|
+
steppingState.previousState = {};
|
1101
|
+
steppingState.previousState[body.handle] = {
|
1102
|
+
position: body.translation(),
|
1103
|
+
rotation: body.rotation()
|
1104
|
+
};
|
1105
|
+
} // Apply attractors
|
1106
|
+
|
1107
|
+
|
1108
|
+
attractorStates.forEach(attractorState => {
|
1109
|
+
applyAttractorForceOnRigidBody(body, attractorState);
|
1110
|
+
});
|
1111
|
+
});
|
1112
|
+
world.step(eventQueue);
|
1113
|
+
steppingState.accumulator -= _timeStep;
|
1114
|
+
}
|
1115
|
+
}
|
1116
|
+
|
1117
|
+
const interpolationAlpha = timeStepVariable || !_interpolate || _paused ? 1 : steppingState.accumulator / _timeStep; // Update meshes
|
1118
|
+
|
1119
|
+
rigidBodyStates.forEach((state, handle) => {
|
1120
|
+
const rigidBody = world.getRigidBody(handle);
|
1121
|
+
const events = rigidBodyEvents.get(handle);
|
1122
|
+
|
1123
|
+
if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
|
1124
|
+
if (rigidBody.isSleeping() && !state.isSleeping) {
|
1125
|
+
var _events$onSleep;
|
1126
|
+
|
1127
|
+
events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
|
1128
|
+
}
|
1129
|
+
|
1130
|
+
if (!rigidBody.isSleeping() && state.isSleeping) {
|
1131
|
+
var _events$onWake;
|
1132
|
+
|
1133
|
+
events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
|
1134
|
+
}
|
1135
|
+
|
1136
|
+
state.isSleeping = rigidBody.isSleeping();
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
|
1140
|
+
return;
|
1141
|
+
} // New states
|
1142
|
+
|
1143
|
+
|
1144
|
+
let t = rigidBody.translation();
|
1145
|
+
let r = rigidBody.rotation();
|
1146
|
+
let previousState = steppingState.previousState[handle];
|
1147
|
+
|
1148
|
+
if (previousState) {
|
1149
|
+
// Get previous simulated world position
|
1150
|
+
_matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale); // Apply previous tick position
|
1151
|
+
|
1152
|
+
|
1153
|
+
if (!(state.object instanceof three.InstancedMesh)) {
|
1154
|
+
state.object.position.copy(_position);
|
1155
|
+
state.object.quaternion.copy(_rotation);
|
1156
|
+
}
|
1157
|
+
} // Get new position
|
1158
|
+
|
1159
|
+
|
1160
|
+
_matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
1161
|
+
|
1162
|
+
if (state.object instanceof three.InstancedMesh) {
|
1163
|
+
state.setMatrix(_matrix4);
|
1164
|
+
state.object.instanceMatrix.needsUpdate = true;
|
1165
|
+
} else {
|
1166
|
+
// Interpolate to new position
|
1167
|
+
state.object.position.lerp(_position, interpolationAlpha);
|
1168
|
+
state.object.quaternion.slerp(_rotation, interpolationAlpha);
|
1169
|
+
}
|
1165
1170
|
});
|
1166
|
-
|
1167
|
-
|
1171
|
+
eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
1172
|
+
const source1 = getSourceFromColliderHandle(handle1);
|
1173
|
+
const source2 = getSourceFromColliderHandle(handle2); // Collision Events
|
1174
|
+
|
1175
|
+
if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
|
1176
|
+
return;
|
1177
|
+
}
|
1178
|
+
|
1179
|
+
const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
|
1180
|
+
const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
|
1168
1181
|
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
const desc = rigidBodyDescFromOptions(options);
|
1173
|
-
const rigidBody = world.createRigidBody(desc);
|
1174
|
-
rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
|
1175
|
-
}
|
1182
|
+
if (started) {
|
1183
|
+
world.contactPair(source1.collider.object, source2.collider.object, (manifold, flipped) => {
|
1184
|
+
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;
|
1176
1185
|
|
1177
|
-
|
1178
|
-
|
1186
|
+
/* RigidBody events */
|
1187
|
+
(_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), {}, {
|
1188
|
+
manifold,
|
1189
|
+
flipped
|
1190
|
+
}));
|
1191
|
+
(_source2$rigidBody$ev = source2.rigidBody.events) === null || _source2$rigidBody$ev === void 0 ? void 0 : (_source2$rigidBody$ev2 = _source2$rigidBody$ev.onCollisionEnter) === null || _source2$rigidBody$ev2 === void 0 ? void 0 : _source2$rigidBody$ev2.call(_source2$rigidBody$ev, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
|
1192
|
+
manifold,
|
1193
|
+
flipped
|
1194
|
+
}));
|
1195
|
+
/* Collider events */
|
1179
1196
|
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1197
|
+
(_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), {}, {
|
1198
|
+
manifold,
|
1199
|
+
flipped
|
1200
|
+
}));
|
1201
|
+
(_source2$collider$eve = source2.collider.events) === null || _source2$collider$eve === void 0 ? void 0 : (_source2$collider$eve2 = _source2$collider$eve.onCollisionEnter) === null || _source2$collider$eve2 === void 0 ? void 0 : _source2$collider$eve2.call(_source2$collider$eve, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
|
1202
|
+
manifold,
|
1203
|
+
flipped
|
1204
|
+
}));
|
1205
|
+
});
|
1206
|
+
} else {
|
1207
|
+
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;
|
1183
1208
|
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1209
|
+
(_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);
|
1210
|
+
(_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);
|
1211
|
+
(_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);
|
1212
|
+
(_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);
|
1213
|
+
} // Sensor Intersections
|
1187
1214
|
|
1188
|
-
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
1189
|
-
rigidBody,
|
1190
|
-
object: ref.current
|
1191
|
-
}));
|
1192
|
-
return () => {
|
1193
|
-
world.removeRigidBody(rigidBody);
|
1194
|
-
rigidBodyStates.delete(rigidBody.handle);
|
1195
|
-
rigidBodyRef.current = undefined;
|
1196
|
-
};
|
1197
|
-
}, []);
|
1198
|
-
useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
|
1199
|
-
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
1200
|
-
const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
1201
|
-
return [ref, api, childColliderProps];
|
1202
|
-
}; // Joints
|
1203
1215
|
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
} = useRapier();
|
1208
|
-
const jointRef = React.useRef();
|
1209
|
-
const getJointRef = React.useRef(() => {
|
1210
|
-
if (!jointRef.current) {
|
1211
|
-
let rb1;
|
1212
|
-
let rb2;
|
1216
|
+
if (started) {
|
1217
|
+
if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
|
1218
|
+
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;
|
1213
1219
|
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1220
|
+
(_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);
|
1221
|
+
(_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);
|
1222
|
+
(_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);
|
1223
|
+
(_source2$collider$eve5 = source2.collider.events) === null || _source2$collider$eve5 === void 0 ? void 0 : (_source2$collider$eve6 = _source2$collider$eve5.onIntersectionEnter) === null || _source2$collider$eve6 === void 0 ? void 0 : _source2$collider$eve6.call(_source2$collider$eve5, collisionPayload2);
|
1224
|
+
}
|
1225
|
+
} else {
|
1226
|
+
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;
|
1227
|
+
|
1228
|
+
(_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);
|
1229
|
+
(_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);
|
1230
|
+
(_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);
|
1231
|
+
(_source2$collider$eve7 = source2.collider.events) === null || _source2$collider$eve7 === void 0 ? void 0 : (_source2$collider$eve8 = _source2$collider$eve7.onIntersectionExit) === null || _source2$collider$eve8 === void 0 ? void 0 : _source2$collider$eve8.call(_source2$collider$eve7, collisionPayload2);
|
1219
1232
|
}
|
1220
|
-
}
|
1233
|
+
});
|
1234
|
+
eventQueue.drainContactForceEvents(event => {
|
1235
|
+
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;
|
1221
1236
|
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
if (joint) {
|
1228
|
-
world.removeImpulseJoint(joint);
|
1229
|
-
jointRef.current = undefined;
|
1237
|
+
const source1 = getSourceFromColliderHandle(event.collider1());
|
1238
|
+
const source2 = getSourceFromColliderHandle(event.collider2()); // Collision Events
|
1239
|
+
|
1240
|
+
if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
|
1241
|
+
return;
|
1230
1242
|
}
|
1231
|
-
};
|
1232
|
-
}, []);
|
1233
|
-
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
1234
|
-
return api;
|
1235
|
-
};
|
1236
|
-
/**
|
1237
|
-
*
|
1238
|
-
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
1239
|
-
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
1240
|
-
* The fixed-joint makes these frames coincide in world-space.
|
1241
|
-
*/
|
1242
1243
|
|
1243
|
-
const
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1244
|
+
const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
|
1245
|
+
const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
|
1246
|
+
(_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), {}, {
|
1247
|
+
totalForce: event.totalForce(),
|
1248
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1249
|
+
maxForceDirection: event.maxForceDirection(),
|
1250
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1251
|
+
}));
|
1252
|
+
(_source2$rigidBody$ev9 = source2.rigidBody.events) === null || _source2$rigidBody$ev9 === void 0 ? void 0 : (_source2$rigidBody$ev10 = _source2$rigidBody$ev9.onContactForce) === null || _source2$rigidBody$ev10 === void 0 ? void 0 : _source2$rigidBody$ev10.call(_source2$rigidBody$ev9, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
|
1253
|
+
totalForce: event.totalForce(),
|
1254
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1255
|
+
maxForceDirection: event.maxForceDirection(),
|
1256
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1257
|
+
}));
|
1258
|
+
(_source1$collider$eve9 = source1.collider.events) === null || _source1$collider$eve9 === void 0 ? void 0 : (_source1$collider$eve10 = _source1$collider$eve9.onContactForce) === null || _source1$collider$eve10 === void 0 ? void 0 : _source1$collider$eve10.call(_source1$collider$eve9, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
|
1259
|
+
totalForce: event.totalForce(),
|
1260
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1261
|
+
maxForceDirection: event.maxForceDirection(),
|
1262
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1263
|
+
}));
|
1264
|
+
(_source2$collider$eve9 = source2.collider.events) === null || _source2$collider$eve9 === void 0 ? void 0 : (_source2$collider$eve10 = _source2$collider$eve9.onContactForce) === null || _source2$collider$eve10 === void 0 ? void 0 : _source2$collider$eve10.call(_source2$collider$eve9, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
|
1265
|
+
totalForce: event.totalForce(),
|
1266
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1267
|
+
maxForceDirection: event.maxForceDirection(),
|
1268
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1269
|
+
}));
|
1270
|
+
});
|
1271
|
+
}, [_paused, _timeStep, _interpolate]);
|
1272
|
+
fiber.useFrame((_, dt) => {
|
1273
|
+
if (!_paused) step(dt);
|
1274
|
+
}, updatePriority);
|
1275
|
+
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
1276
|
+
const context = React.useMemo(() => ({
|
1277
|
+
rapier,
|
1278
|
+
world: api,
|
1279
|
+
physicsOptions: {
|
1280
|
+
colliders: _colliders,
|
1281
|
+
gravity: _gravity
|
1282
|
+
},
|
1283
|
+
rigidBodyStates,
|
1284
|
+
colliderStates,
|
1285
|
+
rigidBodyEvents,
|
1286
|
+
colliderEvents,
|
1287
|
+
attractorStates,
|
1288
|
+
isPaused: _paused,
|
1289
|
+
step
|
1290
|
+
}), [_paused, step]);
|
1291
|
+
return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
|
1292
|
+
value: context
|
1293
|
+
}, children);
|
1252
1294
|
};
|
1253
|
-
/**
|
1254
|
-
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
1255
|
-
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
1256
|
-
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
1257
|
-
* points that need to coincide on the local-space of each rigid-body.
|
1258
|
-
*/
|
1259
1295
|
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
1265
|
-
};
|
1266
|
-
/**
|
1267
|
-
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
1268
|
-
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
1269
|
-
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
1270
|
-
*/
|
1296
|
+
function _extends() {
|
1297
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
1298
|
+
for (var i = 1; i < arguments.length; i++) {
|
1299
|
+
var source = arguments[i];
|
1271
1300
|
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
}
|
1278
|
-
/**
|
1279
|
-
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
1280
|
-
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
1281
|
-
* local tangent axis can be specified for each rigid-body.
|
1282
|
-
*/
|
1301
|
+
for (var key in source) {
|
1302
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
1303
|
+
target[key] = source[key];
|
1304
|
+
}
|
1305
|
+
}
|
1306
|
+
}
|
1283
1307
|
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1308
|
+
return target;
|
1309
|
+
};
|
1310
|
+
return _extends.apply(this, arguments);
|
1311
|
+
}
|
1312
|
+
|
1313
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
1314
|
+
if (source == null) return {};
|
1315
|
+
var target = {};
|
1316
|
+
var sourceKeys = Object.keys(source);
|
1317
|
+
var key, i;
|
1318
|
+
|
1319
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
1320
|
+
key = sourceKeys[i];
|
1321
|
+
if (excluded.indexOf(key) >= 0) continue;
|
1322
|
+
target[key] = source[key];
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
return target;
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
function _objectWithoutProperties(source, excluded) {
|
1329
|
+
if (source == null) return {};
|
1330
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
1331
|
+
var key, i;
|
1332
|
+
|
1333
|
+
if (Object.getOwnPropertySymbols) {
|
1334
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
1335
|
+
|
1336
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
1337
|
+
key = sourceSymbolKeys[i];
|
1338
|
+
if (excluded.indexOf(key) >= 0) continue;
|
1339
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
1340
|
+
target[key] = source[key];
|
1341
|
+
}
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
return target;
|
1345
|
+
}
|
1290
1346
|
|
1291
1347
|
// Colliders
|
1292
1348
|
const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["default"].forwardRef((props, forwardedRef) => {
|
@@ -1414,6 +1470,15 @@ const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((pr
|
|
1414
1470
|
ref: ref
|
1415
1471
|
}));
|
1416
1472
|
});
|
1473
|
+
CuboidCollider.displayName = "CuboidCollider";
|
1474
|
+
RoundCuboidCollider.displayName = "RoundCuboidCollider";
|
1475
|
+
BallCollider.displayName = "BallCollider";
|
1476
|
+
CapsuleCollider.displayName = "CapsuleCollider";
|
1477
|
+
HeightfieldCollider.displayName = "HeightfieldCollider";
|
1478
|
+
TrimeshCollider.displayName = "TrimeshCollider";
|
1479
|
+
ConeCollider.displayName = "ConeCollider";
|
1480
|
+
CylinderCollider.displayName = "CylinderCollider";
|
1481
|
+
ConvexHullCollider.displayName = "ConvexHullCollider";
|
1417
1482
|
|
1418
1483
|
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
|
1419
1484
|
const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
|
@@ -1449,6 +1514,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1449
1514
|
key: index
|
1450
1515
|
}, colliderProps)))));
|
1451
1516
|
}));
|
1517
|
+
RigidBody.displayName = "RigidBody";
|
1452
1518
|
|
1453
1519
|
const MeshCollider = props => {
|
1454
1520
|
const {
|
@@ -1479,26 +1545,96 @@ const MeshCollider = props => {
|
|
1479
1545
|
key: index
|
1480
1546
|
}, colliderProps))));
|
1481
1547
|
};
|
1548
|
+
MeshCollider.displayName = "MeshCollider";
|
1549
|
+
|
1550
|
+
function mapsEqual(map1, map2) {
|
1551
|
+
var testVal;
|
1552
|
+
|
1553
|
+
if (map1.size !== map2.size) {
|
1554
|
+
return false;
|
1555
|
+
}
|
1556
|
+
|
1557
|
+
for (var [key, val] of map1) {
|
1558
|
+
testVal = map2.get(key);
|
1559
|
+
|
1560
|
+
if (testVal !== val || testVal === undefined && !map2.has(key)) {
|
1561
|
+
return false;
|
1562
|
+
}
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
return true;
|
1566
|
+
}
|
1567
|
+
|
1568
|
+
const AttractorHelper = props => {
|
1569
|
+
const {
|
1570
|
+
scene
|
1571
|
+
} = fiber.useThree();
|
1572
|
+
const ref = React.useRef(null);
|
1573
|
+
const normalsHelper = React.useRef();
|
1574
|
+
const color = props.strength > 0 ? 0x0000ff : 0xff0000;
|
1575
|
+
React.useEffect(() => {
|
1576
|
+
if (ref.current) {
|
1577
|
+
normalsHelper.current = new threeStdlib.VertexNormalsHelper(ref.current, props.range, color);
|
1578
|
+
normalsHelper.current.frustumCulled = false;
|
1579
|
+
scene.add(normalsHelper.current);
|
1580
|
+
}
|
1581
|
+
|
1582
|
+
return () => {
|
1583
|
+
if (normalsHelper.current) {
|
1584
|
+
scene.remove(normalsHelper.current);
|
1585
|
+
}
|
1586
|
+
};
|
1587
|
+
}, [props]);
|
1588
|
+
fiber.useFrame(() => {
|
1589
|
+
if (ref.current) {
|
1590
|
+
var _normalsHelper$curren;
|
1591
|
+
|
1592
|
+
const worldPosition = props.object.getWorldPosition(_vector3);
|
1593
|
+
ref.current.position.copy(worldPosition);
|
1594
|
+
(_normalsHelper$curren = normalsHelper.current) === null || _normalsHelper$curren === void 0 ? void 0 : _normalsHelper$curren.update();
|
1595
|
+
}
|
1596
|
+
});
|
1597
|
+
return /*#__PURE__*/React__default["default"].createElement("mesh", {
|
1598
|
+
ref: ref,
|
1599
|
+
position: props.object.position,
|
1600
|
+
frustumCulled: false
|
1601
|
+
}, /*#__PURE__*/React__default["default"].createElement("sphereGeometry", {
|
1602
|
+
args: [0.2, 6, 6]
|
1603
|
+
}), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
|
1604
|
+
color: color,
|
1605
|
+
wireframe: true
|
1606
|
+
}));
|
1607
|
+
};
|
1482
1608
|
|
1483
1609
|
const Debug = () => {
|
1484
1610
|
const {
|
1485
|
-
world
|
1611
|
+
world,
|
1612
|
+
attractorStates
|
1486
1613
|
} = useRapier();
|
1487
1614
|
const ref = React.useRef(null);
|
1615
|
+
const [attractors, setAttractors] = React.useState([]);
|
1616
|
+
const currMap = React.useRef(new Map());
|
1488
1617
|
fiber.useFrame(() => {
|
1489
1618
|
const mesh = ref.current;
|
1490
1619
|
if (!mesh) return;
|
1491
1620
|
const buffers = world.debugRender();
|
1492
1621
|
mesh.geometry.setAttribute("position", new three.BufferAttribute(buffers.vertices, 3));
|
1493
|
-
mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4));
|
1622
|
+
mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4)); // Update attractors
|
1623
|
+
|
1624
|
+
if (!mapsEqual(currMap.current, attractorStates)) {
|
1625
|
+
setAttractors([...attractorStates.values()]);
|
1626
|
+
currMap.current = new Map(attractorStates);
|
1627
|
+
}
|
1494
1628
|
});
|
1495
|
-
return /*#__PURE__*/React__default["default"].createElement("lineSegments", {
|
1629
|
+
return /*#__PURE__*/React__default["default"].createElement("group", null, /*#__PURE__*/React__default["default"].createElement("lineSegments", {
|
1496
1630
|
ref: ref,
|
1497
1631
|
frustumCulled: false
|
1498
1632
|
}, /*#__PURE__*/React__default["default"].createElement("lineBasicMaterial", {
|
1499
1633
|
color: 0xffffff,
|
1500
1634
|
vertexColors: true
|
1501
|
-
}), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null))
|
1635
|
+
}), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React__default["default"].createElement(AttractorHelper, _extends({
|
1636
|
+
key: attractor.object.uuid
|
1637
|
+
}, attractor))));
|
1502
1638
|
};
|
1503
1639
|
|
1504
1640
|
const _excluded = ["positions", "rotations", "children"];
|
@@ -1611,6 +1747,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1611
1747
|
key: index
|
1612
1748
|
}, colliderProps)))));
|
1613
1749
|
});
|
1750
|
+
InstancedRigidBodies.displayName = "InstancedRigidBodies";
|
1614
1751
|
|
1615
1752
|
/**
|
1616
1753
|
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
@@ -1661,6 +1798,7 @@ Object.defineProperty(exports, 'RapierRigidBody', {
|
|
1661
1798
|
get: function () { return rapier3dCompat.RigidBody; }
|
1662
1799
|
});
|
1663
1800
|
exports.AnyCollider = AnyCollider;
|
1801
|
+
exports.Attractor = Attractor;
|
1664
1802
|
exports.BallCollider = BallCollider;
|
1665
1803
|
exports.CapsuleCollider = CapsuleCollider;
|
1666
1804
|
exports.ConeCollider = ConeCollider;
|