@react-three/rapier 0.6.9 → 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 +6 -2
- package/dist/declarations/src/InstancedRigidBodies.d.ts +1 -1
- package/dist/declarations/src/MeshCollider.d.ts +1 -1
- package/dist/declarations/src/Physics.d.ts +32 -19
- package/dist/declarations/src/RigidBody.d.ts +0 -2
- package/dist/declarations/src/hooks.d.ts +3 -1
- package/dist/declarations/src/shared-objects.d.ts +3 -0
- package/dist/declarations/src/types.d.ts +48 -17
- 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 +749 -679
- package/dist/react-three-rapier.cjs.prod.js +749 -679
- package/dist/react-three-rapier.esm.js +750 -682
- package/package.json +1 -1
- package/readme.md +19 -3
@@ -7,7 +7,6 @@ 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 BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
|
11
10
|
var MathUtils = require('three/src/math/MathUtils');
|
12
11
|
var threeStdlib = require('three-stdlib');
|
13
12
|
|
@@ -34,18 +33,18 @@ function _interopNamespace(e) {
|
|
34
33
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
35
34
|
|
36
35
|
const _quaternion = new three.Quaternion();
|
37
|
-
|
36
|
+
new three.Euler();
|
38
37
|
const _vector3 = new three.Vector3();
|
39
|
-
new three.Object3D();
|
38
|
+
const _object3d = new three.Object3D();
|
40
39
|
const _matrix4 = new three.Matrix4();
|
40
|
+
const _position = new three.Vector3();
|
41
|
+
const _rotation = new three.Quaternion();
|
42
|
+
const _scale = new three.Vector3();
|
41
43
|
|
42
44
|
const vectorArrayToVector3 = arr => {
|
43
45
|
const [x, y, z] = arr;
|
44
46
|
return new three.Vector3(x, y, z);
|
45
47
|
};
|
46
|
-
const vector3ToQuaternion = v => {
|
47
|
-
return _quaternion.setFromEuler(_euler.setFromVector3(v));
|
48
|
-
};
|
49
48
|
const rapierVector3ToVector3 = ({
|
50
49
|
x,
|
51
50
|
y,
|
@@ -64,216 +63,6 @@ const rigidBodyTypeMap = {
|
|
64
63
|
kinematicVelocity: 3
|
65
64
|
};
|
66
65
|
const rigidBodyTypeFromString = type => rigidBodyTypeMap[type];
|
67
|
-
const decomposeMatrix4 = m => {
|
68
|
-
const position = new three.Vector3();
|
69
|
-
const rotation = new three.Quaternion();
|
70
|
-
const scale = new three.Vector3();
|
71
|
-
m.decompose(position, rotation, scale);
|
72
|
-
return {
|
73
|
-
position,
|
74
|
-
rotation,
|
75
|
-
scale
|
76
|
-
};
|
77
|
-
};
|
78
|
-
const scaleColliderArgs = (shape, args, scale) => {
|
79
|
-
const newArgs = args.slice(); // Heightfield uses a vector
|
80
|
-
|
81
|
-
if (shape === "heightfield") {
|
82
|
-
const s = newArgs[3];
|
83
|
-
s.x *= scale.x;
|
84
|
-
s.x *= scale.y;
|
85
|
-
s.x *= scale.z;
|
86
|
-
return newArgs;
|
87
|
-
} // Trimesh and convex scale the vertices
|
88
|
-
|
89
|
-
|
90
|
-
if (shape === "trimesh" || shape === "convexHull") {
|
91
|
-
newArgs[0] = scaleVertices(newArgs[0], scale);
|
92
|
-
return newArgs;
|
93
|
-
} // Prepfill with some extra
|
94
|
-
|
95
|
-
|
96
|
-
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
97
|
-
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
98
|
-
};
|
99
|
-
|
100
|
-
const applyColliderOptions = (collider, options) => {
|
101
|
-
if (options.collisionGroups !== undefined) collider.setCollisionGroups(options.collisionGroups);
|
102
|
-
if (options.solverGroups !== undefined) collider.setSolverGroups(options.solverGroups);
|
103
|
-
};
|
104
|
-
|
105
|
-
const createColliderFromOptions = ({
|
106
|
-
options,
|
107
|
-
world,
|
108
|
-
rigidBody,
|
109
|
-
scale,
|
110
|
-
hasCollisionEvents
|
111
|
-
}) => {
|
112
|
-
var _options$shape, _options$args, _options$restitution, _options$restitutionC, _options$friction, _options$frictionComb;
|
113
|
-
|
114
|
-
const mass = (options === null || options === void 0 ? void 0 : options.mass) || 1;
|
115
|
-
const colliderShape = (_options$shape = options === null || options === void 0 ? void 0 : options.shape) !== null && _options$shape !== void 0 ? _options$shape : "cuboid";
|
116
|
-
const colliderArgs = (_options$args = options === null || options === void 0 ? void 0 : options.args) !== null && _options$args !== void 0 ? _options$args : [];
|
117
|
-
const [cmx, cmy, cmz] = (options === null || options === void 0 ? void 0 : options.centerOfMass) || [0, 0, 0];
|
118
|
-
const [pix, piy, piz] = (options === null || options === void 0 ? void 0 : options.principalAngularInertia) || [mass * 0.2, mass * 0.2, mass * 0.2];
|
119
|
-
const [x, y, z] = (options === null || options === void 0 ? void 0 : options.position) || [0, 0, 0];
|
120
|
-
const [rx, ry, rz] = (options === null || options === void 0 ? void 0 : options.rotation) || [0, 0, 0];
|
121
|
-
const qRotation = vector3ToQuaternion(new three.Vector3(rx, ry, rz)); // @ts-ignore
|
122
|
-
|
123
|
-
const scaledArgs = scaleColliderArgs(options.shape, colliderArgs, scale);
|
124
|
-
let colliderDesc = rapier3dCompat.ColliderDesc[colliderShape]( // @ts-ignore
|
125
|
-
...scaledArgs).setTranslation(x * scale.x, y * scale.y, z * scale.z).setRotation({
|
126
|
-
x: qRotation.x,
|
127
|
-
y: qRotation.y,
|
128
|
-
z: qRotation.z,
|
129
|
-
w: qRotation.w
|
130
|
-
}).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);
|
131
|
-
|
132
|
-
if (hasCollisionEvents) {
|
133
|
-
colliderDesc = colliderDesc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
|
134
|
-
} // If any of the mass properties are specified, add mass properties
|
135
|
-
|
136
|
-
|
137
|
-
const qMassRot = vector3ToQuaternion(new three.Vector3(0, 0, 0));
|
138
|
-
|
139
|
-
if (options !== null && options !== void 0 && options.mass || options !== null && options !== void 0 && options.centerOfMass || options !== null && options !== void 0 && options.principalAngularInertia) {
|
140
|
-
colliderDesc.setDensity(0);
|
141
|
-
colliderDesc.setMassProperties(mass, {
|
142
|
-
x: cmx,
|
143
|
-
y: cmy,
|
144
|
-
z: cmz
|
145
|
-
}, {
|
146
|
-
x: pix,
|
147
|
-
y: piy,
|
148
|
-
z: piz
|
149
|
-
}, {
|
150
|
-
x: qMassRot.x,
|
151
|
-
y: qMassRot.y,
|
152
|
-
z: qMassRot.z,
|
153
|
-
w: qMassRot.w
|
154
|
-
});
|
155
|
-
}
|
156
|
-
|
157
|
-
const collider = world.createCollider(colliderDesc, rigidBody);
|
158
|
-
applyColliderOptions(collider, options);
|
159
|
-
return collider;
|
160
|
-
};
|
161
|
-
|
162
|
-
const isChildOfMeshCollider = child => {
|
163
|
-
let flag = false;
|
164
|
-
child.traverseAncestors(a => {
|
165
|
-
if (a.userData.r3RapierType === "MeshCollider") flag = true;
|
166
|
-
});
|
167
|
-
return flag;
|
168
|
-
};
|
169
|
-
|
170
|
-
const createCollidersFromChildren = ({
|
171
|
-
object,
|
172
|
-
rigidBody,
|
173
|
-
options,
|
174
|
-
world,
|
175
|
-
ignoreMeshColliders: _ignoreMeshColliders = true
|
176
|
-
}) => {
|
177
|
-
const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
|
178
|
-
const colliders = [];
|
179
|
-
object.traverseVisible(child => {
|
180
|
-
if ("isMesh" in child) {
|
181
|
-
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
182
|
-
const {
|
183
|
-
geometry
|
184
|
-
} = child;
|
185
|
-
const {
|
186
|
-
x,
|
187
|
-
y,
|
188
|
-
z
|
189
|
-
} = child.position;
|
190
|
-
const {
|
191
|
-
x: rx,
|
192
|
-
y: ry,
|
193
|
-
z: rz,
|
194
|
-
w: rw
|
195
|
-
} = new three.Quaternion().setFromEuler(child.rotation);
|
196
|
-
const scale = child.getWorldScale(new three.Vector3()); // We translate the colliders based on the parent's world scale
|
197
|
-
|
198
|
-
const parentWorldScale = child.parent.getWorldScale(new three.Vector3());
|
199
|
-
const desc = colliderDescFromGeometry(geometry, options.colliders, scale, hasCollisionEvents);
|
200
|
-
const offset = new three.Vector3(0, 0, 0);
|
201
|
-
|
202
|
-
if (options.colliders === "cuboid") {
|
203
|
-
var _geometry$boundingBox;
|
204
|
-
|
205
|
-
geometry.computeBoundingBox();
|
206
|
-
(_geometry$boundingBox = geometry.boundingBox) === null || _geometry$boundingBox === void 0 ? void 0 : _geometry$boundingBox.getCenter(offset);
|
207
|
-
}
|
208
|
-
|
209
|
-
if (options.colliders === "ball") {
|
210
|
-
geometry.computeBoundingSphere();
|
211
|
-
offset.copy(geometry.boundingSphere.center);
|
212
|
-
}
|
213
|
-
|
214
|
-
if (Number.isFinite(options.friction)) desc.setFriction(options.friction);
|
215
|
-
if (Number.isFinite(options.restitution)) desc.setRestitution(options.restitution);
|
216
|
-
desc.setTranslation((x + offset.x) * parentWorldScale.x, (y + offset.y) * parentWorldScale.y, (z + offset.z) * parentWorldScale.z).setRotation({
|
217
|
-
x: rx,
|
218
|
-
y: ry,
|
219
|
-
z: rz,
|
220
|
-
w: rw
|
221
|
-
});
|
222
|
-
const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
|
223
|
-
const collider = world.createCollider(desc, actualRigidBody);
|
224
|
-
applyColliderOptions(collider, options);
|
225
|
-
colliders.push(collider);
|
226
|
-
}
|
227
|
-
});
|
228
|
-
return colliders;
|
229
|
-
};
|
230
|
-
const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents) => {
|
231
|
-
let desc;
|
232
|
-
|
233
|
-
switch (colliders) {
|
234
|
-
case "cuboid":
|
235
|
-
{
|
236
|
-
geometry.computeBoundingBox();
|
237
|
-
const {
|
238
|
-
boundingBox
|
239
|
-
} = geometry;
|
240
|
-
const size = boundingBox.getSize(new three.Vector3());
|
241
|
-
desc = rapier3dCompat.ColliderDesc.cuboid(size.x / 2 * scale.x, size.y / 2 * scale.y, size.z / 2 * scale.z);
|
242
|
-
}
|
243
|
-
break;
|
244
|
-
|
245
|
-
case "ball":
|
246
|
-
{
|
247
|
-
geometry.computeBoundingSphere();
|
248
|
-
const {
|
249
|
-
boundingSphere
|
250
|
-
} = geometry;
|
251
|
-
const radius = boundingSphere.radius * scale.x;
|
252
|
-
desc = rapier3dCompat.ColliderDesc.ball(radius);
|
253
|
-
}
|
254
|
-
break;
|
255
|
-
|
256
|
-
case "trimesh":
|
257
|
-
{
|
258
|
-
var _g$index;
|
259
|
-
|
260
|
-
const clonedGeometry = geometry.index ? geometry.clone() : BufferGeometryUtils.mergeVertices(geometry);
|
261
|
-
const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
|
262
|
-
desc = rapier3dCompat.ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
|
263
|
-
}
|
264
|
-
break;
|
265
|
-
|
266
|
-
case "hull":
|
267
|
-
{
|
268
|
-
const g = geometry.clone().scale(scale.x, scale.y, scale.z);
|
269
|
-
desc = rapier3dCompat.ColliderDesc.convexHull(g.attributes.position.array);
|
270
|
-
}
|
271
|
-
break;
|
272
|
-
}
|
273
|
-
|
274
|
-
if (hasCollisionEvents) desc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
|
275
|
-
return desc;
|
276
|
-
};
|
277
66
|
const scaleVertices = (vertices, scale) => {
|
278
67
|
const scaledVerts = Array.from(vertices);
|
279
68
|
|
@@ -285,28 +74,6 @@ const scaleVertices = (vertices, scale) => {
|
|
285
74
|
|
286
75
|
return scaledVerts;
|
287
76
|
};
|
288
|
-
const rigidBodyDescFromOptions = options => {
|
289
|
-
var _options$linearVeloci, _options$angularVeloc, _options$angularDampi, _options$linearDampin, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
|
290
|
-
|
291
|
-
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
292
|
-
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];
|
293
|
-
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];
|
294
|
-
const angularDamping = (_options$angularDampi = options === null || options === void 0 ? void 0 : options.angularDamping) !== null && _options$angularDampi !== void 0 ? _options$angularDampi : 0;
|
295
|
-
const linearDamping = (_options$linearDampin = options === null || options === void 0 ? void 0 : options.linearDamping) !== null && _options$linearDampin !== void 0 ? _options$linearDampin : 0;
|
296
|
-
const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
|
297
|
-
const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
298
|
-
const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
|
299
|
-
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];
|
300
|
-
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];
|
301
|
-
const desc = new rapier3dCompat.RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
|
302
|
-
x: avx,
|
303
|
-
y: avy,
|
304
|
-
z: avz
|
305
|
-
}).setLinearDamping(linearDamping).setAngularDamping(angularDamping).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
|
306
|
-
if (options.lockRotations) desc.lockRotations();
|
307
|
-
if (options.lockTranslations) desc.lockTranslations();
|
308
|
-
return desc;
|
309
|
-
};
|
310
77
|
|
311
78
|
const createRigidBodyApi = ref => {
|
312
79
|
return {
|
@@ -458,7 +225,6 @@ const Physics = ({
|
|
458
225
|
gravity: _gravity = [0, -9.81, 0],
|
459
226
|
children,
|
460
227
|
timeStep: _timeStep = 1 / 60,
|
461
|
-
maxSubSteps: _maxSubSteps = 10,
|
462
228
|
paused: _paused = false,
|
463
229
|
updatePriority
|
464
230
|
}) => {
|
@@ -477,6 +243,7 @@ const Physics = ({
|
|
477
243
|
return worldRef.current;
|
478
244
|
});
|
479
245
|
const [rigidBodyStates] = React.useState(() => new Map());
|
246
|
+
const [colliderStates] = React.useState(() => new Map());
|
480
247
|
const [rigidBodyEvents] = React.useState(() => new Map());
|
481
248
|
const [colliderEvents] = React.useState(() => new Map());
|
482
249
|
const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
|
@@ -498,11 +265,9 @@ const Physics = ({
|
|
498
265
|
}
|
499
266
|
}, [_gravity]);
|
500
267
|
const [steppingState] = React.useState({
|
501
|
-
time: 0,
|
502
|
-
lastTime: 0,
|
503
268
|
accumulator: 0
|
504
269
|
});
|
505
|
-
fiber.useFrame((_,
|
270
|
+
fiber.useFrame((_, dt) => {
|
506
271
|
const world = worldRef.current;
|
507
272
|
if (!world) return;
|
508
273
|
world.timestep = _timeStep;
|
@@ -510,33 +275,19 @@ const Physics = ({
|
|
510
275
|
* Fixed timeStep simulation progression
|
511
276
|
* @see https://gafferongames.com/post/fix_your_timestep/
|
512
277
|
*/
|
278
|
+
// don't step time forwards if paused
|
279
|
+
// Increase accumulator
|
513
280
|
|
514
|
-
|
515
|
-
|
516
|
-
const nowTime = steppingState.time += _paused ? 0 : MathUtils.clamp(delta, 0, 1) * 1000;
|
517
|
-
const timeStepMs = _timeStep * 1000;
|
518
|
-
const timeSinceLast = nowTime - steppingState.lastTime;
|
519
|
-
steppingState.lastTime = nowTime;
|
520
|
-
steppingState.accumulator += timeSinceLast;
|
281
|
+
steppingState.accumulator += _paused ? 0 : MathUtils.clamp(dt, 0, 0.2);
|
521
282
|
|
522
283
|
if (!_paused) {
|
523
|
-
|
524
|
-
|
525
|
-
while (steppingState.accumulator >= timeStepMs && subSteps < _maxSubSteps) {
|
526
|
-
// Collect previous state
|
527
|
-
world.bodies.forEach(b => {
|
528
|
-
previousTranslations[b.handle] = {
|
529
|
-
rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
|
530
|
-
translation: rapierVector3ToVector3(b.translation())
|
531
|
-
};
|
532
|
-
});
|
284
|
+
while (steppingState.accumulator >= _timeStep) {
|
533
285
|
world.step(eventQueue);
|
534
|
-
|
535
|
-
steppingState.accumulator -= timeStepMs;
|
286
|
+
steppingState.accumulator -= _timeStep;
|
536
287
|
}
|
537
288
|
}
|
538
289
|
|
539
|
-
const interpolationAlpha = steppingState.accumulator %
|
290
|
+
const interpolationAlpha = steppingState.accumulator % _timeStep / _timeStep; // Update meshes
|
540
291
|
|
541
292
|
rigidBodyStates.forEach((state, handle) => {
|
542
293
|
const rigidBody = world.getRigidBody(handle);
|
@@ -562,86 +313,151 @@ const Physics = ({
|
|
562
313
|
return;
|
563
314
|
}
|
564
315
|
|
565
|
-
let
|
566
|
-
let
|
567
|
-
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
568
|
-
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
569
|
-
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
570
|
-
state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
|
316
|
+
let t = rigidBody.translation();
|
317
|
+
let r = rigidBody.rotation(); // Get new position
|
571
318
|
|
572
|
-
|
573
|
-
state.mesh.instanceMatrix.needsUpdate = true;
|
574
|
-
}
|
575
|
-
}); // Collision events
|
319
|
+
_matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
|
576
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
|
+
});
|
577
330
|
eventQueue.drainCollisionEvents((handle1, handle2, started) => {
|
578
331
|
var _collider1$parent, _collider2$parent;
|
579
332
|
|
580
333
|
const collider1 = world.getCollider(handle1);
|
581
334
|
const collider2 = world.getCollider(handle2);
|
582
335
|
const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
|
583
|
-
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
|
584
337
|
|
585
|
-
if (!collider1 || !collider2
|
338
|
+
if (!collider1 || !collider2) {
|
586
339
|
return;
|
587
340
|
}
|
588
341
|
|
589
|
-
const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
|
590
|
-
const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
|
591
|
-
const rigidBody1Events = rigidBodyEvents.get(rigidBodyHandle1);
|
592
|
-
const rigidBoyd2Events = rigidBodyEvents.get(rigidBodyHandle2);
|
593
342
|
const collider1Events = colliderEvents.get(collider1.handle);
|
594
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;
|
595
352
|
|
596
353
|
if (started) {
|
597
354
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
598
|
-
var _rigidBody1Events$onC,
|
355
|
+
var _rigidBody1Events$onC, _rigidBody2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
|
599
356
|
|
600
357
|
/* RigidBody events */
|
601
358
|
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
|
602
|
-
|
359
|
+
rigidBody: rigidBody2,
|
603
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,
|
604
363
|
manifold,
|
605
364
|
flipped
|
606
365
|
});
|
607
|
-
|
608
|
-
|
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,
|
609
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,
|
610
371
|
manifold,
|
611
372
|
flipped
|
612
373
|
});
|
613
374
|
/* Collider events */
|
614
375
|
|
615
376
|
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
|
616
|
-
|
377
|
+
rigidBody: rigidBody2,
|
617
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,
|
618
381
|
manifold,
|
619
382
|
flipped
|
620
383
|
});
|
621
384
|
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
|
622
|
-
|
385
|
+
rigidBody: rigidBody1,
|
623
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,
|
624
389
|
manifold,
|
625
390
|
flipped
|
626
391
|
});
|
627
392
|
});
|
628
393
|
} else {
|
629
|
-
var _rigidBody1Events$onC2,
|
394
|
+
var _rigidBody1Events$onC2, _rigidBody2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
|
630
395
|
|
631
396
|
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
|
632
|
-
|
397
|
+
rigidBody: rigidBody2,
|
633
398
|
collider: collider2
|
634
399
|
});
|
635
|
-
|
636
|
-
|
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,
|
637
402
|
collider: collider1
|
638
403
|
});
|
639
404
|
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
|
640
|
-
|
405
|
+
rigidBody: rigidBody2,
|
641
406
|
collider: collider2
|
642
407
|
});
|
643
408
|
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
|
644
|
-
|
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,
|
645
461
|
collider: collider1
|
646
462
|
});
|
647
463
|
}
|
@@ -656,6 +472,7 @@ const Physics = ({
|
|
656
472
|
gravity: _gravity
|
657
473
|
},
|
658
474
|
rigidBodyStates,
|
475
|
+
colliderStates,
|
659
476
|
rigidBodyEvents,
|
660
477
|
colliderEvents,
|
661
478
|
isPaused
|
@@ -758,151 +575,450 @@ function _objectSpread2(target) {
|
|
758
575
|
return target;
|
759
576
|
}
|
760
577
|
|
761
|
-
const
|
762
|
-
|
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;
|
763
582
|
};
|
764
|
-
const
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
}
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
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
|
+
}
|
786
643
|
|
787
|
-
|
788
|
-
rigidBodyRef.current = rigidBody;
|
644
|
+
const state = states.get(rigidBody.handle);
|
789
645
|
|
790
|
-
|
791
|
-
|
792
|
-
} // isSleeping used for onSleep and onWake events
|
646
|
+
if (state) {
|
647
|
+
state.object.updateWorldMatrix(true, false);
|
793
648
|
|
649
|
+
_matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
|
794
650
|
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
y: 1,
|
802
|
-
z: 1
|
803
|
-
}; // Transforms from options
|
804
|
-
|
805
|
-
const [x, y, z] = (options === null || options === void 0 ? void 0 : options.position) || [0, 0, 0];
|
806
|
-
const [rx, ry, rz] = (options === null || options === void 0 ? void 0 : options.rotation) || [0, 0, 0]; // Set initial transforms based on world transforms
|
807
|
-
|
808
|
-
rigidBody.setTranslation({
|
809
|
-
x: worldPosition.x + x * scale.x,
|
810
|
-
y: worldPosition.y + y * scale.y,
|
811
|
-
z: worldPosition.z + z * scale.z
|
812
|
-
}, false);
|
813
|
-
const rotation = vector3ToQuaternion(new three.Vector3(rx, ry, rz)).multiply(worldRotation);
|
814
|
-
rigidBody.setRotation({
|
815
|
-
x: rotation.x,
|
816
|
-
y: rotation.y,
|
817
|
-
z: rotation.z,
|
818
|
-
w: rotation.w
|
819
|
-
}, false);
|
820
|
-
rigidBody.resetForces(false);
|
821
|
-
rigidBody.resetTorques(false);
|
822
|
-
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;
|
823
|
-
const autoColliders = colliderSetting !== false ? createCollidersFromChildren({
|
824
|
-
object: ref.current,
|
825
|
-
rigidBody,
|
826
|
-
options: _objectSpread2(_objectSpread2({}, options), {}, {
|
827
|
-
colliders: colliderSetting
|
828
|
-
}),
|
829
|
-
world,
|
830
|
-
ignoreMeshColliders: true
|
831
|
-
}) : [];
|
832
|
-
rigidBodyStates.set(rigidBody.handle, {
|
833
|
-
mesh: ref.current,
|
834
|
-
invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
|
835
|
-
isSleeping: false,
|
836
|
-
worldScale: ref.current.getWorldScale(_vector3).clone(),
|
837
|
-
setMatrix: mat => ref.current.matrix.copy(mat),
|
838
|
-
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
|
+
}
|
839
657
|
});
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
autoColliders.forEach(collider => world.removeCollider(collider));
|
844
|
-
rigidBodyRef.current = undefined;
|
845
|
-
rigidBodyStates.delete(rigidBody.handle);
|
846
|
-
};
|
847
|
-
}, []); // Events
|
848
|
-
|
658
|
+
}
|
659
|
+
};
|
660
|
+
const useUpdateRigidBodyOptions = (rigidBodyRef, props, states) => {
|
849
661
|
React.useEffect(() => {
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
onSleep: options === null || options === void 0 ? void 0 : options.onSleep,
|
855
|
-
onWake: options === null || options === void 0 ? void 0 : options.onWake
|
856
|
-
});
|
857
|
-
return () => {
|
858
|
-
rigidBodyEvents.delete(rigidBody.handle);
|
859
|
-
};
|
860
|
-
}, [options.onCollisionEnter, options.onCollisionExit]);
|
861
|
-
const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
862
|
-
return [ref, api];
|
863
|
-
}; // Joints
|
864
|
-
|
865
|
-
const useImpulseJoint = (body1, body2, params) => {
|
662
|
+
setRigidBodyOptions(rigidBodyRef.current, props, states);
|
663
|
+
}, [props]);
|
664
|
+
};
|
665
|
+
const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
866
666
|
const {
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
876
|
-
rb1 = world.getRigidBody(body1.current.handle);
|
877
|
-
rb2 = world.getRigidBody(body2.current.handle);
|
878
|
-
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
879
|
-
jointRef.current = newJoint;
|
880
|
-
}
|
881
|
-
}
|
882
|
-
|
883
|
-
return jointRef.current;
|
884
|
-
});
|
667
|
+
onWake,
|
668
|
+
onSleep,
|
669
|
+
onCollisionEnter,
|
670
|
+
onCollisionExit,
|
671
|
+
onIntersectionEnter,
|
672
|
+
onIntersectionExit
|
673
|
+
} = props;
|
885
674
|
React.useEffect(() => {
|
886
|
-
|
675
|
+
events.set(rigidBodyRef.current.handle, {
|
676
|
+
onWake,
|
677
|
+
onSleep,
|
678
|
+
onCollisionEnter,
|
679
|
+
onCollisionExit,
|
680
|
+
onIntersectionEnter,
|
681
|
+
onIntersectionExit
|
682
|
+
});
|
887
683
|
return () => {
|
888
|
-
|
889
|
-
world.removeImpulseJoint(joint);
|
890
|
-
jointRef.current = undefined;
|
891
|
-
}
|
684
|
+
events.delete(rigidBodyRef.current.handle);
|
892
685
|
};
|
893
|
-
}, []);
|
894
|
-
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
895
|
-
return api;
|
686
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
|
896
687
|
};
|
897
|
-
/**
|
898
|
-
*
|
899
|
-
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
900
|
-
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
901
|
-
* The fixed-joint makes these frames coincide in world-space.
|
902
|
-
*/
|
903
688
|
|
904
|
-
const
|
905
|
-
const
|
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 {
|
906
1022
|
rapier
|
907
1023
|
} = useRapier();
|
908
1024
|
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
|
@@ -949,80 +1065,173 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
949
1065
|
return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
950
1066
|
};
|
951
1067
|
|
952
|
-
|
953
|
-
|
954
|
-
const
|
955
|
-
|
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
|
956
1089
|
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
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
|
+
}
|
962
1099
|
|
963
|
-
|
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
|
+
}
|
1109
|
+
|
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
|
+
};
|
964
1172
|
|
965
|
-
|
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);
|
966
1186
|
|
1187
|
+
const [object, api, childColliderProps] = useRigidBody(props);
|
967
1188
|
React.useImperativeHandle(ref, () => api);
|
968
1189
|
return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
|
969
1190
|
value: {
|
970
1191
|
ref: object,
|
971
1192
|
api,
|
972
|
-
hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
|
973
1193
|
options: props
|
974
1194
|
}
|
975
1195
|
}, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
|
976
1196
|
ref: object
|
977
|
-
}, 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)))));
|
978
1205
|
});
|
979
1206
|
|
980
|
-
const MeshCollider =
|
981
|
-
|
982
|
-
|
983
|
-
|
1207
|
+
const MeshCollider = props => {
|
1208
|
+
const {
|
1209
|
+
children,
|
1210
|
+
type
|
1211
|
+
} = props;
|
984
1212
|
const {
|
985
1213
|
physicsOptions,
|
986
1214
|
world
|
987
1215
|
} = useRapier();
|
988
1216
|
const object = React.useRef(null);
|
989
1217
|
const {
|
990
|
-
api,
|
991
1218
|
options
|
992
1219
|
} = useRigidBodyContext();
|
993
|
-
React.
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
if ("raw" in api) {
|
1002
|
-
autoColliders = createCollidersFromChildren({
|
1003
|
-
object: object.current,
|
1004
|
-
rigidBody: api,
|
1005
|
-
options: _objectSpread2(_objectSpread2({}, options), {}, {
|
1006
|
-
colliders: colliderSetting
|
1007
|
-
}),
|
1008
|
-
world,
|
1009
|
-
ignoreMeshColliders: false
|
1010
|
-
});
|
1011
|
-
}
|
1012
|
-
}
|
1013
|
-
|
1014
|
-
return () => {
|
1015
|
-
autoColliders.forEach(collider => {
|
1016
|
-
world.removeCollider(collider);
|
1017
|
-
});
|
1018
|
-
};
|
1019
|
-
}, []);
|
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);
|
1020
1227
|
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1021
1228
|
ref: object,
|
1022
1229
|
userData: {
|
1023
1230
|
r3RapierType: "MeshCollider"
|
1024
1231
|
}
|
1025
|
-
}, children)
|
1232
|
+
}, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
|
1233
|
+
key: index
|
1234
|
+
}, colliderProps))));
|
1026
1235
|
};
|
1027
1236
|
|
1028
1237
|
const geometryFromCollider = collider => {
|
@@ -1199,6 +1408,7 @@ const Debug = ({
|
|
1199
1408
|
})));
|
1200
1409
|
};
|
1201
1410
|
|
1411
|
+
const _excluded = ["positions", "rotations", "children"];
|
1202
1412
|
const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
1203
1413
|
const {
|
1204
1414
|
world,
|
@@ -1206,6 +1416,14 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1206
1416
|
physicsOptions
|
1207
1417
|
} = useRapier();
|
1208
1418
|
const object = React.useRef(null);
|
1419
|
+
|
1420
|
+
const {
|
1421
|
+
positions,
|
1422
|
+
rotations,
|
1423
|
+
children
|
1424
|
+
} = props,
|
1425
|
+
options = _objectWithoutProperties(props, _excluded);
|
1426
|
+
|
1209
1427
|
const instancesRef = React.useRef();
|
1210
1428
|
const instancesRefGetter = React.useRef(() => {
|
1211
1429
|
if (!instancesRef.current) {
|
@@ -1214,235 +1432,85 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1214
1432
|
|
1215
1433
|
return instancesRef.current;
|
1216
1434
|
});
|
1435
|
+
const mergedOptions = React.useMemo(() => {
|
1436
|
+
return _objectSpread2(_objectSpread2({}, physicsOptions), options);
|
1437
|
+
}, [physicsOptions, options]);
|
1438
|
+
const childColliderProps = useChildColliderProps(object, mergedOptions);
|
1217
1439
|
React.useLayoutEffect(() => {
|
1218
|
-
|
1440
|
+
object.current.updateWorldMatrix(true, false);
|
1219
1441
|
const rigidBodies = instancesRefGetter.current();
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
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;
|
1241
1481
|
}
|
1242
1482
|
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
rotation
|
1249
|
-
} = decomposeMatrix4(matrix);
|
1250
|
-
|
1251
|
-
if (props.colliders !== false) {
|
1252
|
-
const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders !== undefined ? props.colliders : physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
|
1253
|
-
);
|
1254
|
-
const collider = world.createCollider(colliderDesc, rigidBody);
|
1255
|
-
colliders.push(collider);
|
1256
|
-
} // Set positions
|
1257
|
-
|
1258
|
-
|
1259
|
-
if (props.positions && props.positions[index]) {
|
1260
|
-
rigidBody.setTranslation(vectorArrayToVector3(props.positions[index]), true);
|
1261
|
-
} else {
|
1262
|
-
rigidBody.setTranslation(position, true);
|
1263
|
-
} // Set rotations
|
1264
|
-
|
1265
|
-
|
1266
|
-
if (props.rotations && props.rotations[index]) {
|
1267
|
-
const [x, y, z] = props.rotations[index];
|
1268
|
-
rigidBody.setRotation(vector3ToQuaternion(new three.Vector3(x, y, z)), true);
|
1269
|
-
} else {
|
1270
|
-
rigidBody.setRotation(rotation, true);
|
1271
|
-
}
|
1272
|
-
|
1273
|
-
rigidBodyStates.set(rigidBody.handle, {
|
1274
|
-
mesh: mesh,
|
1275
|
-
isSleeping: false,
|
1276
|
-
invertedMatrixWorld: object.current.matrixWorld.clone().invert(),
|
1277
|
-
setMatrix: matrix => mesh.setMatrixAt(index, matrix),
|
1278
|
-
getMatrix: () => {
|
1279
|
-
const m = new three.Matrix4();
|
1280
|
-
mesh.getMatrixAt(index, m);
|
1281
|
-
return m;
|
1282
|
-
},
|
1283
|
-
// Setting the world scale to the scale here, because
|
1284
|
-
// we want the scales to be reflected by instance
|
1285
|
-
worldScale: scale
|
1286
|
-
});
|
1287
|
-
const api = createRigidBodyApi({
|
1288
|
-
current() {
|
1289
|
-
return rigidBody;
|
1290
|
-
}
|
1291
|
-
|
1292
|
-
});
|
1293
|
-
rigidBodies.push({
|
1294
|
-
rigidBody,
|
1295
|
-
api
|
1296
|
-
});
|
1297
|
-
}
|
1298
|
-
}
|
1299
|
-
|
1300
|
-
if (mesh.type === "Mesh" && !("isInstancedMesh" in mesh)) {
|
1301
|
-
console.warn("Can only use InstancedMesh inside <InstancedRigidBodies />, Mesh will be ignored.");
|
1483
|
+
});
|
1484
|
+
rigidBodies.push({
|
1485
|
+
rigidBody,
|
1486
|
+
api
|
1487
|
+
});
|
1302
1488
|
}
|
1489
|
+
}
|
1490
|
+
});
|
1491
|
+
return () => {
|
1492
|
+
rigidBodies.forEach(rb => {
|
1493
|
+
world.removeRigidBody(rb.rigidBody);
|
1494
|
+
rigidBodyStates.delete(rb.rigidBody.handle);
|
1303
1495
|
});
|
1304
|
-
|
1305
|
-
|
1306
|
-
colliders.forEach(coll => world.removeCollider(coll));
|
1307
|
-
instancesRef.current = undefined;
|
1308
|
-
};
|
1309
|
-
}
|
1496
|
+
instancesRef.current = undefined;
|
1497
|
+
};
|
1310
1498
|
}, []);
|
1311
1499
|
const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
|
1312
|
-
React.useImperativeHandle(ref, () => api);
|
1313
|
-
|
1500
|
+
React.useImperativeHandle(ref, () => api);
|
1314
1501
|
return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
|
1315
1502
|
value: {
|
1316
1503
|
ref: object,
|
1317
1504
|
api,
|
1318
|
-
hasCollisionEvents: false,
|
1319
1505
|
options: props
|
1320
1506
|
}
|
1321
1507
|
}, /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1322
1508
|
ref: object
|
1323
|
-
}, props.children)
|
1509
|
+
}, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
|
1510
|
+
key: index
|
1511
|
+
}, colliderProps)))));
|
1324
1512
|
});
|
1325
1513
|
|
1326
|
-
const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
|
1327
|
-
|
1328
|
-
const AnyCollider = _ref => {
|
1329
|
-
let {
|
1330
|
-
children,
|
1331
|
-
onCollisionEnter,
|
1332
|
-
onCollisionExit
|
1333
|
-
} = _ref,
|
1334
|
-
props = _objectWithoutProperties(_ref, _excluded);
|
1335
|
-
|
1336
|
-
const {
|
1337
|
-
world,
|
1338
|
-
colliderEvents
|
1339
|
-
} = useRapier();
|
1340
|
-
const rigidBodyContext = useRigidBodyContext();
|
1341
|
-
const ref = React.useRef(null);
|
1342
|
-
React.useEffect(() => {
|
1343
|
-
const scale = ref.current.getWorldScale(new three.Vector3());
|
1344
|
-
const colliders = [];
|
1345
|
-
const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
|
1346
|
-
|
1347
|
-
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1348
|
-
rigidBodyContext.api.forEach((body, index) => {
|
1349
|
-
var _rigidBodyContext$opt, _rigidBodyContext$opt2;
|
1350
|
-
|
1351
|
-
let instanceScale = scale.clone();
|
1352
|
-
|
1353
|
-
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]) {
|
1354
|
-
instanceScale.multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
|
1355
|
-
}
|
1356
|
-
|
1357
|
-
colliders.push(createColliderFromOptions({
|
1358
|
-
options: _objectSpread2({
|
1359
|
-
solverGroups: rigidBodyContext.options.solverGroups,
|
1360
|
-
collisionGroups: rigidBodyContext.options.collisionGroups
|
1361
|
-
}, props),
|
1362
|
-
world,
|
1363
|
-
rigidBody: body.raw(),
|
1364
|
-
scale: instanceScale,
|
1365
|
-
hasCollisionEvents
|
1366
|
-
}));
|
1367
|
-
});
|
1368
|
-
} else {
|
1369
|
-
colliders.push(createColliderFromOptions({
|
1370
|
-
options: _objectSpread2({
|
1371
|
-
solverGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.solverGroups) || props.solverGroups,
|
1372
|
-
collisionGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.collisionGroups) || props.collisionGroups
|
1373
|
-
}, props),
|
1374
|
-
world,
|
1375
|
-
// Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
|
1376
|
-
rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
|
1377
|
-
scale,
|
1378
|
-
hasCollisionEvents
|
1379
|
-
}));
|
1380
|
-
}
|
1381
|
-
/* Register collision events. */
|
1382
|
-
|
1383
|
-
|
1384
|
-
colliders.forEach(collider => colliderEvents.set(collider.handle, {
|
1385
|
-
onCollisionEnter,
|
1386
|
-
onCollisionExit
|
1387
|
-
}));
|
1388
|
-
return () => {
|
1389
|
-
colliders.forEach(collider => {
|
1390
|
-
colliderEvents.delete(collider.handle);
|
1391
|
-
world.removeCollider(collider);
|
1392
|
-
});
|
1393
|
-
};
|
1394
|
-
}, []);
|
1395
|
-
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1396
|
-
ref: ref
|
1397
|
-
}, children);
|
1398
|
-
};
|
1399
|
-
|
1400
|
-
const CuboidCollider = props => {
|
1401
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1402
|
-
shape: "cuboid"
|
1403
|
-
}));
|
1404
|
-
};
|
1405
|
-
const RoundCuboidCollider = props => {
|
1406
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1407
|
-
shape: "roundCuboid"
|
1408
|
-
}));
|
1409
|
-
};
|
1410
|
-
const BallCollider = props => {
|
1411
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1412
|
-
shape: "ball"
|
1413
|
-
}));
|
1414
|
-
};
|
1415
|
-
const CapsuleCollider = props => {
|
1416
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1417
|
-
shape: "capsule"
|
1418
|
-
}));
|
1419
|
-
};
|
1420
|
-
const HeightfieldCollider = props => {
|
1421
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1422
|
-
shape: "heightfield"
|
1423
|
-
}));
|
1424
|
-
};
|
1425
|
-
const TrimeshCollider = props => {
|
1426
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1427
|
-
shape: "trimesh"
|
1428
|
-
}));
|
1429
|
-
};
|
1430
|
-
const ConeCollider = props => {
|
1431
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1432
|
-
shape: "cone"
|
1433
|
-
}));
|
1434
|
-
};
|
1435
|
-
const CylinderCollider = props => {
|
1436
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1437
|
-
shape: "cylinder"
|
1438
|
-
}));
|
1439
|
-
};
|
1440
|
-
const ConvexHullCollider = props => {
|
1441
|
-
return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
|
1442
|
-
shape: "convexHull"
|
1443
|
-
}));
|
1444
|
-
};
|
1445
|
-
|
1446
1514
|
/**
|
1447
1515
|
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
1448
1516
|
* properties of RigidBody or Collider components. The first argument represents a list of
|
@@ -1491,6 +1559,7 @@ Object.defineProperty(exports, 'RapierRigidBody', {
|
|
1491
1559
|
enumerable: true,
|
1492
1560
|
get: function () { return rapier3dCompat.RigidBody; }
|
1493
1561
|
});
|
1562
|
+
exports.AnyCollider = AnyCollider;
|
1494
1563
|
exports.BallCollider = BallCollider;
|
1495
1564
|
exports.CapsuleCollider = CapsuleCollider;
|
1496
1565
|
exports.ConeCollider = ConeCollider;
|
@@ -1506,6 +1575,7 @@ exports.RigidBody = RigidBody;
|
|
1506
1575
|
exports.RoundCuboidCollider = RoundCuboidCollider;
|
1507
1576
|
exports.TrimeshCollider = TrimeshCollider;
|
1508
1577
|
exports.interactionGroups = interactionGroups;
|
1578
|
+
exports.useChildColliderProps = useChildColliderProps;
|
1509
1579
|
exports.useFixedJoint = useFixedJoint;
|
1510
1580
|
exports.useImpulseJoint = useImpulseJoint;
|
1511
1581
|
exports.usePrismaticJoint = usePrismaticJoint;
|