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