@react-three/rapier 0.9.0 → 0.11.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 +1061 -917
- package/dist/react-three-rapier.cjs.prod.js +1061 -917
- package/dist/react-three-rapier.esm.js +1065 -922
- package/package.json +4 -4
- 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,1076 @@ 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
|
+
lockRotations: (rb, value) => {
|
624
|
+
rb.lockRotations(value, true);
|
772
625
|
},
|
773
|
-
|
774
|
-
|
626
|
+
lockTranslations: (rb, value) => {
|
627
|
+
rb.lockTranslations(value, true);
|
628
|
+
},
|
629
|
+
angularVelocity: (rb, [x, y, z]) => {
|
630
|
+
rb.setAngvel({
|
631
|
+
x,
|
632
|
+
y,
|
633
|
+
z
|
634
|
+
}, true);
|
635
|
+
},
|
636
|
+
linearVelocity: (rb, [x, y, z]) => {
|
637
|
+
rb.setLinvel({
|
638
|
+
x,
|
639
|
+
y,
|
640
|
+
z
|
641
|
+
}, true);
|
642
|
+
},
|
643
|
+
ccd: (rb, value) => {
|
644
|
+
rb.enableCcd(value);
|
645
|
+
},
|
646
|
+
userData: (rb, value) => {
|
647
|
+
rb.userData = value;
|
775
648
|
},
|
776
|
-
// To make sure the options all mutalbe options are listed
|
777
|
-
quaternion: () => {},
|
778
649
|
position: () => {},
|
779
650
|
rotation: () => {},
|
651
|
+
quaternion: () => {},
|
780
652
|
scale: () => {}
|
781
653
|
};
|
782
|
-
const
|
783
|
-
const
|
784
|
-
|
654
|
+
const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
|
655
|
+
const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
|
656
|
+
if (!rigidBody) {
|
657
|
+
return;
|
658
|
+
}
|
659
|
+
|
660
|
+
const state = states.get(rigidBody.handle);
|
785
661
|
|
786
662
|
if (state) {
|
787
|
-
|
788
|
-
|
789
|
-
state.object.updateWorldMatrix(true, false);
|
663
|
+
if (updateTranslations) {
|
664
|
+
state.object.updateWorldMatrix(true, false);
|
790
665
|
|
791
|
-
|
666
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
792
667
|
|
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);
|
668
|
+
rigidBody.setTranslation(_position, false);
|
669
|
+
rigidBody.setRotation(_rotation, false);
|
807
670
|
}
|
808
671
|
|
809
|
-
|
672
|
+
mutableRigidBodyOptionKeys.forEach(key => {
|
810
673
|
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);
|
674
|
+
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
814
675
|
}
|
815
|
-
});
|
816
|
-
// are exclusive.
|
817
|
-
|
818
|
-
setColliderMassOptions(collider, options);
|
676
|
+
});
|
819
677
|
}
|
820
678
|
};
|
821
|
-
const
|
679
|
+
const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
|
822
680
|
// TODO: Improve this, split each prop into its own effect
|
823
|
-
const mutablePropsAsFlatArray = React.useMemo(() =>
|
681
|
+
const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
824
682
|
return vectorToTuple(props[key]);
|
825
683
|
}), [props]);
|
826
684
|
React.useEffect(() => {
|
827
|
-
|
828
|
-
|
829
|
-
|
685
|
+
if (Array.isArray(rigidBodyRef.current)) {
|
686
|
+
for (const rigidBody of rigidBodyRef.current) {
|
687
|
+
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
688
|
+
}
|
689
|
+
} else if (rigidBodyRef.current) {
|
690
|
+
setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
|
691
|
+
}
|
830
692
|
}, mutablePropsAsFlatArray);
|
831
693
|
};
|
694
|
+
const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
695
|
+
const {
|
696
|
+
onWake,
|
697
|
+
onSleep,
|
698
|
+
onCollisionEnter,
|
699
|
+
onCollisionExit,
|
700
|
+
onIntersectionEnter,
|
701
|
+
onIntersectionExit
|
702
|
+
} = props;
|
703
|
+
const eventHandlers = {
|
704
|
+
onWake,
|
705
|
+
onSleep,
|
706
|
+
onCollisionEnter,
|
707
|
+
onCollisionExit,
|
708
|
+
onIntersectionEnter,
|
709
|
+
onIntersectionExit
|
710
|
+
};
|
711
|
+
React.useEffect(() => {
|
712
|
+
if (Array.isArray(rigidBodyRef.current)) {
|
713
|
+
for (const rigidBody of rigidBodyRef.current) {
|
714
|
+
events.set(rigidBody.handle, eventHandlers);
|
715
|
+
}
|
716
|
+
} else if (rigidBodyRef.current) {
|
717
|
+
events.set(rigidBodyRef.current.handle, eventHandlers);
|
718
|
+
}
|
832
719
|
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
720
|
+
return () => {
|
721
|
+
if (Array.isArray(rigidBodyRef.current)) {
|
722
|
+
for (const rigidBody of rigidBodyRef.current) {
|
723
|
+
events.delete(rigidBody.handle);
|
724
|
+
}
|
725
|
+
} else if (rigidBodyRef.current) {
|
726
|
+
events.delete(rigidBodyRef.current.handle);
|
727
|
+
}
|
728
|
+
};
|
729
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
839
730
|
};
|
840
731
|
|
841
|
-
const
|
842
|
-
return
|
843
|
-
collider,
|
844
|
-
worldParent: rigidBodyObject || object.parent,
|
845
|
-
object
|
846
|
-
};
|
847
|
-
};
|
848
|
-
const autoColliderMap = {
|
849
|
-
cuboid: "cuboid",
|
850
|
-
ball: "ball",
|
851
|
-
hull: "convexHull",
|
852
|
-
trimesh: "trimesh"
|
732
|
+
const useRapier = () => {
|
733
|
+
return React.useContext(RapierContext);
|
853
734
|
};
|
854
|
-
const
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
}) => {
|
859
|
-
const colliderProps = [];
|
860
|
-
object.updateWorldMatrix(true, false);
|
861
|
-
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
862
|
-
|
863
|
-
const colliderFromChild = child => {
|
864
|
-
if ("isMesh" in child) {
|
865
|
-
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
866
|
-
const worldScale = child.getWorldScale(_scale);
|
867
|
-
const shape = autoColliderMap[options.colliders || "cuboid"];
|
868
|
-
child.updateWorldMatrix(true, false);
|
869
|
-
|
870
|
-
_matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
|
735
|
+
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
736
|
+
const [colliderProps, setColliderProps] = React.useState([]);
|
737
|
+
React.useEffect(() => {
|
738
|
+
const object = ref.current;
|
871
739
|
|
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]
|
740
|
+
if (object && options.colliders !== false) {
|
741
|
+
setColliderProps(createColliderPropsFromChildren({
|
742
|
+
object: ref.current,
|
743
|
+
options,
|
744
|
+
ignoreMeshColliders
|
886
745
|
}));
|
887
746
|
}
|
888
|
-
};
|
889
|
-
|
890
|
-
if (options.includeInvisible) {
|
891
|
-
object.traverse(colliderFromChild);
|
892
|
-
} else {
|
893
|
-
object.traverseVisible(colliderFromChild);
|
894
|
-
}
|
895
|
-
|
747
|
+
}, [options.colliders]);
|
896
748
|
return colliderProps;
|
897
749
|
};
|
898
|
-
const
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
750
|
+
const useRigidBody = (options = {}) => {
|
751
|
+
const {
|
752
|
+
world,
|
753
|
+
rigidBodyStates,
|
754
|
+
physicsOptions,
|
755
|
+
rigidBodyEvents
|
756
|
+
} = useRapier();
|
757
|
+
const ref = React.useRef();
|
758
|
+
const mergedOptions = React.useMemo(() => {
|
759
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
|
760
|
+
children: undefined
|
761
|
+
});
|
762
|
+
}, [physicsOptions, options]);
|
763
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
|
912
764
|
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
return {
|
921
|
-
args: [radius],
|
922
|
-
offset: boundingSphere.center
|
923
|
-
};
|
924
|
-
}
|
765
|
+
const rigidBodyRef = React.useRef();
|
766
|
+
const getRigidBodyRef = React.useRef(() => {
|
767
|
+
if (!rigidBodyRef.current) {
|
768
|
+
const desc = rigidBodyDescFromOptions(options);
|
769
|
+
const rigidBody = world.createRigidBody(desc);
|
770
|
+
rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
|
771
|
+
}
|
925
772
|
|
926
|
-
|
927
|
-
|
928
|
-
var _clonedGeometry$index;
|
773
|
+
return rigidBodyRef.current;
|
774
|
+
}); // Setup
|
929
775
|
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
offset: new three.Vector3()
|
934
|
-
};
|
935
|
-
}
|
776
|
+
React.useEffect(() => {
|
777
|
+
const rigidBody = getRigidBodyRef.current();
|
778
|
+
rigidBodyRef.current = rigidBody;
|
936
779
|
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
return {
|
941
|
-
args: [g.attributes.position.array],
|
942
|
-
offset: new three.Vector3()
|
943
|
-
};
|
944
|
-
}
|
945
|
-
}
|
780
|
+
if (!ref.current) {
|
781
|
+
ref.current = new three.Object3D();
|
782
|
+
}
|
946
783
|
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
784
|
+
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
785
|
+
rigidBody,
|
786
|
+
object: ref.current
|
787
|
+
}));
|
788
|
+
return () => {
|
789
|
+
world.removeRigidBody(rigidBody);
|
790
|
+
rigidBodyStates.delete(rigidBody.handle);
|
791
|
+
rigidBodyRef.current = undefined;
|
792
|
+
};
|
793
|
+
}, []);
|
794
|
+
useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
|
795
|
+
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
796
|
+
const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
797
|
+
return [ref, api, childColliderProps];
|
798
|
+
}; // Joints
|
962
799
|
|
963
|
-
|
964
|
-
|
965
|
-
|
800
|
+
const useImpulseJoint = (body1, body2, params) => {
|
801
|
+
const {
|
802
|
+
world
|
803
|
+
} = useRapier();
|
804
|
+
const jointRef = React.useRef();
|
805
|
+
const getJointRef = React.useRef(() => {
|
806
|
+
if (!jointRef.current) {
|
807
|
+
let rb1;
|
808
|
+
let rb2;
|
966
809
|
|
967
|
-
if (
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
collider.setActiveEvents(rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
|
810
|
+
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
811
|
+
rb1 = world.getRigidBody(body1.current.handle);
|
812
|
+
rb2 = world.getRigidBody(body2.current.handle);
|
813
|
+
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
814
|
+
jointRef.current = newJoint;
|
973
815
|
}
|
816
|
+
}
|
974
817
|
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
onIntersectionExit,
|
980
|
-
onContactForce
|
981
|
-
});
|
982
|
-
});
|
818
|
+
return jointRef.current;
|
819
|
+
});
|
820
|
+
React.useEffect(() => {
|
821
|
+
const joint = getJointRef.current();
|
983
822
|
return () => {
|
984
|
-
|
985
|
-
|
986
|
-
|
823
|
+
if (joint) {
|
824
|
+
world.removeImpulseJoint(joint);
|
825
|
+
jointRef.current = undefined;
|
826
|
+
}
|
987
827
|
};
|
988
|
-
}, [
|
828
|
+
}, []);
|
829
|
+
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
830
|
+
return api;
|
989
831
|
};
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
832
|
+
/**
|
833
|
+
*
|
834
|
+
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
835
|
+
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
836
|
+
* The fixed-joint makes these frames coincide in world-space.
|
837
|
+
*/
|
838
|
+
|
839
|
+
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
840
|
+
const {
|
841
|
+
rapier
|
842
|
+
} = useRapier();
|
843
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
|
844
|
+
w: 1
|
845
|
+
}), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
|
846
|
+
w: 1
|
847
|
+
})));
|
995
848
|
};
|
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
|
-
};
|
849
|
+
/**
|
850
|
+
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
851
|
+
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
852
|
+
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
853
|
+
* points that need to coincide on the local-space of each rigid-body.
|
854
|
+
*/
|
855
|
+
|
856
|
+
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
857
|
+
const {
|
858
|
+
rapier
|
859
|
+
} = useRapier();
|
860
|
+
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
1016
861
|
};
|
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: () => {}
|
862
|
+
/**
|
863
|
+
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
864
|
+
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
865
|
+
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
866
|
+
*/
|
867
|
+
|
868
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
869
|
+
const {
|
870
|
+
rapier
|
871
|
+
} = useRapier();
|
872
|
+
return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
1057
873
|
};
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
874
|
+
/**
|
875
|
+
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
876
|
+
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
877
|
+
* local tangent axis can be specified for each rigid-body.
|
878
|
+
*/
|
1063
879
|
|
1064
|
-
|
880
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
881
|
+
const {
|
882
|
+
rapier
|
883
|
+
} = useRapier();
|
884
|
+
return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
885
|
+
};
|
1065
886
|
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
887
|
+
const calcForceByType = {
|
888
|
+
static: (s, m2, r, d, G) => s,
|
889
|
+
linear: (s, m2, r, d, G) => s * (d / r),
|
890
|
+
newtonian: (s, m2, r, d, G) => G * s * m2 / Math.pow(d, 2)
|
891
|
+
};
|
892
|
+
const applyAttractorForceOnRigidBody = (rigidBody, {
|
893
|
+
object,
|
894
|
+
strength,
|
895
|
+
range,
|
896
|
+
gravitationalConstant,
|
897
|
+
collisionGroups,
|
898
|
+
type
|
899
|
+
}) => {
|
900
|
+
const rbPosition = rigidBody.translation();
|
1069
901
|
|
1070
|
-
|
902
|
+
_position.set(rbPosition.x, rbPosition.y, rbPosition.z);
|
1071
903
|
|
1072
|
-
|
1073
|
-
|
1074
|
-
}
|
904
|
+
const worldPosition = object.getWorldPosition(new three.Vector3());
|
905
|
+
const distance = worldPosition.distanceTo(_position);
|
1075
906
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
907
|
+
if (distance < range) {
|
908
|
+
let force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant); // Prevent wild forces when Attractors collide
|
909
|
+
|
910
|
+
force = force === Infinity ? strength : force; // Naively test if the rigidBody contains a collider in one of the collision groups
|
911
|
+
|
912
|
+
let isRigidBodyInCollisionGroup = collisionGroups === undefined ? true : false;
|
913
|
+
|
914
|
+
if (collisionGroups !== undefined) {
|
915
|
+
for (let i = 0; i < rigidBody.numColliders(); i++) {
|
916
|
+
const collider = rigidBody.collider(i);
|
917
|
+
const colliderCollisionGroups = collider.collisionGroups();
|
918
|
+
|
919
|
+
if ((collisionGroups >> 16 & colliderCollisionGroups) != 0 && (colliderCollisionGroups >> 16 & collisionGroups) != 0) {
|
920
|
+
isRigidBodyInCollisionGroup = true;
|
921
|
+
break;
|
922
|
+
}
|
1092
923
|
}
|
1093
|
-
} else if (rigidBodyRef.current) {
|
1094
|
-
setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
|
1095
924
|
}
|
1096
|
-
|
925
|
+
|
926
|
+
if (isRigidBodyInCollisionGroup) {
|
927
|
+
_vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);
|
928
|
+
|
929
|
+
rigidBody.applyImpulse(_vector3, true);
|
930
|
+
}
|
931
|
+
}
|
1097
932
|
};
|
1098
|
-
const
|
933
|
+
const Attractor = /*#__PURE__*/React.memo(props => {
|
1099
934
|
const {
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
935
|
+
position = [0, 0, 0],
|
936
|
+
strength = 1,
|
937
|
+
range = 10,
|
938
|
+
type = "static",
|
939
|
+
gravitationalConstant = 6.673e-11,
|
940
|
+
collisionGroups
|
1106
941
|
} = props;
|
1107
|
-
const
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
onCollisionExit,
|
1112
|
-
onIntersectionEnter,
|
1113
|
-
onIntersectionExit
|
1114
|
-
};
|
942
|
+
const {
|
943
|
+
attractorStates
|
944
|
+
} = useRapier();
|
945
|
+
const object = React.useRef(null);
|
1115
946
|
React.useEffect(() => {
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
947
|
+
var _object$current;
|
948
|
+
|
949
|
+
let uuid = ((_object$current = object.current) === null || _object$current === void 0 ? void 0 : _object$current.uuid) || "_";
|
950
|
+
|
951
|
+
if (object.current) {
|
952
|
+
attractorStates.set(uuid, {
|
953
|
+
object: object.current,
|
954
|
+
strength,
|
955
|
+
range,
|
956
|
+
type,
|
957
|
+
gravitationalConstant,
|
958
|
+
collisionGroups
|
959
|
+
});
|
1122
960
|
}
|
1123
961
|
|
1124
962
|
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
|
-
}
|
963
|
+
attractorStates.delete(uuid);
|
1132
964
|
};
|
1133
|
-
}, [
|
965
|
+
}, [props]);
|
966
|
+
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
967
|
+
ref: object,
|
968
|
+
position: position
|
969
|
+
});
|
970
|
+
});
|
971
|
+
|
972
|
+
const RapierContext = /*#__PURE__*/React.createContext(undefined);
|
973
|
+
|
974
|
+
const getCollisionPayloadFromSource = (target, other) => {
|
975
|
+
var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
|
976
|
+
|
977
|
+
return {
|
978
|
+
target: {
|
979
|
+
rigidBody: target.rigidBody.object,
|
980
|
+
collider: target.collider.object,
|
981
|
+
colliderObject: (_target$collider$stat = target.collider.state) === null || _target$collider$stat === void 0 ? void 0 : _target$collider$stat.object,
|
982
|
+
rigidBodyObject: (_target$rigidBody$sta = target.rigidBody.state) === null || _target$rigidBody$sta === void 0 ? void 0 : _target$rigidBody$sta.object
|
983
|
+
},
|
984
|
+
other: {
|
985
|
+
rigidBody: other.rigidBody.object,
|
986
|
+
collider: other.collider.object,
|
987
|
+
colliderObject: (_other$collider$state = other.collider.state) === null || _other$collider$state === void 0 ? void 0 : _other$collider$state.object,
|
988
|
+
rigidBodyObject: (_other$rigidBody$stat = other.rigidBody.state) === null || _other$rigidBody$stat === void 0 ? void 0 : _other$rigidBody$stat.object
|
989
|
+
},
|
990
|
+
rigidBody: other.rigidBody.object,
|
991
|
+
collider: other.collider.object,
|
992
|
+
colliderObject: (_other$collider$state2 = other.collider.state) === null || _other$collider$state2 === void 0 ? void 0 : _other$collider$state2.object,
|
993
|
+
rigidBodyObject: (_other$rigidBody$stat2 = other.rigidBody.state) === null || _other$rigidBody$stat2 === void 0 ? void 0 : _other$rigidBody$stat2.object
|
994
|
+
};
|
1134
995
|
};
|
1135
996
|
|
1136
|
-
const
|
1137
|
-
|
997
|
+
const importRapier = async () => {
|
998
|
+
let r = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@dimforge/rapier3d-compat')); });
|
999
|
+
await r.init();
|
1000
|
+
return r;
|
1138
1001
|
};
|
1139
|
-
|
1140
|
-
|
1002
|
+
|
1003
|
+
const Physics = ({
|
1004
|
+
colliders: _colliders = "cuboid",
|
1005
|
+
gravity: _gravity = [0, -9.81, 0],
|
1006
|
+
children,
|
1007
|
+
timeStep: _timeStep = 1 / 60,
|
1008
|
+
paused: _paused = false,
|
1009
|
+
updatePriority,
|
1010
|
+
interpolate: _interpolate = true
|
1011
|
+
}) => {
|
1012
|
+
const rapier = useAsset.useAsset(importRapier);
|
1013
|
+
const worldRef = React.useRef();
|
1014
|
+
const getWorldRef = React.useRef(() => {
|
1015
|
+
if (!worldRef.current) {
|
1016
|
+
const world = new rapier.World(vectorArrayToVector3(_gravity));
|
1017
|
+
worldRef.current = world;
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
return worldRef.current;
|
1021
|
+
});
|
1022
|
+
const [rigidBodyStates] = React.useState(() => new Map());
|
1023
|
+
const [colliderStates] = React.useState(() => new Map());
|
1024
|
+
const [rigidBodyEvents] = React.useState(() => new Map());
|
1025
|
+
const [colliderEvents] = React.useState(() => new Map());
|
1026
|
+
const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false));
|
1027
|
+
const [attractorStates] = React.useState(() => new Map()); // Init world
|
1028
|
+
|
1141
1029
|
React.useEffect(() => {
|
1142
|
-
const
|
1030
|
+
const world = getWorldRef.current();
|
1031
|
+
return () => {
|
1032
|
+
if (world) {
|
1033
|
+
world.free();
|
1034
|
+
worldRef.current = undefined;
|
1035
|
+
}
|
1036
|
+
};
|
1037
|
+
}, []); // Update gravity
|
1143
1038
|
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
}));
|
1039
|
+
React.useEffect(() => {
|
1040
|
+
const world = worldRef.current;
|
1041
|
+
|
1042
|
+
if (world) {
|
1043
|
+
world.gravity = vectorArrayToVector3(_gravity);
|
1150
1044
|
}
|
1151
|
-
}, [
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1045
|
+
}, [_gravity]);
|
1046
|
+
const getSourceFromColliderHandle = React.useCallback(handle => {
|
1047
|
+
const world = worldRef.current;
|
1048
|
+
|
1049
|
+
if (world) {
|
1050
|
+
var _collider$parent;
|
1051
|
+
|
1052
|
+
const collider = world.getCollider(handle);
|
1053
|
+
const colEvents = colliderEvents.get(handle);
|
1054
|
+
const colliderState = colliderStates.get(handle);
|
1055
|
+
const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
|
1056
|
+
const rigidBody = rigidBodyHandle !== undefined ? world.getRigidBody(rigidBodyHandle) : undefined;
|
1057
|
+
const rbEvents = rigidBody && rigidBodyHandle !== undefined ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
|
1058
|
+
const rigidBodyState = rigidBodyHandle !== undefined ? rigidBodyStates.get(rigidBodyHandle) : undefined;
|
1059
|
+
const source = {
|
1060
|
+
collider: {
|
1061
|
+
object: collider,
|
1062
|
+
events: colEvents,
|
1063
|
+
state: colliderState
|
1064
|
+
},
|
1065
|
+
rigidBody: {
|
1066
|
+
object: rigidBody,
|
1067
|
+
events: rbEvents,
|
1068
|
+
state: rigidBodyState
|
1069
|
+
}
|
1070
|
+
};
|
1071
|
+
return source;
|
1072
|
+
}
|
1073
|
+
}, []);
|
1074
|
+
const [steppingState] = React.useState({
|
1075
|
+
previousState: {},
|
1076
|
+
accumulator: 0
|
1077
|
+
});
|
1078
|
+
const step = React.useCallback(dt => {
|
1079
|
+
const world = worldRef.current;
|
1080
|
+
if (!world) return;
|
1081
|
+
/* Check if the timestep is supposed to be variable. We'll do this here
|
1082
|
+
once so we don't have to string-check every frame. */
|
1083
|
+
|
1084
|
+
const timeStepVariable = _timeStep === "vary";
|
1085
|
+
/**
|
1086
|
+
* Fixed timeStep simulation progression
|
1087
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
1088
|
+
*/
|
1089
|
+
|
1090
|
+
const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
|
1091
|
+
|
1092
|
+
if (timeStepVariable) {
|
1093
|
+
world.timestep = clampedDelta;
|
1094
|
+
world.step(eventQueue);
|
1095
|
+
} else {
|
1096
|
+
world.timestep = _timeStep; // don't step time forwards if paused
|
1097
|
+
// Increase accumulator
|
1098
|
+
|
1099
|
+
steppingState.accumulator += clampedDelta;
|
1100
|
+
|
1101
|
+
while (steppingState.accumulator >= _timeStep) {
|
1102
|
+
world.forEachRigidBody(body => {
|
1103
|
+
// Set up previous state
|
1104
|
+
// needed for accurate interpolations if the world steps more than once
|
1105
|
+
if (_interpolate) {
|
1106
|
+
steppingState.previousState = {};
|
1107
|
+
steppingState.previousState[body.handle] = {
|
1108
|
+
position: body.translation(),
|
1109
|
+
rotation: body.rotation()
|
1110
|
+
};
|
1111
|
+
} // Apply attractors
|
1112
|
+
|
1113
|
+
|
1114
|
+
attractorStates.forEach(attractorState => {
|
1115
|
+
applyAttractorForceOnRigidBody(body, attractorState);
|
1116
|
+
});
|
1117
|
+
});
|
1118
|
+
world.step(eventQueue);
|
1119
|
+
steppingState.accumulator -= _timeStep;
|
1120
|
+
}
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
const interpolationAlpha = timeStepVariable || !_interpolate || _paused ? 1 : steppingState.accumulator / _timeStep; // Update meshes
|
1124
|
+
|
1125
|
+
rigidBodyStates.forEach((state, handle) => {
|
1126
|
+
const rigidBody = world.getRigidBody(handle);
|
1127
|
+
const events = rigidBodyEvents.get(handle);
|
1128
|
+
|
1129
|
+
if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
|
1130
|
+
if (rigidBody.isSleeping() && !state.isSleeping) {
|
1131
|
+
var _events$onSleep;
|
1132
|
+
|
1133
|
+
events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
|
1134
|
+
}
|
1135
|
+
|
1136
|
+
if (!rigidBody.isSleeping() && state.isSleeping) {
|
1137
|
+
var _events$onWake;
|
1138
|
+
|
1139
|
+
events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
|
1140
|
+
}
|
1141
|
+
|
1142
|
+
state.isSleeping = rigidBody.isSleeping();
|
1143
|
+
}
|
1144
|
+
|
1145
|
+
if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
|
1146
|
+
return;
|
1147
|
+
} // New states
|
1148
|
+
|
1149
|
+
|
1150
|
+
let t = rigidBody.translation();
|
1151
|
+
let r = rigidBody.rotation();
|
1152
|
+
let previousState = steppingState.previousState[handle];
|
1153
|
+
|
1154
|
+
if (previousState) {
|
1155
|
+
// Get previous simulated world position
|
1156
|
+
_matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale); // Apply previous tick position
|
1157
|
+
|
1158
|
+
|
1159
|
+
if (!(state.object instanceof three.InstancedMesh)) {
|
1160
|
+
state.object.position.copy(_position);
|
1161
|
+
state.object.quaternion.copy(_rotation);
|
1162
|
+
}
|
1163
|
+
} // Get new position
|
1164
|
+
|
1165
|
+
|
1166
|
+
_matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
1167
|
+
|
1168
|
+
if (state.object instanceof three.InstancedMesh) {
|
1169
|
+
state.setMatrix(_matrix4);
|
1170
|
+
state.object.instanceMatrix.needsUpdate = true;
|
1171
|
+
} else {
|
1172
|
+
// Interpolate to new position
|
1173
|
+
state.object.position.lerp(_position, interpolationAlpha);
|
1174
|
+
state.object.quaternion.slerp(_rotation, interpolationAlpha);
|
1175
|
+
}
|
1165
1176
|
});
|
1166
|
-
|
1167
|
-
|
1177
|
+
eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
1178
|
+
const source1 = getSourceFromColliderHandle(handle1);
|
1179
|
+
const source2 = getSourceFromColliderHandle(handle2); // Collision Events
|
1180
|
+
|
1181
|
+
if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
|
1182
|
+
return;
|
1183
|
+
}
|
1184
|
+
|
1185
|
+
const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
|
1186
|
+
const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
|
1168
1187
|
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
const desc = rigidBodyDescFromOptions(options);
|
1173
|
-
const rigidBody = world.createRigidBody(desc);
|
1174
|
-
rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
|
1175
|
-
}
|
1188
|
+
if (started) {
|
1189
|
+
world.contactPair(source1.collider.object, source2.collider.object, (manifold, flipped) => {
|
1190
|
+
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
1191
|
|
1177
|
-
|
1178
|
-
|
1192
|
+
/* RigidBody events */
|
1193
|
+
(_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), {}, {
|
1194
|
+
manifold,
|
1195
|
+
flipped
|
1196
|
+
}));
|
1197
|
+
(_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), {}, {
|
1198
|
+
manifold,
|
1199
|
+
flipped
|
1200
|
+
}));
|
1201
|
+
/* Collider events */
|
1179
1202
|
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1203
|
+
(_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), {}, {
|
1204
|
+
manifold,
|
1205
|
+
flipped
|
1206
|
+
}));
|
1207
|
+
(_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), {}, {
|
1208
|
+
manifold,
|
1209
|
+
flipped
|
1210
|
+
}));
|
1211
|
+
});
|
1212
|
+
} else {
|
1213
|
+
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
1214
|
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1215
|
+
(_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);
|
1216
|
+
(_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);
|
1217
|
+
(_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);
|
1218
|
+
(_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);
|
1219
|
+
} // Sensor Intersections
|
1187
1220
|
|
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
1221
|
|
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;
|
1222
|
+
if (started) {
|
1223
|
+
if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
|
1224
|
+
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
1225
|
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1226
|
+
(_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);
|
1227
|
+
(_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);
|
1228
|
+
(_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);
|
1229
|
+
(_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);
|
1230
|
+
}
|
1231
|
+
} else {
|
1232
|
+
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;
|
1233
|
+
|
1234
|
+
(_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);
|
1235
|
+
(_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);
|
1236
|
+
(_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);
|
1237
|
+
(_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
1238
|
}
|
1220
|
-
}
|
1239
|
+
});
|
1240
|
+
eventQueue.drainContactForceEvents(event => {
|
1241
|
+
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
1242
|
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
if (joint) {
|
1228
|
-
world.removeImpulseJoint(joint);
|
1229
|
-
jointRef.current = undefined;
|
1243
|
+
const source1 = getSourceFromColliderHandle(event.collider1());
|
1244
|
+
const source2 = getSourceFromColliderHandle(event.collider2()); // Collision Events
|
1245
|
+
|
1246
|
+
if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
|
1247
|
+
return;
|
1230
1248
|
}
|
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
1249
|
|
1243
|
-
const
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1250
|
+
const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
|
1251
|
+
const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
|
1252
|
+
(_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), {}, {
|
1253
|
+
totalForce: event.totalForce(),
|
1254
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1255
|
+
maxForceDirection: event.maxForceDirection(),
|
1256
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1257
|
+
}));
|
1258
|
+
(_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), {}, {
|
1259
|
+
totalForce: event.totalForce(),
|
1260
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1261
|
+
maxForceDirection: event.maxForceDirection(),
|
1262
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1263
|
+
}));
|
1264
|
+
(_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), {}, {
|
1265
|
+
totalForce: event.totalForce(),
|
1266
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1267
|
+
maxForceDirection: event.maxForceDirection(),
|
1268
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1269
|
+
}));
|
1270
|
+
(_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), {}, {
|
1271
|
+
totalForce: event.totalForce(),
|
1272
|
+
totalForceMagnitude: event.totalForceMagnitude(),
|
1273
|
+
maxForceDirection: event.maxForceDirection(),
|
1274
|
+
maxForceMagnitude: event.maxForceMagnitude()
|
1275
|
+
}));
|
1276
|
+
});
|
1277
|
+
}, [_paused, _timeStep, _interpolate]);
|
1278
|
+
fiber.useFrame((_, dt) => {
|
1279
|
+
if (!_paused) step(dt);
|
1280
|
+
}, updatePriority);
|
1281
|
+
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
1282
|
+
const context = React.useMemo(() => ({
|
1283
|
+
rapier,
|
1284
|
+
world: api,
|
1285
|
+
physicsOptions: {
|
1286
|
+
colliders: _colliders,
|
1287
|
+
gravity: _gravity
|
1288
|
+
},
|
1289
|
+
rigidBodyStates,
|
1290
|
+
colliderStates,
|
1291
|
+
rigidBodyEvents,
|
1292
|
+
colliderEvents,
|
1293
|
+
attractorStates,
|
1294
|
+
isPaused: _paused,
|
1295
|
+
step
|
1296
|
+
}), [_paused, step]);
|
1297
|
+
return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
|
1298
|
+
value: context
|
1299
|
+
}, children);
|
1252
1300
|
};
|
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
1301
|
|
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
|
-
*/
|
1302
|
+
function _extends() {
|
1303
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
1304
|
+
for (var i = 1; i < arguments.length; i++) {
|
1305
|
+
var source = arguments[i];
|
1271
1306
|
|
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
|
-
*/
|
1307
|
+
for (var key in source) {
|
1308
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
1309
|
+
target[key] = source[key];
|
1310
|
+
}
|
1311
|
+
}
|
1312
|
+
}
|
1283
1313
|
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1314
|
+
return target;
|
1315
|
+
};
|
1316
|
+
return _extends.apply(this, arguments);
|
1317
|
+
}
|
1318
|
+
|
1319
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
1320
|
+
if (source == null) return {};
|
1321
|
+
var target = {};
|
1322
|
+
var sourceKeys = Object.keys(source);
|
1323
|
+
var key, i;
|
1324
|
+
|
1325
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
1326
|
+
key = sourceKeys[i];
|
1327
|
+
if (excluded.indexOf(key) >= 0) continue;
|
1328
|
+
target[key] = source[key];
|
1329
|
+
}
|
1330
|
+
|
1331
|
+
return target;
|
1332
|
+
}
|
1333
|
+
|
1334
|
+
function _objectWithoutProperties(source, excluded) {
|
1335
|
+
if (source == null) return {};
|
1336
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
1337
|
+
var key, i;
|
1338
|
+
|
1339
|
+
if (Object.getOwnPropertySymbols) {
|
1340
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
1341
|
+
|
1342
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
1343
|
+
key = sourceSymbolKeys[i];
|
1344
|
+
if (excluded.indexOf(key) >= 0) continue;
|
1345
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
1346
|
+
target[key] = source[key];
|
1347
|
+
}
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
return target;
|
1351
|
+
}
|
1290
1352
|
|
1291
1353
|
// Colliders
|
1292
1354
|
const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["default"].forwardRef((props, forwardedRef) => {
|
@@ -1414,6 +1476,15 @@ const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((pr
|
|
1414
1476
|
ref: ref
|
1415
1477
|
}));
|
1416
1478
|
});
|
1479
|
+
CuboidCollider.displayName = "CuboidCollider";
|
1480
|
+
RoundCuboidCollider.displayName = "RoundCuboidCollider";
|
1481
|
+
BallCollider.displayName = "BallCollider";
|
1482
|
+
CapsuleCollider.displayName = "CapsuleCollider";
|
1483
|
+
HeightfieldCollider.displayName = "HeightfieldCollider";
|
1484
|
+
TrimeshCollider.displayName = "TrimeshCollider";
|
1485
|
+
ConeCollider.displayName = "ConeCollider";
|
1486
|
+
CylinderCollider.displayName = "CylinderCollider";
|
1487
|
+
ConvexHullCollider.displayName = "ConvexHullCollider";
|
1417
1488
|
|
1418
1489
|
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
|
1419
1490
|
const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
|
@@ -1449,6 +1520,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1449
1520
|
key: index
|
1450
1521
|
}, colliderProps)))));
|
1451
1522
|
}));
|
1523
|
+
RigidBody.displayName = "RigidBody";
|
1452
1524
|
|
1453
1525
|
const MeshCollider = props => {
|
1454
1526
|
const {
|
@@ -1479,26 +1551,96 @@ const MeshCollider = props => {
|
|
1479
1551
|
key: index
|
1480
1552
|
}, colliderProps))));
|
1481
1553
|
};
|
1554
|
+
MeshCollider.displayName = "MeshCollider";
|
1555
|
+
|
1556
|
+
function mapsEqual(map1, map2) {
|
1557
|
+
var testVal;
|
1558
|
+
|
1559
|
+
if (map1.size !== map2.size) {
|
1560
|
+
return false;
|
1561
|
+
}
|
1562
|
+
|
1563
|
+
for (var [key, val] of map1) {
|
1564
|
+
testVal = map2.get(key);
|
1565
|
+
|
1566
|
+
if (testVal !== val || testVal === undefined && !map2.has(key)) {
|
1567
|
+
return false;
|
1568
|
+
}
|
1569
|
+
}
|
1570
|
+
|
1571
|
+
return true;
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
const AttractorHelper = props => {
|
1575
|
+
const {
|
1576
|
+
scene
|
1577
|
+
} = fiber.useThree();
|
1578
|
+
const ref = React.useRef(null);
|
1579
|
+
const normalsHelper = React.useRef();
|
1580
|
+
const color = props.strength > 0 ? 0x0000ff : 0xff0000;
|
1581
|
+
React.useEffect(() => {
|
1582
|
+
if (ref.current) {
|
1583
|
+
normalsHelper.current = new threeStdlib.VertexNormalsHelper(ref.current, props.range, color);
|
1584
|
+
normalsHelper.current.frustumCulled = false;
|
1585
|
+
scene.add(normalsHelper.current);
|
1586
|
+
}
|
1587
|
+
|
1588
|
+
return () => {
|
1589
|
+
if (normalsHelper.current) {
|
1590
|
+
scene.remove(normalsHelper.current);
|
1591
|
+
}
|
1592
|
+
};
|
1593
|
+
}, [props]);
|
1594
|
+
fiber.useFrame(() => {
|
1595
|
+
if (ref.current) {
|
1596
|
+
var _normalsHelper$curren;
|
1597
|
+
|
1598
|
+
const worldPosition = props.object.getWorldPosition(_vector3);
|
1599
|
+
ref.current.position.copy(worldPosition);
|
1600
|
+
(_normalsHelper$curren = normalsHelper.current) === null || _normalsHelper$curren === void 0 ? void 0 : _normalsHelper$curren.update();
|
1601
|
+
}
|
1602
|
+
});
|
1603
|
+
return /*#__PURE__*/React__default["default"].createElement("mesh", {
|
1604
|
+
ref: ref,
|
1605
|
+
position: props.object.position,
|
1606
|
+
frustumCulled: false
|
1607
|
+
}, /*#__PURE__*/React__default["default"].createElement("sphereGeometry", {
|
1608
|
+
args: [0.2, 6, 6]
|
1609
|
+
}), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
|
1610
|
+
color: color,
|
1611
|
+
wireframe: true
|
1612
|
+
}));
|
1613
|
+
};
|
1482
1614
|
|
1483
1615
|
const Debug = () => {
|
1484
1616
|
const {
|
1485
|
-
world
|
1617
|
+
world,
|
1618
|
+
attractorStates
|
1486
1619
|
} = useRapier();
|
1487
1620
|
const ref = React.useRef(null);
|
1621
|
+
const [attractors, setAttractors] = React.useState([]);
|
1622
|
+
const currMap = React.useRef(new Map());
|
1488
1623
|
fiber.useFrame(() => {
|
1489
1624
|
const mesh = ref.current;
|
1490
1625
|
if (!mesh) return;
|
1491
1626
|
const buffers = world.debugRender();
|
1492
1627
|
mesh.geometry.setAttribute("position", new three.BufferAttribute(buffers.vertices, 3));
|
1493
|
-
mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4));
|
1628
|
+
mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4)); // Update attractors
|
1629
|
+
|
1630
|
+
if (!mapsEqual(currMap.current, attractorStates)) {
|
1631
|
+
setAttractors([...attractorStates.values()]);
|
1632
|
+
currMap.current = new Map(attractorStates);
|
1633
|
+
}
|
1494
1634
|
});
|
1495
|
-
return /*#__PURE__*/React__default["default"].createElement("lineSegments", {
|
1635
|
+
return /*#__PURE__*/React__default["default"].createElement("group", null, /*#__PURE__*/React__default["default"].createElement("lineSegments", {
|
1496
1636
|
ref: ref,
|
1497
1637
|
frustumCulled: false
|
1498
1638
|
}, /*#__PURE__*/React__default["default"].createElement("lineBasicMaterial", {
|
1499
1639
|
color: 0xffffff,
|
1500
1640
|
vertexColors: true
|
1501
|
-
}), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null))
|
1641
|
+
}), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React__default["default"].createElement(AttractorHelper, _extends({
|
1642
|
+
key: attractor.object.uuid
|
1643
|
+
}, attractor))));
|
1502
1644
|
};
|
1503
1645
|
|
1504
1646
|
const _excluded = ["positions", "rotations", "children"];
|
@@ -1611,6 +1753,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1611
1753
|
key: index
|
1612
1754
|
}, colliderProps)))));
|
1613
1755
|
});
|
1756
|
+
InstancedRigidBodies.displayName = "InstancedRigidBodies";
|
1614
1757
|
|
1615
1758
|
/**
|
1616
1759
|
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
@@ -1661,6 +1804,7 @@ Object.defineProperty(exports, 'RapierRigidBody', {
|
|
1661
1804
|
get: function () { return rapier3dCompat.RigidBody; }
|
1662
1805
|
});
|
1663
1806
|
exports.AnyCollider = AnyCollider;
|
1807
|
+
exports.Attractor = Attractor;
|
1664
1808
|
exports.BallCollider = BallCollider;
|
1665
1809
|
exports.CapsuleCollider = CapsuleCollider;
|
1666
1810
|
exports.ConeCollider = ConeCollider;
|