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