@babylonjs/core 8.45.0 → 8.45.2
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/Cameras/Inputs/index.d.ts +1 -0
- package/Cameras/Inputs/index.js +1 -0
- package/Cameras/Inputs/index.js.map +1 -1
- package/Engines/Extensions/engine.debugging.d.ts +4 -0
- package/Engines/Extensions/engine.debugging.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.d.ts +1 -1
- package/FrameGraph/Tasks/PostProcesses/volumetricLightingTask.js.map +1 -1
- package/FrameGraph/frameGraphContext.js +3 -3
- package/FrameGraph/frameGraphContext.js.map +1 -1
- package/FrameGraph/frameGraphTask.js +4 -4
- package/FrameGraph/frameGraphTask.js.map +1 -1
- package/Lights/Shadows/cascadedShadowGenerator.js +1 -1
- package/Lights/Shadows/cascadedShadowGenerator.js.map +1 -1
- package/Lights/Shadows/shadowGenerator.js +3 -3
- package/Lights/Shadows/shadowGenerator.js.map +1 -1
- package/Lights/lightingVolume.js +6 -6
- package/Lights/lightingVolume.js.map +1 -1
- package/Loading/Plugins/babylonFileLoader.js +17 -0
- package/Loading/Plugins/babylonFileLoader.js.map +1 -1
- package/Materials/PBR/pbrBaseMaterial.d.ts +2 -1
- package/Materials/PBR/pbrBaseMaterial.js +1 -0
- package/Materials/PBR/pbrBaseMaterial.js.map +1 -1
- package/Materials/PBR/pbrSubSurfaceConfiguration.d.ts +2 -0
- package/Materials/PBR/pbrSubSurfaceConfiguration.js +8 -4
- package/Materials/PBR/pbrSubSurfaceConfiguration.js.map +1 -1
- package/Materials/Textures/Procedurals/proceduralTexture.js +2 -2
- package/Materials/Textures/Procedurals/proceduralTexture.js.map +1 -1
- package/Materials/Textures/renderTargetTexture.js +2 -2
- package/Materials/Textures/renderTargetTexture.js.map +1 -1
- package/Misc/minMaxReducer.js +2 -2
- package/Misc/minMaxReducer.js.map +1 -1
- package/Particles/Node/Blocks/Conditions/particleConditionBlock.js +2 -0
- package/Particles/Node/Blocks/Conditions/particleConditionBlock.js.map +1 -1
- package/Particles/Node/Blocks/Emitters/setupSpriteSheetBlock.d.ts +4 -0
- package/Particles/Node/Blocks/Emitters/setupSpriteSheetBlock.js +10 -0
- package/Particles/Node/Blocks/Emitters/setupSpriteSheetBlock.js.map +1 -1
- package/Particles/Node/Blocks/Update/updateRemapBlock.d.ts +39 -0
- package/Particles/Node/Blocks/Update/updateRemapBlock.js +93 -0
- package/Particles/Node/Blocks/Update/updateRemapBlock.js.map +1 -0
- package/Particles/Node/Blocks/systemBlock.d.ts +4 -0
- package/Particles/Node/Blocks/systemBlock.js +32 -1
- package/Particles/Node/Blocks/systemBlock.js.map +1 -1
- package/Particles/Node/nodeParticleSystemSet.helper.js +88 -0
- package/Particles/Node/nodeParticleSystemSet.helper.js.map +1 -1
- package/Particles/thinParticleSystem.js +10 -6
- package/Particles/thinParticleSystem.js.map +1 -1
- package/Probes/reflectionProbe.js +2 -2
- package/Probes/reflectionProbe.js.map +1 -1
- package/Rendering/depthRenderer.js +2 -2
- package/Rendering/depthRenderer.js.map +1 -1
- package/XR/features/WebXRControllerPhysics.d.ts +30 -1
- package/XR/features/WebXRControllerPhysics.js +269 -16
- package/XR/features/WebXRControllerPhysics.js.map +1 -1
- package/XR/features/WebXRHandTracking.js +36 -2
- package/XR/features/WebXRHandTracking.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { PhysicsImpostor } from "../../Physics/v1/physicsImpostor.js";
|
|
|
4
4
|
import { CreateSphere } from "../../Meshes/Builders/sphereBuilder.js";
|
|
5
5
|
import { WebXRFeatureName, WebXRFeaturesManager } from "../webXRFeaturesManager.js";
|
|
6
6
|
import { Logger } from "../../Misc/logger.js";
|
|
7
|
+
import { PhysicsAggregate } from "../../Physics/v2/physicsAggregate.js";
|
|
7
8
|
/**
|
|
8
9
|
* Options for the controller physics feature
|
|
9
10
|
*/
|
|
@@ -14,6 +15,26 @@ export class IWebXRControllerPhysicsOptions {
|
|
|
14
15
|
* including naive calculation of their linear and angular velocity
|
|
15
16
|
*/
|
|
16
17
|
export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
18
|
+
_mapImpostorTypeToShapeType(impostorType) {
|
|
19
|
+
// Map v1 PhysicsImpostor types to v2 PhysicsShapeType
|
|
20
|
+
switch (impostorType) {
|
|
21
|
+
case PhysicsImpostor.SphereImpostor:
|
|
22
|
+
return 0 /* PhysicsShapeType.SPHERE */;
|
|
23
|
+
case PhysicsImpostor.BoxImpostor:
|
|
24
|
+
return 3 /* PhysicsShapeType.BOX */;
|
|
25
|
+
case PhysicsImpostor.CapsuleImpostor:
|
|
26
|
+
return 1 /* PhysicsShapeType.CAPSULE */;
|
|
27
|
+
case PhysicsImpostor.CylinderImpostor:
|
|
28
|
+
return 2 /* PhysicsShapeType.CYLINDER */;
|
|
29
|
+
case PhysicsImpostor.MeshImpostor:
|
|
30
|
+
return 6 /* PhysicsShapeType.MESH */;
|
|
31
|
+
case PhysicsImpostor.ConvexHullImpostor:
|
|
32
|
+
return 4 /* PhysicsShapeType.CONVEX_HULL */;
|
|
33
|
+
default:
|
|
34
|
+
Logger.Warn(`Unsupported impostor type ${impostorType} for v2 physics, defaulting to SPHERE`);
|
|
35
|
+
return 0 /* PhysicsShapeType.SPHERE */;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
17
38
|
_createPhysicsImpostor(xrController) {
|
|
18
39
|
const impostorType = this._options.physicsProperties.impostorType || PhysicsImpostor.SphereImpostor;
|
|
19
40
|
const impostorSize = this._options.physicsProperties.impostorSize || 0.1;
|
|
@@ -38,6 +59,36 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
38
59
|
impostorMesh,
|
|
39
60
|
};
|
|
40
61
|
}
|
|
62
|
+
_createPhysicsAggregate(xrController) {
|
|
63
|
+
const impostorType = this._options.physicsProperties.impostorType || PhysicsImpostor.SphereImpostor;
|
|
64
|
+
const impostorSize = this._options.physicsProperties.impostorSize || 0.1;
|
|
65
|
+
const impostorMesh = CreateSphere("impostor-mesh-" + xrController.uniqueId, {
|
|
66
|
+
diameterX: typeof impostorSize === "number" ? impostorSize : impostorSize.width,
|
|
67
|
+
diameterY: typeof impostorSize === "number" ? impostorSize : impostorSize.height,
|
|
68
|
+
diameterZ: typeof impostorSize === "number" ? impostorSize : impostorSize.depth,
|
|
69
|
+
});
|
|
70
|
+
impostorMesh.isVisible = this._debugMode;
|
|
71
|
+
impostorMesh.isPickable = false;
|
|
72
|
+
impostorMesh.rotationQuaternion = new Quaternion();
|
|
73
|
+
const controllerMesh = xrController.grip || xrController.pointer;
|
|
74
|
+
impostorMesh.position.copyFrom(controllerMesh.position);
|
|
75
|
+
impostorMesh.rotationQuaternion.copyFrom(controllerMesh.rotationQuaternion);
|
|
76
|
+
const shapeType = this._mapImpostorTypeToShapeType(impostorType);
|
|
77
|
+
const aggregate = new PhysicsAggregate(impostorMesh, shapeType, {
|
|
78
|
+
mass: 0,
|
|
79
|
+
friction: this._options.physicsProperties?.friction ?? 0.2,
|
|
80
|
+
restitution: this._options.physicsProperties?.restitution ?? 0.2,
|
|
81
|
+
}, this._xrSessionManager.scene);
|
|
82
|
+
aggregate.body.setMotionType(1 /* PhysicsMotionType.ANIMATED */);
|
|
83
|
+
aggregate.body.disableSync = true;
|
|
84
|
+
this._controllers[xrController.uniqueId] = {
|
|
85
|
+
xrController,
|
|
86
|
+
physicsAggregate: aggregate,
|
|
87
|
+
physicsBody: aggregate.body,
|
|
88
|
+
isPhysicsV2: true,
|
|
89
|
+
impostorMesh,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
41
92
|
/**
|
|
42
93
|
* Construct a new Controller Physics Feature
|
|
43
94
|
* @param _xrSessionManager the corresponding xr session manager
|
|
@@ -54,6 +105,14 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
54
105
|
if (!this._xrSessionManager.scene.isPhysicsEnabled()) {
|
|
55
106
|
Logger.Warn("physics engine not enabled, skipped. Please add this controller manually.");
|
|
56
107
|
}
|
|
108
|
+
if (this._physicsVersion === 2) {
|
|
109
|
+
this._attachControllerV2(xrController);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
this._attachControllerV1(xrController);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
this._attachControllerV1 = (xrController) => {
|
|
57
116
|
// if no motion controller available, create impostors!
|
|
58
117
|
if (this._options.physicsProperties.useControllerMesh && xrController.inputSource.gamepad) {
|
|
59
118
|
xrController.onMotionControllerInitObservable.addOnce((motionController) => {
|
|
@@ -82,10 +141,46 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
82
141
|
this._createPhysicsImpostor(xrController);
|
|
83
142
|
}
|
|
84
143
|
};
|
|
144
|
+
this._attachControllerV2 = (xrController) => {
|
|
145
|
+
// if no motion controller available, create physics aggregates!
|
|
146
|
+
if (this._options.physicsProperties.useControllerMesh && xrController.inputSource.gamepad) {
|
|
147
|
+
xrController.onMotionControllerInitObservable.addOnce((motionController) => {
|
|
148
|
+
if (!motionController._doNotLoadControllerMesh) {
|
|
149
|
+
motionController.onModelLoadedObservable.addOnce(() => {
|
|
150
|
+
const shapeType = this._mapImpostorTypeToShapeType(PhysicsImpostor.MeshImpostor);
|
|
151
|
+
const aggregate = new PhysicsAggregate(motionController.rootMesh, shapeType, {
|
|
152
|
+
mass: 0,
|
|
153
|
+
friction: this._options.physicsProperties?.friction ?? 0.2,
|
|
154
|
+
restitution: this._options.physicsProperties?.restitution ?? 0.2,
|
|
155
|
+
}, this._xrSessionManager.scene);
|
|
156
|
+
aggregate.body.setMotionType(1 /* PhysicsMotionType.ANIMATED */);
|
|
157
|
+
aggregate.body.disableSync = true;
|
|
158
|
+
const controllerMesh = xrController.grip || xrController.pointer;
|
|
159
|
+
this._controllers[xrController.uniqueId] = {
|
|
160
|
+
xrController,
|
|
161
|
+
physicsAggregate: aggregate,
|
|
162
|
+
physicsBody: aggregate.body,
|
|
163
|
+
isPhysicsV2: true,
|
|
164
|
+
oldPos: controllerMesh.position.clone(),
|
|
165
|
+
oldRotation: controllerMesh.rotationQuaternion.clone(),
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// This controller isn't using a model, create physics aggregate instead
|
|
171
|
+
this._createPhysicsAggregate(xrController);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
this._createPhysicsAggregate(xrController);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
85
179
|
this._controllers = {};
|
|
86
180
|
this._debugMode = false;
|
|
87
181
|
this._delta = 0;
|
|
88
182
|
this._lastTimestamp = 0;
|
|
183
|
+
this._physicsVersion = 1;
|
|
89
184
|
this._tmpQuaternion = new Quaternion();
|
|
90
185
|
this._tmpVector = new Vector3();
|
|
91
186
|
if (!this._options.physicsProperties) {
|
|
@@ -123,6 +218,15 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
123
218
|
if (!super.attach()) {
|
|
124
219
|
return false;
|
|
125
220
|
}
|
|
221
|
+
// Detect physics version
|
|
222
|
+
const physicsEngine = this._xrSessionManager.scene.getPhysicsEngine();
|
|
223
|
+
if (physicsEngine) {
|
|
224
|
+
this._physicsVersion = physicsEngine.getPluginVersion() || 1;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
// Default to v1 if no physics engine (warning will be shown later)
|
|
228
|
+
this._physicsVersion = 1;
|
|
229
|
+
}
|
|
126
230
|
if (!this._options.xrInput) {
|
|
127
231
|
return true;
|
|
128
232
|
}
|
|
@@ -135,20 +239,12 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
135
239
|
this._detachController(controller.uniqueId);
|
|
136
240
|
});
|
|
137
241
|
if (this._options.enableHeadsetImpostor) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
this._headsetMesh = CreateSphere("headset-mesh", {
|
|
145
|
-
diameterX: typeof impostorSize === "number" ? impostorSize : impostorSize.width,
|
|
146
|
-
diameterY: typeof impostorSize === "number" ? impostorSize : impostorSize.height,
|
|
147
|
-
diameterZ: typeof impostorSize === "number" ? impostorSize : impostorSize.depth,
|
|
148
|
-
});
|
|
149
|
-
this._headsetMesh.rotationQuaternion = new Quaternion();
|
|
150
|
-
this._headsetMesh.isVisible = false;
|
|
151
|
-
this._headsetImpostor = new PhysicsImpostor(this._headsetMesh, params.impostorType, { mass: 0, ...params });
|
|
242
|
+
if (this._physicsVersion === 2) {
|
|
243
|
+
this._enableHeadsetPhysicsV2();
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
this._enableHeadsetPhysicsV1();
|
|
247
|
+
}
|
|
152
248
|
}
|
|
153
249
|
return true;
|
|
154
250
|
}
|
|
@@ -169,6 +265,11 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
169
265
|
if (this._headsetMesh) {
|
|
170
266
|
this._headsetMesh.dispose();
|
|
171
267
|
}
|
|
268
|
+
// Dispose v2 aggregate if present
|
|
269
|
+
if (this._headsetAggregateV2) {
|
|
270
|
+
this._headsetAggregateV2.dispose();
|
|
271
|
+
this._headsetAggregateV2 = undefined;
|
|
272
|
+
}
|
|
172
273
|
return true;
|
|
173
274
|
}
|
|
174
275
|
/**
|
|
@@ -187,12 +288,47 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
187
288
|
getImpostorForController(controller) {
|
|
188
289
|
const id = typeof controller === "string" ? controller : controller.uniqueId;
|
|
189
290
|
if (this._controllers[id]) {
|
|
190
|
-
return this._controllers[id].impostor;
|
|
291
|
+
return this._controllers[id].impostor || null;
|
|
191
292
|
}
|
|
192
293
|
else {
|
|
193
294
|
return null;
|
|
194
295
|
}
|
|
195
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* Get the physics aggregate for a controller (v2 only)
|
|
299
|
+
* @param controller the controller or the controller id
|
|
300
|
+
* @returns the aggregate or null
|
|
301
|
+
*/
|
|
302
|
+
getPhysicsAggregateForController(controller) {
|
|
303
|
+
const id = typeof controller === "string" ? controller : controller.uniqueId;
|
|
304
|
+
if (this._controllers[id]) {
|
|
305
|
+
return this._controllers[id].physicsAggregate || null;
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Get the physics body for a controller (v2 only)
|
|
313
|
+
* @param controller the controller or the controller id
|
|
314
|
+
* @returns the physics body or null
|
|
315
|
+
*/
|
|
316
|
+
getPhysicsBodyForController(controller) {
|
|
317
|
+
const id = typeof controller === "string" ? controller : controller.uniqueId;
|
|
318
|
+
if (this._controllers[id]) {
|
|
319
|
+
return this._controllers[id].physicsBody || null;
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get the headset physics aggregate (v2 only)
|
|
327
|
+
* @returns the physics aggregate or null
|
|
328
|
+
*/
|
|
329
|
+
getHeadsetPhysicsAggregate() {
|
|
330
|
+
return this._headsetAggregateV2 || null;
|
|
331
|
+
}
|
|
196
332
|
/**
|
|
197
333
|
* Update the physics properties provided in the constructor
|
|
198
334
|
* @param newProperties the new properties object
|
|
@@ -210,6 +346,14 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
210
346
|
_onXRFrame(_xrFrame) {
|
|
211
347
|
this._delta = this._xrSessionManager.currentTimestamp - this._lastTimestamp;
|
|
212
348
|
this._lastTimestamp = this._xrSessionManager.currentTimestamp;
|
|
349
|
+
if (this._physicsVersion === 2) {
|
|
350
|
+
this._onXRFrameV2();
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
this._onXRFrameV1();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
_onXRFrameV1() {
|
|
213
357
|
if (this._headsetMesh && this._headsetImpostor) {
|
|
214
358
|
this._headsetMesh.position.copyFrom(this._options.xrInput.xrCamera.globalPosition);
|
|
215
359
|
this._headsetMesh.rotationQuaternion.copyFrom(this._options.xrInput.xrCamera.absoluteRotation);
|
|
@@ -272,6 +416,111 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
272
416
|
}
|
|
273
417
|
}
|
|
274
418
|
}
|
|
419
|
+
_onXRFrameV2() {
|
|
420
|
+
if (this._headsetMesh && this._headsetAggregateV2) {
|
|
421
|
+
this._headsetMesh.position.copyFrom(this._options.xrInput.xrCamera.globalPosition);
|
|
422
|
+
this._headsetMesh.rotationQuaternion.copyFrom(this._options.xrInput.xrCamera.absoluteRotation);
|
|
423
|
+
if (this._options.xrInput.xrCamera._lastXRViewerPose?.linearVelocity) {
|
|
424
|
+
const lv = this._options.xrInput.xrCamera._lastXRViewerPose.linearVelocity;
|
|
425
|
+
this._tmpVector.set(lv.x, lv.y, lv.z);
|
|
426
|
+
this._headsetAggregateV2.body.setLinearVelocity(this._tmpVector);
|
|
427
|
+
}
|
|
428
|
+
if (this._options.xrInput.xrCamera._lastXRViewerPose?.angularVelocity) {
|
|
429
|
+
const av = this._options.xrInput.xrCamera._lastXRViewerPose.angularVelocity;
|
|
430
|
+
this._tmpVector.set(av.x, av.y, av.z);
|
|
431
|
+
this._headsetAggregateV2.body.setAngularVelocity(this._tmpVector);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
const keys = Object.keys(this._controllers);
|
|
435
|
+
for (const controllerId of keys) {
|
|
436
|
+
const controllerData = this._controllers[controllerId];
|
|
437
|
+
if (!controllerData.isPhysicsV2) {
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
const controllerMesh = controllerData.xrController.grip || controllerData.xrController.pointer;
|
|
441
|
+
const comparedPosition = controllerData.oldPos || controllerData.impostorMesh.position;
|
|
442
|
+
if (controllerData.xrController._lastXRPose?.linearVelocity) {
|
|
443
|
+
const lv = controllerData.xrController._lastXRPose.linearVelocity;
|
|
444
|
+
this._tmpVector.set(lv.x, lv.y, lv.z);
|
|
445
|
+
controllerData.physicsBody.setLinearVelocity(this._tmpVector);
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
controllerMesh.position.subtractToRef(comparedPosition, this._tmpVector);
|
|
449
|
+
this._tmpVector.scaleInPlace(1000 / this._delta);
|
|
450
|
+
controllerData.physicsBody.setLinearVelocity(this._tmpVector);
|
|
451
|
+
}
|
|
452
|
+
comparedPosition.copyFrom(controllerMesh.position);
|
|
453
|
+
if (this._debugMode) {
|
|
454
|
+
Logger.Log([this._tmpVector, "linear"]);
|
|
455
|
+
}
|
|
456
|
+
const comparedQuaternion = controllerData.oldRotation || controllerData.impostorMesh.rotationQuaternion;
|
|
457
|
+
if (controllerData.xrController._lastXRPose?.angularVelocity) {
|
|
458
|
+
const av = controllerData.xrController._lastXRPose.angularVelocity;
|
|
459
|
+
this._tmpVector.set(av.x, av.y, av.z);
|
|
460
|
+
controllerData.physicsBody.setAngularVelocity(this._tmpVector);
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
if (!comparedQuaternion.equalsWithEpsilon(controllerMesh.rotationQuaternion)) {
|
|
464
|
+
// roughly based on this - https://www.gamedev.net/forums/topic/347752-quaternion-and-angular-velocity/
|
|
465
|
+
comparedQuaternion.conjugateInPlace().multiplyToRef(controllerMesh.rotationQuaternion, this._tmpQuaternion);
|
|
466
|
+
const len = Math.sqrt(this._tmpQuaternion.x * this._tmpQuaternion.x + this._tmpQuaternion.y * this._tmpQuaternion.y + this._tmpQuaternion.z * this._tmpQuaternion.z);
|
|
467
|
+
this._tmpVector.set(this._tmpQuaternion.x, this._tmpQuaternion.y, this._tmpQuaternion.z);
|
|
468
|
+
// define a better epsilon
|
|
469
|
+
if (len < 0.001) {
|
|
470
|
+
this._tmpVector.scaleInPlace(2);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
const angle = 2 * Math.atan2(len, this._tmpQuaternion.w);
|
|
474
|
+
this._tmpVector.scaleInPlace(angle / (len * (this._delta / 1000)));
|
|
475
|
+
}
|
|
476
|
+
controllerData.physicsBody.setAngularVelocity(this._tmpVector);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
comparedQuaternion.copyFrom(controllerMesh.rotationQuaternion);
|
|
480
|
+
if (this._debugMode) {
|
|
481
|
+
Logger.Log([this._tmpVector, this._tmpQuaternion, "angular"]);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
_enableHeadsetPhysicsV1() {
|
|
486
|
+
const params = this._options.headsetImpostorParams || {
|
|
487
|
+
impostorType: PhysicsImpostor.SphereImpostor,
|
|
488
|
+
restitution: 0.8,
|
|
489
|
+
impostorSize: 0.3,
|
|
490
|
+
};
|
|
491
|
+
const impostorSize = params.impostorSize || 0.3;
|
|
492
|
+
this._headsetMesh = CreateSphere("headset-mesh", {
|
|
493
|
+
diameterX: typeof impostorSize === "number" ? impostorSize : impostorSize.width,
|
|
494
|
+
diameterY: typeof impostorSize === "number" ? impostorSize : impostorSize.height,
|
|
495
|
+
diameterZ: typeof impostorSize === "number" ? impostorSize : impostorSize.depth,
|
|
496
|
+
});
|
|
497
|
+
this._headsetMesh.rotationQuaternion = new Quaternion();
|
|
498
|
+
this._headsetMesh.isVisible = false;
|
|
499
|
+
this._headsetImpostor = new PhysicsImpostor(this._headsetMesh, params.impostorType, { mass: 0, ...params });
|
|
500
|
+
}
|
|
501
|
+
_enableHeadsetPhysicsV2() {
|
|
502
|
+
const params = this._options.headsetImpostorParams || {
|
|
503
|
+
impostorType: PhysicsImpostor.SphereImpostor,
|
|
504
|
+
restitution: 0.8,
|
|
505
|
+
impostorSize: 0.3,
|
|
506
|
+
};
|
|
507
|
+
const impostorSize = params.impostorSize || 0.3;
|
|
508
|
+
this._headsetMesh = CreateSphere("headset-mesh", {
|
|
509
|
+
diameterX: typeof impostorSize === "number" ? impostorSize : impostorSize.width,
|
|
510
|
+
diameterY: typeof impostorSize === "number" ? impostorSize : impostorSize.height,
|
|
511
|
+
diameterZ: typeof impostorSize === "number" ? impostorSize : impostorSize.depth,
|
|
512
|
+
});
|
|
513
|
+
this._headsetMesh.rotationQuaternion = new Quaternion();
|
|
514
|
+
this._headsetMesh.isVisible = false;
|
|
515
|
+
const shapeType = this._mapImpostorTypeToShapeType(params.impostorType);
|
|
516
|
+
this._headsetAggregateV2 = new PhysicsAggregate(this._headsetMesh, shapeType, {
|
|
517
|
+
mass: 0,
|
|
518
|
+
friction: params.friction ?? 0.2,
|
|
519
|
+
restitution: params.restitution ?? 0.8,
|
|
520
|
+
}, this._xrSessionManager.scene);
|
|
521
|
+
this._headsetAggregateV2.body.setMotionType(1 /* PhysicsMotionType.ANIMATED */);
|
|
522
|
+
this._headsetAggregateV2.body.disableSync = true;
|
|
523
|
+
}
|
|
275
524
|
_detachController(xrControllerUniqueId) {
|
|
276
525
|
const controllerData = this._controllers[xrControllerUniqueId];
|
|
277
526
|
if (!controllerData) {
|
|
@@ -280,6 +529,10 @@ export class WebXRControllerPhysics extends WebXRAbstractFeature {
|
|
|
280
529
|
if (controllerData.impostorMesh) {
|
|
281
530
|
controllerData.impostorMesh.dispose();
|
|
282
531
|
}
|
|
532
|
+
// Dispose v2 aggregate if present
|
|
533
|
+
if (controllerData.physicsAggregate) {
|
|
534
|
+
controllerData.physicsAggregate.dispose();
|
|
535
|
+
}
|
|
283
536
|
// remove from the map
|
|
284
537
|
delete this._controllers[xrControllerUniqueId];
|
|
285
538
|
}
|
|
@@ -293,7 +546,7 @@ WebXRControllerPhysics.Name = WebXRFeatureName.PHYSICS_CONTROLLERS;
|
|
|
293
546
|
* This is an integer representing the implementation version.
|
|
294
547
|
* This number does not correspond to the webxr specs version
|
|
295
548
|
*/
|
|
296
|
-
WebXRControllerPhysics.Version =
|
|
549
|
+
WebXRControllerPhysics.Version = 2;
|
|
297
550
|
//register the plugin
|
|
298
551
|
WebXRFeaturesManager.AddWebXRFeature(WebXRControllerPhysics.Name, (xrSessionManager, options) => {
|
|
299
552
|
return () => new WebXRControllerPhysics(xrSessionManager, options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebXRControllerPhysics.js","sourceRoot":"","sources":["../../../../../dev/core/src/XR/features/WebXRControllerPhysics.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebXRAbstractFeature } from \"./WebXRAbstractFeature\";\r\nimport { Vector3, Quaternion } from \"../../Maths/math.vector\";\r\nimport type { WebXRInputSource } from \"../webXRInputSource\";\r\nimport { PhysicsImpostor } from \"../../Physics/v1/physicsImpostor\";\r\nimport type { WebXRInput } from \"../webXRInput\";\r\nimport type { WebXRSessionManager } from \"../webXRSessionManager\";\r\nimport type { AbstractMesh } from \"../../Meshes/abstractMesh\";\r\nimport { CreateSphere } from \"../../Meshes/Builders/sphereBuilder\";\r\nimport { WebXRFeatureName, WebXRFeaturesManager } from \"../webXRFeaturesManager\";\r\nimport { Logger } from \"../../Misc/logger\";\r\nimport type { Nullable } from \"../../types\";\r\n\r\n/**\r\n * Options for the controller physics feature\r\n */\r\nexport class IWebXRControllerPhysicsOptions {\r\n /**\r\n * Should the headset get its own impostor\r\n */\r\n enableHeadsetImpostor?: boolean;\r\n /**\r\n * Optional parameters for the headset impostor\r\n */\r\n headsetImpostorParams?: {\r\n /**\r\n * The type of impostor to create. Default is sphere\r\n */\r\n impostorType: number;\r\n /**\r\n * the size of the impostor. Defaults to 10cm\r\n */\r\n impostorSize?: number | { width: number; height: number; depth: number };\r\n /**\r\n * Friction definitions\r\n */\r\n friction?: number;\r\n /**\r\n * Restitution\r\n */\r\n restitution?: number;\r\n };\r\n /**\r\n * The physics properties of the future impostors\r\n */\r\n physicsProperties?: {\r\n /**\r\n * If set to true, a mesh impostor will be created when the controller mesh was loaded\r\n * Note that this requires a physics engine that supports mesh impostors!\r\n */\r\n useControllerMesh?: boolean;\r\n /**\r\n * The type of impostor to create. Default is sphere\r\n */\r\n impostorType?: number;\r\n /**\r\n * the size of the impostor. Defaults to 10cm\r\n */\r\n impostorSize?: number | { width: number; height: number; depth: number };\r\n /**\r\n * Friction definitions\r\n */\r\n friction?: number;\r\n /**\r\n * Restitution\r\n */\r\n restitution?: number;\r\n };\r\n /**\r\n * the xr input to use with this pointer selection\r\n */\r\n public xrInput: WebXRInput;\r\n}\r\n\r\n/**\r\n * Add physics impostor to your webxr controllers,\r\n * including naive calculation of their linear and angular velocity\r\n */\r\nexport class WebXRControllerPhysics extends WebXRAbstractFeature {\r\n private _attachController = (xrController: WebXRInputSource) => {\r\n if (this._controllers[xrController.uniqueId]) {\r\n // already attached\r\n return;\r\n }\r\n if (!this._xrSessionManager.scene.isPhysicsEnabled()) {\r\n Logger.Warn(\"physics engine not enabled, skipped. Please add this controller manually.\");\r\n }\r\n // if no motion controller available, create impostors!\r\n if (this._options.physicsProperties!.useControllerMesh && xrController.inputSource.gamepad) {\r\n xrController.onMotionControllerInitObservable.addOnce((motionController) => {\r\n if (!motionController._doNotLoadControllerMesh) {\r\n motionController.onModelLoadedObservable.addOnce(() => {\r\n const impostor = new PhysicsImpostor(motionController.rootMesh!, PhysicsImpostor.MeshImpostor, {\r\n mass: 0,\r\n ...this._options.physicsProperties,\r\n });\r\n\r\n const controllerMesh = xrController.grip || xrController.pointer;\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n impostor,\r\n oldPos: controllerMesh.position.clone(),\r\n oldRotation: controllerMesh.rotationQuaternion!.clone(),\r\n };\r\n });\r\n } else {\r\n // This controller isn't using a model, create impostors instead\r\n this._createPhysicsImpostor(xrController);\r\n }\r\n });\r\n } else {\r\n this._createPhysicsImpostor(xrController);\r\n }\r\n };\r\n\r\n private _createPhysicsImpostor(xrController: WebXRInputSource) {\r\n const impostorType: number = this._options.physicsProperties!.impostorType || PhysicsImpostor.SphereImpostor;\r\n const impostorSize: number | { width: number; height: number; depth: number } = this._options.physicsProperties!.impostorSize || 0.1;\r\n const impostorMesh = CreateSphere(\"impostor-mesh-\" + xrController.uniqueId, {\r\n diameterX: typeof impostorSize === \"number\" ? impostorSize : impostorSize.width,\r\n diameterY: typeof impostorSize === \"number\" ? impostorSize : impostorSize.height,\r\n diameterZ: typeof impostorSize === \"number\" ? impostorSize : impostorSize.depth,\r\n });\r\n impostorMesh.isVisible = this._debugMode;\r\n impostorMesh.isPickable = false;\r\n impostorMesh.rotationQuaternion = new Quaternion();\r\n const controllerMesh = xrController.grip || xrController.pointer;\r\n impostorMesh.position.copyFrom(controllerMesh.position);\r\n impostorMesh.rotationQuaternion.copyFrom(controllerMesh.rotationQuaternion!);\r\n const impostor = new PhysicsImpostor(impostorMesh, impostorType, {\r\n mass: 0,\r\n ...this._options.physicsProperties,\r\n });\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n impostor,\r\n impostorMesh,\r\n };\r\n }\r\n\r\n private _controllers: {\r\n [id: string]: {\r\n xrController: WebXRInputSource;\r\n impostorMesh?: AbstractMesh;\r\n impostor: PhysicsImpostor;\r\n oldPos?: Vector3;\r\n oldSpeed?: Vector3;\r\n oldRotation?: Quaternion;\r\n };\r\n } = {};\r\n private _debugMode = false;\r\n private _delta: number = 0;\r\n private _headsetImpostor?: PhysicsImpostor;\r\n private _headsetMesh?: AbstractMesh;\r\n private _lastTimestamp: number = 0;\r\n private _tmpQuaternion: Quaternion = new Quaternion();\r\n private _tmpVector: Vector3 = new Vector3();\r\n\r\n /**\r\n * The module's name\r\n */\r\n public static readonly Name = WebXRFeatureName.PHYSICS_CONTROLLERS;\r\n /**\r\n * The (Babylon) version of this module.\r\n * This is an integer representing the implementation version.\r\n * This number does not correspond to the webxr specs version\r\n */\r\n public static readonly Version = 1;\r\n\r\n /**\r\n * Construct a new Controller Physics Feature\r\n * @param _xrSessionManager the corresponding xr session manager\r\n * @param _options options to create this feature with\r\n */\r\n constructor(\r\n _xrSessionManager: WebXRSessionManager,\r\n private readonly _options: IWebXRControllerPhysicsOptions\r\n ) {\r\n super(_xrSessionManager);\r\n if (!this._options.physicsProperties) {\r\n this._options.physicsProperties = {};\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n * enable debugging - will show console outputs and the impostor mesh\r\n */\r\n public _enablePhysicsDebug() {\r\n this._debugMode = true;\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n const controllerData = this._controllers[controllerId];\r\n if (controllerData.impostorMesh) {\r\n controllerData.impostorMesh.isVisible = true;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Manually add a controller (if no xrInput was provided or physics engine was not enabled)\r\n * @param xrController the controller to add\r\n */\r\n public addController(xrController: WebXRInputSource) {\r\n this._attachController(xrController);\r\n }\r\n\r\n /**\r\n * attach this feature\r\n * Will usually be called by the features manager\r\n *\r\n * @returns true if successful.\r\n */\r\n public override attach(): boolean {\r\n if (!super.attach()) {\r\n return false;\r\n }\r\n\r\n if (!this._options.xrInput) {\r\n return true;\r\n }\r\n\r\n for (const controller of this._options.xrInput.controllers) {\r\n this._attachController(controller);\r\n }\r\n this._addNewAttachObserver(this._options.xrInput.onControllerAddedObservable, this._attachController);\r\n this._addNewAttachObserver(this._options.xrInput.onControllerRemovedObservable, (controller) => {\r\n // REMOVE the controller\r\n this._detachController(controller.uniqueId);\r\n });\r\n\r\n if (this._options.enableHeadsetImpostor) {\r\n const params = this._options.headsetImpostorParams || {\r\n impostorType: PhysicsImpostor.SphereImpostor,\r\n restitution: 0.8,\r\n impostorSize: 0.3,\r\n };\r\n const impostorSize = params.impostorSize || 0.3;\r\n this._headsetMesh = CreateSphere(\"headset-mesh\", {\r\n diameterX: typeof impostorSize === \"number\" ? impostorSize : impostorSize.width,\r\n diameterY: typeof impostorSize === \"number\" ? impostorSize : impostorSize.height,\r\n diameterZ: typeof impostorSize === \"number\" ? impostorSize : impostorSize.depth,\r\n });\r\n this._headsetMesh.rotationQuaternion = new Quaternion();\r\n this._headsetMesh.isVisible = false;\r\n this._headsetImpostor = new PhysicsImpostor(this._headsetMesh, params.impostorType, { mass: 0, ...params });\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * detach this feature.\r\n * Will usually be called by the features manager\r\n *\r\n * @returns true if successful.\r\n */\r\n public override detach(): boolean {\r\n if (!super.detach()) {\r\n return false;\r\n }\r\n\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n this._detachController(controllerId);\r\n }\r\n\r\n if (this._headsetMesh) {\r\n this._headsetMesh.dispose();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the headset impostor, if enabled\r\n * @returns the impostor\r\n */\r\n public getHeadsetImpostor() {\r\n return this._headsetImpostor;\r\n }\r\n\r\n /**\r\n * Get the physics impostor of a specific controller.\r\n * The impostor is not attached to a mesh because a mesh for each controller is not obligatory\r\n * @param controller the controller or the controller id of which to get the impostor\r\n * @returns the impostor or null\r\n */\r\n public getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor> {\r\n const id = typeof controller === \"string\" ? controller : controller.uniqueId;\r\n if (this._controllers[id]) {\r\n return this._controllers[id].impostor;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Update the physics properties provided in the constructor\r\n * @param newProperties the new properties object\r\n * @param newProperties.impostorType\r\n * @param newProperties.impostorSize\r\n * @param newProperties.friction\r\n * @param newProperties.restitution\r\n */\r\n public setPhysicsProperties(newProperties: {\r\n impostorType?: number;\r\n impostorSize?: number | { width: number; height: number; depth: number };\r\n friction?: number;\r\n restitution?: number;\r\n }) {\r\n this._options.physicsProperties = {\r\n ...this._options.physicsProperties,\r\n ...newProperties,\r\n };\r\n }\r\n\r\n protected _onXRFrame(_xrFrame: any): void {\r\n this._delta = this._xrSessionManager.currentTimestamp - this._lastTimestamp;\r\n this._lastTimestamp = this._xrSessionManager.currentTimestamp;\r\n if (this._headsetMesh && this._headsetImpostor) {\r\n this._headsetMesh.position.copyFrom(this._options.xrInput.xrCamera.globalPosition);\r\n this._headsetMesh.rotationQuaternion!.copyFrom(this._options.xrInput.xrCamera.absoluteRotation);\r\n if (this._options.xrInput.xrCamera._lastXRViewerPose?.linearVelocity) {\r\n const lv = this._options.xrInput.xrCamera._lastXRViewerPose.linearVelocity;\r\n this._tmpVector.set(lv.x, lv.y, lv.z);\r\n this._headsetImpostor.setLinearVelocity(this._tmpVector);\r\n }\r\n if (this._options.xrInput.xrCamera._lastXRViewerPose?.angularVelocity) {\r\n const av = this._options.xrInput.xrCamera._lastXRViewerPose.angularVelocity;\r\n this._tmpVector.set(av.x, av.y, av.z);\r\n this._headsetImpostor.setAngularVelocity(this._tmpVector);\r\n }\r\n }\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n const controllerData = this._controllers[controllerId];\r\n const controllerMesh = controllerData.xrController.grip || controllerData.xrController.pointer;\r\n const comparedPosition = controllerData.oldPos || controllerData.impostorMesh!.position;\r\n if (controllerData.xrController._lastXRPose?.linearVelocity) {\r\n const lv = controllerData.xrController._lastXRPose.linearVelocity;\r\n this._tmpVector.set(lv.x, lv.y, lv.z);\r\n controllerData.impostor.setLinearVelocity(this._tmpVector);\r\n } else {\r\n controllerMesh.position.subtractToRef(comparedPosition, this._tmpVector);\r\n this._tmpVector.scaleInPlace(1000 / this._delta);\r\n controllerData.impostor.setLinearVelocity(this._tmpVector);\r\n }\r\n comparedPosition.copyFrom(controllerMesh.position);\r\n if (this._debugMode) {\r\n Logger.Log([this._tmpVector, \"linear\"]);\r\n }\r\n\r\n const comparedQuaternion = controllerData.oldRotation || controllerData.impostorMesh!.rotationQuaternion!;\r\n if (controllerData.xrController._lastXRPose?.angularVelocity) {\r\n const av = controllerData.xrController._lastXRPose.angularVelocity;\r\n this._tmpVector.set(av.x, av.y, av.z);\r\n controllerData.impostor.setAngularVelocity(this._tmpVector);\r\n } else {\r\n if (!comparedQuaternion.equalsWithEpsilon(controllerMesh.rotationQuaternion!)) {\r\n // roughly based on this - https://www.gamedev.net/forums/topic/347752-quaternion-and-angular-velocity/\r\n comparedQuaternion.conjugateInPlace().multiplyToRef(controllerMesh.rotationQuaternion!, this._tmpQuaternion);\r\n const len = Math.sqrt(\r\n this._tmpQuaternion.x * this._tmpQuaternion.x + this._tmpQuaternion.y * this._tmpQuaternion.y + this._tmpQuaternion.z * this._tmpQuaternion.z\r\n );\r\n this._tmpVector.set(this._tmpQuaternion.x, this._tmpQuaternion.y, this._tmpQuaternion.z);\r\n // define a better epsilon\r\n if (len < 0.001) {\r\n this._tmpVector.scaleInPlace(2);\r\n } else {\r\n const angle = 2 * Math.atan2(len, this._tmpQuaternion.w);\r\n this._tmpVector.scaleInPlace(angle / (len * (this._delta / 1000)));\r\n }\r\n controllerData.impostor.setAngularVelocity(this._tmpVector);\r\n }\r\n }\r\n comparedQuaternion.copyFrom(controllerMesh.rotationQuaternion!);\r\n if (this._debugMode) {\r\n Logger.Log([this._tmpVector, this._tmpQuaternion, \"angular\"]);\r\n }\r\n }\r\n }\r\n\r\n private _detachController(xrControllerUniqueId: string) {\r\n const controllerData = this._controllers[xrControllerUniqueId];\r\n if (!controllerData) {\r\n return;\r\n }\r\n if (controllerData.impostorMesh) {\r\n controllerData.impostorMesh.dispose();\r\n }\r\n // remove from the map\r\n delete this._controllers[xrControllerUniqueId];\r\n }\r\n}\r\n\r\n//register the plugin\r\nWebXRFeaturesManager.AddWebXRFeature(\r\n WebXRControllerPhysics.Name,\r\n (xrSessionManager, options) => {\r\n return () => new WebXRControllerPhysics(xrSessionManager, options);\r\n },\r\n WebXRControllerPhysics.Version,\r\n true\r\n);\r\n"]}
|
|
1
|
+
{"version":3,"file":"WebXRControllerPhysics.js","sourceRoot":"","sources":["../../../../../dev/core/src/XR/features/WebXRControllerPhysics.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebXRAbstractFeature } from \"./WebXRAbstractFeature\";\r\nimport { Vector3, Quaternion } from \"../../Maths/math.vector\";\r\nimport type { WebXRInputSource } from \"../webXRInputSource\";\r\nimport { PhysicsImpostor } from \"../../Physics/v1/physicsImpostor\";\r\nimport type { WebXRInput } from \"../webXRInput\";\r\nimport type { WebXRSessionManager } from \"../webXRSessionManager\";\r\nimport type { AbstractMesh } from \"../../Meshes/abstractMesh\";\r\nimport { CreateSphere } from \"../../Meshes/Builders/sphereBuilder\";\r\nimport { WebXRFeatureName, WebXRFeaturesManager } from \"../webXRFeaturesManager\";\r\nimport { Logger } from \"../../Misc/logger\";\r\nimport type { Nullable } from \"../../types\";\r\nimport { PhysicsAggregate } from \"../../Physics/v2/physicsAggregate\";\r\nimport type { PhysicsBody } from \"../../Physics/v2/physicsBody\";\r\nimport { PhysicsMotionType, PhysicsShapeType } from \"../../Physics/v2/IPhysicsEnginePlugin\";\r\n\r\n/**\r\n * Options for the controller physics feature\r\n */\r\nexport class IWebXRControllerPhysicsOptions {\r\n /**\r\n * Should the headset get its own impostor\r\n */\r\n enableHeadsetImpostor?: boolean;\r\n /**\r\n * Optional parameters for the headset impostor\r\n */\r\n headsetImpostorParams?: {\r\n /**\r\n * The type of impostor to create. Default is sphere\r\n */\r\n impostorType: number;\r\n /**\r\n * the size of the impostor. Defaults to 10cm\r\n */\r\n impostorSize?: number | { width: number; height: number; depth: number };\r\n /**\r\n * Friction definitions\r\n */\r\n friction?: number;\r\n /**\r\n * Restitution\r\n */\r\n restitution?: number;\r\n };\r\n /**\r\n * The physics properties of the future impostors\r\n */\r\n physicsProperties?: {\r\n /**\r\n * If set to true, a mesh impostor will be created when the controller mesh was loaded\r\n * Note that this requires a physics engine that supports mesh impostors!\r\n */\r\n useControllerMesh?: boolean;\r\n /**\r\n * The type of impostor to create. Default is sphere\r\n */\r\n impostorType?: number;\r\n /**\r\n * the size of the impostor. Defaults to 10cm\r\n */\r\n impostorSize?: number | { width: number; height: number; depth: number };\r\n /**\r\n * Friction definitions\r\n */\r\n friction?: number;\r\n /**\r\n * Restitution\r\n */\r\n restitution?: number;\r\n };\r\n /**\r\n * the xr input to use with this pointer selection\r\n */\r\n public xrInput: WebXRInput;\r\n}\r\n\r\n/**\r\n * Add physics impostor to your webxr controllers,\r\n * including naive calculation of their linear and angular velocity\r\n */\r\nexport class WebXRControllerPhysics extends WebXRAbstractFeature {\r\n private _attachController = (xrController: WebXRInputSource) => {\r\n if (this._controllers[xrController.uniqueId]) {\r\n // already attached\r\n return;\r\n }\r\n if (!this._xrSessionManager.scene.isPhysicsEnabled()) {\r\n Logger.Warn(\"physics engine not enabled, skipped. Please add this controller manually.\");\r\n }\r\n\r\n if (this._physicsVersion === 2) {\r\n this._attachControllerV2(xrController);\r\n } else {\r\n this._attachControllerV1(xrController);\r\n }\r\n };\r\n\r\n private _attachControllerV1 = (xrController: WebXRInputSource) => {\r\n // if no motion controller available, create impostors!\r\n if (this._options.physicsProperties!.useControllerMesh && xrController.inputSource.gamepad) {\r\n xrController.onMotionControllerInitObservable.addOnce((motionController) => {\r\n if (!motionController._doNotLoadControllerMesh) {\r\n motionController.onModelLoadedObservable.addOnce(() => {\r\n const impostor = new PhysicsImpostor(motionController.rootMesh!, PhysicsImpostor.MeshImpostor, {\r\n mass: 0,\r\n ...this._options.physicsProperties,\r\n });\r\n\r\n const controllerMesh = xrController.grip || xrController.pointer;\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n impostor,\r\n oldPos: controllerMesh.position.clone(),\r\n oldRotation: controllerMesh.rotationQuaternion!.clone(),\r\n };\r\n });\r\n } else {\r\n // This controller isn't using a model, create impostors instead\r\n this._createPhysicsImpostor(xrController);\r\n }\r\n });\r\n } else {\r\n this._createPhysicsImpostor(xrController);\r\n }\r\n };\r\n\r\n private _attachControllerV2 = (xrController: WebXRInputSource) => {\r\n // if no motion controller available, create physics aggregates!\r\n if (this._options.physicsProperties!.useControllerMesh && xrController.inputSource.gamepad) {\r\n xrController.onMotionControllerInitObservable.addOnce((motionController) => {\r\n if (!motionController._doNotLoadControllerMesh) {\r\n motionController.onModelLoadedObservable.addOnce(() => {\r\n const shapeType = this._mapImpostorTypeToShapeType(PhysicsImpostor.MeshImpostor);\r\n const aggregate = new PhysicsAggregate(\r\n motionController.rootMesh!,\r\n shapeType,\r\n {\r\n mass: 0,\r\n friction: this._options.physicsProperties?.friction ?? 0.2,\r\n restitution: this._options.physicsProperties?.restitution ?? 0.2,\r\n },\r\n this._xrSessionManager.scene\r\n );\r\n\r\n aggregate.body.setMotionType(PhysicsMotionType.ANIMATED);\r\n aggregate.body.disableSync = true;\r\n\r\n const controllerMesh = xrController.grip || xrController.pointer;\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n physicsAggregate: aggregate,\r\n physicsBody: aggregate.body,\r\n isPhysicsV2: true,\r\n oldPos: controllerMesh.position.clone(),\r\n oldRotation: controllerMesh.rotationQuaternion!.clone(),\r\n };\r\n });\r\n } else {\r\n // This controller isn't using a model, create physics aggregate instead\r\n this._createPhysicsAggregate(xrController);\r\n }\r\n });\r\n } else {\r\n this._createPhysicsAggregate(xrController);\r\n }\r\n };\r\n\r\n private _mapImpostorTypeToShapeType(impostorType: number): PhysicsShapeType {\r\n // Map v1 PhysicsImpostor types to v2 PhysicsShapeType\r\n switch (impostorType) {\r\n case PhysicsImpostor.SphereImpostor:\r\n return PhysicsShapeType.SPHERE;\r\n case PhysicsImpostor.BoxImpostor:\r\n return PhysicsShapeType.BOX;\r\n case PhysicsImpostor.CapsuleImpostor:\r\n return PhysicsShapeType.CAPSULE;\r\n case PhysicsImpostor.CylinderImpostor:\r\n return PhysicsShapeType.CYLINDER;\r\n case PhysicsImpostor.MeshImpostor:\r\n return PhysicsShapeType.MESH;\r\n case PhysicsImpostor.ConvexHullImpostor:\r\n return PhysicsShapeType.CONVEX_HULL;\r\n default:\r\n Logger.Warn(`Unsupported impostor type ${impostorType} for v2 physics, defaulting to SPHERE`);\r\n return PhysicsShapeType.SPHERE;\r\n }\r\n }\r\n\r\n private _createPhysicsImpostor(xrController: WebXRInputSource) {\r\n const impostorType: number = this._options.physicsProperties!.impostorType || PhysicsImpostor.SphereImpostor;\r\n const impostorSize: number | { width: number; height: number; depth: number } = this._options.physicsProperties!.impostorSize || 0.1;\r\n const impostorMesh = CreateSphere(\"impostor-mesh-\" + xrController.uniqueId, {\r\n diameterX: typeof impostorSize === \"number\" ? impostorSize : impostorSize.width,\r\n diameterY: typeof impostorSize === \"number\" ? impostorSize : impostorSize.height,\r\n diameterZ: typeof impostorSize === \"number\" ? impostorSize : impostorSize.depth,\r\n });\r\n impostorMesh.isVisible = this._debugMode;\r\n impostorMesh.isPickable = false;\r\n impostorMesh.rotationQuaternion = new Quaternion();\r\n const controllerMesh = xrController.grip || xrController.pointer;\r\n impostorMesh.position.copyFrom(controllerMesh.position);\r\n impostorMesh.rotationQuaternion.copyFrom(controllerMesh.rotationQuaternion!);\r\n const impostor = new PhysicsImpostor(impostorMesh, impostorType, {\r\n mass: 0,\r\n ...this._options.physicsProperties,\r\n });\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n impostor,\r\n impostorMesh,\r\n };\r\n }\r\n\r\n private _createPhysicsAggregate(xrController: WebXRInputSource) {\r\n const impostorType: number = this._options.physicsProperties!.impostorType || PhysicsImpostor.SphereImpostor;\r\n const impostorSize: number | { width: number; height: number; depth: number } = this._options.physicsProperties!.impostorSize || 0.1;\r\n const impostorMesh = CreateSphere(\"impostor-mesh-\" + xrController.uniqueId, {\r\n diameterX: typeof impostorSize === \"number\" ? impostorSize : impostorSize.width,\r\n diameterY: typeof impostorSize === \"number\" ? impostorSize : impostorSize.height,\r\n diameterZ: typeof impostorSize === \"number\" ? impostorSize : impostorSize.depth,\r\n });\r\n impostorMesh.isVisible = this._debugMode;\r\n impostorMesh.isPickable = false;\r\n impostorMesh.rotationQuaternion = new Quaternion();\r\n const controllerMesh = xrController.grip || xrController.pointer;\r\n impostorMesh.position.copyFrom(controllerMesh.position);\r\n impostorMesh.rotationQuaternion.copyFrom(controllerMesh.rotationQuaternion!);\r\n\r\n const shapeType = this._mapImpostorTypeToShapeType(impostorType);\r\n const aggregate = new PhysicsAggregate(\r\n impostorMesh,\r\n shapeType,\r\n {\r\n mass: 0,\r\n friction: this._options.physicsProperties?.friction ?? 0.2,\r\n restitution: this._options.physicsProperties?.restitution ?? 0.2,\r\n },\r\n this._xrSessionManager.scene\r\n );\r\n\r\n aggregate.body.setMotionType(PhysicsMotionType.ANIMATED);\r\n aggregate.body.disableSync = true;\r\n\r\n this._controllers[xrController.uniqueId] = {\r\n xrController,\r\n physicsAggregate: aggregate,\r\n physicsBody: aggregate.body,\r\n isPhysicsV2: true,\r\n impostorMesh,\r\n };\r\n }\r\n\r\n private _controllers: {\r\n [id: string]: {\r\n xrController: WebXRInputSource;\r\n impostorMesh?: AbstractMesh;\r\n impostor?: PhysicsImpostor;\r\n physicsAggregate?: PhysicsAggregate;\r\n physicsBody?: PhysicsBody;\r\n isPhysicsV2?: boolean;\r\n oldPos?: Vector3;\r\n oldSpeed?: Vector3;\r\n oldRotation?: Quaternion;\r\n };\r\n } = {};\r\n private _debugMode = false;\r\n private _delta: number = 0;\r\n private _headsetImpostor?: PhysicsImpostor;\r\n private _headsetMesh?: AbstractMesh;\r\n private _headsetAggregateV2?: PhysicsAggregate;\r\n private _lastTimestamp: number = 0;\r\n private _physicsVersion: 1 | 2 = 1;\r\n private _tmpQuaternion: Quaternion = new Quaternion();\r\n private _tmpVector: Vector3 = new Vector3();\r\n\r\n /**\r\n * The module's name\r\n */\r\n public static readonly Name = WebXRFeatureName.PHYSICS_CONTROLLERS;\r\n /**\r\n * The (Babylon) version of this module.\r\n * This is an integer representing the implementation version.\r\n * This number does not correspond to the webxr specs version\r\n */\r\n public static readonly Version = 2;\r\n\r\n /**\r\n * Construct a new Controller Physics Feature\r\n * @param _xrSessionManager the corresponding xr session manager\r\n * @param _options options to create this feature with\r\n */\r\n constructor(\r\n _xrSessionManager: WebXRSessionManager,\r\n private readonly _options: IWebXRControllerPhysicsOptions\r\n ) {\r\n super(_xrSessionManager);\r\n if (!this._options.physicsProperties) {\r\n this._options.physicsProperties = {};\r\n }\r\n }\r\n\r\n /**\r\n * @internal\r\n * enable debugging - will show console outputs and the impostor mesh\r\n */\r\n public _enablePhysicsDebug() {\r\n this._debugMode = true;\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n const controllerData = this._controllers[controllerId];\r\n if (controllerData.impostorMesh) {\r\n controllerData.impostorMesh.isVisible = true;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Manually add a controller (if no xrInput was provided or physics engine was not enabled)\r\n * @param xrController the controller to add\r\n */\r\n public addController(xrController: WebXRInputSource) {\r\n this._attachController(xrController);\r\n }\r\n\r\n /**\r\n * attach this feature\r\n * Will usually be called by the features manager\r\n *\r\n * @returns true if successful.\r\n */\r\n public override attach(): boolean {\r\n if (!super.attach()) {\r\n return false;\r\n }\r\n\r\n // Detect physics version\r\n const physicsEngine = this._xrSessionManager.scene.getPhysicsEngine();\r\n if (physicsEngine) {\r\n this._physicsVersion = (physicsEngine.getPluginVersion() as 1 | 2) || 1;\r\n } else {\r\n // Default to v1 if no physics engine (warning will be shown later)\r\n this._physicsVersion = 1;\r\n }\r\n\r\n if (!this._options.xrInput) {\r\n return true;\r\n }\r\n\r\n for (const controller of this._options.xrInput.controllers) {\r\n this._attachController(controller);\r\n }\r\n this._addNewAttachObserver(this._options.xrInput.onControllerAddedObservable, this._attachController);\r\n this._addNewAttachObserver(this._options.xrInput.onControllerRemovedObservable, (controller) => {\r\n // REMOVE the controller\r\n this._detachController(controller.uniqueId);\r\n });\r\n\r\n if (this._options.enableHeadsetImpostor) {\r\n if (this._physicsVersion === 2) {\r\n this._enableHeadsetPhysicsV2();\r\n } else {\r\n this._enableHeadsetPhysicsV1();\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * detach this feature.\r\n * Will usually be called by the features manager\r\n *\r\n * @returns true if successful.\r\n */\r\n public override detach(): boolean {\r\n if (!super.detach()) {\r\n return false;\r\n }\r\n\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n this._detachController(controllerId);\r\n }\r\n\r\n if (this._headsetMesh) {\r\n this._headsetMesh.dispose();\r\n }\r\n\r\n // Dispose v2 aggregate if present\r\n if (this._headsetAggregateV2) {\r\n this._headsetAggregateV2.dispose();\r\n this._headsetAggregateV2 = undefined;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the headset impostor, if enabled\r\n * @returns the impostor\r\n */\r\n public getHeadsetImpostor() {\r\n return this._headsetImpostor;\r\n }\r\n\r\n /**\r\n * Get the physics impostor of a specific controller.\r\n * The impostor is not attached to a mesh because a mesh for each controller is not obligatory\r\n * @param controller the controller or the controller id of which to get the impostor\r\n * @returns the impostor or null\r\n */\r\n public getImpostorForController(controller: WebXRInputSource | string): Nullable<PhysicsImpostor> {\r\n const id = typeof controller === \"string\" ? controller : controller.uniqueId;\r\n if (this._controllers[id]) {\r\n return this._controllers[id].impostor || null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the physics aggregate for a controller (v2 only)\r\n * @param controller the controller or the controller id\r\n * @returns the aggregate or null\r\n */\r\n public getPhysicsAggregateForController(controller: WebXRInputSource | string): Nullable<PhysicsAggregate> {\r\n const id = typeof controller === \"string\" ? controller : controller.uniqueId;\r\n if (this._controllers[id]) {\r\n return this._controllers[id].physicsAggregate || null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the physics body for a controller (v2 only)\r\n * @param controller the controller or the controller id\r\n * @returns the physics body or null\r\n */\r\n public getPhysicsBodyForController(controller: WebXRInputSource | string): Nullable<PhysicsBody> {\r\n const id = typeof controller === \"string\" ? controller : controller.uniqueId;\r\n if (this._controllers[id]) {\r\n return this._controllers[id].physicsBody || null;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get the headset physics aggregate (v2 only)\r\n * @returns the physics aggregate or null\r\n */\r\n public getHeadsetPhysicsAggregate(): Nullable<PhysicsAggregate> {\r\n return this._headsetAggregateV2 || null;\r\n }\r\n\r\n /**\r\n * Update the physics properties provided in the constructor\r\n * @param newProperties the new properties object\r\n * @param newProperties.impostorType\r\n * @param newProperties.impostorSize\r\n * @param newProperties.friction\r\n * @param newProperties.restitution\r\n */\r\n public setPhysicsProperties(newProperties: {\r\n impostorType?: number;\r\n impostorSize?: number | { width: number; height: number; depth: number };\r\n friction?: number;\r\n restitution?: number;\r\n }) {\r\n this._options.physicsProperties = {\r\n ...this._options.physicsProperties,\r\n ...newProperties,\r\n };\r\n }\r\n\r\n protected _onXRFrame(_xrFrame: any): void {\r\n this._delta = this._xrSessionManager.currentTimestamp - this._lastTimestamp;\r\n this._lastTimestamp = this._xrSessionManager.currentTimestamp;\r\n\r\n if (this._physicsVersion === 2) {\r\n this._onXRFrameV2();\r\n } else {\r\n this._onXRFrameV1();\r\n }\r\n }\r\n\r\n private _onXRFrameV1(): void {\r\n if (this._headsetMesh && this._headsetImpostor) {\r\n this._headsetMesh.position.copyFrom(this._options.xrInput.xrCamera.globalPosition);\r\n this._headsetMesh.rotationQuaternion!.copyFrom(this._options.xrInput.xrCamera.absoluteRotation);\r\n if (this._options.xrInput.xrCamera._lastXRViewerPose?.linearVelocity) {\r\n const lv = this._options.xrInput.xrCamera._lastXRViewerPose.linearVelocity;\r\n this._tmpVector.set(lv.x, lv.y, lv.z);\r\n this._headsetImpostor.setLinearVelocity(this._tmpVector);\r\n }\r\n if (this._options.xrInput.xrCamera._lastXRViewerPose?.angularVelocity) {\r\n const av = this._options.xrInput.xrCamera._lastXRViewerPose.angularVelocity;\r\n this._tmpVector.set(av.x, av.y, av.z);\r\n this._headsetImpostor.setAngularVelocity(this._tmpVector);\r\n }\r\n }\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n const controllerData = this._controllers[controllerId];\r\n const controllerMesh = controllerData.xrController.grip || controllerData.xrController.pointer;\r\n const comparedPosition = controllerData.oldPos || controllerData.impostorMesh!.position;\r\n if (controllerData.xrController._lastXRPose?.linearVelocity) {\r\n const lv = controllerData.xrController._lastXRPose.linearVelocity;\r\n this._tmpVector.set(lv.x, lv.y, lv.z);\r\n controllerData.impostor!.setLinearVelocity(this._tmpVector);\r\n } else {\r\n controllerMesh.position.subtractToRef(comparedPosition, this._tmpVector);\r\n this._tmpVector.scaleInPlace(1000 / this._delta);\r\n controllerData.impostor!.setLinearVelocity(this._tmpVector);\r\n }\r\n comparedPosition.copyFrom(controllerMesh.position);\r\n if (this._debugMode) {\r\n Logger.Log([this._tmpVector, \"linear\"]);\r\n }\r\n\r\n const comparedQuaternion = controllerData.oldRotation || controllerData.impostorMesh!.rotationQuaternion!;\r\n if (controllerData.xrController._lastXRPose?.angularVelocity) {\r\n const av = controllerData.xrController._lastXRPose.angularVelocity;\r\n this._tmpVector.set(av.x, av.y, av.z);\r\n controllerData.impostor!.setAngularVelocity(this._tmpVector);\r\n } else {\r\n if (!comparedQuaternion.equalsWithEpsilon(controllerMesh.rotationQuaternion!)) {\r\n // roughly based on this - https://www.gamedev.net/forums/topic/347752-quaternion-and-angular-velocity/\r\n comparedQuaternion.conjugateInPlace().multiplyToRef(controllerMesh.rotationQuaternion!, this._tmpQuaternion);\r\n const len = Math.sqrt(\r\n this._tmpQuaternion.x * this._tmpQuaternion.x + this._tmpQuaternion.y * this._tmpQuaternion.y + this._tmpQuaternion.z * this._tmpQuaternion.z\r\n );\r\n this._tmpVector.set(this._tmpQuaternion.x, this._tmpQuaternion.y, this._tmpQuaternion.z);\r\n // define a better epsilon\r\n if (len < 0.001) {\r\n this._tmpVector.scaleInPlace(2);\r\n } else {\r\n const angle = 2 * Math.atan2(len, this._tmpQuaternion.w);\r\n this._tmpVector.scaleInPlace(angle / (len * (this._delta / 1000)));\r\n }\r\n controllerData.impostor!.setAngularVelocity(this._tmpVector);\r\n }\r\n }\r\n comparedQuaternion.copyFrom(controllerMesh.rotationQuaternion!);\r\n if (this._debugMode) {\r\n Logger.Log([this._tmpVector, this._tmpQuaternion, \"angular\"]);\r\n }\r\n }\r\n }\r\n\r\n private _onXRFrameV2(): void {\r\n if (this._headsetMesh && this._headsetAggregateV2) {\r\n this._headsetMesh.position.copyFrom(this._options.xrInput.xrCamera.globalPosition);\r\n this._headsetMesh.rotationQuaternion!.copyFrom(this._options.xrInput.xrCamera.absoluteRotation);\r\n if (this._options.xrInput.xrCamera._lastXRViewerPose?.linearVelocity) {\r\n const lv = this._options.xrInput.xrCamera._lastXRViewerPose.linearVelocity;\r\n this._tmpVector.set(lv.x, lv.y, lv.z);\r\n this._headsetAggregateV2.body.setLinearVelocity(this._tmpVector);\r\n }\r\n if (this._options.xrInput.xrCamera._lastXRViewerPose?.angularVelocity) {\r\n const av = this._options.xrInput.xrCamera._lastXRViewerPose.angularVelocity;\r\n this._tmpVector.set(av.x, av.y, av.z);\r\n this._headsetAggregateV2.body.setAngularVelocity(this._tmpVector);\r\n }\r\n }\r\n const keys = Object.keys(this._controllers);\r\n for (const controllerId of keys) {\r\n const controllerData = this._controllers[controllerId];\r\n if (!controllerData.isPhysicsV2) {\r\n continue;\r\n }\r\n\r\n const controllerMesh = controllerData.xrController.grip || controllerData.xrController.pointer;\r\n const comparedPosition = controllerData.oldPos || controllerData.impostorMesh!.position;\r\n if (controllerData.xrController._lastXRPose?.linearVelocity) {\r\n const lv = controllerData.xrController._lastXRPose.linearVelocity;\r\n this._tmpVector.set(lv.x, lv.y, lv.z);\r\n controllerData.physicsBody!.setLinearVelocity(this._tmpVector);\r\n } else {\r\n controllerMesh.position.subtractToRef(comparedPosition, this._tmpVector);\r\n this._tmpVector.scaleInPlace(1000 / this._delta);\r\n controllerData.physicsBody!.setLinearVelocity(this._tmpVector);\r\n }\r\n comparedPosition.copyFrom(controllerMesh.position);\r\n if (this._debugMode) {\r\n Logger.Log([this._tmpVector, \"linear\"]);\r\n }\r\n\r\n const comparedQuaternion = controllerData.oldRotation || controllerData.impostorMesh!.rotationQuaternion!;\r\n if (controllerData.xrController._lastXRPose?.angularVelocity) {\r\n const av = controllerData.xrController._lastXRPose.angularVelocity;\r\n this._tmpVector.set(av.x, av.y, av.z);\r\n controllerData.physicsBody!.setAngularVelocity(this._tmpVector);\r\n } else {\r\n if (!comparedQuaternion.equalsWithEpsilon(controllerMesh.rotationQuaternion!)) {\r\n // roughly based on this - https://www.gamedev.net/forums/topic/347752-quaternion-and-angular-velocity/\r\n comparedQuaternion.conjugateInPlace().multiplyToRef(controllerMesh.rotationQuaternion!, this._tmpQuaternion);\r\n const len = Math.sqrt(\r\n this._tmpQuaternion.x * this._tmpQuaternion.x + this._tmpQuaternion.y * this._tmpQuaternion.y + this._tmpQuaternion.z * this._tmpQuaternion.z\r\n );\r\n this._tmpVector.set(this._tmpQuaternion.x, this._tmpQuaternion.y, this._tmpQuaternion.z);\r\n // define a better epsilon\r\n if (len < 0.001) {\r\n this._tmpVector.scaleInPlace(2);\r\n } else {\r\n const angle = 2 * Math.atan2(len, this._tmpQuaternion.w);\r\n this._tmpVector.scaleInPlace(angle / (len * (this._delta / 1000)));\r\n }\r\n controllerData.physicsBody!.setAngularVelocity(this._tmpVector);\r\n }\r\n }\r\n comparedQuaternion.copyFrom(controllerMesh.rotationQuaternion!);\r\n if (this._debugMode) {\r\n Logger.Log([this._tmpVector, this._tmpQuaternion, \"angular\"]);\r\n }\r\n }\r\n }\r\n\r\n private _enableHeadsetPhysicsV1(): void {\r\n const params = this._options.headsetImpostorParams || {\r\n impostorType: PhysicsImpostor.SphereImpostor,\r\n restitution: 0.8,\r\n impostorSize: 0.3,\r\n };\r\n const impostorSize = params.impostorSize || 0.3;\r\n this._headsetMesh = CreateSphere(\"headset-mesh\", {\r\n diameterX: typeof impostorSize === \"number\" ? impostorSize : impostorSize.width,\r\n diameterY: typeof impostorSize === \"number\" ? impostorSize : impostorSize.height,\r\n diameterZ: typeof impostorSize === \"number\" ? impostorSize : impostorSize.depth,\r\n });\r\n this._headsetMesh.rotationQuaternion = new Quaternion();\r\n this._headsetMesh.isVisible = false;\r\n this._headsetImpostor = new PhysicsImpostor(this._headsetMesh, params.impostorType, { mass: 0, ...params });\r\n }\r\n\r\n private _enableHeadsetPhysicsV2(): void {\r\n const params = this._options.headsetImpostorParams || {\r\n impostorType: PhysicsImpostor.SphereImpostor,\r\n restitution: 0.8,\r\n impostorSize: 0.3,\r\n };\r\n const impostorSize = params.impostorSize || 0.3;\r\n this._headsetMesh = CreateSphere(\"headset-mesh\", {\r\n diameterX: typeof impostorSize === \"number\" ? impostorSize : impostorSize.width,\r\n diameterY: typeof impostorSize === \"number\" ? impostorSize : impostorSize.height,\r\n diameterZ: typeof impostorSize === \"number\" ? impostorSize : impostorSize.depth,\r\n });\r\n this._headsetMesh.rotationQuaternion = new Quaternion();\r\n this._headsetMesh.isVisible = false;\r\n\r\n const shapeType = this._mapImpostorTypeToShapeType(params.impostorType);\r\n this._headsetAggregateV2 = new PhysicsAggregate(\r\n this._headsetMesh,\r\n shapeType,\r\n {\r\n mass: 0,\r\n friction: params.friction ?? 0.2,\r\n restitution: params.restitution ?? 0.8,\r\n },\r\n this._xrSessionManager.scene\r\n );\r\n\r\n this._headsetAggregateV2.body.setMotionType(PhysicsMotionType.ANIMATED);\r\n this._headsetAggregateV2.body.disableSync = true;\r\n }\r\n\r\n private _detachController(xrControllerUniqueId: string) {\r\n const controllerData = this._controllers[xrControllerUniqueId];\r\n if (!controllerData) {\r\n return;\r\n }\r\n if (controllerData.impostorMesh) {\r\n controllerData.impostorMesh.dispose();\r\n }\r\n\r\n // Dispose v2 aggregate if present\r\n if (controllerData.physicsAggregate) {\r\n controllerData.physicsAggregate.dispose();\r\n }\r\n\r\n // remove from the map\r\n delete this._controllers[xrControllerUniqueId];\r\n }\r\n}\r\n\r\n//register the plugin\r\nWebXRFeaturesManager.AddWebXRFeature(\r\n WebXRControllerPhysics.Name,\r\n (xrSessionManager, options) => {\r\n return () => new WebXRControllerPhysics(xrSessionManager, options);\r\n },\r\n WebXRControllerPhysics.Version,\r\n true\r\n);\r\n"]}
|
|
@@ -2,6 +2,7 @@ import { WebXRAbstractFeature } from "./WebXRAbstractFeature.js";
|
|
|
2
2
|
import { WebXRFeatureName, WebXRFeaturesManager } from "../webXRFeaturesManager.js";
|
|
3
3
|
import { Matrix, Quaternion } from "../../Maths/math.vector.js";
|
|
4
4
|
import { PhysicsImpostor } from "../../Physics/v1/physicsImpostor.js";
|
|
5
|
+
import { PhysicsAggregate } from "../../Physics/v2/physicsAggregate.js";
|
|
5
6
|
import { Observable } from "../../Misc/observable.js";
|
|
6
7
|
import { SceneLoader } from "../../Loading/sceneLoader.js";
|
|
7
8
|
import { Color3 } from "../../Maths/math.color.js";
|
|
@@ -405,8 +406,41 @@ export class WebXRHandTracking extends WebXRAbstractFeature {
|
|
|
405
406
|
const props = featureOptions.jointMeshes?.physicsProps || {};
|
|
406
407
|
// downscale the instances so that physics will be initialized correctly
|
|
407
408
|
newInstance.scaling.setAll(0.02);
|
|
408
|
-
|
|
409
|
-
|
|
409
|
+
// Detect physics version
|
|
410
|
+
const scene = newInstance.getScene();
|
|
411
|
+
const physicsEngine = scene.getPhysicsEngine();
|
|
412
|
+
const physicsVersion = physicsEngine?.getPluginVersion() || 1;
|
|
413
|
+
if (physicsVersion === 2) {
|
|
414
|
+
// V2 physics
|
|
415
|
+
const impostorType = props.impostorType !== undefined ? props.impostorType : PhysicsImpostor.SphereImpostor;
|
|
416
|
+
let shapeType = 0 /* PhysicsShapeType.SPHERE */;
|
|
417
|
+
// Map v1 impostor types to v2 shape types
|
|
418
|
+
switch (impostorType) {
|
|
419
|
+
case PhysicsImpostor.SphereImpostor:
|
|
420
|
+
shapeType = 0 /* PhysicsShapeType.SPHERE */;
|
|
421
|
+
break;
|
|
422
|
+
case PhysicsImpostor.BoxImpostor:
|
|
423
|
+
shapeType = 3 /* PhysicsShapeType.BOX */;
|
|
424
|
+
break;
|
|
425
|
+
case PhysicsImpostor.CapsuleImpostor:
|
|
426
|
+
shapeType = 1 /* PhysicsShapeType.CAPSULE */;
|
|
427
|
+
break;
|
|
428
|
+
default:
|
|
429
|
+
shapeType = 0 /* PhysicsShapeType.SPHERE */;
|
|
430
|
+
}
|
|
431
|
+
const aggregate = new PhysicsAggregate(newInstance, shapeType, {
|
|
432
|
+
mass: 0,
|
|
433
|
+
friction: props.friction ?? 0.2,
|
|
434
|
+
restitution: props.restitution ?? 0.2,
|
|
435
|
+
}, scene);
|
|
436
|
+
aggregate.body.setMotionType(1 /* PhysicsMotionType.ANIMATED */);
|
|
437
|
+
aggregate.body.disableSync = true;
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
// V1 physics
|
|
441
|
+
const type = props.impostorType !== undefined ? props.impostorType : PhysicsImpostor.SphereImpostor;
|
|
442
|
+
newInstance.physicsImpostor = new PhysicsImpostor(newInstance, type, { mass: 0, ...props });
|
|
443
|
+
}
|
|
410
444
|
}
|
|
411
445
|
newInstance.rotationQuaternion = new Quaternion();
|
|
412
446
|
newInstance.isVisible = false;
|