@react-three/rapier 0.12.2 → 0.13.1
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/{AnyCollider.d.ts → components/AnyCollider.d.ts} +51 -11
- package/dist/declarations/src/{Attractor.d.ts → components/Attractor.d.ts} +0 -0
- package/dist/declarations/src/{Debug.d.ts → components/Debug.d.ts} +0 -0
- package/dist/declarations/src/components/InstancedRigidBodies.d.ts +12 -0
- package/dist/declarations/src/{MeshCollider.d.ts → components/MeshCollider.d.ts} +5 -1
- package/dist/declarations/src/{Physics.d.ts → components/Physics.d.ts} +10 -3
- package/dist/declarations/src/{RigidBody.d.ts → components/RigidBody.d.ts} +10 -8
- package/dist/declarations/src/{hooks.d.ts → hooks/hooks.d.ts} +17 -5
- package/dist/declarations/src/{joints.d.ts → hooks/joints.d.ts} +19 -8
- package/dist/declarations/src/hooks/use-imperative-instance.d.ts +4 -0
- package/dist/declarations/src/index.d.ts +18 -17
- package/dist/declarations/src/types.d.ts +10 -10
- package/dist/declarations/src/utils/api.d.ts +18 -0
- package/dist/declarations/src/{interaction-groups.d.ts → utils/interaction-groups.d.ts} +0 -0
- package/dist/declarations/src/{shared-objects.d.ts → utils/shared-objects.d.ts} +0 -0
- package/dist/declarations/src/utils/three-object-helpers.d.ts +29 -0
- package/dist/declarations/src/{utils-collider.d.ts → utils/utils-collider.d.ts} +6 -7
- package/dist/declarations/src/{utils-rigidbody.d.ts → utils/utils-rigidbody.d.ts} +6 -6
- package/dist/declarations/src/{utils.d.ts → utils/utils.d.ts} +2 -2
- package/dist/react-three-rapier.cjs.dev.js +546 -589
- package/dist/react-three-rapier.cjs.prod.js +546 -589
- package/dist/react-three-rapier.esm.js +547 -593
- package/package.json +12 -12
- package/readme.md +165 -52
- package/dist/declarations/src/InstancedRigidBodies.d.ts +0 -10
- package/dist/declarations/src/api.d.ts +0 -179
@@ -72,10 +72,44 @@ function _objectSpread2(target) {
|
|
72
72
|
return target;
|
73
73
|
}
|
74
74
|
|
75
|
+
const createWorldApi = ref => {
|
76
|
+
return {
|
77
|
+
raw: () => ref.current(),
|
78
|
+
getCollider: handle => ref.current().getCollider(handle),
|
79
|
+
getRigidBody: handle => ref.current().getRigidBody(handle),
|
80
|
+
createRigidBody: desc => ref.current().createRigidBody(desc),
|
81
|
+
createCollider: (desc, rigidBody) => ref.current().createCollider(desc, rigidBody),
|
82
|
+
removeRigidBody: rigidBody => {
|
83
|
+
if (!ref.current().bodies.contains(rigidBody.handle)) return;
|
84
|
+
ref.current().removeRigidBody(rigidBody);
|
85
|
+
},
|
86
|
+
removeCollider: (collider, wakeUp = true) => {
|
87
|
+
if (!ref.current().colliders.contains(collider.handle)) return;
|
88
|
+
ref.current().removeCollider(collider, wakeUp);
|
89
|
+
},
|
90
|
+
createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
|
91
|
+
removeImpulseJoint: (joint, wakeUp = true) => {
|
92
|
+
if (!ref.current().impulseJoints.contains(joint.handle)) return;
|
93
|
+
ref.current().removeImpulseJoint(joint, wakeUp);
|
94
|
+
},
|
95
|
+
forEachCollider: callback => ref.current().forEachCollider(callback),
|
96
|
+
setGravity: ({
|
97
|
+
x,
|
98
|
+
y,
|
99
|
+
z
|
100
|
+
}) => ref.current().gravity = {
|
101
|
+
x,
|
102
|
+
y,
|
103
|
+
z
|
104
|
+
},
|
105
|
+
debugRender: () => ref.current().debugRender()
|
106
|
+
};
|
107
|
+
};
|
108
|
+
|
75
109
|
const _quaternion = new three.Quaternion();
|
76
110
|
new three.Euler();
|
77
111
|
const _vector3 = new three.Vector3();
|
78
|
-
|
112
|
+
new three.Object3D();
|
79
113
|
const _matrix4 = new three.Matrix4();
|
80
114
|
const _position = new three.Vector3();
|
81
115
|
const _rotation = new three.Quaternion();
|
@@ -91,11 +125,6 @@ const tupleToObject = (tuple, keys) => {
|
|
91
125
|
return obj;
|
92
126
|
}, {});
|
93
127
|
};
|
94
|
-
const rapierVector3ToVector3 = ({
|
95
|
-
x,
|
96
|
-
y,
|
97
|
-
z
|
98
|
-
}) => _vector3.set(x, y, z);
|
99
128
|
const rapierQuaternionToQuaternion = ({
|
100
129
|
x,
|
101
130
|
y,
|
@@ -149,152 +178,6 @@ function useConst(initialValue) {
|
|
149
178
|
return ref.current.value;
|
150
179
|
}
|
151
180
|
|
152
|
-
const createRigidBodyApi = ref => {
|
153
|
-
return {
|
154
|
-
raw: () => ref.current(),
|
155
|
-
|
156
|
-
get handle() {
|
157
|
-
return ref.current().handle;
|
158
|
-
},
|
159
|
-
|
160
|
-
mass: () => ref.current().mass(),
|
161
|
-
|
162
|
-
applyImpulse(impulseVector, wakeUp = true) {
|
163
|
-
ref.current().applyImpulse(impulseVector, wakeUp);
|
164
|
-
},
|
165
|
-
|
166
|
-
applyTorqueImpulse(torqueVector, wakeUp = true) {
|
167
|
-
ref.current().applyTorqueImpulse(torqueVector, wakeUp);
|
168
|
-
},
|
169
|
-
|
170
|
-
applyImpulseAtPoint: (impulseVector, impulsePoint, wakeUp = true) => ref.current().applyImpulseAtPoint(impulseVector, impulsePoint, wakeUp),
|
171
|
-
addForce: (force, wakeUp = true) => ref.current().addForce(force, wakeUp),
|
172
|
-
addForceAtPoint: (force, point, wakeUp = true) => ref.current().addForceAtPoint(force, point, wakeUp),
|
173
|
-
addTorque: (torque, wakeUp = true) => ref.current().addTorque(torque, wakeUp),
|
174
|
-
|
175
|
-
translation() {
|
176
|
-
return rapierVector3ToVector3(ref.current().translation());
|
177
|
-
},
|
178
|
-
|
179
|
-
setTranslation: (translation, wakeUp = true) => ref.current().setTranslation(translation, wakeUp),
|
180
|
-
|
181
|
-
rotation() {
|
182
|
-
const {
|
183
|
-
x,
|
184
|
-
y,
|
185
|
-
z,
|
186
|
-
w
|
187
|
-
} = ref.current().rotation();
|
188
|
-
return new three.Quaternion(x, y, z, w);
|
189
|
-
},
|
190
|
-
|
191
|
-
setRotation: (rotation, wakeUp = true) => {
|
192
|
-
ref.current().setRotation(rotation, wakeUp);
|
193
|
-
},
|
194
|
-
|
195
|
-
linvel() {
|
196
|
-
const {
|
197
|
-
x,
|
198
|
-
y,
|
199
|
-
z
|
200
|
-
} = ref.current().linvel();
|
201
|
-
return new three.Vector3(x, y, z);
|
202
|
-
},
|
203
|
-
|
204
|
-
setLinvel: (velocity, wakeUp = true) => ref.current().setLinvel(velocity, wakeUp),
|
205
|
-
|
206
|
-
angvel() {
|
207
|
-
const {
|
208
|
-
x,
|
209
|
-
y,
|
210
|
-
z
|
211
|
-
} = ref.current().angvel();
|
212
|
-
return new three.Vector3(x, y, z);
|
213
|
-
},
|
214
|
-
|
215
|
-
setAngvel: (velocity, wakeUp = true) => ref.current().setAngvel(velocity, wakeUp),
|
216
|
-
|
217
|
-
linearDamping() {
|
218
|
-
return ref.current().linearDamping();
|
219
|
-
},
|
220
|
-
|
221
|
-
setLinearDamping: factor => ref.current().setLinearDamping(factor),
|
222
|
-
|
223
|
-
angularDamping() {
|
224
|
-
return ref.current().angularDamping();
|
225
|
-
},
|
226
|
-
|
227
|
-
setAngularDamping: factor => ref.current().setAngularDamping(factor),
|
228
|
-
setNextKinematicRotation: rotation => {
|
229
|
-
ref.current().setNextKinematicRotation(rotation);
|
230
|
-
},
|
231
|
-
setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
|
232
|
-
resetForces: (wakeUp = true) => ref.current().resetForces(wakeUp),
|
233
|
-
resetTorques: (wakeUp = true) => ref.current().resetTorques(wakeUp),
|
234
|
-
lockRotations: (locked, wakeUp = true) => ref.current().lockRotations(locked, wakeUp),
|
235
|
-
lockTranslations: (locked, wakeUp = true) => ref.current().lockTranslations(locked, wakeUp),
|
236
|
-
setEnabledRotations: (x, y, z, wakeUp = true) => ref.current().setEnabledRotations(x, y, z, wakeUp),
|
237
|
-
setEnabledTranslations: (x, y, z, wakeUp = true) => ref.current().setEnabledTranslations(x, y, z, wakeUp)
|
238
|
-
};
|
239
|
-
};
|
240
|
-
const createInstancedRigidBodiesApi = bodiesGetter => ({
|
241
|
-
at: index => bodiesGetter.current()[index].api,
|
242
|
-
|
243
|
-
forEach(callback) {
|
244
|
-
return bodiesGetter.current().map(b => b.api).forEach(callback);
|
245
|
-
},
|
246
|
-
|
247
|
-
get count() {
|
248
|
-
return bodiesGetter.current().length;
|
249
|
-
}
|
250
|
-
|
251
|
-
});
|
252
|
-
const createWorldApi = ref => {
|
253
|
-
return {
|
254
|
-
raw: () => ref.current(),
|
255
|
-
getCollider: handle => ref.current().getCollider(handle),
|
256
|
-
getRigidBody: handle => ref.current().getRigidBody(handle),
|
257
|
-
createRigidBody: desc => ref.current().createRigidBody(desc),
|
258
|
-
createCollider: (desc, rigidBody) => ref.current().createCollider(desc, rigidBody),
|
259
|
-
removeRigidBody: rigidBody => {
|
260
|
-
if (!ref.current().bodies.contains(rigidBody.handle)) return;
|
261
|
-
ref.current().removeRigidBody(rigidBody);
|
262
|
-
},
|
263
|
-
removeCollider: (collider, wakeUp = true) => {
|
264
|
-
if (!ref.current().colliders.contains(collider.handle)) return;
|
265
|
-
ref.current().removeCollider(collider, wakeUp);
|
266
|
-
},
|
267
|
-
createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
|
268
|
-
removeImpulseJoint: (joint, wakeUp = true) => {
|
269
|
-
if (!ref.current().impulseJoints.contains(joint.handle)) return;
|
270
|
-
ref.current().removeImpulseJoint(joint, wakeUp);
|
271
|
-
},
|
272
|
-
forEachCollider: callback => ref.current().forEachCollider(callback),
|
273
|
-
setGravity: ({
|
274
|
-
x,
|
275
|
-
y,
|
276
|
-
z
|
277
|
-
}) => ref.current().gravity = {
|
278
|
-
x,
|
279
|
-
y,
|
280
|
-
z
|
281
|
-
},
|
282
|
-
debugRender: () => ref.current().debugRender()
|
283
|
-
};
|
284
|
-
};
|
285
|
-
const createJointApi = ref => {
|
286
|
-
return {
|
287
|
-
raw: () => ref.current(),
|
288
|
-
|
289
|
-
get handle() {
|
290
|
-
return ref.current().handle;
|
291
|
-
},
|
292
|
-
|
293
|
-
configureMotorPosition: (targetPos, stiffness, damping) => ref.current().configureMotorPosition(targetPos, stiffness, damping),
|
294
|
-
configureMotorVelocity: (targetVel, damping) => ref.current().configureMotorVelocity(targetVel, damping)
|
295
|
-
};
|
296
|
-
};
|
297
|
-
|
298
181
|
const scaleColliderArgs = (shape, args, scale) => {
|
299
182
|
const newArgs = args.slice(); // Heightfield uses a vector
|
300
183
|
|
@@ -316,11 +199,11 @@ const scaleColliderArgs = (shape, args, scale) => {
|
|
316
199
|
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
317
200
|
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
318
201
|
};
|
319
|
-
const createColliderFromOptions = (options, world, scale,
|
202
|
+
const createColliderFromOptions = (options, world, scale, getRigidBody) => {
|
320
203
|
const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
|
321
204
|
|
322
205
|
const desc = rapier3dCompat.ColliderDesc[options.shape](...scaledArgs);
|
323
|
-
return world.createCollider(desc,
|
206
|
+
return world.createCollider(desc, getRigidBody === null || getRigidBody === void 0 ? void 0 : getRigidBody());
|
324
207
|
};
|
325
208
|
const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
|
326
209
|
|
@@ -424,15 +307,14 @@ const setColliderOptions = (collider, options, states) => {
|
|
424
307
|
setColliderMassOptions(collider, options);
|
425
308
|
}
|
426
309
|
};
|
427
|
-
const useUpdateColliderOptions = (
|
310
|
+
const useUpdateColliderOptions = (getCollider, props, states) => {
|
428
311
|
// TODO: Improve this, split each prop into its own effect
|
429
312
|
const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
|
430
313
|
return vectorToTuple(props[key]);
|
431
314
|
}), [props]);
|
432
315
|
React.useEffect(() => {
|
433
|
-
|
434
|
-
|
435
|
-
});
|
316
|
+
const collider = getCollider();
|
317
|
+
setColliderOptions(collider, props, states);
|
436
318
|
}, mutablePropsAsFlatArray);
|
437
319
|
};
|
438
320
|
|
@@ -555,7 +437,7 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
555
437
|
offset: new three.Vector3()
|
556
438
|
};
|
557
439
|
};
|
558
|
-
const useColliderEvents = (
|
440
|
+
const useColliderEvents = (getCollider, props, events) => {
|
559
441
|
const {
|
560
442
|
onCollisionEnter,
|
561
443
|
onCollisionExit,
|
@@ -564,9 +446,9 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
564
446
|
onContactForce
|
565
447
|
} = props;
|
566
448
|
React.useEffect(() => {
|
567
|
-
|
449
|
+
const collider = getCollider();
|
568
450
|
|
569
|
-
|
451
|
+
if (collider) {
|
570
452
|
const hasCollisionEvent = !!(onCollisionEnter || onCollisionExit || onIntersectionEnter || onIntersectionExit);
|
571
453
|
const hasContactForceEvent = !!onContactForce;
|
572
454
|
|
@@ -585,265 +467,87 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
585
467
|
onIntersectionExit,
|
586
468
|
onContactForce
|
587
469
|
});
|
588
|
-
}
|
589
|
-
return () => {
|
590
|
-
var _collidersRef$current2;
|
470
|
+
}
|
591
471
|
|
592
|
-
|
472
|
+
return () => {
|
473
|
+
if (collider) {
|
474
|
+
events.delete(collider.handle);
|
475
|
+
}
|
593
476
|
};
|
594
477
|
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
595
478
|
};
|
596
479
|
|
597
|
-
const
|
598
|
-
|
480
|
+
const useMutableCallback = fn => {
|
481
|
+
const ref = React.useRef(fn);
|
482
|
+
React.useEffect(() => {
|
483
|
+
ref.current = fn;
|
484
|
+
}, [fn]);
|
485
|
+
return ref;
|
486
|
+
}; // External hooks
|
599
487
|
|
600
|
-
|
601
|
-
|
488
|
+
/**
|
489
|
+
* Exposes the Rapier context, and world
|
490
|
+
* @category Hooks
|
491
|
+
*/
|
602
492
|
|
603
|
-
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
604
|
-
return desc;
|
605
|
-
};
|
606
|
-
const createRigidBodyState = ({
|
607
|
-
rigidBody,
|
608
|
-
object,
|
609
|
-
setMatrix,
|
610
|
-
getMatrix,
|
611
|
-
worldScale
|
612
|
-
}) => {
|
613
|
-
object.updateWorldMatrix(true, false);
|
614
|
-
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
615
|
-
return {
|
616
|
-
object,
|
617
|
-
rigidBody,
|
618
|
-
invertedWorldMatrix,
|
619
|
-
setMatrix: setMatrix ? setMatrix : matrix => {
|
620
|
-
object.matrix.copy(matrix);
|
621
|
-
},
|
622
|
-
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
623
|
-
scale: worldScale || object.getWorldScale(_scale).clone(),
|
624
|
-
isSleeping: false
|
625
|
-
};
|
626
|
-
};
|
627
|
-
const mutableRigidBodyOptions = {
|
628
|
-
gravityScale: (rb, value) => {
|
629
|
-
rb.setGravityScale(value, true);
|
630
|
-
},
|
631
|
-
linearDamping: (rb, value) => {
|
632
|
-
rb.setLinearDamping(value);
|
633
|
-
},
|
634
|
-
angularDamping: (rb, value) => {
|
635
|
-
rb.setAngularDamping(value);
|
636
|
-
},
|
637
|
-
enabledRotations: (rb, [x, y, z]) => {
|
638
|
-
rb.setEnabledRotations(x, y, z, true);
|
639
|
-
},
|
640
|
-
enabledTranslations: (rb, [x, y, z]) => {
|
641
|
-
rb.setEnabledTranslations(x, y, z, true);
|
642
|
-
},
|
643
|
-
lockRotations: (rb, value) => {
|
644
|
-
rb.lockRotations(value, true);
|
645
|
-
},
|
646
|
-
lockTranslations: (rb, value) => {
|
647
|
-
rb.lockTranslations(value, true);
|
648
|
-
},
|
649
|
-
angularVelocity: (rb, [x, y, z]) => {
|
650
|
-
rb.setAngvel({
|
651
|
-
x,
|
652
|
-
y,
|
653
|
-
z
|
654
|
-
}, true);
|
655
|
-
},
|
656
|
-
linearVelocity: (rb, [x, y, z]) => {
|
657
|
-
rb.setLinvel({
|
658
|
-
x,
|
659
|
-
y,
|
660
|
-
z
|
661
|
-
}, true);
|
662
|
-
},
|
663
|
-
ccd: (rb, value) => {
|
664
|
-
rb.enableCcd(value);
|
665
|
-
},
|
666
|
-
userData: (rb, value) => {
|
667
|
-
rb.userData = value;
|
668
|
-
},
|
669
493
|
|
670
|
-
|
671
|
-
|
672
|
-
|
494
|
+
const useRapier = () => {
|
495
|
+
return React.useContext(rapierContext);
|
496
|
+
};
|
497
|
+
/**
|
498
|
+
* Registers a callback to be called before the physics step
|
499
|
+
* @category Hooks
|
500
|
+
*/
|
673
501
|
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
502
|
+
const useBeforePhysicsStep = callback => {
|
503
|
+
const {
|
504
|
+
beforeStepCallbacks
|
505
|
+
} = useRapier();
|
506
|
+
const ref = useMutableCallback(callback);
|
507
|
+
React.useEffect(() => {
|
508
|
+
beforeStepCallbacks.add(ref);
|
509
|
+
return () => {
|
510
|
+
beforeStepCallbacks.delete(ref);
|
511
|
+
};
|
512
|
+
}, []);
|
678
513
|
};
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
}
|
514
|
+
/**
|
515
|
+
* Registers a callback to be called after the physics step
|
516
|
+
* @category Hooks
|
517
|
+
*/
|
684
518
|
|
685
|
-
|
519
|
+
const useAfterPhysicsStep = callback => {
|
520
|
+
const {
|
521
|
+
afterStepCallbacks
|
522
|
+
} = useRapier();
|
523
|
+
const ref = useMutableCallback(callback);
|
524
|
+
React.useEffect(() => {
|
525
|
+
afterStepCallbacks.add(ref);
|
526
|
+
return () => {
|
527
|
+
afterStepCallbacks.delete(ref);
|
528
|
+
};
|
529
|
+
}, []);
|
530
|
+
}; // Internal hooks
|
686
531
|
|
687
|
-
|
688
|
-
|
689
|
-
|
532
|
+
/**
|
533
|
+
* @internal
|
534
|
+
*/
|
690
535
|
|
691
|
-
|
536
|
+
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
537
|
+
const [colliderProps, setColliderProps] = React.useState([]);
|
538
|
+
React.useEffect(() => {
|
539
|
+
const object = ref.current;
|
692
540
|
|
693
|
-
|
694
|
-
|
541
|
+
if (object && options.colliders !== false) {
|
542
|
+
setColliderProps(createColliderPropsFromChildren({
|
543
|
+
object: ref.current,
|
544
|
+
options,
|
545
|
+
ignoreMeshColliders
|
546
|
+
}));
|
695
547
|
}
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
700
|
-
}
|
701
|
-
});
|
702
|
-
}
|
703
|
-
};
|
704
|
-
const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
|
705
|
-
// TODO: Improve this, split each prop into its own effect
|
706
|
-
const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
707
|
-
return vectorToTuple(props[key]);
|
708
|
-
}), [props]);
|
709
|
-
React.useEffect(() => {
|
710
|
-
if (Array.isArray(rigidBodyRef.current)) {
|
711
|
-
for (const rigidBody of rigidBodyRef.current) {
|
712
|
-
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
713
|
-
}
|
714
|
-
} else if (rigidBodyRef.current) {
|
715
|
-
setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
|
716
|
-
}
|
717
|
-
}, mutablePropsAsFlatArray);
|
718
|
-
};
|
719
|
-
const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
720
|
-
const {
|
721
|
-
onWake,
|
722
|
-
onSleep,
|
723
|
-
onCollisionEnter,
|
724
|
-
onCollisionExit,
|
725
|
-
onIntersectionEnter,
|
726
|
-
onIntersectionExit
|
727
|
-
} = props;
|
728
|
-
const eventHandlers = {
|
729
|
-
onWake,
|
730
|
-
onSleep,
|
731
|
-
onCollisionEnter,
|
732
|
-
onCollisionExit,
|
733
|
-
onIntersectionEnter,
|
734
|
-
onIntersectionExit
|
735
|
-
};
|
736
|
-
React.useEffect(() => {
|
737
|
-
if (Array.isArray(rigidBodyRef.current)) {
|
738
|
-
for (const rigidBody of rigidBodyRef.current) {
|
739
|
-
events.set(rigidBody.handle, eventHandlers);
|
740
|
-
}
|
741
|
-
} else if (rigidBodyRef.current) {
|
742
|
-
events.set(rigidBodyRef.current.handle, eventHandlers);
|
743
|
-
}
|
744
|
-
|
745
|
-
return () => {
|
746
|
-
if (Array.isArray(rigidBodyRef.current)) {
|
747
|
-
for (const rigidBody of rigidBodyRef.current) {
|
748
|
-
events.delete(rigidBody.handle);
|
749
|
-
}
|
750
|
-
} else if (rigidBodyRef.current) {
|
751
|
-
events.delete(rigidBodyRef.current.handle);
|
752
|
-
}
|
753
|
-
};
|
754
|
-
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
755
|
-
};
|
756
|
-
|
757
|
-
const useRapier = () => {
|
758
|
-
return React.useContext(rapierContext);
|
759
|
-
};
|
760
|
-
const useBeforePhysicsStep = callback => {
|
761
|
-
const {
|
762
|
-
beforeStepCallbacks
|
763
|
-
} = useRapier();
|
764
|
-
React.useEffect(() => {
|
765
|
-
beforeStepCallbacks.add(callback);
|
766
|
-
return () => {
|
767
|
-
beforeStepCallbacks.delete(callback);
|
768
|
-
};
|
769
|
-
}, []);
|
770
|
-
};
|
771
|
-
const useAfterPhysicsStep = callback => {
|
772
|
-
const {
|
773
|
-
afterStepCallbacks
|
774
|
-
} = useRapier();
|
775
|
-
React.useEffect(() => {
|
776
|
-
afterStepCallbacks.add(callback);
|
777
|
-
return () => {
|
778
|
-
afterStepCallbacks.delete(callback);
|
779
|
-
};
|
780
|
-
}, []);
|
781
|
-
}; // Internal hooks
|
782
|
-
|
783
|
-
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
784
|
-
const [colliderProps, setColliderProps] = React.useState([]);
|
785
|
-
React.useEffect(() => {
|
786
|
-
const object = ref.current;
|
787
|
-
|
788
|
-
if (object && options.colliders !== false) {
|
789
|
-
setColliderProps(createColliderPropsFromChildren({
|
790
|
-
object: ref.current,
|
791
|
-
options,
|
792
|
-
ignoreMeshColliders
|
793
|
-
}));
|
794
|
-
}
|
795
|
-
}, [options.colliders]);
|
796
|
-
return colliderProps;
|
797
|
-
};
|
798
|
-
const useRigidBody = (options = {}) => {
|
799
|
-
const {
|
800
|
-
world,
|
801
|
-
rigidBodyStates,
|
802
|
-
physicsOptions,
|
803
|
-
rigidBodyEvents
|
804
|
-
} = useRapier();
|
805
|
-
const ref = React.useRef();
|
806
|
-
const mergedOptions = React.useMemo(() => {
|
807
|
-
return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
|
808
|
-
children: undefined
|
809
|
-
});
|
810
|
-
}, [physicsOptions, options]);
|
811
|
-
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
|
812
|
-
|
813
|
-
const rigidBodyRef = React.useRef();
|
814
|
-
const getRigidBodyRef = React.useRef(() => {
|
815
|
-
if (!rigidBodyRef.current) {
|
816
|
-
const desc = rigidBodyDescFromOptions(options);
|
817
|
-
const rigidBody = world.createRigidBody(desc);
|
818
|
-
rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
|
819
|
-
}
|
820
|
-
|
821
|
-
return rigidBodyRef.current;
|
822
|
-
}); // Setup
|
823
|
-
|
824
|
-
React.useEffect(() => {
|
825
|
-
const rigidBody = getRigidBodyRef.current();
|
826
|
-
rigidBodyRef.current = rigidBody;
|
827
|
-
|
828
|
-
if (!ref.current) {
|
829
|
-
ref.current = new three.Object3D();
|
830
|
-
}
|
831
|
-
|
832
|
-
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
833
|
-
rigidBody,
|
834
|
-
object: ref.current
|
835
|
-
}));
|
836
|
-
return () => {
|
837
|
-
world.removeRigidBody(rigidBody);
|
838
|
-
rigidBodyStates.delete(rigidBody.handle);
|
839
|
-
rigidBodyRef.current = undefined;
|
840
|
-
};
|
841
|
-
}, []);
|
842
|
-
useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
|
843
|
-
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
844
|
-
const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
845
|
-
return [ref, api, childColliderProps];
|
846
|
-
};
|
548
|
+
}, [options.colliders]);
|
549
|
+
return colliderProps;
|
550
|
+
};
|
847
551
|
|
848
552
|
const calcForceByType = {
|
849
553
|
static: (s, m2, r, d, G) => s,
|
@@ -961,6 +665,10 @@ const importRapier = async () => {
|
|
961
665
|
return r;
|
962
666
|
};
|
963
667
|
|
668
|
+
/**
|
669
|
+
* The main physics component used to create a physics world.
|
670
|
+
* @category Components
|
671
|
+
*/
|
964
672
|
const Physics = ({
|
965
673
|
colliders: _colliders = "cuboid",
|
966
674
|
gravity: _gravity = [0, -9.81, 0],
|
@@ -1062,12 +770,12 @@ const Physics = ({
|
|
1062
770
|
}); // Trigger beforeStep callbacks
|
1063
771
|
|
1064
772
|
beforeStepCallbacks.forEach(callback => {
|
1065
|
-
callback(api);
|
773
|
+
callback.current(api);
|
1066
774
|
});
|
1067
775
|
world.step(eventQueue); // Trigger afterStep callbacks
|
1068
776
|
|
1069
777
|
afterStepCallbacks.forEach(callback => {
|
1070
|
-
callback(api);
|
778
|
+
callback.current(api);
|
1071
779
|
});
|
1072
780
|
};
|
1073
781
|
|
@@ -1120,7 +828,7 @@ const Physics = ({
|
|
1120
828
|
state.isSleeping = rigidBody.isSleeping();
|
1121
829
|
}
|
1122
830
|
|
1123
|
-
if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
|
831
|
+
if (!rigidBody || rigidBody.isSleeping() && !("isInstancedMesh" in state.object) || !state.setMatrix) {
|
1124
832
|
return;
|
1125
833
|
} // New states
|
1126
834
|
|
@@ -1134,7 +842,7 @@ const Physics = ({
|
|
1134
842
|
_matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale); // Apply previous tick position
|
1135
843
|
|
1136
844
|
|
1137
|
-
if (
|
845
|
+
if (state.meshType == "mesh") {
|
1138
846
|
state.object.position.copy(_position);
|
1139
847
|
state.object.quaternion.copy(_rotation);
|
1140
848
|
}
|
@@ -1143,9 +851,8 @@ const Physics = ({
|
|
1143
851
|
|
1144
852
|
_matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
1145
853
|
|
1146
|
-
if (state.
|
854
|
+
if (state.meshType == "instancedMesh") {
|
1147
855
|
state.setMatrix(_matrix4);
|
1148
|
-
state.object.instanceMatrix.needsUpdate = true;
|
1149
856
|
} else {
|
1150
857
|
// Interpolate to new position
|
1151
858
|
state.object.position.lerp(_position, interpolationAlpha);
|
@@ -1329,8 +1036,87 @@ function _objectWithoutProperties(source, excluded) {
|
|
1329
1036
|
return target;
|
1330
1037
|
}
|
1331
1038
|
|
1039
|
+
/**
|
1040
|
+
* Initiate an instance and return a safe getter
|
1041
|
+
*/
|
1042
|
+
|
1043
|
+
const useImperativeInstance = (createFn, destroyFn) => {
|
1044
|
+
const ref = React.useRef();
|
1045
|
+
const refGetter = React.useMemo(() => () => {
|
1046
|
+
if (!ref.current) {
|
1047
|
+
ref.current = createFn();
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
return ref.current;
|
1051
|
+
}, []);
|
1052
|
+
React.useEffect(() => {
|
1053
|
+
const instance = refGetter();
|
1054
|
+
return () => {
|
1055
|
+
destroyFn(instance);
|
1056
|
+
ref.current = undefined;
|
1057
|
+
};
|
1058
|
+
}, []);
|
1059
|
+
return refGetter;
|
1060
|
+
};
|
1061
|
+
|
1062
|
+
/**
|
1063
|
+
* Takes an object resembling a Vector3 and returs a Three.Vector3
|
1064
|
+
* @category Math helpers
|
1065
|
+
*/
|
1066
|
+
|
1067
|
+
const vec3 = ({
|
1068
|
+
x,
|
1069
|
+
y,
|
1070
|
+
z
|
1071
|
+
} = {
|
1072
|
+
x: 0,
|
1073
|
+
y: 0,
|
1074
|
+
z: 0
|
1075
|
+
}) => {
|
1076
|
+
return new three.Vector3(x, y, z);
|
1077
|
+
};
|
1078
|
+
/**
|
1079
|
+
* Takes an object resembling a Quaternion and returs a Three.Quaternion
|
1080
|
+
* @category Math helpers
|
1081
|
+
*/
|
1082
|
+
|
1083
|
+
const quat = ({
|
1084
|
+
x,
|
1085
|
+
y,
|
1086
|
+
z,
|
1087
|
+
w
|
1088
|
+
} = {
|
1089
|
+
x: 0,
|
1090
|
+
y: 0,
|
1091
|
+
z: 0,
|
1092
|
+
w: 1
|
1093
|
+
}) => {
|
1094
|
+
return new three.Quaternion(x, y, z, w);
|
1095
|
+
};
|
1096
|
+
/**
|
1097
|
+
* Takes an object resembling an Euler and returs a Three.Euler
|
1098
|
+
* @category Math helpers
|
1099
|
+
*/
|
1100
|
+
|
1101
|
+
const euler = ({
|
1102
|
+
x,
|
1103
|
+
y,
|
1104
|
+
z
|
1105
|
+
} = {
|
1106
|
+
x: 0,
|
1107
|
+
y: 0,
|
1108
|
+
z: 0
|
1109
|
+
}) => {
|
1110
|
+
return new three.Euler(x, y, z);
|
1111
|
+
};
|
1112
|
+
|
1332
1113
|
// Colliders
|
1333
|
-
|
1114
|
+
|
1115
|
+
/**
|
1116
|
+
* A collider is a shape that can be attached to a rigid body to define its physical properties.
|
1117
|
+
* @internal
|
1118
|
+
*/
|
1119
|
+
const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
|
1334
1120
|
const {
|
1335
1121
|
children,
|
1336
1122
|
position,
|
@@ -1346,52 +1132,21 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["defaul
|
|
1346
1132
|
} = useRapier();
|
1347
1133
|
const rigidBodyContext = useRigidBodyContext();
|
1348
1134
|
const ref = React.useRef(null);
|
1349
|
-
const
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
}
|
1358
|
-
React.
|
1359
|
-
const object = ref.current;
|
1360
|
-
const worldScale = object.getWorldScale(new three.Vector3());
|
1361
|
-
const colliders = []; // If this is an InstancedRigidBody api
|
1362
|
-
|
1363
|
-
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1364
|
-
rigidBodyContext.api.forEach((body, index) => {
|
1365
|
-
var _rigidBodyContext$opt, _rigidBodyContext$opt2;
|
1366
|
-
|
1367
|
-
let instanceScale = worldScale;
|
1368
|
-
|
1369
|
-
if ("scales" in rigidBodyContext.options && rigidBodyContext !== null && rigidBodyContext !== void 0 && (_rigidBodyContext$opt = rigidBodyContext.options) !== null && _rigidBodyContext$opt !== void 0 && (_rigidBodyContext$opt2 = _rigidBodyContext$opt.scales) !== null && _rigidBodyContext$opt2 !== void 0 && _rigidBodyContext$opt2[index]) {
|
1370
|
-
instanceScale = instanceScale.clone().multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
|
1371
|
-
}
|
1372
|
-
|
1373
|
-
const collider = createColliderFromOptions(props, world, instanceScale, body.raw());
|
1374
|
-
colliderStates.set(collider.handle, createColliderState(collider, object, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1375
|
-
colliders.push(collider);
|
1376
|
-
});
|
1377
|
-
} else {
|
1378
|
-
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext && (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.api).raw());
|
1379
|
-
colliderStates.set(collider.handle, createColliderState(collider, object, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1380
|
-
colliders.push(collider);
|
1381
|
-
}
|
1382
|
-
|
1383
|
-
collidersRef.current = colliders;
|
1384
|
-
return () => {
|
1385
|
-
colliders.forEach(collider => {
|
1386
|
-
world.removeCollider(collider);
|
1387
|
-
});
|
1388
|
-
};
|
1389
|
-
}, []);
|
1135
|
+
const getInstance = useImperativeInstance(() => {
|
1136
|
+
const worldScale = ref.current.getWorldScale(vec3());
|
1137
|
+
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
|
1138
|
+
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1139
|
+
return collider;
|
1140
|
+
}, collider => {
|
1141
|
+
colliderStates.delete(collider.handle);
|
1142
|
+
world.removeCollider(collider);
|
1143
|
+
});
|
1144
|
+
React.useImperativeHandle(forwardedRef, () => getInstance());
|
1390
1145
|
const mergedProps = React.useMemo(() => {
|
1391
1146
|
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
1392
1147
|
}, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
|
1393
|
-
useUpdateColliderOptions(
|
1394
|
-
useColliderEvents(
|
1148
|
+
useUpdateColliderOptions(getInstance, mergedProps, colliderStates);
|
1149
|
+
useColliderEvents(getInstance, mergedProps, colliderEvents);
|
1395
1150
|
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1396
1151
|
position: position,
|
1397
1152
|
rotation: rotation,
|
@@ -1401,54 +1156,99 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["defaul
|
|
1401
1156
|
name: name
|
1402
1157
|
}, children);
|
1403
1158
|
}));
|
1159
|
+
|
1160
|
+
/**
|
1161
|
+
* A cuboid collider shape
|
1162
|
+
* @category Colliders
|
1163
|
+
*/
|
1404
1164
|
const CuboidCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1405
1165
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1406
1166
|
shape: "cuboid",
|
1407
1167
|
ref: ref
|
1408
1168
|
}));
|
1409
1169
|
});
|
1170
|
+
/**
|
1171
|
+
* A round cuboid collider shape
|
1172
|
+
* @category Colliders
|
1173
|
+
*/
|
1174
|
+
|
1410
1175
|
const RoundCuboidCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1411
1176
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1412
1177
|
shape: "roundCuboid",
|
1413
1178
|
ref: ref
|
1414
1179
|
}));
|
1415
1180
|
});
|
1181
|
+
/**
|
1182
|
+
* A ball collider shape
|
1183
|
+
* @category Colliders
|
1184
|
+
*/
|
1185
|
+
|
1416
1186
|
const BallCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1417
1187
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1418
1188
|
shape: "ball",
|
1419
1189
|
ref: ref
|
1420
1190
|
}));
|
1421
1191
|
});
|
1192
|
+
/**
|
1193
|
+
* A capsule collider shape
|
1194
|
+
* @category Colliders
|
1195
|
+
*/
|
1196
|
+
|
1422
1197
|
const CapsuleCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1423
1198
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1424
1199
|
shape: "capsule",
|
1425
1200
|
ref: ref
|
1426
1201
|
}));
|
1427
1202
|
});
|
1203
|
+
/**
|
1204
|
+
* A heightfield collider shape
|
1205
|
+
* @category Colliders
|
1206
|
+
*/
|
1207
|
+
|
1428
1208
|
const HeightfieldCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1429
1209
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1430
1210
|
shape: "heightfield",
|
1431
1211
|
ref: ref
|
1432
1212
|
}));
|
1433
1213
|
});
|
1214
|
+
/**
|
1215
|
+
* A trimesh collider shape
|
1216
|
+
* @category Colliders
|
1217
|
+
*/
|
1218
|
+
|
1434
1219
|
const TrimeshCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1435
1220
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1436
1221
|
shape: "trimesh",
|
1437
1222
|
ref: ref
|
1438
1223
|
}));
|
1439
1224
|
});
|
1225
|
+
/**
|
1226
|
+
* A cone collider shape
|
1227
|
+
* @category Colliders
|
1228
|
+
*/
|
1229
|
+
|
1440
1230
|
const ConeCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1441
1231
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1442
1232
|
shape: "cone",
|
1443
1233
|
ref: ref
|
1444
1234
|
}));
|
1445
1235
|
});
|
1236
|
+
/**
|
1237
|
+
* A cylinder collider shape
|
1238
|
+
* @category Colliders
|
1239
|
+
*/
|
1240
|
+
|
1446
1241
|
const CylinderCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1447
1242
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1448
1243
|
shape: "cylinder",
|
1449
1244
|
ref: ref
|
1450
1245
|
}));
|
1451
1246
|
});
|
1247
|
+
/**
|
1248
|
+
* A convex hull collider shape
|
1249
|
+
* @category Colliders
|
1250
|
+
*/
|
1251
|
+
|
1452
1252
|
const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((props, ref) => {
|
1453
1253
|
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1454
1254
|
shape: "convexHull",
|
@@ -1465,31 +1265,212 @@ ConeCollider.displayName = "ConeCollider";
|
|
1465
1265
|
CylinderCollider.displayName = "CylinderCollider";
|
1466
1266
|
ConvexHullCollider.displayName = "ConvexHullCollider";
|
1467
1267
|
|
1468
|
-
const
|
1268
|
+
const rigidBodyDescFromOptions = options => {
|
1269
|
+
var _options$canSleep;
|
1270
|
+
|
1271
|
+
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
1272
|
+
const desc = new rapier3dCompat.RigidBodyDesc(type); // Apply immutable options
|
1273
|
+
|
1274
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
1275
|
+
return desc;
|
1276
|
+
};
|
1277
|
+
const createRigidBodyState = ({
|
1278
|
+
rigidBody,
|
1279
|
+
object,
|
1280
|
+
setMatrix,
|
1281
|
+
getMatrix,
|
1282
|
+
worldScale,
|
1283
|
+
meshType: _meshType = "mesh"
|
1284
|
+
}) => {
|
1285
|
+
object.updateWorldMatrix(true, false);
|
1286
|
+
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
1287
|
+
return {
|
1288
|
+
object,
|
1289
|
+
rigidBody,
|
1290
|
+
invertedWorldMatrix,
|
1291
|
+
setMatrix: setMatrix ? setMatrix : matrix => {
|
1292
|
+
object.matrix.copy(matrix);
|
1293
|
+
},
|
1294
|
+
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
1295
|
+
scale: worldScale || object.getWorldScale(_scale).clone(),
|
1296
|
+
isSleeping: false,
|
1297
|
+
meshType: _meshType
|
1298
|
+
};
|
1299
|
+
};
|
1300
|
+
const mutableRigidBodyOptions = {
|
1301
|
+
gravityScale: (rb, value) => {
|
1302
|
+
rb.setGravityScale(value, true);
|
1303
|
+
},
|
1304
|
+
linearDamping: (rb, value) => {
|
1305
|
+
rb.setLinearDamping(value);
|
1306
|
+
},
|
1307
|
+
angularDamping: (rb, value) => {
|
1308
|
+
rb.setAngularDamping(value);
|
1309
|
+
},
|
1310
|
+
enabledRotations: (rb, [x, y, z]) => {
|
1311
|
+
rb.setEnabledRotations(x, y, z, true);
|
1312
|
+
},
|
1313
|
+
enabledTranslations: (rb, [x, y, z]) => {
|
1314
|
+
rb.setEnabledTranslations(x, y, z, true);
|
1315
|
+
},
|
1316
|
+
lockRotations: (rb, value) => {
|
1317
|
+
rb.lockRotations(value, true);
|
1318
|
+
},
|
1319
|
+
lockTranslations: (rb, value) => {
|
1320
|
+
rb.lockTranslations(value, true);
|
1321
|
+
},
|
1322
|
+
angularVelocity: (rb, [x, y, z]) => {
|
1323
|
+
rb.setAngvel({
|
1324
|
+
x,
|
1325
|
+
y,
|
1326
|
+
z
|
1327
|
+
}, true);
|
1328
|
+
},
|
1329
|
+
linearVelocity: (rb, [x, y, z]) => {
|
1330
|
+
rb.setLinvel({
|
1331
|
+
x,
|
1332
|
+
y,
|
1333
|
+
z
|
1334
|
+
}, true);
|
1335
|
+
},
|
1336
|
+
ccd: (rb, value) => {
|
1337
|
+
rb.enableCcd(value);
|
1338
|
+
},
|
1339
|
+
userData: (rb, value) => {
|
1340
|
+
rb.userData = value;
|
1341
|
+
},
|
1342
|
+
|
1343
|
+
type(rb, value) {
|
1344
|
+
rb.setBodyType(rigidBodyTypeFromString(value), true);
|
1345
|
+
},
|
1346
|
+
|
1347
|
+
position: () => {},
|
1348
|
+
rotation: () => {},
|
1349
|
+
quaternion: () => {},
|
1350
|
+
scale: () => {}
|
1351
|
+
};
|
1352
|
+
const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
|
1353
|
+
const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
|
1354
|
+
if (!rigidBody) {
|
1355
|
+
return;
|
1356
|
+
}
|
1357
|
+
|
1358
|
+
const state = states.get(rigidBody.handle);
|
1359
|
+
|
1360
|
+
if (state) {
|
1361
|
+
if (updateTranslations) {
|
1362
|
+
state.object.updateWorldMatrix(true, false);
|
1363
|
+
|
1364
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
1365
|
+
|
1366
|
+
rigidBody.setTranslation(_position, false);
|
1367
|
+
rigidBody.setRotation(_rotation, false);
|
1368
|
+
}
|
1369
|
+
|
1370
|
+
mutableRigidBodyOptionKeys.forEach(key => {
|
1371
|
+
if (key in options) {
|
1372
|
+
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
1373
|
+
}
|
1374
|
+
});
|
1375
|
+
}
|
1376
|
+
};
|
1377
|
+
const useUpdateRigidBodyOptions = (getRigidBody, props, states, updateTranslations = true) => {
|
1378
|
+
// TODO: Improve this, split each prop into its own effect
|
1379
|
+
const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
|
1380
|
+
return vectorToTuple(props[key]);
|
1381
|
+
}), [props]);
|
1382
|
+
React.useEffect(() => {
|
1383
|
+
const rigidBody = getRigidBody();
|
1384
|
+
setRigidBodyOptions(rigidBody, props, states, updateTranslations);
|
1385
|
+
}, mutablePropsAsFlatArray);
|
1386
|
+
};
|
1387
|
+
const useRigidBodyEvents = (getRigidBody, props, events) => {
|
1388
|
+
const {
|
1389
|
+
onWake,
|
1390
|
+
onSleep,
|
1391
|
+
onCollisionEnter,
|
1392
|
+
onCollisionExit,
|
1393
|
+
onIntersectionEnter,
|
1394
|
+
onIntersectionExit
|
1395
|
+
} = props;
|
1396
|
+
const eventHandlers = {
|
1397
|
+
onWake,
|
1398
|
+
onSleep,
|
1399
|
+
onCollisionEnter,
|
1400
|
+
onCollisionExit,
|
1401
|
+
onIntersectionEnter,
|
1402
|
+
onIntersectionExit
|
1403
|
+
};
|
1404
|
+
React.useEffect(() => {
|
1405
|
+
const rigidBody = getRigidBody();
|
1406
|
+
events.set(rigidBody.handle, eventHandlers);
|
1407
|
+
return () => {
|
1408
|
+
events.delete(rigidBody.handle);
|
1409
|
+
};
|
1410
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
1411
|
+
};
|
1412
|
+
|
1413
|
+
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
|
1469
1414
|
const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
|
1470
1415
|
const useRigidBodyContext = () => React.useContext(RigidBodyContext);
|
1471
|
-
|
1416
|
+
|
1417
|
+
/**
|
1418
|
+
* A rigid body is a physical object that can be simulated by the physics engine.
|
1419
|
+
* @category Components
|
1420
|
+
*/
|
1421
|
+
const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
|
1472
1422
|
const {
|
1473
1423
|
children,
|
1474
1424
|
type,
|
1475
1425
|
position,
|
1476
1426
|
rotation,
|
1477
1427
|
scale,
|
1478
|
-
quaternion
|
1428
|
+
quaternion,
|
1429
|
+
transformState
|
1479
1430
|
} = props,
|
1480
1431
|
objectProps = _objectWithoutProperties(props, _excluded$1);
|
1481
1432
|
|
1482
|
-
const
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
}
|
1433
|
+
const ref = React.useRef(null);
|
1434
|
+
const {
|
1435
|
+
world,
|
1436
|
+
rigidBodyStates,
|
1437
|
+
physicsOptions,
|
1438
|
+
rigidBodyEvents
|
1439
|
+
} = useRapier();
|
1440
|
+
const mergedOptions = React.useMemo(() => {
|
1441
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), props), {}, {
|
1442
|
+
children: undefined
|
1443
|
+
});
|
1444
|
+
}, [physicsOptions, props]);
|
1445
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
|
1446
|
+
|
1447
|
+
const getInstance = useImperativeInstance(() => {
|
1448
|
+
const desc = rigidBodyDescFromOptions(mergedOptions);
|
1449
|
+
const rigidBody = world.createRigidBody(desc);
|
1450
|
+
const state = createRigidBodyState({
|
1451
|
+
rigidBody,
|
1452
|
+
object: ref.current
|
1453
|
+
});
|
1454
|
+
rigidBodyStates.set(rigidBody.handle, props.transformState ? props.transformState(state) : state);
|
1455
|
+
return rigidBody;
|
1456
|
+
}, rigidBody => {
|
1457
|
+
world.removeRigidBody(rigidBody);
|
1458
|
+
rigidBodyStates.delete(rigidBody.handle);
|
1459
|
+
});
|
1460
|
+
useUpdateRigidBodyOptions(getInstance, mergedOptions, rigidBodyStates);
|
1461
|
+
useRigidBodyEvents(getInstance, mergedOptions, rigidBodyEvents);
|
1462
|
+
React.useImperativeHandle(forwardedRef, () => getInstance());
|
1463
|
+
const contextValue = React.useMemo(() => {
|
1464
|
+
return {
|
1465
|
+
ref,
|
1466
|
+
getRigidBody: getInstance,
|
1467
|
+
options: mergedOptions
|
1468
|
+
};
|
1469
|
+
}, [mergedOptions]);
|
1489
1470
|
return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
|
1490
1471
|
value: contextValue
|
1491
1472
|
}, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
|
1492
|
-
ref:
|
1473
|
+
ref: ref
|
1493
1474
|
}, objectProps, {
|
1494
1475
|
position: position,
|
1495
1476
|
rotation: rotation,
|
@@ -1501,14 +1482,17 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1501
1482
|
}));
|
1502
1483
|
RigidBody.displayName = "RigidBody";
|
1503
1484
|
|
1485
|
+
/**
|
1486
|
+
* A mesh collider is a collider that is automatically generated from the geometry of the children.
|
1487
|
+
* @category Colliders
|
1488
|
+
*/
|
1504
1489
|
const MeshCollider = /*#__PURE__*/React.memo(props => {
|
1505
1490
|
const {
|
1506
1491
|
children,
|
1507
1492
|
type
|
1508
1493
|
} = props;
|
1509
1494
|
const {
|
1510
|
-
physicsOptions
|
1511
|
-
world
|
1495
|
+
physicsOptions
|
1512
1496
|
} = useRapier();
|
1513
1497
|
const object = React.useRef(null);
|
1514
1498
|
const {
|
@@ -1622,155 +1606,119 @@ const Debug = /*#__PURE__*/React.memo(() => {
|
|
1622
1606
|
}, attractor))));
|
1623
1607
|
});
|
1624
1608
|
|
1625
|
-
const _excluded = ["
|
1626
|
-
const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
1627
|
-
const {
|
1628
|
-
world,
|
1629
|
-
rigidBodyStates,
|
1630
|
-
physicsOptions,
|
1631
|
-
rigidBodyEvents
|
1632
|
-
} = useRapier();
|
1609
|
+
const _excluded = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
|
1610
|
+
const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, ref) => {
|
1633
1611
|
const object = React.useRef(null);
|
1612
|
+
const instancedWrapper = React.useRef(null);
|
1634
1613
|
|
1635
1614
|
const {
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1615
|
+
// instanced props
|
1616
|
+
children,
|
1617
|
+
instances,
|
1618
|
+
colliderNodes = [],
|
1619
|
+
// wrapper object props
|
1620
|
+
position,
|
1621
|
+
rotation,
|
1622
|
+
quaternion,
|
1623
|
+
scale
|
1639
1624
|
} = props,
|
1640
|
-
|
1625
|
+
rigidBodyProps = _objectWithoutProperties(props, _excluded);
|
1641
1626
|
|
1642
|
-
const
|
1643
|
-
|
1644
|
-
const
|
1645
|
-
|
1646
|
-
|
1647
|
-
}
|
1627
|
+
const rigidBodyApis = React.useRef([]);
|
1628
|
+
React.useImperativeHandle(ref, () => rigidBodyApis.current, [instances]);
|
1629
|
+
const childColliderProps = useChildColliderProps(object, _objectSpread2(_objectSpread2({}, props), {}, {
|
1630
|
+
children: undefined
|
1631
|
+
}));
|
1648
1632
|
|
1649
|
-
|
1650
|
-
|
1651
|
-
const mergedOptions = React.useMemo(() => {
|
1652
|
-
return _objectSpread2(_objectSpread2({}, physicsOptions), options);
|
1653
|
-
}, [physicsOptions, options]);
|
1654
|
-
const childColliderProps = useChildColliderProps(object, mergedOptions);
|
1655
|
-
React.useLayoutEffect(() => {
|
1656
|
-
object.current.updateWorldMatrix(true, false);
|
1657
|
-
const instances = instancesRefGetter.current();
|
1658
|
-
const invertedWorld = object.current.matrixWorld.clone().invert();
|
1659
|
-
object.current.traverseVisible(mesh => {
|
1660
|
-
if (mesh instanceof three.InstancedMesh) {
|
1661
|
-
mesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
|
1662
|
-
const worldScale = mesh.getWorldScale(_scale);
|
1663
|
-
|
1664
|
-
for (let index = 0; index < mesh.count; index++) {
|
1665
|
-
var _options$scales;
|
1666
|
-
|
1667
|
-
const desc = rigidBodyDescFromOptions(props);
|
1668
|
-
const rigidBody = world.createRigidBody(desc);
|
1669
|
-
rigidBodyRefs.current.push(rigidBody);
|
1670
|
-
const scale = ((_options$scales = options.scales) === null || _options$scales === void 0 ? void 0 : _options$scales[index]) || [1, 1, 1];
|
1671
|
-
const instanceScale = worldScale.clone().multiply(vectorArrayToVector3(scale));
|
1672
|
-
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
1673
|
-
rigidBody,
|
1674
|
-
object: mesh,
|
1675
|
-
setMatrix: matrix => mesh.setMatrixAt(index, matrix),
|
1676
|
-
getMatrix: matrix => {
|
1677
|
-
mesh.getMatrixAt(index, matrix);
|
1678
|
-
return matrix;
|
1679
|
-
},
|
1680
|
-
worldScale: instanceScale
|
1681
|
-
}));
|
1682
|
-
const [x, y, z] = (positions === null || positions === void 0 ? void 0 : positions[index]) || [0, 0, 0];
|
1683
|
-
const [rx, ry, rz] = (rotations === null || rotations === void 0 ? void 0 : rotations[index]) || [0, 0, 0];
|
1633
|
+
const getInstancedMesh = () => {
|
1634
|
+
const firstChild = instancedWrapper.current.children[0];
|
1684
1635
|
|
1685
|
-
|
1636
|
+
if (firstChild && "isInstancedMesh" in firstChild) {
|
1637
|
+
return firstChild;
|
1638
|
+
}
|
1686
1639
|
|
1687
|
-
|
1640
|
+
return undefined;
|
1641
|
+
};
|
1688
1642
|
|
1689
|
-
|
1643
|
+
React.useEffect(() => {
|
1644
|
+
const instancedMesh = getInstancedMesh();
|
1690
1645
|
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
}
|
1646
|
+
if (instancedMesh) {
|
1647
|
+
instancedMesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
|
1648
|
+
} else {
|
1649
|
+
console.warn("InstancedRigidBodies expects exactly one child, which must be an InstancedMesh");
|
1650
|
+
}
|
1651
|
+
}, []); // Update the RigidBodyStates whenever the instances change
|
1698
1652
|
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1653
|
+
const applyInstancedState = (state, index) => {
|
1654
|
+
const instancedMesh = getInstancedMesh();
|
1655
|
+
|
1656
|
+
if (instancedMesh) {
|
1657
|
+
return _objectSpread2(_objectSpread2({}, state), {}, {
|
1658
|
+
getMatrix: matrix => {
|
1659
|
+
instancedMesh.getMatrixAt(index, matrix);
|
1660
|
+
return matrix;
|
1661
|
+
},
|
1662
|
+
setMatrix: matrix => {
|
1663
|
+
instancedMesh.setMatrixAt(index, matrix);
|
1664
|
+
instancedMesh.instanceMatrix.needsUpdate = true;
|
1665
|
+
},
|
1666
|
+
meshType: "instancedMesh"
|
1711
1667
|
});
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
}
|
1716
|
-
|
1717
|
-
|
1718
|
-
useUpdateRigidBodyOptions(rigidBodyRefs, mergedOptions, rigidBodyStates, false);
|
1719
|
-
useRigidBodyEvents(rigidBodyRefs, mergedOptions, rigidBodyEvents);
|
1720
|
-
const contextValue = React.useMemo(() => {
|
1721
|
-
return {
|
1722
|
-
ref: object,
|
1723
|
-
api,
|
1724
|
-
options: mergedOptions
|
1725
|
-
};
|
1726
|
-
}, [api, mergedOptions]);
|
1727
|
-
return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
|
1728
|
-
value: contextValue
|
1729
|
-
}, /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
return state;
|
1671
|
+
};
|
1672
|
+
|
1673
|
+
return /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
|
1730
1674
|
ref: object
|
1731
|
-
},
|
1675
|
+
}, rigidBodyProps, {
|
1676
|
+
position: position,
|
1677
|
+
rotation: rotation,
|
1678
|
+
quaternion: quaternion,
|
1679
|
+
scale: scale
|
1680
|
+
}), /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1681
|
+
ref: instancedWrapper
|
1682
|
+
}, children), instances === null || instances === void 0 ? void 0 : instances.map((instance, index) => /*#__PURE__*/React__default["default"].createElement(RigidBody, _extends({}, rigidBodyProps, instance, {
|
1683
|
+
ref: body => rigidBodyApis.current[index] = body,
|
1684
|
+
transformState: state => applyInstancedState(state, index)
|
1685
|
+
}), /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, colliderNodes.map((node, index) => /*#__PURE__*/React__default["default"].createElement(React.Fragment, {
|
1732
1686
|
key: index
|
1733
|
-
},
|
1734
|
-
|
1687
|
+
}, node)), childColliderProps.map((colliderProps, colliderIndex) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
|
1688
|
+
key: colliderIndex
|
1689
|
+
}, colliderProps)))))));
|
1690
|
+
}));
|
1735
1691
|
InstancedRigidBodies.displayName = "InstancedRigidBodies";
|
1736
1692
|
|
1693
|
+
/**
|
1694
|
+
* @internal
|
1695
|
+
*/
|
1696
|
+
|
1737
1697
|
const useImpulseJoint = (body1, body2, params) => {
|
1738
1698
|
const {
|
1739
1699
|
world
|
1740
1700
|
} = useRapier();
|
1741
1701
|
const jointRef = React.useRef();
|
1742
|
-
|
1743
|
-
if (
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
}
|
1702
|
+
useImperativeInstance(() => {
|
1703
|
+
if (body1.current && body2.current) {
|
1704
|
+
const newJoint = world.createImpulseJoint(params, body1.current, body2.current);
|
1705
|
+
jointRef.current = newJoint;
|
1706
|
+
return newJoint;
|
1707
|
+
}
|
1708
|
+
}, joint => {
|
1709
|
+
if (joint) {
|
1710
|
+
jointRef.current = undefined;
|
1711
|
+
world.removeImpulseJoint(joint);
|
1753
1712
|
}
|
1754
|
-
|
1755
|
-
return jointRef.current;
|
1756
1713
|
});
|
1757
|
-
|
1758
|
-
const joint = getJointRef.current();
|
1759
|
-
return () => {
|
1760
|
-
if (joint) {
|
1761
|
-
world.removeImpulseJoint(joint);
|
1762
|
-
jointRef.current = undefined;
|
1763
|
-
}
|
1764
|
-
};
|
1765
|
-
}, []);
|
1766
|
-
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
1767
|
-
return api;
|
1714
|
+
return jointRef;
|
1768
1715
|
};
|
1769
1716
|
/**
|
1770
|
-
*
|
1771
1717
|
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
1772
1718
|
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
1773
1719
|
* The fixed-joint makes these frames coincide in world-space.
|
1720
|
+
*
|
1721
|
+
* @category Hooks - Joints
|
1774
1722
|
*/
|
1775
1723
|
|
1776
1724
|
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
@@ -1784,6 +1732,8 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
|
|
1784
1732
|
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
1785
1733
|
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
1786
1734
|
* points that need to coincide on the local-space of each rigid-body.
|
1735
|
+
*
|
1736
|
+
* @category Hooks - Joints
|
1787
1737
|
*/
|
1788
1738
|
|
1789
1739
|
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
@@ -1796,6 +1746,8 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
1796
1746
|
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
1797
1747
|
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
1798
1748
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
1749
|
+
*
|
1750
|
+
* @category Hooks - Joints
|
1799
1751
|
*/
|
1800
1752
|
|
1801
1753
|
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
@@ -1815,6 +1767,8 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]
|
|
1815
1767
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
1816
1768
|
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
1817
1769
|
* local tangent axis can be specified for each rigid-body.
|
1770
|
+
*
|
1771
|
+
* @category Hooks - Joints
|
1818
1772
|
*/
|
1819
1773
|
|
1820
1774
|
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
@@ -1895,7 +1849,9 @@ exports.Physics = Physics;
|
|
1895
1849
|
exports.RigidBody = RigidBody;
|
1896
1850
|
exports.RoundCuboidCollider = RoundCuboidCollider;
|
1897
1851
|
exports.TrimeshCollider = TrimeshCollider;
|
1852
|
+
exports.euler = euler;
|
1898
1853
|
exports.interactionGroups = interactionGroups;
|
1854
|
+
exports.quat = quat;
|
1899
1855
|
exports.useAfterPhysicsStep = useAfterPhysicsStep;
|
1900
1856
|
exports.useBeforePhysicsStep = useBeforePhysicsStep;
|
1901
1857
|
exports.useFixedJoint = useFixedJoint;
|
@@ -1904,3 +1860,4 @@ exports.usePrismaticJoint = usePrismaticJoint;
|
|
1904
1860
|
exports.useRapier = useRapier;
|
1905
1861
|
exports.useRevoluteJoint = useRevoluteJoint;
|
1906
1862
|
exports.useSphericalJoint = useSphericalJoint;
|
1863
|
+
exports.vec3 = vec3;
|