@react-three/rapier 0.6.8 → 0.7.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/AnyCollider.d.ts +24 -11
- package/dist/declarations/src/InstancedRigidBodies.d.ts +2 -2
- package/dist/declarations/src/MeshCollider.d.ts +1 -1
- package/dist/declarations/src/Physics.d.ts +40 -26
- package/dist/declarations/src/RigidBody.d.ts +2 -5
- package/dist/declarations/src/bitmasks.d.ts +34 -0
- package/dist/declarations/src/hooks.d.ts +3 -1
- package/dist/declarations/src/index.d.ts +4 -0
- package/dist/declarations/src/shared-objects.d.ts +3 -0
- package/dist/declarations/src/types.d.ts +81 -18
- package/dist/declarations/src/utils-collider.d.ts +36 -0
- package/dist/declarations/src/utils-rigidbody.d.ts +20 -0
- package/dist/declarations/src/utils.d.ts +5 -46
- package/dist/react-three-rapier.cjs.dev.js +824 -657
- package/dist/react-three-rapier.cjs.prod.js +824 -657
- package/dist/react-three-rapier.esm.js +824 -660
- package/package.json +4 -4
- package/readme.md +80 -10
@@ -1,30 +1,30 @@
|
|
1
|
-
import {
|
1
|
+
import { EventQueue, RigidBodyDesc, ColliderDesc, ActiveEvents, ShapeType } from '@dimforge/rapier3d-compat';
|
2
2
|
export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
|
3
|
-
import React, { useState, useEffect, useRef, useMemo, createContext, useContext, forwardRef, useImperativeHandle,
|
3
|
+
import React, { useState, useEffect, useRef, useMemo, createContext, useContext, memo, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
|
4
4
|
import { useAsset } from 'use-asset';
|
5
5
|
import { useFrame } from '@react-three/fiber';
|
6
6
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeBufferGeometry, CapsuleBufferGeometry, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
|
7
|
-
import {
|
8
|
-
import { RoundedBoxGeometry } from 'three-stdlib';
|
7
|
+
import { clamp } from 'three/src/math/MathUtils';
|
8
|
+
import { mergeVertices, RoundedBoxGeometry } from 'three-stdlib';
|
9
9
|
|
10
10
|
const _quaternion = new Quaternion();
|
11
|
-
|
11
|
+
new Euler();
|
12
12
|
const _vector3 = new Vector3();
|
13
|
-
new Object3D();
|
13
|
+
const _object3d = new Object3D();
|
14
14
|
const _matrix4 = new Matrix4();
|
15
|
+
const _position = new Vector3();
|
16
|
+
const _rotation = new Quaternion();
|
17
|
+
const _scale = new Vector3();
|
15
18
|
|
16
19
|
const vectorArrayToVector3 = arr => {
|
17
20
|
const [x, y, z] = arr;
|
18
21
|
return new Vector3(x, y, z);
|
19
22
|
};
|
20
|
-
const vector3ToQuaternion = v => {
|
21
|
-
return _quaternion.setFromEuler(_euler.setFromVector3(v));
|
22
|
-
};
|
23
23
|
const rapierVector3ToVector3 = ({
|
24
24
|
x,
|
25
25
|
y,
|
26
26
|
z
|
27
|
-
}) => _vector3.set(x, y, z)
|
27
|
+
}) => _vector3.set(x, y, z);
|
28
28
|
const rapierQuaternionToQuaternion = ({
|
29
29
|
x,
|
30
30
|
y,
|
@@ -38,208 +38,6 @@ const rigidBodyTypeMap = {
|
|
38
38
|
kinematicVelocity: 3
|
39
39
|
};
|
40
40
|
const rigidBodyTypeFromString = type => rigidBodyTypeMap[type];
|
41
|
-
const decomposeMatrix4 = m => {
|
42
|
-
const position = new Vector3();
|
43
|
-
const rotation = new Quaternion();
|
44
|
-
const scale = new Vector3();
|
45
|
-
m.decompose(position, rotation, scale);
|
46
|
-
return {
|
47
|
-
position,
|
48
|
-
rotation,
|
49
|
-
scale
|
50
|
-
};
|
51
|
-
};
|
52
|
-
const scaleColliderArgs = (shape, args, scale) => {
|
53
|
-
const newArgs = args.slice(); // Heightfield uses a vector
|
54
|
-
|
55
|
-
if (shape === "heightfield") {
|
56
|
-
const s = newArgs[3];
|
57
|
-
s.x *= scale.x;
|
58
|
-
s.x *= scale.y;
|
59
|
-
s.x *= scale.z;
|
60
|
-
return newArgs;
|
61
|
-
} // Trimesh and convex scale the vertices
|
62
|
-
|
63
|
-
|
64
|
-
if (shape === "trimesh" || shape === "convexHull") {
|
65
|
-
newArgs[0] = scaleVertices(newArgs[0], scale);
|
66
|
-
return newArgs;
|
67
|
-
} // Prepfill with some extra
|
68
|
-
|
69
|
-
|
70
|
-
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
71
|
-
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
72
|
-
};
|
73
|
-
const createColliderFromOptions = ({
|
74
|
-
options,
|
75
|
-
world,
|
76
|
-
rigidBody,
|
77
|
-
scale,
|
78
|
-
hasCollisionEvents
|
79
|
-
}) => {
|
80
|
-
var _options$shape, _options$args, _options$restitution, _options$restitutionC, _options$friction, _options$frictionComb;
|
81
|
-
|
82
|
-
const mass = (options === null || options === void 0 ? void 0 : options.mass) || 1;
|
83
|
-
const colliderShape = (_options$shape = options === null || options === void 0 ? void 0 : options.shape) !== null && _options$shape !== void 0 ? _options$shape : "cuboid";
|
84
|
-
const colliderArgs = (_options$args = options === null || options === void 0 ? void 0 : options.args) !== null && _options$args !== void 0 ? _options$args : [];
|
85
|
-
const [cmx, cmy, cmz] = (options === null || options === void 0 ? void 0 : options.centerOfMass) || [0, 0, 0];
|
86
|
-
const [pix, piy, piz] = (options === null || options === void 0 ? void 0 : options.principalAngularInertia) || [mass * 0.2, mass * 0.2, mass * 0.2];
|
87
|
-
const [x, y, z] = (options === null || options === void 0 ? void 0 : options.position) || [0, 0, 0];
|
88
|
-
const [rx, ry, rz] = (options === null || options === void 0 ? void 0 : options.rotation) || [0, 0, 0];
|
89
|
-
const qRotation = vector3ToQuaternion(new Vector3(rx, ry, rz)); // @ts-ignore
|
90
|
-
|
91
|
-
const scaledArgs = scaleColliderArgs(options.shape, colliderArgs, scale);
|
92
|
-
let colliderDesc = ColliderDesc[colliderShape]( // @ts-ignore
|
93
|
-
...scaledArgs).setTranslation(x * scale.x, y * scale.y, z * scale.z).setRotation({
|
94
|
-
x: qRotation.x,
|
95
|
-
y: qRotation.y,
|
96
|
-
z: qRotation.z,
|
97
|
-
w: qRotation.w
|
98
|
-
}).setRestitution((_options$restitution = options === null || options === void 0 ? void 0 : options.restitution) !== null && _options$restitution !== void 0 ? _options$restitution : 0).setRestitutionCombineRule((_options$restitutionC = options === null || options === void 0 ? void 0 : options.restitutionCombineRule) !== null && _options$restitutionC !== void 0 ? _options$restitutionC : CoefficientCombineRule.Average).setFriction((_options$friction = options === null || options === void 0 ? void 0 : options.friction) !== null && _options$friction !== void 0 ? _options$friction : 0.7).setFrictionCombineRule((_options$frictionComb = options === null || options === void 0 ? void 0 : options.frictionCombineRule) !== null && _options$frictionComb !== void 0 ? _options$frictionComb : CoefficientCombineRule.Average);
|
99
|
-
|
100
|
-
if (hasCollisionEvents) {
|
101
|
-
colliderDesc = colliderDesc.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
|
102
|
-
} // If any of the mass properties are specified, add mass properties
|
103
|
-
|
104
|
-
|
105
|
-
const qMassRot = vector3ToQuaternion(new Vector3(0, 0, 0));
|
106
|
-
|
107
|
-
if (options !== null && options !== void 0 && options.mass || options !== null && options !== void 0 && options.centerOfMass || options !== null && options !== void 0 && options.principalAngularInertia) {
|
108
|
-
colliderDesc.setDensity(0);
|
109
|
-
colliderDesc.setMassProperties(mass, {
|
110
|
-
x: cmx,
|
111
|
-
y: cmy,
|
112
|
-
z: cmz
|
113
|
-
}, {
|
114
|
-
x: pix,
|
115
|
-
y: piy,
|
116
|
-
z: piz
|
117
|
-
}, {
|
118
|
-
x: qMassRot.x,
|
119
|
-
y: qMassRot.y,
|
120
|
-
z: qMassRot.z,
|
121
|
-
w: qMassRot.w
|
122
|
-
});
|
123
|
-
}
|
124
|
-
|
125
|
-
const collider = world.createCollider(colliderDesc, rigidBody);
|
126
|
-
return collider;
|
127
|
-
};
|
128
|
-
|
129
|
-
const isChildOfMeshCollider = child => {
|
130
|
-
let flag = false;
|
131
|
-
child.traverseAncestors(a => {
|
132
|
-
if (a.userData.r3RapierType === "MeshCollider") flag = true;
|
133
|
-
});
|
134
|
-
return flag;
|
135
|
-
};
|
136
|
-
|
137
|
-
const createCollidersFromChildren = ({
|
138
|
-
object,
|
139
|
-
rigidBody,
|
140
|
-
options,
|
141
|
-
world,
|
142
|
-
ignoreMeshColliders: _ignoreMeshColliders = true
|
143
|
-
}) => {
|
144
|
-
const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
|
145
|
-
const colliders = [];
|
146
|
-
object.traverseVisible(child => {
|
147
|
-
if ("isMesh" in child) {
|
148
|
-
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
149
|
-
const {
|
150
|
-
geometry
|
151
|
-
} = child;
|
152
|
-
const {
|
153
|
-
x,
|
154
|
-
y,
|
155
|
-
z
|
156
|
-
} = child.position;
|
157
|
-
const {
|
158
|
-
x: rx,
|
159
|
-
y: ry,
|
160
|
-
z: rz,
|
161
|
-
w: rw
|
162
|
-
} = new Quaternion().setFromEuler(child.rotation);
|
163
|
-
const scale = child.getWorldScale(new Vector3()); // We translate the colliders based on the parent's world scale
|
164
|
-
|
165
|
-
const parentWorldScale = child.parent.getWorldScale(new Vector3());
|
166
|
-
const desc = colliderDescFromGeometry(geometry, options.colliders, scale, hasCollisionEvents);
|
167
|
-
const offset = new Vector3(0, 0, 0);
|
168
|
-
|
169
|
-
if (options.colliders === "cuboid") {
|
170
|
-
var _geometry$boundingBox;
|
171
|
-
|
172
|
-
geometry.computeBoundingBox();
|
173
|
-
(_geometry$boundingBox = geometry.boundingBox) === null || _geometry$boundingBox === void 0 ? void 0 : _geometry$boundingBox.getCenter(offset);
|
174
|
-
}
|
175
|
-
|
176
|
-
if (options.colliders === "ball") {
|
177
|
-
geometry.computeBoundingSphere();
|
178
|
-
offset.copy(geometry.boundingSphere.center);
|
179
|
-
}
|
180
|
-
|
181
|
-
if (Number.isFinite(options.friction)) desc.setFriction(options.friction);
|
182
|
-
if (Number.isFinite(options.restitution)) desc.setRestitution(options.restitution);
|
183
|
-
desc.setTranslation((x + offset.x) * parentWorldScale.x, (y + offset.y) * parentWorldScale.y, (z + offset.z) * parentWorldScale.z).setRotation({
|
184
|
-
x: rx,
|
185
|
-
y: ry,
|
186
|
-
z: rz,
|
187
|
-
w: rw
|
188
|
-
});
|
189
|
-
const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
|
190
|
-
const collider = world.createCollider(desc, actualRigidBody);
|
191
|
-
colliders.push(collider);
|
192
|
-
}
|
193
|
-
});
|
194
|
-
return colliders;
|
195
|
-
};
|
196
|
-
const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents) => {
|
197
|
-
let desc;
|
198
|
-
|
199
|
-
switch (colliders) {
|
200
|
-
case "cuboid":
|
201
|
-
{
|
202
|
-
geometry.computeBoundingBox();
|
203
|
-
const {
|
204
|
-
boundingBox
|
205
|
-
} = geometry;
|
206
|
-
const size = boundingBox.getSize(new Vector3());
|
207
|
-
desc = ColliderDesc.cuboid(size.x / 2 * scale.x, size.y / 2 * scale.y, size.z / 2 * scale.z);
|
208
|
-
}
|
209
|
-
break;
|
210
|
-
|
211
|
-
case "ball":
|
212
|
-
{
|
213
|
-
geometry.computeBoundingSphere();
|
214
|
-
const {
|
215
|
-
boundingSphere
|
216
|
-
} = geometry;
|
217
|
-
const radius = boundingSphere.radius * scale.x;
|
218
|
-
desc = ColliderDesc.ball(radius);
|
219
|
-
}
|
220
|
-
break;
|
221
|
-
|
222
|
-
case "trimesh":
|
223
|
-
{
|
224
|
-
var _g$index;
|
225
|
-
|
226
|
-
const clonedGeometry = geometry.index ? geometry.clone() : mergeVertices(geometry);
|
227
|
-
const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
|
228
|
-
desc = ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
|
229
|
-
}
|
230
|
-
break;
|
231
|
-
|
232
|
-
case "hull":
|
233
|
-
{
|
234
|
-
const g = geometry.clone().scale(scale.x, scale.y, scale.z);
|
235
|
-
desc = ColliderDesc.convexHull(g.attributes.position.array);
|
236
|
-
}
|
237
|
-
break;
|
238
|
-
}
|
239
|
-
|
240
|
-
if (hasCollisionEvents) desc.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
|
241
|
-
return desc;
|
242
|
-
};
|
243
41
|
const scaleVertices = (vertices, scale) => {
|
244
42
|
const scaledVerts = Array.from(vertices);
|
245
43
|
|
@@ -251,28 +49,6 @@ const scaleVertices = (vertices, scale) => {
|
|
251
49
|
|
252
50
|
return scaledVerts;
|
253
51
|
};
|
254
|
-
const rigidBodyDescFromOptions = options => {
|
255
|
-
var _options$linearVeloci, _options$angularVeloc, _options$angularDampi, _options$linearDampin, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
|
256
|
-
|
257
|
-
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
258
|
-
const [lvx, lvy, lvz] = (_options$linearVeloci = options === null || options === void 0 ? void 0 : options.linearVelocity) !== null && _options$linearVeloci !== void 0 ? _options$linearVeloci : [0, 0, 0];
|
259
|
-
const [avx, avy, avz] = (_options$angularVeloc = options === null || options === void 0 ? void 0 : options.angularVelocity) !== null && _options$angularVeloc !== void 0 ? _options$angularVeloc : [0, 0, 0];
|
260
|
-
const angularDamping = (_options$angularDampi = options === null || options === void 0 ? void 0 : options.angularDamping) !== null && _options$angularDampi !== void 0 ? _options$angularDampi : 0;
|
261
|
-
const linearDamping = (_options$linearDampin = options === null || options === void 0 ? void 0 : options.linearDamping) !== null && _options$linearDampin !== void 0 ? _options$linearDampin : 0;
|
262
|
-
const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
|
263
|
-
const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
264
|
-
const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
|
265
|
-
const [erx, ery, erz] = (_options$enabledRotat = options === null || options === void 0 ? void 0 : options.enabledRotations) !== null && _options$enabledRotat !== void 0 ? _options$enabledRotat : [true, true, true];
|
266
|
-
const [etx, ety, etz] = (_options$enabledTrans = options === null || options === void 0 ? void 0 : options.enabledTranslations) !== null && _options$enabledTrans !== void 0 ? _options$enabledTrans : [true, true, true];
|
267
|
-
const desc = new RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
|
268
|
-
x: avx,
|
269
|
-
y: avy,
|
270
|
-
z: avz
|
271
|
-
}).setLinearDamping(linearDamping).setAngularDamping(angularDamping).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
|
272
|
-
if (options.lockRotations) desc.lockRotations();
|
273
|
-
if (options.lockTranslations) desc.lockTranslations();
|
274
|
-
return desc;
|
275
|
-
};
|
276
52
|
|
277
53
|
const createRigidBodyApi = ref => {
|
278
54
|
return {
|
@@ -424,8 +200,8 @@ const Physics = ({
|
|
424
200
|
gravity: _gravity = [0, -9.81, 0],
|
425
201
|
children,
|
426
202
|
timeStep: _timeStep = 1 / 60,
|
427
|
-
|
428
|
-
|
203
|
+
paused: _paused = false,
|
204
|
+
updatePriority
|
429
205
|
}) => {
|
430
206
|
const rapier = useAsset(importRapier);
|
431
207
|
const [isPaused, setIsPaused] = useState(_paused);
|
@@ -442,7 +218,9 @@ const Physics = ({
|
|
442
218
|
return worldRef.current;
|
443
219
|
});
|
444
220
|
const [rigidBodyStates] = useState(() => new Map());
|
221
|
+
const [colliderStates] = useState(() => new Map());
|
445
222
|
const [rigidBodyEvents] = useState(() => new Map());
|
223
|
+
const [colliderEvents] = useState(() => new Map());
|
446
224
|
const [eventQueue] = useState(() => new EventQueue(false)); // Init world
|
447
225
|
|
448
226
|
useEffect(() => {
|
@@ -462,45 +240,29 @@ const Physics = ({
|
|
462
240
|
}
|
463
241
|
}, [_gravity]);
|
464
242
|
const [steppingState] = useState({
|
465
|
-
time: 0,
|
466
|
-
lastTime: 0,
|
467
243
|
accumulator: 0
|
468
244
|
});
|
469
|
-
useFrame((_,
|
245
|
+
useFrame((_, dt) => {
|
470
246
|
const world = worldRef.current;
|
471
247
|
if (!world) return;
|
472
248
|
world.timestep = _timeStep;
|
473
249
|
/**
|
474
250
|
* Fixed timeStep simulation progression
|
475
|
-
* @see https://gafferongames.com/post/fix_your_timestep/
|
251
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
476
252
|
*/
|
253
|
+
// don't step time forwards if paused
|
254
|
+
// Increase accumulator
|
477
255
|
|
478
|
-
|
479
|
-
|
480
|
-
const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
|
481
|
-
const timeStepMs = _timeStep * 1000;
|
482
|
-
const timeSinceLast = nowTime - steppingState.lastTime;
|
483
|
-
steppingState.lastTime = nowTime;
|
484
|
-
steppingState.accumulator += timeSinceLast;
|
256
|
+
steppingState.accumulator += _paused ? 0 : clamp(dt, 0, 0.2);
|
485
257
|
|
486
258
|
if (!_paused) {
|
487
|
-
|
488
|
-
|
489
|
-
while (steppingState.accumulator >= timeStepMs && subSteps < _maxSubSteps) {
|
490
|
-
// Collect previous state
|
491
|
-
world.bodies.forEach(b => {
|
492
|
-
previousTranslations[b.handle] = {
|
493
|
-
rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
|
494
|
-
translation: rapierVector3ToVector3(b.translation())
|
495
|
-
};
|
496
|
-
});
|
259
|
+
while (steppingState.accumulator >= _timeStep) {
|
497
260
|
world.step(eventQueue);
|
498
|
-
|
499
|
-
steppingState.accumulator -= timeStepMs;
|
261
|
+
steppingState.accumulator -= _timeStep;
|
500
262
|
}
|
501
263
|
}
|
502
264
|
|
503
|
-
const interpolationAlpha = steppingState.accumulator %
|
265
|
+
const interpolationAlpha = steppingState.accumulator % _timeStep / _timeStep; // Update meshes
|
504
266
|
|
505
267
|
rigidBodyStates.forEach((state, handle) => {
|
506
268
|
const rigidBody = world.getRigidBody(handle);
|
@@ -526,62 +288,156 @@ const Physics = ({
|
|
526
288
|
return;
|
527
289
|
}
|
528
290
|
|
529
|
-
let
|
530
|
-
let
|
531
|
-
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
532
|
-
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
533
|
-
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
534
|
-
state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
|
291
|
+
let t = rigidBody.translation();
|
292
|
+
let r = rigidBody.rotation(); // Get new position
|
535
293
|
|
536
|
-
|
537
|
-
state.mesh.instanceMatrix.needsUpdate = true;
|
538
|
-
}
|
539
|
-
}); // Collision events
|
294
|
+
_matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
540
295
|
|
296
|
+
if (state.object instanceof InstancedMesh) {
|
297
|
+
state.setMatrix(_matrix4);
|
298
|
+
state.object.instanceMatrix.needsUpdate = true;
|
299
|
+
} else {
|
300
|
+
// Interpolate from last position
|
301
|
+
state.object.position.lerp(_position, interpolationAlpha);
|
302
|
+
state.object.quaternion.slerp(_rotation, interpolationAlpha);
|
303
|
+
}
|
304
|
+
});
|
541
305
|
eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
542
306
|
var _collider1$parent, _collider2$parent;
|
543
307
|
|
544
308
|
const collider1 = world.getCollider(handle1);
|
545
309
|
const collider2 = world.getCollider(handle2);
|
546
310
|
const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
|
547
|
-
const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
|
311
|
+
const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle; // Collision Events
|
548
312
|
|
549
|
-
if (!collider1 || !collider2
|
313
|
+
if (!collider1 || !collider2) {
|
550
314
|
return;
|
551
315
|
}
|
552
316
|
|
553
|
-
const
|
554
|
-
const
|
555
|
-
const
|
556
|
-
const
|
317
|
+
const collider1Events = colliderEvents.get(collider1.handle);
|
318
|
+
const collider2Events = colliderEvents.get(collider2.handle);
|
319
|
+
const rigidBody1 = rigidBodyHandle1 ? world.getRigidBody(rigidBodyHandle1) : undefined;
|
320
|
+
const rigidBody2 = rigidBodyHandle2 ? world.getRigidBody(rigidBodyHandle2) : undefined;
|
321
|
+
const rigidBody1Events = rigidBodyHandle1 ? rigidBodyEvents.get(rigidBodyHandle1) : undefined;
|
322
|
+
const rigidBody2Events = rigidBodyHandle2 ? rigidBodyEvents.get(rigidBodyHandle2) : undefined;
|
323
|
+
const collider1State = colliderStates.get(collider1.handle);
|
324
|
+
const collider2State = colliderStates.get(collider2.handle);
|
325
|
+
const rigidBody1State = rigidBodyHandle1 ? rigidBodyStates.get(rigidBodyHandle1) : undefined;
|
326
|
+
const rigidBody2State = rigidBodyHandle2 ? rigidBodyStates.get(rigidBodyHandle2) : undefined;
|
557
327
|
|
558
328
|
if (started) {
|
559
329
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
560
|
-
var
|
330
|
+
var _rigidBody1Events$onC, _rigidBody2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
|
331
|
+
|
332
|
+
/* RigidBody events */
|
333
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
|
334
|
+
rigidBody: rigidBody2,
|
335
|
+
collider: collider2,
|
336
|
+
colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
|
337
|
+
rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object,
|
338
|
+
manifold,
|
339
|
+
flipped
|
340
|
+
});
|
341
|
+
rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onC = rigidBody2Events.onCollisionEnter) === null || _rigidBody2Events$onC === void 0 ? void 0 : _rigidBody2Events$onC.call(rigidBody2Events, {
|
342
|
+
rigidBody: rigidBody1,
|
343
|
+
collider: collider1,
|
344
|
+
colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
|
345
|
+
rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object,
|
346
|
+
manifold,
|
347
|
+
flipped
|
348
|
+
});
|
349
|
+
/* Collider events */
|
561
350
|
|
562
|
-
|
563
|
-
|
351
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
|
352
|
+
rigidBody: rigidBody2,
|
353
|
+
collider: collider2,
|
354
|
+
colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
|
355
|
+
rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object,
|
564
356
|
manifold,
|
565
357
|
flipped
|
566
358
|
});
|
567
|
-
|
568
|
-
|
359
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
|
360
|
+
rigidBody: rigidBody1,
|
361
|
+
collider: collider1,
|
362
|
+
colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
|
363
|
+
rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object,
|
569
364
|
manifold,
|
570
365
|
flipped
|
571
366
|
});
|
572
367
|
});
|
573
368
|
} else {
|
574
|
-
var
|
369
|
+
var _rigidBody1Events$onC2, _rigidBody2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
|
370
|
+
|
371
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
|
372
|
+
rigidBody: rigidBody2,
|
373
|
+
collider: collider2
|
374
|
+
});
|
375
|
+
rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onC2 = rigidBody2Events.onCollisionExit) === null || _rigidBody2Events$onC2 === void 0 ? void 0 : _rigidBody2Events$onC2.call(rigidBody2Events, {
|
376
|
+
rigidBody: rigidBody1,
|
377
|
+
collider: collider1
|
378
|
+
});
|
379
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
|
380
|
+
rigidBody: rigidBody2,
|
381
|
+
collider: collider2
|
382
|
+
});
|
383
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
|
384
|
+
rigidBody: rigidBody1,
|
385
|
+
collider: collider1
|
386
|
+
});
|
387
|
+
} // Sensor Intersections
|
388
|
+
|
389
|
+
|
390
|
+
if (started) {
|
391
|
+
if (world.intersectionPair(collider1, collider2)) {
|
392
|
+
var _rigidBody1Events$onI, _rigidBody2Events$onI, _collider1Events$onIn, _collider2Events$onIn;
|
393
|
+
|
394
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onI = rigidBody1Events.onIntersectionEnter) === null || _rigidBody1Events$onI === void 0 ? void 0 : _rigidBody1Events$onI.call(rigidBody1Events, {
|
395
|
+
rigidBody: rigidBody2,
|
396
|
+
collider: collider2,
|
397
|
+
colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
|
398
|
+
rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object
|
399
|
+
});
|
400
|
+
rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onI = rigidBody2Events.onIntersectionEnter) === null || _rigidBody2Events$onI === void 0 ? void 0 : _rigidBody2Events$onI.call(rigidBody2Events, {
|
401
|
+
rigidBody: rigidBody1,
|
402
|
+
collider: collider1,
|
403
|
+
colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
|
404
|
+
rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object
|
405
|
+
});
|
406
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onIn = collider1Events.onIntersectionEnter) === null || _collider1Events$onIn === void 0 ? void 0 : _collider1Events$onIn.call(collider1Events, {
|
407
|
+
rigidBody: rigidBody2,
|
408
|
+
collider: collider2,
|
409
|
+
colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
|
410
|
+
rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object
|
411
|
+
});
|
412
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onIn = collider2Events.onIntersectionEnter) === null || _collider2Events$onIn === void 0 ? void 0 : _collider2Events$onIn.call(collider2Events, {
|
413
|
+
rigidBody: rigidBody1,
|
414
|
+
collider: collider1,
|
415
|
+
colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
|
416
|
+
rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object
|
417
|
+
});
|
418
|
+
}
|
419
|
+
} else {
|
420
|
+
var _rigidBody1Events$onI2, _rigidBody2Events$onI2, _collider1Events$onIn2, _collider2Events$onIn2;
|
575
421
|
|
576
|
-
|
577
|
-
|
422
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onI2 = rigidBody1Events.onIntersectionExit) === null || _rigidBody1Events$onI2 === void 0 ? void 0 : _rigidBody1Events$onI2.call(rigidBody1Events, {
|
423
|
+
rigidBody: rigidBody2,
|
424
|
+
collider: collider2
|
425
|
+
});
|
426
|
+
rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onI2 = rigidBody2Events.onIntersectionExit) === null || _rigidBody2Events$onI2 === void 0 ? void 0 : _rigidBody2Events$onI2.call(rigidBody2Events, {
|
427
|
+
rigidBody: rigidBody1,
|
428
|
+
collider: collider1
|
578
429
|
});
|
579
|
-
|
580
|
-
|
430
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onIn2 = collider1Events.onIntersectionExit) === null || _collider1Events$onIn2 === void 0 ? void 0 : _collider1Events$onIn2.call(collider1Events, {
|
431
|
+
rigidBody: rigidBody2,
|
432
|
+
collider: collider2
|
433
|
+
});
|
434
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onIn2 = collider2Events.onIntersectionExit) === null || _collider2Events$onIn2 === void 0 ? void 0 : _collider2Events$onIn2.call(collider2Events, {
|
435
|
+
rigidBody: rigidBody1,
|
436
|
+
collider: collider1
|
581
437
|
});
|
582
438
|
}
|
583
439
|
});
|
584
|
-
});
|
440
|
+
}, updatePriority);
|
585
441
|
const api = useMemo(() => createWorldApi(getWorldRef), []);
|
586
442
|
const context = useMemo(() => ({
|
587
443
|
rapier,
|
@@ -591,7 +447,9 @@ const Physics = ({
|
|
591
447
|
gravity: _gravity
|
592
448
|
},
|
593
449
|
rigidBodyStates,
|
450
|
+
colliderStates,
|
594
451
|
rigidBodyEvents,
|
452
|
+
colliderEvents,
|
595
453
|
isPaused
|
596
454
|
}), [isPaused]);
|
597
455
|
return /*#__PURE__*/React.createElement(RapierContext.Provider, {
|
@@ -692,155 +550,454 @@ function _objectSpread2(target) {
|
|
692
550
|
return target;
|
693
551
|
}
|
694
552
|
|
695
|
-
const
|
696
|
-
|
553
|
+
const rigidBodyDescFromOptions = options => {
|
554
|
+
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
555
|
+
const desc = new RigidBodyDesc(type);
|
556
|
+
return desc;
|
697
557
|
};
|
698
|
-
const
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
}
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
558
|
+
const createRigidBodyState = ({
|
559
|
+
rigidBody,
|
560
|
+
object,
|
561
|
+
setMatrix,
|
562
|
+
getMatrix,
|
563
|
+
worldScale
|
564
|
+
}) => {
|
565
|
+
object.updateWorldMatrix(true, false);
|
566
|
+
const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
|
567
|
+
return {
|
568
|
+
object,
|
569
|
+
rigidBody,
|
570
|
+
invertedWorldMatrix,
|
571
|
+
setMatrix: setMatrix ? setMatrix : matrix => {
|
572
|
+
object.matrix.copy(matrix);
|
573
|
+
},
|
574
|
+
getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
|
575
|
+
scale: worldScale || object.getWorldScale(_scale).clone(),
|
576
|
+
isSleeping: false
|
577
|
+
};
|
578
|
+
};
|
579
|
+
const mutableRigidBodyOptions = {
|
580
|
+
gravityScale: (rb, value) => {
|
581
|
+
rb.setGravityScale(value, true);
|
582
|
+
},
|
583
|
+
linearDamping: (rb, value) => {
|
584
|
+
rb.setLinearDamping(value);
|
585
|
+
},
|
586
|
+
angularDamping: (rb, value) => {
|
587
|
+
rb.setAngularDamping(value);
|
588
|
+
},
|
589
|
+
enabledRotations: (rb, [x, y, z]) => {
|
590
|
+
rb.setEnabledRotations(x, y, z, true);
|
591
|
+
},
|
592
|
+
enabledTranslations: (rb, [x, y, z]) => {
|
593
|
+
rb.setEnabledTranslations(x, y, z, true);
|
594
|
+
},
|
595
|
+
angularVelocity: (rb, [x, y, z]) => {
|
596
|
+
rb.setAngvel({
|
597
|
+
x,
|
598
|
+
y,
|
599
|
+
z
|
600
|
+
}, true);
|
601
|
+
},
|
602
|
+
linearVelocity: (rb, [x, y, z]) => {
|
603
|
+
rb.setLinvel({
|
604
|
+
x,
|
605
|
+
y,
|
606
|
+
z
|
607
|
+
}, true);
|
608
|
+
},
|
609
|
+
ccd: (rb, value) => {
|
610
|
+
rb.enableCcd(value);
|
611
|
+
}
|
612
|
+
};
|
613
|
+
const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
|
614
|
+
const setRigidBodyOptions = (rigidBody, options, states) => {
|
615
|
+
if (!rigidBody) {
|
616
|
+
return;
|
617
|
+
}
|
720
618
|
|
721
|
-
|
722
|
-
rigidBodyRef.current = rigidBody;
|
619
|
+
const state = states.get(rigidBody.handle);
|
723
620
|
|
724
|
-
|
725
|
-
|
726
|
-
} // isSleeping used for onSleep and onWake events
|
621
|
+
if (state) {
|
622
|
+
state.object.updateWorldMatrix(true, false);
|
727
623
|
|
624
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
728
625
|
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
y: 1,
|
736
|
-
z: 1
|
737
|
-
}; // Transforms from options
|
738
|
-
|
739
|
-
const [x, y, z] = (options === null || options === void 0 ? void 0 : options.position) || [0, 0, 0];
|
740
|
-
const [rx, ry, rz] = (options === null || options === void 0 ? void 0 : options.rotation) || [0, 0, 0]; // Set initial transforms based on world transforms
|
741
|
-
|
742
|
-
rigidBody.setTranslation({
|
743
|
-
x: worldPosition.x + x * scale.x,
|
744
|
-
y: worldPosition.y + y * scale.y,
|
745
|
-
z: worldPosition.z + z * scale.z
|
746
|
-
}, false);
|
747
|
-
const rotation = vector3ToQuaternion(new Vector3(rx, ry, rz)).multiply(worldRotation);
|
748
|
-
rigidBody.setRotation({
|
749
|
-
x: rotation.x,
|
750
|
-
y: rotation.y,
|
751
|
-
z: rotation.z,
|
752
|
-
w: rotation.w
|
753
|
-
}, false);
|
754
|
-
rigidBody.resetForces(false);
|
755
|
-
rigidBody.resetTorques(false);
|
756
|
-
const colliderSetting = (_ref = (_options$colliders = options === null || options === void 0 ? void 0 : options.colliders) !== null && _options$colliders !== void 0 ? _options$colliders : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
|
757
|
-
const autoColliders = colliderSetting !== false ? createCollidersFromChildren({
|
758
|
-
object: ref.current,
|
759
|
-
rigidBody,
|
760
|
-
options: _objectSpread2(_objectSpread2({}, options), {}, {
|
761
|
-
colliders: colliderSetting
|
762
|
-
}),
|
763
|
-
world,
|
764
|
-
ignoreMeshColliders: true
|
765
|
-
}) : [];
|
766
|
-
rigidBodyStates.set(rigidBody.handle, {
|
767
|
-
mesh: ref.current,
|
768
|
-
invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
|
769
|
-
isSleeping: false,
|
770
|
-
worldScale: ref.current.getWorldScale(_vector3).clone(),
|
771
|
-
setMatrix: mat => ref.current.matrix.copy(mat),
|
772
|
-
getMatrix: () => ref.current.matrix
|
626
|
+
rigidBody.setTranslation(_position, false);
|
627
|
+
rigidBody.setRotation(_rotation, false);
|
628
|
+
mutableRigidBodyOptionKeys.forEach(key => {
|
629
|
+
if (key in options) {
|
630
|
+
mutableRigidBodyOptions[key](rigidBody, options[key]);
|
631
|
+
}
|
773
632
|
});
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
autoColliders.forEach(collider => world.removeCollider(collider));
|
778
|
-
rigidBodyRef.current = undefined;
|
779
|
-
rigidBodyStates.delete(rigidBody.handle);
|
780
|
-
};
|
781
|
-
}, []); // Events
|
782
|
-
|
633
|
+
}
|
634
|
+
};
|
635
|
+
const useUpdateRigidBodyOptions = (rigidBodyRef, props, states) => {
|
783
636
|
useEffect(() => {
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
onSleep: options === null || options === void 0 ? void 0 : options.onSleep,
|
789
|
-
onWake: options === null || options === void 0 ? void 0 : options.onWake
|
790
|
-
});
|
791
|
-
return () => {
|
792
|
-
rigidBodyEvents.delete(rigidBody.handle);
|
793
|
-
};
|
794
|
-
}, [options.onCollisionEnter, options.onCollisionExit]);
|
795
|
-
const api = useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
796
|
-
return [ref, api];
|
797
|
-
}; // Joints
|
798
|
-
|
799
|
-
const useImpulseJoint = (body1, body2, params) => {
|
637
|
+
setRigidBodyOptions(rigidBodyRef.current, props, states);
|
638
|
+
}, [props]);
|
639
|
+
};
|
640
|
+
const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
800
641
|
const {
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
810
|
-
rb1 = world.getRigidBody(body1.current.handle);
|
811
|
-
rb2 = world.getRigidBody(body2.current.handle);
|
812
|
-
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
813
|
-
jointRef.current = newJoint;
|
814
|
-
}
|
815
|
-
}
|
816
|
-
|
817
|
-
return jointRef.current;
|
818
|
-
});
|
642
|
+
onWake,
|
643
|
+
onSleep,
|
644
|
+
onCollisionEnter,
|
645
|
+
onCollisionExit,
|
646
|
+
onIntersectionEnter,
|
647
|
+
onIntersectionExit
|
648
|
+
} = props;
|
819
649
|
useEffect(() => {
|
820
|
-
|
650
|
+
events.set(rigidBodyRef.current.handle, {
|
651
|
+
onWake,
|
652
|
+
onSleep,
|
653
|
+
onCollisionEnter,
|
654
|
+
onCollisionExit,
|
655
|
+
onIntersectionEnter,
|
656
|
+
onIntersectionExit
|
657
|
+
});
|
821
658
|
return () => {
|
822
|
-
|
823
|
-
world.removeImpulseJoint(joint);
|
824
|
-
jointRef.current = undefined;
|
825
|
-
}
|
659
|
+
events.delete(rigidBodyRef.current.handle);
|
826
660
|
};
|
827
|
-
}, []);
|
828
|
-
const api = useMemo(() => createJointApi(getJointRef), []);
|
829
|
-
return api;
|
661
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
|
830
662
|
};
|
831
|
-
/**
|
832
|
-
*
|
833
|
-
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
834
|
-
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
835
|
-
* The fixed-joint makes these frames coincide in world-space.
|
836
|
-
*/
|
837
663
|
|
838
|
-
const
|
839
|
-
const
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
664
|
+
const scaleColliderArgs = (shape, args, scale) => {
|
665
|
+
const newArgs = args.slice(); // Heightfield uses a vector
|
666
|
+
|
667
|
+
if (shape === "heightfield") {
|
668
|
+
const s = newArgs[3];
|
669
|
+
s.x *= scale.x;
|
670
|
+
s.x *= scale.y;
|
671
|
+
s.x *= scale.z;
|
672
|
+
return newArgs;
|
673
|
+
} // Trimesh and convex scale the vertices
|
674
|
+
|
675
|
+
|
676
|
+
if (shape === "trimesh" || shape === "convexHull") {
|
677
|
+
newArgs[0] = scaleVertices(newArgs[0], scale);
|
678
|
+
return newArgs;
|
679
|
+
} // Prepfill with some extra
|
680
|
+
|
681
|
+
|
682
|
+
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
683
|
+
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
684
|
+
};
|
685
|
+
const createColliderFromOptions = (options, world, scale, rigidBody) => {
|
686
|
+
const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
|
687
|
+
|
688
|
+
const desc = ColliderDesc[options.shape](...scaledArgs);
|
689
|
+
return world.createCollider(desc, rigidBody);
|
690
|
+
};
|
691
|
+
const mutableColliderOptions = {
|
692
|
+
sensor: (collider, value) => {
|
693
|
+
collider.setSensor(value);
|
694
|
+
},
|
695
|
+
collisionGroups: (collider, value) => {
|
696
|
+
collider.setCollisionGroups(value);
|
697
|
+
},
|
698
|
+
solverGroups: (collider, value) => {
|
699
|
+
collider.setSolverGroups(value);
|
700
|
+
},
|
701
|
+
friction: (collider, value) => {
|
702
|
+
collider.setFriction(value);
|
703
|
+
},
|
704
|
+
restitution: (collider, value) => {
|
705
|
+
collider.setRestitution(value);
|
706
|
+
},
|
707
|
+
density: (collider, value) => {
|
708
|
+
collider.setDensity(value);
|
709
|
+
},
|
710
|
+
mass: (collider, value) => {
|
711
|
+
collider.setMass(value);
|
712
|
+
}
|
713
|
+
};
|
714
|
+
const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
|
715
|
+
const setColliderOptions = (collider, options, states) => {
|
716
|
+
const state = states.get(collider.handle);
|
717
|
+
|
718
|
+
if (state) {
|
719
|
+
// Update collider position based on the object's position
|
720
|
+
const parentWorldScale = state.object.parent.getWorldScale(_vector3);
|
721
|
+
state.object.updateWorldMatrix(true, false);
|
722
|
+
|
723
|
+
_matrix4.copy(state.object.matrixWorld).premultiply(state.worldParent.matrixWorld.clone().invert()).decompose(_position, _rotation, _scale);
|
724
|
+
|
725
|
+
collider.setTranslationWrtParent({
|
726
|
+
x: _position.x * parentWorldScale.x,
|
727
|
+
y: _position.y * parentWorldScale.y,
|
728
|
+
z: _position.z * parentWorldScale.z
|
729
|
+
});
|
730
|
+
collider.setRotationWrtParent(_rotation);
|
731
|
+
mutableColliderOptionKeys.forEach(key => {
|
732
|
+
if (key in options) {
|
733
|
+
mutableColliderOptions[key](collider, options[key]);
|
734
|
+
}
|
735
|
+
});
|
736
|
+
}
|
737
|
+
};
|
738
|
+
const useUpdateColliderOptions = (collidersRef, props, states) => {
|
739
|
+
useEffect(() => {
|
740
|
+
collidersRef.current.forEach(collider => {
|
741
|
+
setColliderOptions(collider, props, states);
|
742
|
+
});
|
743
|
+
}, [props]);
|
744
|
+
};
|
745
|
+
|
746
|
+
const isChildOfMeshCollider = child => {
|
747
|
+
let flag = false;
|
748
|
+
child.traverseAncestors(a => {
|
749
|
+
if (a.userData.r3RapierType === "MeshCollider") flag = true;
|
750
|
+
});
|
751
|
+
return flag;
|
752
|
+
};
|
753
|
+
|
754
|
+
const createColliderState = (collider, object, rigidBodyObject) => {
|
755
|
+
return {
|
756
|
+
collider,
|
757
|
+
worldParent: rigidBodyObject || object.parent,
|
758
|
+
object
|
759
|
+
};
|
760
|
+
};
|
761
|
+
const autoColliderMap = {
|
762
|
+
cuboid: "cuboid",
|
763
|
+
ball: "ball",
|
764
|
+
hull: "convexHull",
|
765
|
+
trimesh: "trimesh"
|
766
|
+
};
|
767
|
+
const createColliderPropsFromChildren = ({
|
768
|
+
object,
|
769
|
+
ignoreMeshColliders: _ignoreMeshColliders = true,
|
770
|
+
options
|
771
|
+
}) => {
|
772
|
+
const colliderProps = [];
|
773
|
+
object.updateWorldMatrix(true, false);
|
774
|
+
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
775
|
+
object.traverseVisible(child => {
|
776
|
+
if ("isMesh" in child) {
|
777
|
+
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
778
|
+
const worldScale = child.getWorldScale(_scale);
|
779
|
+
const shape = autoColliderMap[options.colliders || "cuboid"];
|
780
|
+
child.updateWorldMatrix(true, false);
|
781
|
+
|
782
|
+
_matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
|
783
|
+
|
784
|
+
const rotationEuler = new Euler().setFromQuaternion(_rotation, "XYZ");
|
785
|
+
const {
|
786
|
+
geometry
|
787
|
+
} = child;
|
788
|
+
const {
|
789
|
+
args,
|
790
|
+
offset
|
791
|
+
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
792
|
+
colliderProps.push(_objectSpread2(_objectSpread2({}, options), {}, {
|
793
|
+
args: args,
|
794
|
+
shape: shape,
|
795
|
+
rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
|
796
|
+
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
797
|
+
scale: [worldScale.x, worldScale.y, worldScale.z]
|
798
|
+
}));
|
799
|
+
}
|
800
|
+
});
|
801
|
+
return colliderProps;
|
802
|
+
};
|
803
|
+
const getColliderArgsFromGeometry = (geometry, colliders) => {
|
804
|
+
switch (colliders) {
|
805
|
+
case "cuboid":
|
806
|
+
{
|
807
|
+
geometry.computeBoundingBox();
|
808
|
+
const {
|
809
|
+
boundingBox
|
810
|
+
} = geometry;
|
811
|
+
const size = boundingBox.getSize(new Vector3());
|
812
|
+
return {
|
813
|
+
args: [size.x / 2, size.y / 2, size.z / 2],
|
814
|
+
offset: boundingBox.getCenter(new Vector3())
|
815
|
+
};
|
816
|
+
}
|
817
|
+
|
818
|
+
case "ball":
|
819
|
+
{
|
820
|
+
geometry.computeBoundingSphere();
|
821
|
+
const {
|
822
|
+
boundingSphere
|
823
|
+
} = geometry;
|
824
|
+
const radius = boundingSphere.radius;
|
825
|
+
return {
|
826
|
+
args: [radius],
|
827
|
+
offset: boundingSphere.center
|
828
|
+
};
|
829
|
+
}
|
830
|
+
|
831
|
+
case "trimesh":
|
832
|
+
{
|
833
|
+
var _clonedGeometry$index;
|
834
|
+
|
835
|
+
const clonedGeometry = geometry.index ? geometry.clone() : mergeVertices(geometry);
|
836
|
+
return {
|
837
|
+
args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
|
838
|
+
offset: new Vector3()
|
839
|
+
};
|
840
|
+
}
|
841
|
+
|
842
|
+
case "hull":
|
843
|
+
{
|
844
|
+
const g = geometry.clone();
|
845
|
+
return {
|
846
|
+
args: [g.attributes.position.array],
|
847
|
+
offset: new Vector3()
|
848
|
+
};
|
849
|
+
}
|
850
|
+
}
|
851
|
+
|
852
|
+
return {
|
853
|
+
args: [],
|
854
|
+
offset: new Vector3()
|
855
|
+
};
|
856
|
+
};
|
857
|
+
const useColliderEvents = (collidersRef, props, events) => {
|
858
|
+
const {
|
859
|
+
onCollisionEnter,
|
860
|
+
onCollisionExit,
|
861
|
+
onIntersectionEnter,
|
862
|
+
onIntersectionExit
|
863
|
+
} = props;
|
864
|
+
useEffect(() => {
|
865
|
+
var _collidersRef$current;
|
866
|
+
|
867
|
+
(_collidersRef$current = collidersRef.current) === null || _collidersRef$current === void 0 ? void 0 : _collidersRef$current.forEach(collider => {
|
868
|
+
if (onCollisionEnter || onCollisionExit || onIntersectionEnter || onIntersectionExit) {
|
869
|
+
collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
|
870
|
+
}
|
871
|
+
|
872
|
+
events.set(collider.handle, {
|
873
|
+
onCollisionEnter,
|
874
|
+
onCollisionExit,
|
875
|
+
onIntersectionEnter,
|
876
|
+
onIntersectionExit
|
877
|
+
});
|
878
|
+
});
|
879
|
+
return () => {
|
880
|
+
var _collidersRef$current2;
|
881
|
+
|
882
|
+
(_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
|
883
|
+
};
|
884
|
+
}, [onCollisionEnter, onCollisionExit]);
|
885
|
+
};
|
886
|
+
|
887
|
+
const useRapier = () => {
|
888
|
+
return useContext(RapierContext);
|
889
|
+
};
|
890
|
+
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
891
|
+
const [colliderProps, setColliderProps] = useState([]);
|
892
|
+
useEffect(() => {
|
893
|
+
const object = ref.current;
|
894
|
+
|
895
|
+
if (object && options.colliders !== false) {
|
896
|
+
setColliderProps(createColliderPropsFromChildren({
|
897
|
+
object: ref.current,
|
898
|
+
options,
|
899
|
+
ignoreMeshColliders
|
900
|
+
}));
|
901
|
+
}
|
902
|
+
}, [options]);
|
903
|
+
return colliderProps;
|
904
|
+
};
|
905
|
+
const useRigidBody = (options = {}) => {
|
906
|
+
const {
|
907
|
+
world,
|
908
|
+
rigidBodyStates,
|
909
|
+
physicsOptions,
|
910
|
+
rigidBodyEvents
|
911
|
+
} = useRapier();
|
912
|
+
const ref = useRef();
|
913
|
+
const mergedOptions = useMemo(() => {
|
914
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
|
915
|
+
children: undefined
|
916
|
+
});
|
917
|
+
}, [physicsOptions, options]);
|
918
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
|
919
|
+
|
920
|
+
const rigidBodyRef = useRef();
|
921
|
+
const getRigidBodyRef = useRef(() => {
|
922
|
+
if (!rigidBodyRef.current) {
|
923
|
+
const desc = rigidBodyDescFromOptions(options);
|
924
|
+
const rigidBody = world.createRigidBody(desc);
|
925
|
+
rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
|
926
|
+
}
|
927
|
+
|
928
|
+
return rigidBodyRef.current;
|
929
|
+
}); // Setup
|
930
|
+
|
931
|
+
useEffect(() => {
|
932
|
+
const rigidBody = getRigidBodyRef.current();
|
933
|
+
rigidBodyRef.current = rigidBody;
|
934
|
+
|
935
|
+
if (!ref.current) {
|
936
|
+
ref.current = new Object3D();
|
937
|
+
} // isSleeping used for onSleep and onWake events
|
938
|
+
|
939
|
+
|
940
|
+
ref.current.userData.isSleeping = false;
|
941
|
+
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
942
|
+
rigidBody,
|
943
|
+
object: ref.current
|
944
|
+
}));
|
945
|
+
return () => {
|
946
|
+
world.removeRigidBody(rigidBody);
|
947
|
+
rigidBodyStates.delete(rigidBody.handle);
|
948
|
+
};
|
949
|
+
}, []);
|
950
|
+
useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
|
951
|
+
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
952
|
+
const api = useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
953
|
+
return [ref, api, childColliderProps];
|
954
|
+
}; // Joints
|
955
|
+
|
956
|
+
const useImpulseJoint = (body1, body2, params) => {
|
957
|
+
const {
|
958
|
+
world
|
959
|
+
} = useRapier();
|
960
|
+
const jointRef = useRef();
|
961
|
+
const getJointRef = useRef(() => {
|
962
|
+
if (!jointRef.current) {
|
963
|
+
let rb1;
|
964
|
+
let rb2;
|
965
|
+
|
966
|
+
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
967
|
+
rb1 = world.getRigidBody(body1.current.handle);
|
968
|
+
rb2 = world.getRigidBody(body2.current.handle);
|
969
|
+
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
970
|
+
jointRef.current = newJoint;
|
971
|
+
}
|
972
|
+
}
|
973
|
+
|
974
|
+
return jointRef.current;
|
975
|
+
});
|
976
|
+
useEffect(() => {
|
977
|
+
const joint = getJointRef.current();
|
978
|
+
return () => {
|
979
|
+
if (joint) {
|
980
|
+
world.removeImpulseJoint(joint);
|
981
|
+
jointRef.current = undefined;
|
982
|
+
}
|
983
|
+
};
|
984
|
+
}, []);
|
985
|
+
const api = useMemo(() => createJointApi(getJointRef), []);
|
986
|
+
return api;
|
987
|
+
};
|
988
|
+
/**
|
989
|
+
*
|
990
|
+
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
991
|
+
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
992
|
+
* The fixed-joint makes these frames coincide in world-space.
|
993
|
+
*/
|
994
|
+
|
995
|
+
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
996
|
+
const {
|
997
|
+
rapier
|
998
|
+
} = useRapier();
|
999
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
|
1000
|
+
w: 1
|
844
1001
|
}), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
|
845
1002
|
w: 1
|
846
1003
|
})));
|
@@ -883,80 +1040,173 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
883
1040
|
return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
884
1041
|
};
|
885
1042
|
|
886
|
-
|
887
|
-
|
888
|
-
const
|
889
|
-
|
1043
|
+
// Colliders
|
1044
|
+
const AnyCollider = /*#__PURE__*/memo(props => {
|
1045
|
+
const {
|
1046
|
+
children,
|
1047
|
+
position,
|
1048
|
+
rotation,
|
1049
|
+
quaternion,
|
1050
|
+
scale
|
1051
|
+
} = props;
|
1052
|
+
const {
|
1053
|
+
world,
|
1054
|
+
colliderEvents,
|
1055
|
+
colliderStates
|
1056
|
+
} = useRapier();
|
1057
|
+
const rigidBodyContext = useRigidBodyContext();
|
1058
|
+
const ref = useRef(null);
|
1059
|
+
const collidersRef = useRef([]);
|
1060
|
+
useEffect(() => {
|
1061
|
+
const object = ref.current;
|
1062
|
+
const worldScale = object.getWorldScale(new Vector3());
|
1063
|
+
const colliders = []; // If this is an InstancedRigidBody api
|
890
1064
|
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
1065
|
+
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1066
|
+
rigidBodyContext.api.forEach((body, index) => {
|
1067
|
+
var _rigidBodyContext$opt, _rigidBodyContext$opt2;
|
1068
|
+
|
1069
|
+
let instanceScale = worldScale;
|
1070
|
+
|
1071
|
+
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]) {
|
1072
|
+
instanceScale = instanceScale.clone().multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
const collider = createColliderFromOptions(props, world, instanceScale, body.raw());
|
1076
|
+
colliderStates.set(collider.handle, createColliderState(collider, object, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1077
|
+
colliders.push(collider);
|
1078
|
+
});
|
1079
|
+
} else {
|
1080
|
+
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext && (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.api).raw());
|
1081
|
+
colliderStates.set(collider.handle, createColliderState(collider, object, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1082
|
+
colliders.push(collider);
|
1083
|
+
}
|
896
1084
|
|
897
|
-
|
1085
|
+
collidersRef.current = colliders;
|
1086
|
+
return () => {
|
1087
|
+
colliders.forEach(collider => {
|
1088
|
+
world.removeCollider(collider);
|
1089
|
+
});
|
1090
|
+
};
|
1091
|
+
}, []);
|
1092
|
+
useUpdateColliderOptions(collidersRef, props, colliderStates);
|
1093
|
+
useColliderEvents(collidersRef, props, colliderEvents);
|
1094
|
+
return /*#__PURE__*/React.createElement("object3D", {
|
1095
|
+
position: position,
|
1096
|
+
rotation: rotation,
|
1097
|
+
quaternion: quaternion,
|
1098
|
+
scale: scale,
|
1099
|
+
ref: ref
|
1100
|
+
}, children);
|
1101
|
+
});
|
1102
|
+
const CuboidCollider = props => {
|
1103
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1104
|
+
shape: "cuboid"
|
1105
|
+
}));
|
1106
|
+
};
|
1107
|
+
const RoundCuboidCollider = props => {
|
1108
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1109
|
+
shape: "roundCuboid"
|
1110
|
+
}));
|
1111
|
+
};
|
1112
|
+
const BallCollider = props => {
|
1113
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1114
|
+
shape: "ball"
|
1115
|
+
}));
|
1116
|
+
};
|
1117
|
+
const CapsuleCollider = props => {
|
1118
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1119
|
+
shape: "capsule"
|
1120
|
+
}));
|
1121
|
+
};
|
1122
|
+
const HeightfieldCollider = props => {
|
1123
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1124
|
+
shape: "heightfield"
|
1125
|
+
}));
|
1126
|
+
};
|
1127
|
+
const TrimeshCollider = props => {
|
1128
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1129
|
+
shape: "trimesh"
|
1130
|
+
}));
|
1131
|
+
};
|
1132
|
+
const ConeCollider = props => {
|
1133
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1134
|
+
shape: "cone"
|
1135
|
+
}));
|
1136
|
+
};
|
1137
|
+
const CylinderCollider = props => {
|
1138
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1139
|
+
shape: "cylinder"
|
1140
|
+
}));
|
1141
|
+
};
|
1142
|
+
const ConvexHullCollider = props => {
|
1143
|
+
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1144
|
+
shape: "convexHull"
|
1145
|
+
}));
|
1146
|
+
};
|
898
1147
|
|
899
|
-
|
1148
|
+
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
|
1149
|
+
const RigidBodyContext = /*#__PURE__*/createContext(undefined);
|
1150
|
+
const useRigidBodyContext = () => useContext(RigidBodyContext);
|
1151
|
+
const RigidBody = /*#__PURE__*/forwardRef((props, ref) => {
|
1152
|
+
const {
|
1153
|
+
children,
|
1154
|
+
type,
|
1155
|
+
position,
|
1156
|
+
rotation,
|
1157
|
+
scale,
|
1158
|
+
quaternion
|
1159
|
+
} = props,
|
1160
|
+
objectProps = _objectWithoutProperties(props, _excluded$1);
|
900
1161
|
|
1162
|
+
const [object, api, childColliderProps] = useRigidBody(props);
|
901
1163
|
useImperativeHandle(ref, () => api);
|
902
1164
|
return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
|
903
1165
|
value: {
|
904
1166
|
ref: object,
|
905
1167
|
api,
|
906
|
-
hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
|
907
1168
|
options: props
|
908
1169
|
}
|
909
1170
|
}, /*#__PURE__*/React.createElement("object3D", _extends({
|
910
1171
|
ref: object
|
911
|
-
}, objectProps
|
1172
|
+
}, objectProps, {
|
1173
|
+
position: position,
|
1174
|
+
rotation: rotation,
|
1175
|
+
quaternion: quaternion,
|
1176
|
+
scale: scale
|
1177
|
+
}), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
|
1178
|
+
key: index
|
1179
|
+
}, colliderProps)))));
|
912
1180
|
});
|
913
1181
|
|
914
|
-
const MeshCollider =
|
915
|
-
|
916
|
-
|
917
|
-
|
1182
|
+
const MeshCollider = props => {
|
1183
|
+
const {
|
1184
|
+
children,
|
1185
|
+
type
|
1186
|
+
} = props;
|
918
1187
|
const {
|
919
1188
|
physicsOptions,
|
920
1189
|
world
|
921
1190
|
} = useRapier();
|
922
1191
|
const object = useRef(null);
|
923
1192
|
const {
|
924
|
-
api,
|
925
1193
|
options
|
926
1194
|
} = useRigidBodyContext();
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
if ("raw" in api) {
|
936
|
-
autoColliders = createCollidersFromChildren({
|
937
|
-
object: object.current,
|
938
|
-
rigidBody: api,
|
939
|
-
options: _objectSpread2(_objectSpread2({}, options), {}, {
|
940
|
-
colliders: colliderSetting
|
941
|
-
}),
|
942
|
-
world,
|
943
|
-
ignoreMeshColliders: false
|
944
|
-
});
|
945
|
-
}
|
946
|
-
}
|
947
|
-
|
948
|
-
return () => {
|
949
|
-
autoColliders.forEach(collider => {
|
950
|
-
world.removeCollider(collider);
|
951
|
-
});
|
952
|
-
};
|
953
|
-
}, []);
|
1195
|
+
const mergedOptions = useMemo(() => {
|
1196
|
+
return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
|
1197
|
+
children: undefined,
|
1198
|
+
colliders: type
|
1199
|
+
});
|
1200
|
+
}, [physicsOptions, options]);
|
1201
|
+
const childColliderProps = useChildColliderProps(object, mergedOptions, false);
|
954
1202
|
return /*#__PURE__*/React.createElement("object3D", {
|
955
1203
|
ref: object,
|
956
1204
|
userData: {
|
957
1205
|
r3RapierType: "MeshCollider"
|
958
1206
|
}
|
959
|
-
}, children)
|
1207
|
+
}, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
|
1208
|
+
key: index
|
1209
|
+
}, colliderProps))));
|
960
1210
|
};
|
961
1211
|
|
962
1212
|
const geometryFromCollider = collider => {
|
@@ -1133,6 +1383,7 @@ const Debug = ({
|
|
1133
1383
|
})));
|
1134
1384
|
};
|
1135
1385
|
|
1386
|
+
const _excluded = ["positions", "rotations", "children"];
|
1136
1387
|
const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
1137
1388
|
const {
|
1138
1389
|
world,
|
@@ -1140,6 +1391,14 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
|
1140
1391
|
physicsOptions
|
1141
1392
|
} = useRapier();
|
1142
1393
|
const object = useRef(null);
|
1394
|
+
|
1395
|
+
const {
|
1396
|
+
positions,
|
1397
|
+
rotations,
|
1398
|
+
children
|
1399
|
+
} = props,
|
1400
|
+
options = _objectWithoutProperties(props, _excluded);
|
1401
|
+
|
1143
1402
|
const instancesRef = useRef();
|
1144
1403
|
const instancesRefGetter = useRef(() => {
|
1145
1404
|
if (!instancesRef.current) {
|
@@ -1148,214 +1407,119 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
|
1148
1407
|
|
1149
1408
|
return instancesRef.current;
|
1150
1409
|
});
|
1410
|
+
const mergedOptions = useMemo(() => {
|
1411
|
+
return _objectSpread2(_objectSpread2({}, physicsOptions), options);
|
1412
|
+
}, [physicsOptions, options]);
|
1413
|
+
const childColliderProps = useChildColliderProps(object, mergedOptions);
|
1151
1414
|
useLayoutEffect(() => {
|
1152
|
-
|
1415
|
+
object.current.updateWorldMatrix(true, false);
|
1153
1416
|
const rigidBodies = instancesRefGetter.current();
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
if (props.positions && props.positions[index]) {
|
1194
|
-
rigidBody.setTranslation(vectorArrayToVector3(props.positions[index]), true);
|
1195
|
-
} else {
|
1196
|
-
rigidBody.setTranslation(position, true);
|
1197
|
-
} // Set rotations
|
1198
|
-
|
1199
|
-
|
1200
|
-
if (props.rotations && props.rotations[index]) {
|
1201
|
-
const [x, y, z] = props.rotations[index];
|
1202
|
-
rigidBody.setRotation(vector3ToQuaternion(new Vector3(x, y, z)), true);
|
1203
|
-
} else {
|
1204
|
-
rigidBody.setRotation(rotation, true);
|
1417
|
+
const invertedWorld = object.current.matrixWorld.clone().invert();
|
1418
|
+
object.current.traverseVisible(mesh => {
|
1419
|
+
if (mesh instanceof InstancedMesh) {
|
1420
|
+
mesh.instanceMatrix.setUsage(DynamicDrawUsage);
|
1421
|
+
const worldScale = mesh.getWorldScale(_scale);
|
1422
|
+
|
1423
|
+
for (let index = 0; index < mesh.count; index++) {
|
1424
|
+
var _options$scales;
|
1425
|
+
|
1426
|
+
const desc = rigidBodyDescFromOptions(props);
|
1427
|
+
const rigidBody = world.createRigidBody(desc);
|
1428
|
+
const scale = ((_options$scales = options.scales) === null || _options$scales === void 0 ? void 0 : _options$scales[index]) || [1, 1, 1];
|
1429
|
+
const instanceScale = worldScale.clone().multiply(vectorArrayToVector3(scale));
|
1430
|
+
rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
|
1431
|
+
rigidBody,
|
1432
|
+
object: mesh,
|
1433
|
+
setMatrix: matrix => mesh.setMatrixAt(index, matrix),
|
1434
|
+
getMatrix: matrix => {
|
1435
|
+
mesh.getMatrixAt(index, matrix);
|
1436
|
+
return matrix;
|
1437
|
+
},
|
1438
|
+
worldScale: instanceScale
|
1439
|
+
}));
|
1440
|
+
const [x, y, z] = (positions === null || positions === void 0 ? void 0 : positions[index]) || [0, 0, 0];
|
1441
|
+
const [rx, ry, rz] = (rotations === null || rotations === void 0 ? void 0 : rotations[index]) || [0, 0, 0];
|
1442
|
+
|
1443
|
+
_object3d.position.set(x, y, z);
|
1444
|
+
|
1445
|
+
_object3d.rotation.set(rx, ry, rz);
|
1446
|
+
|
1447
|
+
_object3d.applyMatrix4(invertedWorld); // Set initial transforms based on world transforms
|
1448
|
+
// will be replaced by the setRigidBodyOption below
|
1449
|
+
|
1450
|
+
|
1451
|
+
rigidBody.setTranslation(_object3d.position, false);
|
1452
|
+
rigidBody.setRotation(_object3d.quaternion, false);
|
1453
|
+
const api = createRigidBodyApi({
|
1454
|
+
current() {
|
1455
|
+
return rigidBody;
|
1205
1456
|
}
|
1206
1457
|
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
getMatrix: () => {
|
1213
|
-
const m = new Matrix4();
|
1214
|
-
mesh.getMatrixAt(index, m);
|
1215
|
-
return m;
|
1216
|
-
},
|
1217
|
-
// Setting the world scale to the scale here, because
|
1218
|
-
// we want the scales to be reflected by instance
|
1219
|
-
worldScale: scale
|
1220
|
-
});
|
1221
|
-
const api = createRigidBodyApi({
|
1222
|
-
current() {
|
1223
|
-
return rigidBody;
|
1224
|
-
}
|
1225
|
-
|
1226
|
-
});
|
1227
|
-
rigidBodies.push({
|
1228
|
-
rigidBody,
|
1229
|
-
api
|
1230
|
-
});
|
1231
|
-
}
|
1232
|
-
}
|
1233
|
-
|
1234
|
-
if (mesh.type === "Mesh" && !("isInstancedMesh" in mesh)) {
|
1235
|
-
console.warn("Can only use InstancedMesh inside <InstancedRigidBodies />, Mesh will be ignored.");
|
1458
|
+
});
|
1459
|
+
rigidBodies.push({
|
1460
|
+
rigidBody,
|
1461
|
+
api
|
1462
|
+
});
|
1236
1463
|
}
|
1464
|
+
}
|
1465
|
+
});
|
1466
|
+
return () => {
|
1467
|
+
rigidBodies.forEach(rb => {
|
1468
|
+
world.removeRigidBody(rb.rigidBody);
|
1469
|
+
rigidBodyStates.delete(rb.rigidBody.handle);
|
1237
1470
|
});
|
1238
|
-
|
1239
|
-
|
1240
|
-
colliders.forEach(coll => world.removeCollider(coll));
|
1241
|
-
instancesRef.current = undefined;
|
1242
|
-
};
|
1243
|
-
}
|
1471
|
+
instancesRef.current = undefined;
|
1472
|
+
};
|
1244
1473
|
}, []);
|
1245
1474
|
const api = useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
|
1246
|
-
useImperativeHandle(ref, () => api);
|
1247
|
-
|
1475
|
+
useImperativeHandle(ref, () => api);
|
1248
1476
|
return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
|
1249
1477
|
value: {
|
1250
1478
|
ref: object,
|
1251
1479
|
api,
|
1252
|
-
hasCollisionEvents: false,
|
1253
1480
|
options: props
|
1254
1481
|
}
|
1255
1482
|
}, /*#__PURE__*/React.createElement("object3D", {
|
1256
1483
|
ref: object
|
1257
|
-
}, props.children)
|
1484
|
+
}, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
|
1485
|
+
key: index
|
1486
|
+
}, colliderProps)))));
|
1258
1487
|
});
|
1259
1488
|
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
}));
|
1294
|
-
});
|
1295
|
-
} else {
|
1296
|
-
colliders.push(createColliderFromOptions({
|
1297
|
-
options: props,
|
1298
|
-
world,
|
1299
|
-
// Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
|
1300
|
-
rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
|
1301
|
-
scale,
|
1302
|
-
hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
|
1303
|
-
}));
|
1304
|
-
}
|
1305
|
-
|
1306
|
-
return () => {
|
1307
|
-
colliders.forEach(collider => world.removeCollider(collider));
|
1308
|
-
};
|
1309
|
-
}, []);
|
1310
|
-
return /*#__PURE__*/React.createElement("object3D", {
|
1311
|
-
ref: ref
|
1312
|
-
}, children);
|
1313
|
-
};
|
1489
|
+
/**
|
1490
|
+
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
1491
|
+
* properties of RigidBody or Collider components. The first argument represents a list of
|
1492
|
+
* groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
|
1493
|
+
* of groups that will be filtered against. When it is omitted, all groups are filtered against.
|
1494
|
+
*
|
1495
|
+
* @example
|
1496
|
+
* A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
|
1497
|
+
*
|
1498
|
+
* ```tsx
|
1499
|
+
* <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
|
1500
|
+
* ```
|
1501
|
+
*
|
1502
|
+
* A RigidBody that is member of groups 0 and 1 and will collide with everything else:
|
1503
|
+
*
|
1504
|
+
* ```tsx
|
1505
|
+
* <RigidBody collisionGroups={interactionGroups([0, 1])} />
|
1506
|
+
* ```
|
1507
|
+
*
|
1508
|
+
* A RigidBody that is member of groups 0 and 1 and will not collide with anything:
|
1509
|
+
*
|
1510
|
+
* ```tsx
|
1511
|
+
* <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
|
1512
|
+
* ```
|
1513
|
+
*
|
1514
|
+
* Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
|
1515
|
+
* entities for collision events to trigger.
|
1516
|
+
*
|
1517
|
+
* @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
|
1518
|
+
* @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
|
1519
|
+
* @returns An InteractionGroup bitmask.
|
1520
|
+
*/
|
1521
|
+
const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
|
1314
1522
|
|
1315
|
-
const
|
1316
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1317
|
-
shape: "cuboid"
|
1318
|
-
}));
|
1319
|
-
};
|
1320
|
-
const RoundCuboidCollider = props => {
|
1321
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1322
|
-
shape: "roundCuboid"
|
1323
|
-
}));
|
1324
|
-
};
|
1325
|
-
const BallCollider = props => {
|
1326
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1327
|
-
shape: "ball"
|
1328
|
-
}));
|
1329
|
-
};
|
1330
|
-
const CapsuleCollider = props => {
|
1331
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1332
|
-
shape: "capsule"
|
1333
|
-
}));
|
1334
|
-
};
|
1335
|
-
const HeightfieldCollider = props => {
|
1336
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1337
|
-
shape: "heightfield"
|
1338
|
-
}));
|
1339
|
-
};
|
1340
|
-
const TrimeshCollider = props => {
|
1341
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1342
|
-
shape: "trimesh"
|
1343
|
-
}));
|
1344
|
-
};
|
1345
|
-
const ConeCollider = props => {
|
1346
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1347
|
-
shape: "cone"
|
1348
|
-
}));
|
1349
|
-
};
|
1350
|
-
const CylinderCollider = props => {
|
1351
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1352
|
-
shape: "cylinder"
|
1353
|
-
}));
|
1354
|
-
};
|
1355
|
-
const ConvexHullCollider = props => {
|
1356
|
-
return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
|
1357
|
-
shape: "convexHull"
|
1358
|
-
}));
|
1359
|
-
};
|
1523
|
+
const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
|
1360
1524
|
|
1361
|
-
export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useSphericalJoint };
|
1525
|
+
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 };
|