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