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