xrblocks 0.5.1 → 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/build/xrblocks.js CHANGED
@@ -14,15 +14,15 @@
14
14
  * limitations under the License.
15
15
  *
16
16
  * @file xrblocks.js
17
- * @version v0.5.1
18
- * @commitid 896d66f
19
- * @builddate 2025-12-06T06:19:44.629Z
17
+ * @version v0.7.0
18
+ * @commitid 950b1e5
19
+ * @builddate 2026-01-03T00:05:55.605Z
20
20
  * @description XR Blocks SDK, built from source with the above commit ID.
21
21
  * @agent When using with Gemini to create XR apps, use **Gemini Canvas** mode,
22
22
  * and follow rules below:
23
23
  * 1. Include the following importmap for maximum compatibility:
24
- "three": "https://cdn.jsdelivr.net/npm/three@0.181.0/build/three.module.js",
25
- "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.181.0/examples/jsm/",
24
+ "three": "https://cdn.jsdelivr.net/npm/three@0.182.0/build/three.module.js",
25
+ "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.182.0/examples/jsm/",
26
26
  "troika-three-text": "https://cdn.jsdelivr.net/gh/protectwise/troika@028b81cf308f0f22e5aa8e78196be56ec1997af5/packages/troika-three-text/src/index.js",
27
27
  "troika-three-utils": "https://cdn.jsdelivr.net/gh/protectwise/troika@v0.52.4/packages/troika-three-utils/src/index.js",
28
28
  "troika-worker-utils": "https://cdn.jsdelivr.net/gh/protectwise/troika@v0.52.4/packages/troika-worker-utils/src/index.js",
@@ -286,7 +286,7 @@ class GenerateSkyboxTool extends Tool {
286
286
  async execute(args) {
287
287
  try {
288
288
  const image = await this.ai.generate('Generate a 360 equirectangular skybox image for the prompt of:' +
289
- args.prompt, 'image', 'Generate a 360 equirectangular skybox image for the prompt', 'gemini-2.5-flash-image-preview');
289
+ args.prompt, 'image', 'Generate a 360 equirectangular skybox image for the prompt');
290
290
  if (image) {
291
291
  console.log('Applying texture...');
292
292
  this.scene.background = new THREE.TextureLoader().load(image);
@@ -1365,7 +1365,7 @@ class Gemini extends BaseAIModel {
1365
1365
  }
1366
1366
  return { text: response.text || null };
1367
1367
  }
1368
- async generate(prompt, type = 'image', systemInstruction = 'Generate an image', model = 'gemini-2.5-flash-image-preview') {
1368
+ async generate(prompt, type = 'image', systemInstruction = 'Generate an image', model = 'gemini-2.5-flash-image') {
1369
1369
  if (!this.isAvailable())
1370
1370
  return;
1371
1371
  let contents;
@@ -1674,7 +1674,7 @@ class AI extends Script {
1674
1674
  * In XR mode, show a 3D UI to instruct users to get an API key.
1675
1675
  */
1676
1676
  triggerKeyPopup() { }
1677
- async generate(prompt, type = 'image', systemInstruction = 'Generate an image', model = 'gemini-2.5-flash-image-preview') {
1677
+ async generate(prompt, type = 'image', systemInstruction = 'Generate an image', model = undefined) {
1678
1678
  return this.model.generate(prompt, type, systemInstruction, model);
1679
1679
  }
1680
1680
  /**
@@ -2255,10 +2255,6 @@ class DepthMesh extends MeshScript {
2255
2255
  const depthY = Math.round(clamp((1.0 - v) * height, 0, height - 1));
2256
2256
  const rawDepth = depthArray[depthY * width + depthX];
2257
2257
  let depth = depthData.rawValueToMeters * rawDepth;
2258
- // Workaround for b/382679381.
2259
- if (this.depthOptions.useFloat32) {
2260
- depth = rawDepth;
2261
- }
2262
2258
  // Finds global min/max.
2263
2259
  if (depth > 0) {
2264
2260
  if (depth < this.minDepth) {
@@ -2502,68 +2498,63 @@ const xrDepthMeshPhysicsOptions = deepFreeze(new DepthOptions({
2502
2498
  class DepthTextures {
2503
2499
  constructor(options) {
2504
2500
  this.options = options;
2505
- this.uint16Arrays = [];
2501
+ this.float32Arrays = [];
2506
2502
  this.uint8Arrays = [];
2507
2503
  this.dataTextures = [];
2508
2504
  this.nativeTextures = [];
2509
2505
  this.depthData = [];
2510
2506
  }
2511
- createDataDepthTextures(depthData, view_id) {
2512
- if (this.dataTextures[view_id]) {
2513
- this.dataTextures[view_id].dispose();
2507
+ createDataDepthTextures(depthData, viewId) {
2508
+ if (this.dataTextures[viewId]) {
2509
+ this.dataTextures[viewId].dispose();
2514
2510
  }
2515
2511
  if (this.options.useFloat32) {
2516
- const typedArray = new Uint16Array(depthData.width * depthData.height);
2512
+ const typedArray = new Float32Array(depthData.width * depthData.height);
2517
2513
  const format = THREE.RedFormat;
2518
- const type = THREE.HalfFloatType;
2519
- this.uint16Arrays[view_id] = typedArray;
2520
- this.dataTextures[view_id] = new THREE.DataTexture(typedArray, depthData.width, depthData.height, format, type);
2514
+ const type = THREE.FloatType;
2515
+ this.float32Arrays[viewId] = typedArray;
2516
+ this.dataTextures[viewId] = new THREE.DataTexture(typedArray, depthData.width, depthData.height, format, type);
2521
2517
  }
2522
2518
  else {
2523
2519
  const typedArray = new Uint8Array(depthData.width * depthData.height * 2);
2524
2520
  const format = THREE.RGFormat;
2525
2521
  const type = THREE.UnsignedByteType;
2526
- this.uint8Arrays[view_id] = typedArray;
2527
- this.dataTextures[view_id] = new THREE.DataTexture(typedArray, depthData.width, depthData.height, format, type);
2522
+ this.uint8Arrays[viewId] = typedArray;
2523
+ this.dataTextures[viewId] = new THREE.DataTexture(typedArray, depthData.width, depthData.height, format, type);
2528
2524
  }
2529
2525
  }
2530
- updateData(depthData, view_id) {
2531
- if (this.dataTextures.length < view_id + 1 ||
2532
- this.dataTextures[view_id].image.width !== depthData.width ||
2533
- this.dataTextures[view_id].image.height !== depthData.height) {
2534
- this.createDataDepthTextures(depthData, view_id);
2526
+ updateData(depthData, viewId) {
2527
+ if (this.dataTextures.length < viewId + 1 ||
2528
+ this.dataTextures[viewId].image.width !== depthData.width ||
2529
+ this.dataTextures[viewId].image.height !== depthData.height) {
2530
+ this.createDataDepthTextures(depthData, viewId);
2535
2531
  }
2536
2532
  if (this.options.useFloat32) {
2537
- const float32Data = new Float32Array(depthData.data);
2538
- const float16Data = new Uint16Array(float32Data.length);
2539
- for (let i = 0; i < float16Data.length; i++) {
2540
- float16Data[i] = THREE.DataUtils.toHalfFloat(float32Data[i]);
2541
- }
2542
- this.uint16Arrays[view_id].set(float16Data);
2533
+ this.float32Arrays[viewId].set(new Float32Array(depthData.data));
2543
2534
  }
2544
2535
  else {
2545
- this.uint8Arrays[view_id].set(new Uint8Array(depthData.data));
2536
+ this.uint8Arrays[viewId].set(new Uint8Array(depthData.data));
2546
2537
  }
2547
- this.dataTextures[view_id].needsUpdate = true;
2548
- this.depthData[view_id] = depthData;
2538
+ this.dataTextures[viewId].needsUpdate = true;
2539
+ this.depthData[viewId] = depthData;
2549
2540
  }
2550
- updateNativeTexture(depthData, renderer, view_id) {
2551
- if (this.dataTextures.length < view_id + 1) {
2552
- this.nativeTextures[view_id] = new THREE.ExternalTexture(depthData.texture);
2541
+ updateNativeTexture(depthData, renderer, viewId) {
2542
+ if (this.dataTextures.length < viewId + 1) {
2543
+ this.nativeTextures[viewId] = new THREE.ExternalTexture(depthData.texture);
2553
2544
  }
2554
2545
  else {
2555
- this.nativeTextures[view_id].sourceTexture = depthData.texture;
2546
+ this.nativeTextures[viewId].sourceTexture = depthData.texture;
2556
2547
  }
2557
2548
  // fixed in newer revision of three
2558
- const textureProperties = renderer.properties.get(this.nativeTextures[view_id]);
2549
+ const textureProperties = renderer.properties.get(this.nativeTextures[viewId]);
2559
2550
  textureProperties.__webglTexture = depthData.texture;
2560
2551
  textureProperties.__version = 1;
2561
2552
  }
2562
- get(view_id) {
2553
+ get(viewId) {
2563
2554
  if (this.dataTextures.length > 0) {
2564
- return this.dataTextures[view_id];
2555
+ return this.dataTextures[viewId];
2565
2556
  }
2566
- return this.nativeTextures[view_id];
2557
+ return this.nativeTextures[viewId];
2567
2558
  }
2568
2559
  }
2569
2560
 
@@ -3057,6 +3048,15 @@ const DEFAULT_DEPTH_WIDTH = 160;
3057
3048
  const DEFAULT_DEPTH_HEIGHT = DEFAULT_DEPTH_WIDTH;
3058
3049
  const clipSpacePosition = new THREE.Vector3();
3059
3050
  class Depth {
3051
+ get rawValueToMeters() {
3052
+ if (this.cpuDepthData.length) {
3053
+ return this.cpuDepthData[0].rawValueToMeters;
3054
+ }
3055
+ else if (this.gpuDepthData.length) {
3056
+ return this.gpuDepthData[0].rawValueToMeters;
3057
+ }
3058
+ return 0;
3059
+ }
3060
3060
  /**
3061
3061
  * Depth is a lightweight manager based on three.js to simply prototyping
3062
3062
  * with Depth in WebXR.
@@ -3070,11 +3070,13 @@ class Depth {
3070
3070
  this.options = new DepthOptions();
3071
3071
  this.width = DEFAULT_DEPTH_WIDTH;
3072
3072
  this.height = DEFAULT_DEPTH_HEIGHT;
3073
- this.rawValueToMeters = 0.0010000000474974513;
3074
3073
  this.occludableShaders = new Set();
3075
3074
  // Whether we're counting the number of depth clients.
3076
3075
  this.depthClientsInitialized = false;
3077
3076
  this.depthClients = new Set();
3077
+ this.depthProjectionMatrices = [];
3078
+ this.depthViewMatrices = [];
3079
+ this.depthViewProjectionMatrices = [];
3078
3080
  if (Depth.instance) {
3079
3081
  return Depth.instance;
3080
3082
  }
@@ -3157,16 +3159,29 @@ class Depth {
3157
3159
  vertexPosition.multiplyScalar(-depth / vertexPosition.z);
3158
3160
  return vertexPosition;
3159
3161
  }
3160
- updateCPUDepthData(depthData, view_id = 0) {
3161
- this.cpuDepthData[view_id] = depthData;
3162
- // Workaround for b/382679381.
3163
- this.rawValueToMeters = depthData.rawValueToMeters;
3164
- if (this.options.useFloat32) {
3165
- this.rawValueToMeters = 1.0;
3162
+ updateDepthMatrices(depthData, viewId) {
3163
+ // Populate depth view and projection matrices.
3164
+ while (viewId >= this.depthViewMatrices.length) {
3165
+ this.depthViewMatrices.push(new THREE.Matrix4());
3166
+ this.depthViewProjectionMatrices.push(new THREE.Matrix4());
3167
+ this.depthProjectionMatrices.push(new THREE.Matrix4());
3166
3168
  }
3169
+ if (depthData.projectionMatrix && depthData.transform) {
3170
+ this.depthProjectionMatrices[viewId].fromArray(depthData.projectionMatrix);
3171
+ this.depthViewMatrices[viewId].fromArray(depthData.transform.inverse.matrix);
3172
+ }
3173
+ else {
3174
+ const camera = this.renderer.xr?.getCamera()?.cameras?.[viewId] ?? this.camera;
3175
+ this.depthProjectionMatrices[viewId].copy(camera.projectionMatrix);
3176
+ this.depthViewMatrices[viewId].copy(camera.matrixWorldInverse);
3177
+ }
3178
+ this.depthViewProjectionMatrices[viewId].multiplyMatrices(this.depthProjectionMatrices[viewId], this.depthViewMatrices[viewId]);
3179
+ }
3180
+ updateCPUDepthData(depthData, viewId = 0) {
3181
+ this.cpuDepthData[viewId] = depthData;
3167
3182
  // Updates Depth Array.
3168
- if (this.depthArray[view_id] == null) {
3169
- this.depthArray[view_id] = this.options.useFloat32
3183
+ if (this.depthArray[viewId] == null) {
3184
+ this.depthArray[viewId] = this.options.useFloat32
3170
3185
  ? new Float32Array(depthData.data)
3171
3186
  : new Uint16Array(depthData.data);
3172
3187
  this.width = depthData.width;
@@ -3174,25 +3189,21 @@ class Depth {
3174
3189
  }
3175
3190
  else {
3176
3191
  // Copies the data from an ArrayBuffer to the existing TypedArray.
3177
- this.depthArray[view_id].set(this.options.useFloat32
3192
+ this.depthArray[viewId].set(this.options.useFloat32
3178
3193
  ? new Float32Array(depthData.data)
3179
3194
  : new Uint16Array(depthData.data));
3180
3195
  }
3181
3196
  // Updates Depth Texture.
3182
3197
  if (this.options.depthTexture.enabled && this.depthTextures) {
3183
- this.depthTextures.updateData(depthData, view_id);
3198
+ this.depthTextures.updateData(depthData, viewId);
3184
3199
  }
3185
- if (this.options.depthMesh.enabled && this.depthMesh && view_id == 0) {
3200
+ if (this.options.depthMesh.enabled && this.depthMesh && viewId == 0) {
3186
3201
  this.depthMesh.updateDepth(depthData);
3187
3202
  }
3203
+ this.updateDepthMatrices(depthData, viewId);
3188
3204
  }
3189
- updateGPUDepthData(depthData, view_id = 0) {
3190
- this.gpuDepthData[view_id] = depthData;
3191
- // Workaround for b/382679381.
3192
- this.rawValueToMeters = depthData.rawValueToMeters;
3193
- if (this.options.useFloat32) {
3194
- this.rawValueToMeters = 1.0;
3195
- }
3205
+ updateGPUDepthData(depthData, viewId = 0) {
3206
+ this.gpuDepthData[viewId] = depthData;
3196
3207
  // For now, assume that we need cpu depth only if depth mesh is enabled.
3197
3208
  // In the future, add a separate option.
3198
3209
  const needCpuDepth = this.options.depthMesh.enabled;
@@ -3200,8 +3211,8 @@ class Depth {
3200
3211
  ? this.depthMesh.convertGPUToGPU(depthData)
3201
3212
  : null;
3202
3213
  if (cpuDepth) {
3203
- if (this.depthArray[view_id] == null) {
3204
- this.depthArray[view_id] = this.options.useFloat32
3214
+ if (this.depthArray[viewId] == null) {
3215
+ this.depthArray[viewId] = this.options.useFloat32
3205
3216
  ? new Float32Array(cpuDepth.data)
3206
3217
  : new Uint16Array(cpuDepth.data);
3207
3218
  this.width = cpuDepth.width;
@@ -3209,16 +3220,16 @@ class Depth {
3209
3220
  }
3210
3221
  else {
3211
3222
  // Copies the data from an ArrayBuffer to the existing TypedArray.
3212
- this.depthArray[view_id].set(this.options.useFloat32
3223
+ this.depthArray[viewId].set(this.options.useFloat32
3213
3224
  ? new Float32Array(cpuDepth.data)
3214
3225
  : new Uint16Array(cpuDepth.data));
3215
3226
  }
3216
3227
  }
3217
3228
  // Updates Depth Texture.
3218
3229
  if (this.options.depthTexture.enabled && this.depthTextures) {
3219
- this.depthTextures.updateNativeTexture(depthData, this.renderer, view_id);
3230
+ this.depthTextures.updateNativeTexture(depthData, this.renderer, viewId);
3220
3231
  }
3221
- if (this.options.depthMesh.enabled && this.depthMesh && view_id == 0) {
3232
+ if (this.options.depthMesh.enabled && this.depthMesh && viewId == 0) {
3222
3233
  if (cpuDepth) {
3223
3234
  this.depthMesh.updateDepth(cpuDepth);
3224
3235
  }
@@ -3226,11 +3237,12 @@ class Depth {
3226
3237
  this.depthMesh.updateGPUDepth(depthData);
3227
3238
  }
3228
3239
  }
3240
+ this.updateDepthMatrices(depthData, viewId);
3229
3241
  }
3230
- getTexture(view_id) {
3242
+ getTexture(viewId) {
3231
3243
  if (!this.options.depthTexture.enabled)
3232
3244
  return undefined;
3233
- return this.depthTextures?.get(view_id);
3245
+ return this.depthTextures?.get(viewId);
3234
3246
  }
3235
3247
  update(frame) {
3236
3248
  if (!this.options.enabled)
@@ -3264,33 +3276,26 @@ class Depth {
3264
3276
  return;
3265
3277
  }
3266
3278
  }
3267
- if (this.xrRefSpace == null) {
3268
- session.requestReferenceSpace('local').then((refSpace) => {
3269
- this.xrRefSpace = refSpace;
3270
- });
3271
- session.addEventListener('end', () => {
3272
- this.xrRefSpace = undefined;
3273
- });
3274
- }
3275
- else {
3276
- const pose = frame.getViewerPose(this.xrRefSpace);
3279
+ const xrRefSpace = this.renderer.xr.getReferenceSpace();
3280
+ if (xrRefSpace) {
3281
+ const pose = frame.getViewerPose(xrRefSpace);
3277
3282
  if (pose) {
3278
- for (let view_id = 0; view_id < pose.views.length; ++view_id) {
3279
- const view = pose.views[view_id];
3280
- this.view[view_id] = view;
3283
+ for (let viewId = 0; viewId < pose.views.length; ++viewId) {
3284
+ const view = pose.views[viewId];
3285
+ this.view[viewId] = view;
3281
3286
  if (session.depthUsage === 'gpu-optimized') {
3282
3287
  const depthData = binding.getDepthInformation(view);
3283
3288
  if (!depthData) {
3284
3289
  return;
3285
3290
  }
3286
- this.updateGPUDepthData(depthData, view_id);
3291
+ this.updateGPUDepthData(depthData, viewId);
3287
3292
  }
3288
3293
  else {
3289
3294
  const depthData = frame.getDepthInformation(view);
3290
3295
  if (!depthData) {
3291
3296
  return;
3292
3297
  }
3293
- this.updateCPUDepthData(depthData, view_id);
3298
+ this.updateCPUDepthData(depthData, viewId);
3294
3299
  }
3295
3300
  }
3296
3301
  }
@@ -3348,10 +3353,10 @@ const aspectRatios = {
3348
3353
  *
3349
3354
  * @param rgbUv - The RGB UV coordinate, e.g., \{ u: 0.5, v: 0.5 \}.
3350
3355
  * @param xrDeviceCamera - The device camera instance.
3351
- * @returns The transformed UV coordinate in the depth image space, or null if
3356
+ * @returns The transformed UV coordinate in the render camera clip space, or null if
3352
3357
  * inputs are invalid.
3353
3358
  */
3354
- function transformRgbToDepthUv(rgbUv, xrDeviceCamera) {
3359
+ function transformRgbToRenderCameraClip(rgbUv, xrDeviceCamera) {
3355
3360
  if (xrDeviceCamera?.simulatorCamera) {
3356
3361
  // The simulator camera crops the viewport image to match its aspect ratio,
3357
3362
  // while the depth map covers the entire viewport, so we adjust for this.
@@ -3369,7 +3374,7 @@ function transformRgbToDepthUv(rgbUv, xrDeviceCamera) {
3369
3374
  const relativeHeight = viewportAspect / cameraAspect;
3370
3375
  v = v * relativeHeight + (1.0 - relativeHeight) / 2.0;
3371
3376
  }
3372
- return { u, v: 1.0 - v };
3377
+ return new THREE.Vector2(2 * u - 1, 2 * v - 1);
3373
3378
  }
3374
3379
  if (!aspectRatios || !aspectRatios.depth || !aspectRatios.RGB) {
3375
3380
  console.error('Invalid aspect ratios provided.');
@@ -3408,10 +3413,34 @@ function transformRgbToDepthUv(rgbUv, xrDeviceCamera) {
3408
3413
  // Apply the final user-controlled scaling (zoom and stretch).
3409
3414
  const finalNormX = u_fitted * params.scale * params.scaleX;
3410
3415
  const finalNormY = v_fitted * params.scale * params.scaleY;
3411
- // Convert the final normalized coordinate back to a UV coordinate [0, 1].
3412
- const finalU = finalNormX + 0.5;
3413
- const finalV = finalNormY + 0.5;
3414
- return { u: finalU, v: 1.0 - finalV };
3416
+ return new THREE.Vector2(2 * finalNormX, 2 * finalNormY);
3417
+ }
3418
+ /**
3419
+ * Maps a UV coordinate from a RGB space to a destination depth space,
3420
+ * applying Brown-Conrady distortion and affine transformations based on
3421
+ * aspect ratios. If the simulator camera is used, no transformation is applied.
3422
+ *
3423
+ * @param rgbUv - The RGB UV coordinate, e.g., \{ u: 0.5, v: 0.5 \}.
3424
+ * @param renderCameraWorldFromClip - Render camera world from clip, i.e. inverse of the View Projection matrix.
3425
+ * @param depthCameraClipFromWorld - Depth camera clip from world, i.e.
3426
+ * @param xrDeviceCamera - The device camera instance.
3427
+ * @returns The transformed UV coordinate in the depth image space, or null if
3428
+ * inputs are invalid.
3429
+ */
3430
+ function transformRgbToDepthUv(rgbUv, renderCameraWorldFromClip, depthCameraClipFromWorld, xrDeviceCamera) {
3431
+ // Render camera clip space coordinates.
3432
+ const clipCoords = transformRgbToRenderCameraClip(rgbUv, xrDeviceCamera);
3433
+ if (!clipCoords) {
3434
+ return null;
3435
+ }
3436
+ // Backwards project from the render camera to depth camera.
3437
+ const depthClipCoord = new THREE.Vector4(clipCoords.x, clipCoords.y, 1, 1);
3438
+ depthClipCoord.applyMatrix4(renderCameraWorldFromClip);
3439
+ depthClipCoord.applyMatrix4(depthCameraClipFromWorld);
3440
+ depthClipCoord.multiplyScalar(1 / depthClipCoord.w);
3441
+ const finalU = 0.5 * depthClipCoord.x + 0.5;
3442
+ const finalV = 1.0 - (0.5 * depthClipCoord.y + 0.5);
3443
+ return { u: finalU, v: finalV };
3415
3444
  }
3416
3445
  /**
3417
3446
  * Retrieves the world space position of a given RGB UV coordinate.
@@ -3421,19 +3450,30 @@ function transformRgbToDepthUv(rgbUv, xrDeviceCamera) {
3421
3450
  *
3422
3451
  * @param rgbUv - The RGB UV coordinate, e.g., \{ u: 0.5, v: 0.5 \}.
3423
3452
  * @param depthArray - Array containing depth data.
3424
- * @param viewProjectionMatrix - XRView object with corresponding
3453
+ * @param projectionMatrix - XRView object with corresponding
3425
3454
  * projection matrix.
3426
- * @param matrixWorld - Matrix for view-to-world translation.
3455
+ * @param matrixWorld - Rendering camera's model matrix.
3427
3456
  * @param xrDeviceCamera - The device camera instance.
3428
3457
  * @param xrDepth - The SDK's Depth module.
3429
3458
  * @returns Vertex at (u, v) in world space.
3430
3459
  */
3431
- function transformRgbUvToWorld(rgbUv, depthArray, viewProjectionMatrix, matrixWorld, xrDeviceCamera, xrDepth = Depth.instance) {
3432
- if (!depthArray || !viewProjectionMatrix || !matrixWorld || !xrDepth)
3433
- return null;
3434
- const depthUV = transformRgbToDepthUv(rgbUv, xrDeviceCamera);
3460
+ function transformRgbUvToWorld(rgbUv, depthArray, projectionMatrix, matrixWorld, xrDeviceCamera, xrDepth = Depth.instance) {
3461
+ if (!depthArray || !projectionMatrix || !matrixWorld || !xrDepth) {
3462
+ throw new Error('Missing parameter in transformRgbUvToWorld');
3463
+ }
3464
+ const worldFromClip = matrixWorld
3465
+ .clone()
3466
+ .invert()
3467
+ .premultiply(projectionMatrix)
3468
+ .invert();
3469
+ const depthProjectionMatrixInverse = xrDepth.depthProjectionMatrices[0]
3470
+ .clone()
3471
+ .invert();
3472
+ const depthClipFromWorld = xrDepth.depthViewProjectionMatrices[0];
3473
+ const depthModelMatrix = xrDepth.depthViewMatrices[0].clone().invert();
3474
+ const depthUV = transformRgbToDepthUv(rgbUv, worldFromClip, depthClipFromWorld, xrDeviceCamera);
3435
3475
  if (!depthUV) {
3436
- return null;
3476
+ throw new Error('Failed to get depth UV');
3437
3477
  }
3438
3478
  const { u: depthU, v: depthV } = depthUV;
3439
3479
  const depthX = Math.round(clamp(depthU * xrDepth.width, 0, xrDepth.width - 1));
@@ -3444,12 +3484,13 @@ function transformRgbUvToWorld(rgbUv, depthArray, viewProjectionMatrix, matrixWo
3444
3484
  // Convert UV to normalized device coordinates and create a point on the near
3445
3485
  // plane.
3446
3486
  const viewSpacePosition = new THREE.Vector3(2.0 * (depthU - 0.5), 2.0 * (depthV - 0.5), -1);
3447
- const viewProjectionMatrixInverse = viewProjectionMatrix.clone().invert();
3448
3487
  // Unproject the point from clip space to view space and scale it along the
3449
3488
  // ray from the camera to the correct depth. Camera looks down -Z axis.
3450
- viewSpacePosition.applyMatrix4(viewProjectionMatrixInverse);
3489
+ viewSpacePosition.applyMatrix4(depthProjectionMatrixInverse);
3451
3490
  viewSpacePosition.multiplyScalar(-depthInMeters / viewSpacePosition.z);
3452
- const worldPosition = viewSpacePosition.clone().applyMatrix4(matrixWorld);
3491
+ const worldPosition = viewSpacePosition
3492
+ .clone()
3493
+ .applyMatrix4(depthModelMatrix);
3453
3494
  return worldPosition;
3454
3495
  }
3455
3496
  /**
@@ -4133,6 +4174,9 @@ class ScriptsManager {
4133
4174
  this.callKeyUpBound = this.callKeyUp.bind(this);
4134
4175
  /** The set of scripts currently being initialized. */
4135
4176
  this.initializingScripts = new Set();
4177
+ this.seenScripts = new Set();
4178
+ this.syncPromises = [];
4179
+ this.checkScriptBound = this.checkScript.bind(this);
4136
4180
  }
4137
4181
  /**
4138
4182
  * Initializes a script and adds it to the set of scripts which will receive
@@ -4163,29 +4207,33 @@ class ScriptsManager {
4163
4207
  this.scripts.delete(script);
4164
4208
  this.initializingScripts.delete(script);
4165
4209
  }
4210
+ /**
4211
+ * Helper for scene traversal to avoid closure allocation.
4212
+ */
4213
+ checkScript(obj) {
4214
+ if (obj.isXRScript) {
4215
+ const script = obj;
4216
+ this.syncPromises.push(this.initScript(script));
4217
+ this.seenScripts.add(script);
4218
+ }
4219
+ }
4166
4220
  /**
4167
4221
  * Finds all scripts in the scene and initializes them or uninitailizes them.
4168
4222
  * Returns a promise which resolves when all new scripts are finished
4169
4223
  * initalizing.
4170
4224
  * @param scene - The main scene which is used to find scripts.
4171
4225
  */
4172
- async syncScriptsWithScene(scene) {
4173
- const seenScripts = new Set();
4174
- const promises = [];
4175
- scene.traverse((obj) => {
4176
- if (obj.isXRScript) {
4177
- const script = obj;
4178
- promises.push(this.initScript(script));
4179
- seenScripts.add(script);
4180
- }
4181
- });
4182
- await Promise.allSettled(promises);
4226
+ syncScriptsWithScene(scene) {
4227
+ this.seenScripts.clear();
4228
+ this.syncPromises.length = 0;
4229
+ scene.traverse(this.checkScriptBound);
4183
4230
  // Delete missing scripts.
4184
4231
  for (const script of this.scripts) {
4185
- if (!seenScripts.has(script)) {
4232
+ if (!this.seenScripts.has(script)) {
4186
4233
  this.uninitScript(script);
4187
4234
  }
4188
4235
  }
4236
+ return Promise.allSettled(this.syncPromises);
4189
4237
  }
4190
4238
  callSelectStart(event) {
4191
4239
  for (const script of this.scripts) {
@@ -5778,6 +5826,7 @@ function traverseUtil(node, callback) {
5778
5826
  return false;
5779
5827
  }
5780
5828
 
5829
+ const tempBox = new THREE.Box3();
5781
5830
  /**
5782
5831
  * User is an embodied instance to manage hands, controllers, speech, and
5783
5832
  * avatars. It extends Script to update human-world interaction.
@@ -6140,8 +6189,8 @@ class User extends Script {
6140
6189
  const currentlyTouchedMeshes = [];
6141
6190
  this.scene.traverse((object) => {
6142
6191
  if (object.isMesh && object.visible) {
6143
- const boundingBox = new THREE.Box3().setFromObject(object);
6144
- if (boundingBox.containsPoint(indexTipPosition)) {
6192
+ tempBox.setFromObject(object);
6193
+ if (tempBox.containsPoint(indexTipPosition)) {
6145
6194
  currentlyTouchedMeshes.push(object);
6146
6195
  }
6147
6196
  }
@@ -6429,6 +6478,13 @@ function computePinch(context, config) {
6429
6478
  const index = getJoint(context, 'index-finger-tip');
6430
6479
  if (!thumb || !index)
6431
6480
  return undefined;
6481
+ const supportMetrics = ['middle', 'ring', 'pinky']
6482
+ .map((finger) => computeFingerMetric(context, finger))
6483
+ .filter(Boolean);
6484
+ const supportCurl = supportMetrics.length > 0
6485
+ ? average(supportMetrics.map((metrics) => metrics.curlRatio))
6486
+ : 1;
6487
+ const supportPenalty = clamp01((supportCurl - 1.05) / 0.35);
6432
6488
  const handScale = estimateHandScale(context);
6433
6489
  const threshold = config.threshold ?? Math.max(0.018, handScale * 0.35);
6434
6490
  const distance = thumb.distanceTo(index);
@@ -6437,10 +6493,12 @@ function computePinch(context, config) {
6437
6493
  }
6438
6494
  const tightness = clamp01(1 - distance / (threshold * 0.85));
6439
6495
  const loosePenalty = clamp01(1 - distance / (threshold * 1.4));
6440
- const confidence = clamp01(distance <= threshold ? tightness : loosePenalty * 0.4);
6496
+ let confidence = clamp01(distance <= threshold ? tightness : loosePenalty * 0.4);
6497
+ confidence *= 1 - supportPenalty * 0.45;
6498
+ confidence = clamp01(confidence);
6441
6499
  return {
6442
6500
  confidence,
6443
- data: { distance, threshold },
6501
+ data: { distance, threshold, supportPenalty },
6444
6502
  };
6445
6503
  }
6446
6504
  function computeOpenPalm(context, config) {
@@ -6449,21 +6507,29 @@ function computeOpenPalm(context, config) {
6449
6507
  return undefined;
6450
6508
  const handScale = estimateHandScale(context);
6451
6509
  const palmWidth = getPalmWidth(context) ?? handScale * 0.85;
6510
+ const palmUp = getPalmUp(context);
6452
6511
  const extensionScores = fingerMetrics.map(({ tipDistance }) => clamp01((tipDistance - handScale * 0.5) / (handScale * 0.45)));
6453
6512
  const straightnessScores = fingerMetrics.map(({ curlRatio }) => clamp01((curlRatio - 1.1) / 0.5));
6513
+ const orientationScore = palmUp && fingerMetrics.length
6514
+ ? average(fingerMetrics.map((metrics) => fingerAlignmentScore(context, metrics, palmUp)))
6515
+ : 0.5;
6454
6516
  const neighbors = getAdjacentFingerDistances(context);
6455
6517
  const spreadScore = neighbors.average !== Infinity && palmWidth > EPSILON
6456
6518
  ? clamp01((neighbors.average - palmWidth * 0.55) / (palmWidth * 0.35))
6457
6519
  : 0;
6458
6520
  const extensionScore = average(extensionScores);
6459
6521
  const straightScore = average(straightnessScores);
6460
- const confidence = clamp01(extensionScore * 0.5 + straightScore * 0.3 + spreadScore * 0.2);
6522
+ const confidence = clamp01(extensionScore * 0.4 +
6523
+ straightScore * 0.25 +
6524
+ spreadScore * 0.2 +
6525
+ orientationScore * 0.15);
6461
6526
  return {
6462
6527
  confidence,
6463
6528
  data: {
6464
6529
  extensionScore,
6465
6530
  straightScore,
6466
6531
  spreadScore,
6532
+ orientationScore,
6467
6533
  threshold: config.threshold,
6468
6534
  },
6469
6535
  };
@@ -6480,15 +6546,26 @@ function computeFist(context, config) {
6480
6546
  const clusterScore = neighbors.average !== Infinity && palmWidth > EPSILON
6481
6547
  ? clamp01((palmWidth * 0.5 - neighbors.average) / (palmWidth * 0.35))
6482
6548
  : 0;
6549
+ const thumbTip = getJoint(context, 'thumb-tip');
6550
+ const indexBase = getFingerJoint(context, 'index', 'phalanx-proximal') ??
6551
+ getFingerJoint(context, 'index', 'metacarpal');
6552
+ const thumbWrapScore = thumbTip && indexBase && palmWidth > EPSILON
6553
+ ? clamp01((palmWidth * 0.55 - thumbTip.distanceTo(indexBase)) /
6554
+ (palmWidth * 0.35))
6555
+ : 0;
6483
6556
  const tipScore = clamp01((handScale * 0.55 - tipAverage) / (handScale * 0.25));
6484
6557
  const curlScore = clamp01((1.08 - curlAverage) / 0.25);
6485
- const confidence = clamp01(tipScore * 0.5 + curlScore * 0.35 + clusterScore * 0.15);
6558
+ const confidence = clamp01(tipScore * 0.45 +
6559
+ curlScore * 0.3 +
6560
+ clusterScore * 0.1 +
6561
+ thumbWrapScore * 0.15);
6486
6562
  return {
6487
6563
  confidence,
6488
6564
  data: {
6489
6565
  tipAverage,
6490
6566
  curlAverage,
6491
6567
  clusterScore,
6568
+ thumbWrapScore,
6492
6569
  threshold: config.threshold,
6493
6570
  },
6494
6571
  };
@@ -6525,8 +6602,8 @@ function computeThumbsUp(context, config) {
6525
6602
  orientationScore = clamp01((alignment - 0.35) / 0.35);
6526
6603
  }
6527
6604
  }
6528
- const confidence = clamp01(thumbExtendedScore * 0.35 +
6529
- curledScore * 0.3 +
6605
+ const confidence = clamp01(thumbExtendedScore * 0.3 +
6606
+ curledScore * 0.35 +
6530
6607
  orientationScore * 0.2 +
6531
6608
  separationScore * 0.15);
6532
6609
  return {
@@ -6550,17 +6627,33 @@ function computePoint(context, config) {
6550
6627
  if (!otherMetrics.length)
6551
6628
  return undefined;
6552
6629
  const handScale = estimateHandScale(context);
6630
+ const palmWidth = getPalmWidth(context) ?? handScale * 0.85;
6631
+ const palmUp = getPalmUp(context);
6553
6632
  const indexCurlScore = clamp01((indexMetrics.curlRatio - 1.2) / 0.35);
6554
6633
  const indexReachScore = clamp01((indexMetrics.tipDistance - handScale * 0.6) / (handScale * 0.25));
6634
+ const indexDirectionScore = palmUp && indexMetrics
6635
+ ? fingerAlignmentScore(context, indexMetrics, palmUp)
6636
+ : 0.4;
6555
6637
  const othersCurl = average(otherMetrics.map((metrics) => metrics.curlRatio));
6556
6638
  const othersCurledScore = clamp01((1.05 - othersCurl) / 0.25);
6557
- const confidence = clamp01(indexCurlScore * 0.45 + indexReachScore * 0.25 + othersCurledScore * 0.3);
6639
+ const thumbTip = getJoint(context, 'thumb-tip');
6640
+ const thumbTuckedScore = thumbTip && indexMetrics.metacarpal && palmWidth > EPSILON
6641
+ ? clamp01((palmWidth * 0.75 - thumbTip.distanceTo(indexMetrics.metacarpal)) /
6642
+ (palmWidth * 0.4))
6643
+ : 0.5;
6644
+ const confidence = clamp01(indexCurlScore * 0.35 +
6645
+ indexReachScore * 0.25 +
6646
+ othersCurledScore * 0.2 +
6647
+ indexDirectionScore * 0.1 +
6648
+ thumbTuckedScore * 0.1);
6558
6649
  return {
6559
6650
  confidence,
6560
6651
  data: {
6561
6652
  indexCurlScore,
6562
6653
  indexReachScore,
6563
6654
  othersCurledScore,
6655
+ indexDirectionScore,
6656
+ thumbTuckedScore,
6564
6657
  threshold: config.threshold,
6565
6658
  },
6566
6659
  };
@@ -6572,16 +6665,21 @@ function computeSpread(context, config) {
6572
6665
  const handScale = estimateHandScale(context);
6573
6666
  const palmWidth = getPalmWidth(context) ?? handScale * 0.85;
6574
6667
  const neighbors = getAdjacentFingerDistances(context);
6668
+ const palmUp = getPalmUp(context);
6575
6669
  const spreadScore = neighbors.average !== Infinity && palmWidth > EPSILON
6576
6670
  ? clamp01((neighbors.average - palmWidth * 0.6) / (palmWidth * 0.35))
6577
6671
  : 0;
6578
6672
  const extensionScore = clamp01((average(fingerMetrics.map((metrics) => metrics.curlRatio)) - 1.15) / 0.45);
6579
- const confidence = clamp01(spreadScore * 0.6 + extensionScore * 0.4);
6673
+ const orientationScore = palmUp && fingerMetrics.length
6674
+ ? average(fingerMetrics.map((metrics) => fingerAlignmentScore(context, metrics, palmUp)))
6675
+ : 0.5;
6676
+ const confidence = clamp01(spreadScore * 0.55 + extensionScore * 0.3 + orientationScore * 0.15);
6580
6677
  return {
6581
6678
  confidence,
6582
6679
  data: {
6583
6680
  spreadScore,
6584
6681
  extensionScore,
6682
+ orientationScore,
6585
6683
  threshold: config.threshold,
6586
6684
  },
6587
6685
  };
@@ -6709,6 +6807,16 @@ function getFingerJoint(context, finger, suffix) {
6709
6807
  const prefix = FINGER_PREFIX[finger];
6710
6808
  return getJoint(context, `${prefix}-${suffix}`);
6711
6809
  }
6810
+ function fingerAlignmentScore(context, metrics, palmUp) {
6811
+ const base = metrics.metacarpal ?? getJoint(context, 'wrist');
6812
+ if (!base)
6813
+ return 0;
6814
+ const direction = new THREE.Vector3().subVectors(metrics.tip, base);
6815
+ if (direction.lengthSq() === 0)
6816
+ return 0;
6817
+ direction.normalize();
6818
+ return clamp01((direction.dot(palmUp) - 0.35) / 0.5);
6819
+ }
6712
6820
  function clamp01(value) {
6713
6821
  return THREE.MathUtils.clamp(value, 0, 1);
6714
6822
  }
@@ -8137,6 +8245,15 @@ class SimulatorDepth {
8137
8245
  this.depthWidth = 160;
8138
8246
  this.depthHeight = 160;
8139
8247
  this.depthBufferSlice = new Float32Array();
8248
+ /**
8249
+ * If true, copies the rendering camera's projection matrix each frame.
8250
+ */
8251
+ this.autoUpdateDepthCameraProjection = true;
8252
+ /**
8253
+ * If true, copies the rendering camera's transform each frame.
8254
+ */
8255
+ this.autoUpdateDepthCameraTransform = true;
8256
+ this.projectionMatrixArray = new Float32Array(16);
8140
8257
  }
8141
8258
  /**
8142
8259
  * Initialize Simulator Depth.
@@ -8145,6 +8262,16 @@ class SimulatorDepth {
8145
8262
  this.renderer = renderer;
8146
8263
  this.camera = camera;
8147
8264
  this.depth = depth;
8265
+ if (this.camera instanceof THREE.PerspectiveCamera) {
8266
+ this.depthCamera = new THREE.PerspectiveCamera();
8267
+ }
8268
+ else if (this.camera instanceof THREE.OrthographicCamera) {
8269
+ this.depthCamera = new THREE.OrthographicCamera();
8270
+ }
8271
+ else {
8272
+ throw new Error('Unknown camera type');
8273
+ }
8274
+ this.depthCamera.copy(this.camera, /*recursive=*/ false);
8148
8275
  this.createRenderTarget();
8149
8276
  this.depthMaterial = new SimulatorDepthMaterial();
8150
8277
  }
@@ -8156,23 +8283,44 @@ class SimulatorDepth {
8156
8283
  this.depthBuffer = new Float32Array(this.depthWidth * this.depthHeight);
8157
8284
  }
8158
8285
  update() {
8286
+ this.updateDepthCamera();
8159
8287
  this.renderDepthScene();
8160
8288
  this.updateDepth();
8161
8289
  }
8290
+ updateDepthCamera() {
8291
+ const renderingCamera = this.camera;
8292
+ const depthCamera = this.depthCamera;
8293
+ if (this.autoUpdateDepthCameraProjection) {
8294
+ depthCamera.projectionMatrix.copy(renderingCamera.projectionMatrix);
8295
+ depthCamera.projectionMatrixInverse.copy(renderingCamera.projectionMatrixInverse);
8296
+ }
8297
+ if (this.autoUpdateDepthCameraTransform) {
8298
+ depthCamera.position.copy(renderingCamera.position);
8299
+ depthCamera.rotation.order = renderingCamera.rotation.order;
8300
+ depthCamera.quaternion.copy(renderingCamera.quaternion);
8301
+ depthCamera.scale.copy(renderingCamera.scale);
8302
+ depthCamera.matrix.copy(renderingCamera.matrix);
8303
+ depthCamera.matrixWorld.copy(renderingCamera.matrixWorld);
8304
+ depthCamera.matrixWorldInverse.copy(renderingCamera.matrixWorldInverse);
8305
+ }
8306
+ }
8162
8307
  renderDepthScene() {
8163
8308
  const originalRenderTarget = this.renderer.getRenderTarget();
8164
8309
  this.renderer.setRenderTarget(this.depthRenderTarget);
8165
8310
  this.simulatorScene.overrideMaterial = this.depthMaterial;
8166
- this.renderer.render(this.simulatorScene, this.camera);
8311
+ this.renderer.render(this.simulatorScene, this.depthCamera);
8167
8312
  this.simulatorScene.overrideMaterial = null;
8168
8313
  this.renderer.setRenderTarget(originalRenderTarget);
8169
8314
  }
8170
- updateDepth() {
8315
+ async updateDepth() {
8171
8316
  // We preventively unbind the PIXEL_PACK_BUFFER before reading from the
8172
8317
  // render target in case external libraries (Spark.js) left it bound.
8173
8318
  const context = this.renderer.getContext();
8174
8319
  context.bindBuffer(context.PIXEL_PACK_BUFFER, null);
8175
- this.renderer.readRenderTargetPixels(this.depthRenderTarget, 0, 0, this.depthWidth, this.depthHeight, this.depthBuffer);
8320
+ // Cache the projection matrix and transform of the rendered depth.
8321
+ const projectionMatrix = this.depthCamera.projectionMatrix.clone();
8322
+ const transform = new XRRigidTransform(this.depthCamera.position, this.depthCamera.quaternion);
8323
+ await this.renderer.readRenderTargetPixelsAsync(this.depthRenderTarget, 0, 0, this.depthWidth, this.depthHeight, this.depthBuffer);
8176
8324
  // Flip the depth buffer.
8177
8325
  if (this.depthBufferSlice.length != this.depthWidth) {
8178
8326
  this.depthBufferSlice = new Float32Array(this.depthWidth);
@@ -8188,11 +8336,14 @@ class SimulatorDepth {
8188
8336
  // Copy the temp slice (original row i) to row j
8189
8337
  this.depthBuffer.set(this.depthBufferSlice, j_offset);
8190
8338
  }
8339
+ projectionMatrix.toArray(this.projectionMatrixArray);
8191
8340
  const depthData = {
8192
8341
  width: this.depthWidth,
8193
8342
  height: this.depthHeight,
8194
8343
  data: this.depthBuffer.buffer,
8195
8344
  rawValueToMeters: 1.0,
8345
+ projectionMatrix: this.projectionMatrixArray,
8346
+ transform: transform,
8196
8347
  };
8197
8348
  this.depth.updateCPUDepthData(depthData, 0);
8198
8349
  }
@@ -12308,6 +12459,15 @@ class VideoView extends View {
12308
12459
  /** The cross-origin setting for the video element. Default is 'anonymous'. */
12309
12460
  this.crossOrigin = 'anonymous';
12310
12461
  this.videoAspectRatio = 0.0;
12462
+ // set video options if passed in
12463
+ this.autoplay = options.autoplay ?? this.autoplay;
12464
+ this.muted = options.muted ?? this.muted;
12465
+ this.loop = options.loop ?? this.loop;
12466
+ this.playsInline = options.playsInline ?? this.playsInline;
12467
+ if (options.crossOrigin)
12468
+ this.crossOrigin = options.crossOrigin;
12469
+ if (options.mode)
12470
+ this.mode = options.mode;
12311
12471
  const videoGeometry = new THREE.PlaneGeometry(1, 1);
12312
12472
  const videoMaterial = new THREE.MeshBasicMaterial({
12313
12473
  transparent: true,
@@ -17159,5 +17319,5 @@ class VideoFileStream extends VideoStream {
17159
17319
  }
17160
17320
  }
17161
17321
 
17162
- export { AI, AIOptions, AVERAGE_IPD_METERS, ActiveControllers, Agent, AnimatableNumber, AudioListener, AudioPlayer, BACK, BackgroundMusic, CategoryVolumes, Col, Core, CoreSound, DEFAULT_DEVICE_CAMERA_HEIGHT, DEFAULT_DEVICE_CAMERA_WIDTH, DEFAULT_RGB_TO_DEPTH_PARAMS, DOWN, Depth, DepthMesh, DepthMeshOptions, DepthOptions, DepthTextures, DetectedObject, DetectedPlane, DeviceCameraOptions, DragManager, DragMode, ExitButton, FORWARD, FreestandingSlider, GazeController, Gemini, GeminiOptions, GenerateSkyboxTool, GestureRecognition, GestureRecognitionOptions, GetWeatherTool, Grid, HAND_BONE_IDX_CONNECTION_MAP, HAND_JOINT_COUNT, HAND_JOINT_IDX_CONNECTION_MAP, HAND_JOINT_NAMES, Handedness, Hands, HandsOptions, HorizontalPager, IconButton, IconView, ImageView, Input, InputOptions, Keycodes, LEFT, LEFT_VIEW_ONLY_LAYER, LabelView, Lighting, LightingOptions, LoadingSpinnerManager, MaterialSymbolsView, MeshScript, ModelLoader, ModelViewer, MouseController, NEXT_SIMULATOR_MODE, NUM_HANDS, OCCLUDABLE_ITEMS_LAYER, ObjectDetector, ObjectsOptions, OcclusionPass, OcclusionUtils, OpenAI, OpenAIOptions, Options, PageIndicator, Pager, PagerState, Panel, PanelMesh, Physics, PhysicsOptions, PinchOnButtonAction, PlaneDetector, PlanesOptions, RIGHT, RIGHT_VIEW_ONLY_LAYER, Registry, Reticle, ReticleOptions, RotationRaycastMesh, Row, SIMULATOR_HAND_POSE_NAMES, SIMULATOR_HAND_POSE_TO_JOINTS_LEFT, SIMULATOR_HAND_POSE_TO_JOINTS_RIGHT, SOUND_PRESETS, ScreenshotSynthesizer, Script, ScriptMixin, ScriptsManager, ScrollingTroikaTextView, SetSimulatorModeEvent, ShowHandsAction, Simulator, SimulatorCamera, SimulatorControlMode, SimulatorControllerState, SimulatorControls, SimulatorDepth, SimulatorDepthMaterial, SimulatorHandPose, SimulatorHandPoseChangeRequestEvent, SimulatorHands, SimulatorInterface, SimulatorMediaDeviceInfo, SimulatorMode, SimulatorOptions, SimulatorRenderMode, SimulatorScene, SimulatorUser, SimulatorUserAction, SketchPanel, SkyboxAgent, SoundOptions, SoundSynthesizer, SpatialAudio, SpatialPanel, SpeechRecognizer, SpeechRecognizerOptions, SpeechSynthesizer, SpeechSynthesizerOptions, SplatAnchor, StreamState, TextButton, TextScrollerState, TextView, Tool, UI, UI_OVERLAY_LAYER, UP, UX, User, VIEW_DEPTH_GAP, VerticalPager, VideoFileStream, VideoStream, VideoView, View, VolumeCategory, WaitFrame, WalkTowardsPanelAction, World, WorldOptions, XRButton, XRDeviceCamera, XREffects, XRPass, XRTransitionOptions, XR_BLOCKS_ASSETS_PATH, ZERO_VECTOR3, add, ai, aspectRatios, callInitWithDependencyInjection, clamp, clampRotationToAngle, core, cropImage, extractYaw, getColorHex, getDeltaTime, getUrlParamBool, getUrlParamFloat, getUrlParamInt, getUrlParameter, getVec4ByColorString, getXrCameraLeft, getXrCameraRight, init, initScript, lerp, loadStereoImageAsTextures, loadingSpinnerManager, lookAtRotation, objectIsDescendantOf, parseBase64DataURL, placeObjectAtIntersectionFacingTarget, print, scene, showOnlyInLeftEye, showOnlyInRightEye, showReticleOnDepthMesh, transformRgbToDepthUv, transformRgbUvToWorld, traverseUtil, uninitScript, urlParams, user, world, xrDepthMeshOptions, xrDepthMeshPhysicsOptions, xrDepthMeshVisualizationOptions, xrDeviceCameraEnvironmentContinuousOptions, xrDeviceCameraEnvironmentOptions, xrDeviceCameraUserContinuousOptions, xrDeviceCameraUserOptions };
17322
+ export { AI, AIOptions, AVERAGE_IPD_METERS, ActiveControllers, Agent, AnimatableNumber, AudioListener, AudioPlayer, BACK, BackgroundMusic, CategoryVolumes, Col, Core, CoreSound, DEFAULT_DEVICE_CAMERA_HEIGHT, DEFAULT_DEVICE_CAMERA_WIDTH, DEFAULT_RGB_TO_DEPTH_PARAMS, DOWN, Depth, DepthMesh, DepthMeshOptions, DepthOptions, DepthTextures, DetectedObject, DetectedPlane, DeviceCameraOptions, DragManager, DragMode, ExitButton, FORWARD, FreestandingSlider, GazeController, Gemini, GeminiOptions, GenerateSkyboxTool, GestureRecognition, GestureRecognitionOptions, GetWeatherTool, Grid, HAND_BONE_IDX_CONNECTION_MAP, HAND_JOINT_COUNT, HAND_JOINT_IDX_CONNECTION_MAP, HAND_JOINT_NAMES, Handedness, Hands, HandsOptions, HorizontalPager, IconButton, IconView, ImageView, Input, InputOptions, Keycodes, LEFT, LEFT_VIEW_ONLY_LAYER, LabelView, Lighting, LightingOptions, LoadingSpinnerManager, MaterialSymbolsView, MeshScript, ModelLoader, ModelViewer, MouseController, NEXT_SIMULATOR_MODE, NUM_HANDS, OCCLUDABLE_ITEMS_LAYER, ObjectDetector, ObjectsOptions, OcclusionPass, OcclusionUtils, OpenAI, OpenAIOptions, Options, PageIndicator, Pager, PagerState, Panel, PanelMesh, Physics, PhysicsOptions, PinchOnButtonAction, PlaneDetector, PlanesOptions, RIGHT, RIGHT_VIEW_ONLY_LAYER, Registry, Reticle, ReticleOptions, RotationRaycastMesh, Row, SIMULATOR_HAND_POSE_NAMES, SIMULATOR_HAND_POSE_TO_JOINTS_LEFT, SIMULATOR_HAND_POSE_TO_JOINTS_RIGHT, SOUND_PRESETS, ScreenshotSynthesizer, Script, ScriptMixin, ScriptsManager, ScrollingTroikaTextView, SetSimulatorModeEvent, ShowHandsAction, Simulator, SimulatorCamera, SimulatorControlMode, SimulatorControllerState, SimulatorControls, SimulatorDepth, SimulatorDepthMaterial, SimulatorHandPose, SimulatorHandPoseChangeRequestEvent, SimulatorHands, SimulatorInterface, SimulatorMediaDeviceInfo, SimulatorMode, SimulatorOptions, SimulatorRenderMode, SimulatorScene, SimulatorUser, SimulatorUserAction, SketchPanel, SkyboxAgent, SoundOptions, SoundSynthesizer, SpatialAudio, SpatialPanel, SpeechRecognizer, SpeechRecognizerOptions, SpeechSynthesizer, SpeechSynthesizerOptions, SplatAnchor, StreamState, TextButton, TextScrollerState, TextView, Tool, UI, UI_OVERLAY_LAYER, UP, UX, User, VIEW_DEPTH_GAP, VerticalPager, VideoFileStream, VideoStream, VideoView, View, VolumeCategory, WaitFrame, WalkTowardsPanelAction, World, WorldOptions, XRButton, XRDeviceCamera, XREffects, XRPass, XRTransitionOptions, XR_BLOCKS_ASSETS_PATH, ZERO_VECTOR3, add, ai, aspectRatios, callInitWithDependencyInjection, clamp, clampRotationToAngle, core, cropImage, extractYaw, getColorHex, getDeltaTime, getUrlParamBool, getUrlParamFloat, getUrlParamInt, getUrlParameter, getVec4ByColorString, getXrCameraLeft, getXrCameraRight, init, initScript, lerp, loadStereoImageAsTextures, loadingSpinnerManager, lookAtRotation, objectIsDescendantOf, parseBase64DataURL, placeObjectAtIntersectionFacingTarget, print, scene, showOnlyInLeftEye, showOnlyInRightEye, showReticleOnDepthMesh, transformRgbToDepthUv, transformRgbToRenderCameraClip, transformRgbUvToWorld, traverseUtil, uninitScript, urlParams, user, world, xrDepthMeshOptions, xrDepthMeshPhysicsOptions, xrDepthMeshVisualizationOptions, xrDeviceCameraEnvironmentContinuousOptions, xrDeviceCameraEnvironmentOptions, xrDeviceCameraUserContinuousOptions, xrDeviceCameraUserOptions };
17163
17323
  //# sourceMappingURL=xrblocks.js.map