mujoco-react 9.3.0 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { withContacts, getContact } from './chunk-T3GVZJ4F.js';
2
- export { RobotActuators, RobotBodies, RobotCameras, RobotGeoms, RobotJoints, RobotKeyframes, RobotResources, RobotSensors, RobotSites, ScenarioLighting, SplatEnvironment, SplatEnvironmentReadinessStatus, VisualScenarioEffects, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getContact, getScenarioBackground, getScenarioCameraPosition, getSplatEnvironmentReadiness, registerRobotResources, useSplatEnvironment, useSplatSceneConfig, useVisualScenarioEffects, withSplatEnvironment } from './chunk-T3GVZJ4F.js';
1
+ import { withContacts, getContact, captureCameraFrame, captureCameraFrameBlob, createCameraFrameCaptureSession, CAPTURE_EXCLUDE_KEY } from './chunk-6MOK6ZWB.js';
2
+ export { CAPTURE_EXCLUDE_KEY, RobotActuators, RobotBodies, RobotCameras, RobotGeoms, RobotJoints, RobotKeyframes, RobotResources, RobotSensors, RobotSites, ScenarioLighting, SplatEnvironment, SplatEnvironmentReadinessStatus, VisualScenarioEffects, captureCameraFrame, captureCameraFrameBlob, createCameraFrameCaptureSession, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, createSplatSceneConfig, createVisualScenarioExecutionContext, getContact, getScenarioBackground, getScenarioCameraPosition, getSplatEnvironmentReadiness, registerRobotResources, renderCameraFrameToCanvas, useSplatEnvironment, useSplatSceneConfig, useVisualScenarioEffects, useVisualScenarioExecutionContext, withSplatEnvironment } from './chunk-6MOK6ZWB.js';
3
3
  import loadMujoco from '@mujoco/mujoco';
4
4
  import defaultMujocoWasmUrl from '@mujoco/mujoco/mujoco.wasm?url';
5
5
  import { createContext, forwardRef, useEffect, useContext, useState, useRef, useCallback, useMemo, useLayoutEffect } from 'react';
6
6
  import { jsx, jsxs } from 'react/jsx-runtime';
7
7
  import { Canvas, useThree, useFrame } from '@react-three/fiber';
8
- import * as THREE12 from 'three';
8
+ import * as THREE11 from 'three';
9
9
  import { PivotControls } from '@react-three/drei';
10
10
 
11
11
  var MujocoContext = createContext({
@@ -105,16 +105,16 @@ function MujocoProvider({
105
105
  }
106
106
  );
107
107
  }
108
- var CapsuleGeometry = class extends THREE12.BufferGeometry {
108
+ var CapsuleGeometry = class extends THREE11.BufferGeometry {
109
109
  parameters;
110
110
  constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) {
111
111
  super();
112
112
  this.type = "CapsuleGeometry";
113
113
  this.parameters = { radius, length, capSegments, radialSegments };
114
- const path = new THREE12.Path();
114
+ const path = new THREE11.Path();
115
115
  path.absarc(0, -length / 2, radius, Math.PI * 1.5, 0, false);
116
116
  path.absarc(0, length / 2, radius, 0, Math.PI * 0.5, false);
117
- const latheGeometry = new THREE12.LatheGeometry(path.getPoints(capSegments), radialSegments);
117
+ const latheGeometry = new THREE11.LatheGeometry(path.getPoints(capSegments), radialSegments);
118
118
  const self = this;
119
119
  self.setIndex(latheGeometry.getIndex());
120
120
  self.setAttribute("position", latheGeometry.getAttribute("position"));
@@ -122,27 +122,27 @@ var CapsuleGeometry = class extends THREE12.BufferGeometry {
122
122
  self.setAttribute("uv", latheGeometry.getAttribute("uv"));
123
123
  }
124
124
  };
125
- var Reflector = class extends THREE12.Mesh {
125
+ var Reflector = class extends THREE11.Mesh {
126
126
  isReflector = true;
127
127
  camera;
128
- reflectorPlane = new THREE12.Plane();
129
- normal = new THREE12.Vector3();
130
- reflectorWorldPosition = new THREE12.Vector3();
131
- cameraWorldPosition = new THREE12.Vector3();
132
- rotationMatrix = new THREE12.Matrix4();
133
- lookAtPosition = new THREE12.Vector3(0, 0, -1);
134
- clipPlane = new THREE12.Vector4();
135
- view = new THREE12.Vector3();
136
- target = new THREE12.Vector3();
137
- q = new THREE12.Vector4();
138
- textureMatrix = new THREE12.Matrix4();
128
+ reflectorPlane = new THREE11.Plane();
129
+ normal = new THREE11.Vector3();
130
+ reflectorWorldPosition = new THREE11.Vector3();
131
+ cameraWorldPosition = new THREE11.Vector3();
132
+ rotationMatrix = new THREE11.Matrix4();
133
+ lookAtPosition = new THREE11.Vector3(0, 0, -1);
134
+ clipPlane = new THREE11.Vector4();
135
+ view = new THREE11.Vector3();
136
+ target = new THREE11.Vector3();
137
+ q = new THREE11.Vector4();
138
+ textureMatrix = new THREE11.Matrix4();
139
139
  virtualCamera;
140
140
  renderTarget;
141
141
  constructor(geometry, options = {}) {
142
142
  super(geometry);
143
143
  this.type = "Reflector";
144
- this.camera = new THREE12.PerspectiveCamera();
145
- const color = options.color !== void 0 ? new THREE12.Color(options.color) : new THREE12.Color(8355711);
144
+ this.camera = new THREE11.PerspectiveCamera();
145
+ const color = options.color !== void 0 ? new THREE11.Color(options.color) : new THREE11.Color(8355711);
146
146
  const textureWidth = options.textureWidth || 512;
147
147
  const textureHeight = options.textureHeight || 512;
148
148
  const clipBias = options.clipBias || 0;
@@ -150,11 +150,11 @@ var Reflector = class extends THREE12.Mesh {
150
150
  const blendTexture = options.texture || void 0;
151
151
  const mixStrength = options.mixStrength !== void 0 ? options.mixStrength : 0.25;
152
152
  this.virtualCamera = this.camera;
153
- this.renderTarget = new THREE12.WebGLRenderTarget(textureWidth, textureHeight, {
153
+ this.renderTarget = new THREE11.WebGLRenderTarget(textureWidth, textureHeight, {
154
154
  samples: multisample,
155
- type: THREE12.HalfFloatType
155
+ type: THREE11.HalfFloatType
156
156
  });
157
- this.material = new THREE12.MeshPhysicalMaterial({
157
+ this.material = new THREE11.MeshPhysicalMaterial({
158
158
  map: blendTexture,
159
159
  color,
160
160
  roughness: 0.5,
@@ -280,7 +280,7 @@ var GeomBuilder = class {
280
280
  const pos = mjModel.geom_pos.subarray(g * 3, g * 3 + 3);
281
281
  const quat = mjModel.geom_quat.subarray(g * 4, g * 4 + 4);
282
282
  const matId = mjModel.geom_matid[g];
283
- const color = new THREE12.Color(16777215);
283
+ const color = new THREE11.Color(16777215);
284
284
  let opacity = 1;
285
285
  if (matId >= 0) {
286
286
  const rgba = mjModel.mat_rgba.subarray(matId * 4, matId * 4 + 4);
@@ -295,16 +295,16 @@ var GeomBuilder = class {
295
295
  let geo = null;
296
296
  const getVal = (v) => v?.value ?? v;
297
297
  if (type === getVal(MG.mjGEOM_PLANE)) {
298
- geo = new THREE12.PlaneGeometry(size[0] * 2 || 5, size[1] * 2 || 5);
298
+ geo = new THREE11.PlaneGeometry(size[0] * 2 || 5, size[1] * 2 || 5);
299
299
  } else if (type === getVal(MG.mjGEOM_SPHERE)) {
300
- geo = new THREE12.SphereGeometry(size[0], 24, 24);
300
+ geo = new THREE11.SphereGeometry(size[0], 24, 24);
301
301
  } else if (type === getVal(MG.mjGEOM_CAPSULE)) {
302
302
  geo = new CapsuleGeometry(size[0], size[1] * 2, 24, 12);
303
303
  geo.rotateX(Math.PI / 2);
304
304
  } else if (type === getVal(MG.mjGEOM_BOX)) {
305
- geo = new THREE12.BoxGeometry(size[0] * 2, size[1] * 2, size[2] * 2);
305
+ geo = new THREE11.BoxGeometry(size[0] * 2, size[1] * 2, size[2] * 2);
306
306
  } else if (type === getVal(MG.mjGEOM_CYLINDER)) {
307
- geo = new THREE12.CylinderGeometry(size[0], size[0], size[1] * 2, 24);
307
+ geo = new THREE11.CylinderGeometry(size[0], size[0], size[1] * 2, 24);
308
308
  geo.rotateX(Math.PI / 2);
309
309
  } else if (type === getVal(MG.mjGEOM_MESH)) {
310
310
  const mId = mjModel.geom_dataid[g];
@@ -312,8 +312,8 @@ var GeomBuilder = class {
312
312
  const vNum = mjModel.mesh_vertnum[mId];
313
313
  const fAdr = mjModel.mesh_faceadr[mId];
314
314
  const fNum = mjModel.mesh_facenum[mId];
315
- geo = new THREE12.BufferGeometry();
316
- geo.setAttribute("position", new THREE12.Float32BufferAttribute(mjModel.mesh_vert.subarray(vAdr * 3, (vAdr + vNum) * 3), 3));
315
+ geo = new THREE11.BufferGeometry();
316
+ geo.setAttribute("position", new THREE11.Float32BufferAttribute(mjModel.mesh_vert.subarray(vAdr * 3, (vAdr + vNum) * 3), 3));
317
317
  geo.setIndex(Array.from(mjModel.mesh_face.subarray(fAdr * 3, (fAdr + fNum) * 3)));
318
318
  geo.computeVertexNormals();
319
319
  }
@@ -328,7 +328,7 @@ var GeomBuilder = class {
328
328
  mixStrength: 0.25
329
329
  });
330
330
  } else {
331
- mesh = new THREE12.Mesh(geo, new THREE12.MeshStandardMaterial({
331
+ mesh = new THREE11.Mesh(geo, new THREE11.MeshStandardMaterial({
332
332
  color,
333
333
  transparent: opacity < 1,
334
334
  opacity,
@@ -1142,7 +1142,7 @@ function SceneRenderer(props) {
1142
1142
  }
1143
1143
  const refs = [];
1144
1144
  for (let i = 0; i < model.nbody; i++) {
1145
- const bodyGroup = new THREE12.Group();
1145
+ const bodyGroup = new THREE11.Group();
1146
1146
  bodyGroup.userData.bodyID = i;
1147
1147
  const bodyName = getName(model, model.name_bodyadr[i]);
1148
1148
  if (!hiddenBodiesRef.current.has(bodyName)) {
@@ -1171,9 +1171,9 @@ function SceneRenderer(props) {
1171
1171
  const alpha = interpolation.alpha;
1172
1172
  const i3 = i * 3;
1173
1173
  ref.position.set(
1174
- THREE12.MathUtils.lerp(interpolation.previousXpos[i3], interpolation.currentXpos[i3], alpha),
1175
- THREE12.MathUtils.lerp(interpolation.previousXpos[i3 + 1], interpolation.currentXpos[i3 + 1], alpha),
1176
- THREE12.MathUtils.lerp(interpolation.previousXpos[i3 + 2], interpolation.currentXpos[i3 + 2], alpha)
1174
+ THREE11.MathUtils.lerp(interpolation.previousXpos[i3], interpolation.currentXpos[i3], alpha),
1175
+ THREE11.MathUtils.lerp(interpolation.previousXpos[i3 + 1], interpolation.currentXpos[i3 + 1], alpha),
1176
+ THREE11.MathUtils.lerp(interpolation.previousXpos[i3 + 2], interpolation.currentXpos[i3 + 2], alpha)
1177
1177
  );
1178
1178
  const i4 = i * 4;
1179
1179
  _previousQuat.set(
@@ -1228,8 +1228,8 @@ function SceneRenderer(props) {
1228
1228
  }
1229
1229
  );
1230
1230
  }
1231
- var _previousQuat = new THREE12.Quaternion();
1232
- var _currentQuat = new THREE12.Quaternion();
1231
+ var _previousQuat = new THREE11.Quaternion();
1232
+ var _currentQuat = new THREE11.Quaternion();
1233
1233
  function isTargetRef(target) {
1234
1234
  return Boolean(target && typeof target === "object" && "current" in target);
1235
1235
  }
@@ -1338,251 +1338,26 @@ function useFrameCapture(defaultOptions = {}) {
1338
1338
  reset
1339
1339
  };
1340
1340
  }
1341
- function toVector3(value, fallback) {
1342
- if (!value) return fallback.clone();
1343
- return value instanceof THREE12.Vector3 ? value.clone() : new THREE12.Vector3(value[0], value[1], value[2]);
1344
- }
1345
- function applyCameraPose(camera, options, fallbackCamera) {
1346
- camera.position.copy(toVector3(options.position, fallbackCamera.position));
1347
- camera.up.copy(toVector3(options.up, fallbackCamera.up));
1348
- if (options.quaternion) {
1349
- if (options.quaternion instanceof THREE12.Quaternion) {
1350
- camera.quaternion.copy(options.quaternion);
1351
- } else {
1352
- camera.quaternion.set(
1353
- options.quaternion[0],
1354
- options.quaternion[1],
1355
- options.quaternion[2],
1356
- options.quaternion[3]
1357
- );
1358
- }
1359
- } else if (options.lookAt) {
1360
- camera.lookAt(toVector3(options.lookAt, new THREE12.Vector3()));
1361
- } else {
1362
- camera.quaternion.copy(fallbackCamera.quaternion);
1363
- }
1364
- camera.updateMatrixWorld();
1365
- }
1366
- function createCaptureCamera(options, fallbackCamera, width, height) {
1367
- const camera = options.camera ? options.camera.clone() : fallbackCamera instanceof THREE12.PerspectiveCamera ? fallbackCamera.clone() : new THREE12.PerspectiveCamera(45, width / height, 0.01, 100);
1368
- if (camera instanceof THREE12.PerspectiveCamera) {
1369
- camera.aspect = width / height;
1370
- camera.fov = options.fov ?? camera.fov;
1371
- camera.near = options.near ?? camera.near;
1372
- camera.far = options.far ?? camera.far;
1373
- camera.updateProjectionMatrix();
1374
- }
1375
- applyCameraPose(camera, options, fallbackCamera);
1376
- return camera;
1377
- }
1378
- function getCaptureDimensions(renderer, options) {
1379
- const width = Math.max(
1380
- 1,
1381
- Math.floor(options.width ?? renderer.domElement.width)
1382
- );
1383
- const height = Math.max(
1384
- 1,
1385
- Math.floor(options.height ?? renderer.domElement.height)
1386
- );
1387
- return { width, height };
1388
- }
1389
- function prepareCaptureCamera(camera, options, fallbackCamera, width, height) {
1390
- if (options.camera) {
1391
- camera.copy(options.camera);
1392
- }
1393
- if (camera instanceof THREE12.PerspectiveCamera) {
1394
- camera.aspect = width / height;
1395
- camera.fov = options.fov ?? camera.fov;
1396
- camera.near = options.near ?? camera.near;
1397
- camera.far = options.far ?? camera.far;
1398
- camera.updateProjectionMatrix();
1399
- }
1400
- applyCameraPose(camera, options, fallbackCamera);
1401
- }
1402
- function readRenderTargetToCanvas(renderer, target, canvas, context, pixels, imageData, width, height) {
1403
- renderer.readRenderTargetPixels(target, 0, 0, width, height, pixels);
1404
- const rowBytes = width * 4;
1405
- for (let y = 0; y < height; y += 1) {
1406
- const sourceStart = (height - y - 1) * rowBytes;
1407
- const targetStart = y * rowBytes;
1408
- imageData.data.set(
1409
- pixels.subarray(sourceStart, sourceStart + rowBytes),
1410
- targetStart
1411
- );
1412
- }
1413
- context.putImageData(imageData, 0, 0);
1414
- return canvas;
1415
- }
1416
- function getCameraFrameCaptureSource(options) {
1417
- if (options.source) return options.source;
1418
- if (options.cameraName) {
1419
- return { kind: "mujoco-camera", cameraName: options.cameraName };
1420
- }
1421
- if (options.siteName) {
1422
- return { kind: "mujoco-site", siteName: options.siteName };
1423
- }
1424
- if (options.bodyName) {
1425
- return { kind: "mujoco-body", bodyName: options.bodyName };
1426
- }
1427
- if (options.camera) return { kind: "custom-camera" };
1428
- if (options.position || options.lookAt || options.quaternion) {
1429
- return { kind: "explicit-pose" };
1430
- }
1431
- return { kind: "fallback-camera" };
1432
- }
1433
- function createCameraFrameCaptureSession(renderer, scene, fallbackCamera, options = {}) {
1434
- const { width, height } = getCaptureDimensions(renderer, options);
1435
- const camera = createCaptureCamera(options, fallbackCamera, width, height);
1436
- const target = new THREE12.WebGLRenderTarget(width, height, {
1437
- format: THREE12.RGBAFormat,
1438
- type: THREE12.UnsignedByteType
1439
- });
1440
- const canvas = document.createElement("canvas");
1441
- canvas.width = width;
1442
- canvas.height = height;
1443
- const context = canvas.getContext("2d");
1444
- if (!context) {
1445
- target.dispose();
1446
- throw new Error("Unable to create a 2D canvas for camera frame capture.");
1447
- }
1448
- const drawContext = context;
1449
- const pixels = new Uint8Array(width * height * 4);
1450
- const imageData = drawContext.createImageData(width, height);
1451
- function capture(nextOptions = {}) {
1452
- const captureOptions = { ...options, ...nextOptions };
1453
- const nextDimensions = getCaptureDimensions(renderer, captureOptions);
1454
- if (nextDimensions.width !== width || nextDimensions.height !== height) {
1455
- throw new Error(
1456
- "Camera frame capture sessions require stable width and height."
1457
- );
1458
- }
1459
- prepareCaptureCamera(
1460
- camera,
1461
- captureOptions,
1462
- fallbackCamera,
1463
- width,
1464
- height
1465
- );
1466
- const previousTarget = renderer.getRenderTarget();
1467
- const previousXrEnabled = renderer.xr.enabled;
1468
- scene.updateMatrixWorld(true);
1469
- try {
1470
- renderer.xr.enabled = false;
1471
- renderer.setRenderTarget(target);
1472
- renderer.clear();
1473
- renderer.render(scene, camera);
1474
- readRenderTargetToCanvas(
1475
- renderer,
1476
- target,
1477
- canvas,
1478
- drawContext,
1479
- pixels,
1480
- imageData,
1481
- width,
1482
- height
1483
- );
1484
- return {
1485
- canvas,
1486
- camera,
1487
- width,
1488
- height,
1489
- source: getCameraFrameCaptureSource(captureOptions)
1490
- };
1491
- } finally {
1492
- renderer.setRenderTarget(previousTarget);
1493
- renderer.xr.enabled = previousXrEnabled;
1494
- }
1495
- }
1496
- return {
1497
- width,
1498
- height,
1499
- capture,
1500
- captureDataUrl(nextOptions = {}) {
1501
- const type = nextOptions.type ?? options.type ?? "image/png";
1502
- const result = capture(nextOptions);
1503
- return {
1504
- ...result,
1505
- dataUrl: result.canvas.toDataURL(
1506
- type,
1507
- nextOptions.quality ?? options.quality
1508
- ),
1509
- type
1510
- };
1511
- },
1512
- async captureBlob(nextOptions = {}) {
1513
- const type = nextOptions.type ?? options.type ?? "image/png";
1514
- const result = capture(nextOptions);
1515
- const blob = await new Promise((resolve, reject) => {
1516
- result.canvas.toBlob(
1517
- (nextBlob) => {
1518
- if (nextBlob) resolve(nextBlob);
1519
- else reject(new Error("Camera frame capture did not produce a Blob."));
1520
- },
1521
- type,
1522
- nextOptions.quality ?? options.quality
1523
- );
1524
- });
1525
- return { ...result, blob, type };
1526
- },
1527
- dispose() {
1528
- target.dispose();
1529
- }
1530
- };
1531
- }
1532
- function renderCameraFrameToCanvas(renderer, scene, fallbackCamera, options = {}) {
1533
- const session = createCameraFrameCaptureSession(
1534
- renderer,
1535
- scene,
1536
- fallbackCamera,
1537
- options
1538
- );
1539
- try {
1540
- return session.capture();
1541
- } finally {
1542
- session.dispose();
1543
- }
1544
- }
1545
- async function captureCameraFrame(renderer, scene, fallbackCamera, options = {}) {
1546
- const type = options.type ?? "image/png";
1547
- const result = renderCameraFrameToCanvas(
1548
- renderer,
1549
- scene,
1550
- fallbackCamera,
1551
- options
1552
- );
1553
- return {
1554
- ...result,
1555
- dataUrl: result.canvas.toDataURL(type, options.quality),
1556
- type
1557
- };
1558
- }
1559
- async function captureCameraFrameBlob(renderer, scene, fallbackCamera, options = {}) {
1560
- const type = options.type ?? "image/png";
1561
- const result = renderCameraFrameToCanvas(
1562
- renderer,
1563
- scene,
1564
- fallbackCamera,
1565
- options
1566
- );
1567
- const blob = await new Promise((resolve, reject) => {
1568
- result.canvas.toBlob(
1569
- (nextBlob) => {
1570
- if (nextBlob) resolve(nextBlob);
1571
- else reject(new Error("Camera frame capture did not produce a Blob."));
1572
- },
1573
- type,
1574
- options.quality
1575
- );
1576
- });
1577
- return { ...result, blob, type };
1578
- }
1579
1341
 
1580
1342
  // src/rendering/cameraFrameSource.ts
1343
+ var MountedCameraFrameSourceSuggestionMatch = {
1344
+ Direct: "direct",
1345
+ Alias: "alias",
1346
+ Normalized: "normalized",
1347
+ Prefix: "prefix",
1348
+ Suffix: "suffix",
1349
+ Contains: "contains"
1350
+ };
1581
1351
  var MountedCameraFrameSequenceReadinessStatus = {
1582
1352
  Ready: "ready",
1583
1353
  Partial: "partial",
1584
1354
  Missing: "missing"
1585
1355
  };
1356
+ var MountedCameraFrameSequenceManifestStatus = {
1357
+ Complete: "complete",
1358
+ Partial: "partial",
1359
+ Missing: "missing"
1360
+ };
1586
1361
  function getResourceName(resource) {
1587
1362
  if (!resource) return null;
1588
1363
  return typeof resource === "string" ? resource : resource.name ?? null;
@@ -1592,6 +1367,9 @@ function createNameSet(resources) {
1592
1367
  (resources ?? []).map((resource) => getResourceName(resource)).filter((name) => Boolean(name))
1593
1368
  );
1594
1369
  }
1370
+ function createResourceNames(resources) {
1371
+ return (resources ?? []).map((resource) => getResourceName(resource)).filter((name) => Boolean(name));
1372
+ }
1595
1373
  function normalizeAliasCandidates(value) {
1596
1374
  if (!value) return [];
1597
1375
  return Array.isArray(value) ? value : [value];
@@ -1599,6 +1377,24 @@ function normalizeAliasCandidates(value) {
1599
1377
  function countMountedSelectors(selector) {
1600
1378
  return Number(Boolean(selector.cameraName)) + Number(Boolean(selector.siteName)) + Number(Boolean(selector.bodyName));
1601
1379
  }
1380
+ function normalizeCameraSourceName(value) {
1381
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
1382
+ }
1383
+ function createCameraSourceKeyVariants(key) {
1384
+ const candidates = [
1385
+ key,
1386
+ key.startsWith("observation.images.") ? key.slice("observation.images.".length) : "",
1387
+ key.includes(".") ? key.split(".").at(-1) ?? "" : "",
1388
+ key.includes("/") ? key.split("/").at(-1) ?? "" : ""
1389
+ ];
1390
+ return candidates.map((candidate) => candidate.trim()).filter((candidate, index, items) => candidate && items.indexOf(candidate) === index);
1391
+ }
1392
+ function getSelectorKey(selector) {
1393
+ if (selector.cameraName) return `camera:${selector.cameraName}`;
1394
+ if (selector.siteName) return `site:${selector.siteName}`;
1395
+ if (selector.bodyName) return `body:${selector.bodyName}`;
1396
+ return null;
1397
+ }
1602
1398
  function getMountedCameraFrameCaptureSource(selector) {
1603
1399
  if (countMountedSelectors(selector) !== 1) return null;
1604
1400
  if (selector.cameraName) {
@@ -1623,10 +1419,119 @@ function getCameraFrameCaptureSourceTarget(source) {
1623
1419
  if (source.kind === "explicit-pose") return "explicit pose";
1624
1420
  return "fallback camera";
1625
1421
  }
1422
+ function createMountedCameraFrameSourceSuggestion(key, selector, resourceName, match) {
1423
+ const source = getMountedCameraFrameCaptureSource(selector);
1424
+ if (!source) return null;
1425
+ return {
1426
+ key,
1427
+ selector,
1428
+ source,
1429
+ resourceName,
1430
+ resourceKind: source.kind,
1431
+ match
1432
+ };
1433
+ }
1434
+ function addMountedCameraFrameSourceSuggestion(suggestions, seen, suggestion) {
1435
+ if (!suggestion) return;
1436
+ const selectorKey = getSelectorKey(suggestion.selector);
1437
+ if (!selectorKey || seen.has(selectorKey)) return;
1438
+ seen.add(selectorKey);
1439
+ suggestions.push(suggestion);
1440
+ }
1441
+ function getCameraFrameResourceMatch(key, resourceName) {
1442
+ if (resourceName === key) return MountedCameraFrameSourceSuggestionMatch.Direct;
1443
+ const normalizedResource = normalizeCameraSourceName(resourceName);
1444
+ if (!normalizedResource) return null;
1445
+ for (const variant of createCameraSourceKeyVariants(key)) {
1446
+ if (resourceName === variant) return MountedCameraFrameSourceSuggestionMatch.Direct;
1447
+ const normalizedKey = normalizeCameraSourceName(variant);
1448
+ if (!normalizedKey) continue;
1449
+ if (normalizedResource === normalizedKey) {
1450
+ return MountedCameraFrameSourceSuggestionMatch.Normalized;
1451
+ }
1452
+ if (normalizedResource.startsWith(`${normalizedKey}_`)) {
1453
+ return MountedCameraFrameSourceSuggestionMatch.Prefix;
1454
+ }
1455
+ if (normalizedResource.endsWith(`_${normalizedKey}`)) {
1456
+ return MountedCameraFrameSourceSuggestionMatch.Suffix;
1457
+ }
1458
+ if (normalizedResource.includes(`_${normalizedKey}_`)) {
1459
+ return MountedCameraFrameSourceSuggestionMatch.Contains;
1460
+ }
1461
+ }
1462
+ return null;
1463
+ }
1626
1464
  function isSelectorMounted(selector, cameraNames, siteNames, bodyNames) {
1627
1465
  if (countMountedSelectors(selector) !== 1) return false;
1628
1466
  return (selector.cameraName ? cameraNames.has(selector.cameraName) : false) || (selector.siteName ? siteNames.has(selector.siteName) : false) || (selector.bodyName ? bodyNames.has(selector.bodyName) : false);
1629
1467
  }
1468
+ function createMountedCameraFrameSourceSuggestions(key, options) {
1469
+ const cameraNames = createNameSet(options.cameras);
1470
+ const siteNames = createNameSet(options.sites);
1471
+ const bodyNames = createNameSet(options.bodies);
1472
+ const suggestions = [];
1473
+ const seen = /* @__PURE__ */ new Set();
1474
+ for (const selector of normalizeAliasCandidates(options.aliases?.[key])) {
1475
+ if (!isSelectorMounted(selector, cameraNames, siteNames, bodyNames)) {
1476
+ continue;
1477
+ }
1478
+ const source = getMountedCameraFrameCaptureSource(selector);
1479
+ if (!source) continue;
1480
+ addMountedCameraFrameSourceSuggestion(
1481
+ suggestions,
1482
+ seen,
1483
+ createMountedCameraFrameSourceSuggestion(
1484
+ key,
1485
+ selector,
1486
+ getCameraFrameCaptureSourceTarget(source),
1487
+ MountedCameraFrameSourceSuggestionMatch.Alias
1488
+ )
1489
+ );
1490
+ }
1491
+ for (const cameraName of createResourceNames(options.cameras)) {
1492
+ const match = getCameraFrameResourceMatch(key, cameraName);
1493
+ if (!match) continue;
1494
+ addMountedCameraFrameSourceSuggestion(
1495
+ suggestions,
1496
+ seen,
1497
+ createMountedCameraFrameSourceSuggestion(
1498
+ key,
1499
+ { cameraName },
1500
+ cameraName,
1501
+ match
1502
+ )
1503
+ );
1504
+ }
1505
+ for (const siteName of createResourceNames(options.sites)) {
1506
+ const match = getCameraFrameResourceMatch(key, siteName);
1507
+ if (!match) continue;
1508
+ addMountedCameraFrameSourceSuggestion(
1509
+ suggestions,
1510
+ seen,
1511
+ createMountedCameraFrameSourceSuggestion(
1512
+ key,
1513
+ { siteName },
1514
+ siteName,
1515
+ match
1516
+ )
1517
+ );
1518
+ }
1519
+ for (const bodyName of createResourceNames(options.bodies)) {
1520
+ const match = getCameraFrameResourceMatch(key, bodyName);
1521
+ if (!match) continue;
1522
+ addMountedCameraFrameSourceSuggestion(
1523
+ suggestions,
1524
+ seen,
1525
+ createMountedCameraFrameSourceSuggestion(
1526
+ key,
1527
+ { bodyName },
1528
+ bodyName,
1529
+ match
1530
+ )
1531
+ );
1532
+ }
1533
+ return suggestions;
1534
+ }
1630
1535
  function resolveMountedCameraFrameSource(key, options) {
1631
1536
  const cameraNames = createNameSet(options.cameras);
1632
1537
  const siteNames = createNameSet(options.sites);
@@ -1637,8 +1542,7 @@ function resolveMountedCameraFrameSource(key, options) {
1637
1542
  { bodyName: key }
1638
1543
  ];
1639
1544
  const aliasCandidates = normalizeAliasCandidates(options.aliases?.[key]);
1640
- const candidates = [...directCandidates, ...aliasCandidates];
1641
- for (const selector of candidates) {
1545
+ for (const selector of aliasCandidates) {
1642
1546
  if (!isSelectorMounted(selector, cameraNames, siteNames, bodyNames)) {
1643
1547
  continue;
1644
1548
  }
@@ -1646,6 +1550,14 @@ function resolveMountedCameraFrameSource(key, options) {
1646
1550
  if (!source) continue;
1647
1551
  return { key, selector, source };
1648
1552
  }
1553
+ const [suggestion] = createMountedCameraFrameSourceSuggestions(key, options);
1554
+ if (suggestion) {
1555
+ return {
1556
+ key,
1557
+ selector: suggestion.selector,
1558
+ source: suggestion.source
1559
+ };
1560
+ }
1649
1561
  if (options.allowAliasFallback) {
1650
1562
  for (const selector of aliasCandidates) {
1651
1563
  const source = getMountedCameraFrameCaptureSource(selector);
@@ -1653,6 +1565,14 @@ function resolveMountedCameraFrameSource(key, options) {
1653
1565
  return { key, selector, source };
1654
1566
  }
1655
1567
  }
1568
+ for (const selector of directCandidates) {
1569
+ if (!isSelectorMounted(selector, cameraNames, siteNames, bodyNames)) {
1570
+ continue;
1571
+ }
1572
+ const source = getMountedCameraFrameCaptureSource(selector);
1573
+ if (!source) continue;
1574
+ return { key, selector, source };
1575
+ }
1656
1576
  return null;
1657
1577
  }
1658
1578
  function createMountedCameraFrameSequencePlan(cameraKeys, options) {
@@ -1716,6 +1636,77 @@ function createMountedCameraFrameSequenceReadiness(plan) {
1716
1636
  message: ready ? `All ${plan.cameraKeys.length} requested camera stream${plan.cameraKeys.length === 1 ? "" : "s"} resolve to mounted MuJoCo sources.` : `Missing mounted MuJoCo source${missingKeys.length === 1 ? "" : "s"} for ${missingKeys.join(", ")}.`
1717
1637
  };
1718
1638
  }
1639
+ function normalizeFrameCount(frameCount) {
1640
+ return Number.isFinite(frameCount) && frameCount !== void 0 ? Math.max(0, Math.floor(frameCount)) : 0;
1641
+ }
1642
+ function createMountedCameraFrameSequenceManifest(result, options = {}) {
1643
+ const cameraKeys = [
1644
+ ...options.cameraKeys ?? result.readiness.cameraKeys ?? result.plan.cameraKeys ?? result.cameraKeys
1645
+ ];
1646
+ const expectedFrameCount = normalizeFrameCount(
1647
+ options.expectedFrameCount ?? result.frameCount
1648
+ );
1649
+ const recordedFrameCount = normalizeFrameCount(result.frameCount);
1650
+ const streamSummaries = {};
1651
+ const streams = [];
1652
+ let missingFrameCount = 0;
1653
+ let completeStreamCount = 0;
1654
+ let resolvedOrRecordedStreamCount = 0;
1655
+ for (const key of cameraKeys) {
1656
+ const summary = result.cameraSummaries[key];
1657
+ const readiness = result.readiness.cameras[key];
1658
+ const source = summary?.source ?? readiness?.source;
1659
+ const ready = readiness?.ready ?? Boolean(summary);
1660
+ const recorded = normalizeFrameCount(summary?.frameCount);
1661
+ const missing = Math.max(expectedFrameCount - recorded, 0);
1662
+ const complete2 = ready && missing === 0;
1663
+ const status2 = complete2 ? MountedCameraFrameSequenceManifestStatus.Complete : ready || recorded > 0 ? MountedCameraFrameSequenceManifestStatus.Partial : MountedCameraFrameSequenceManifestStatus.Missing;
1664
+ const target = source ? getCameraFrameCaptureSourceTarget(source) : readiness?.message ? void 0 : "missing MuJoCo camera";
1665
+ const message = complete2 ? `Camera stream "${key}" recorded ${recorded} of ${expectedFrameCount} frame${expectedFrameCount === 1 ? "" : "s"}.` : ready || recorded > 0 ? `Camera stream "${key}" recorded ${recorded} of ${expectedFrameCount} frame${expectedFrameCount === 1 ? "" : "s"}.` : readiness?.message ?? `Camera stream "${key}" did not record any frames.`;
1666
+ const stream = {
1667
+ key,
1668
+ ready,
1669
+ complete: complete2,
1670
+ status: status2,
1671
+ source,
1672
+ selector: readiness?.selector,
1673
+ target,
1674
+ width: summary?.width,
1675
+ height: summary?.height,
1676
+ expectedFrameCount,
1677
+ recordedFrameCount: recorded,
1678
+ missingFrameCount: missing,
1679
+ firstFrameIndex: summary?.firstFrameIndex ?? null,
1680
+ lastFrameIndex: summary?.lastFrameIndex ?? null,
1681
+ firstTimestamp: summary?.firstTimestamp ?? null,
1682
+ lastTimestamp: summary?.lastTimestamp ?? null,
1683
+ message
1684
+ };
1685
+ streamSummaries[key] = stream;
1686
+ streams.push(stream);
1687
+ missingFrameCount += missing;
1688
+ if (complete2) completeStreamCount += 1;
1689
+ if (ready || recorded > 0) resolvedOrRecordedStreamCount += 1;
1690
+ }
1691
+ const complete = result.readiness.ready && streams.length === completeStreamCount && missingFrameCount === 0;
1692
+ const status = complete ? MountedCameraFrameSequenceManifestStatus.Complete : resolvedOrRecordedStreamCount > 0 ? MountedCameraFrameSequenceManifestStatus.Partial : MountedCameraFrameSequenceManifestStatus.Missing;
1693
+ return {
1694
+ schema: "mujoco-react/mounted-camera-frame-sequence-manifest@1",
1695
+ ready: result.readiness.ready,
1696
+ complete,
1697
+ status,
1698
+ cameraKeys,
1699
+ resolvedKeys: [...result.readiness.resolvedKeys],
1700
+ missingKeys: [...result.readiness.missingKeys],
1701
+ expectedFrameCount,
1702
+ recordedFrameCount,
1703
+ missingFrameCount,
1704
+ streamSummaries,
1705
+ streams,
1706
+ readiness: result.readiness,
1707
+ message: complete ? `All ${cameraKeys.length} camera stream${cameraKeys.length === 1 ? "" : "s"} recorded ${expectedFrameCount} frame${expectedFrameCount === 1 ? "" : "s"}.` : `Mounted camera sequence coverage is ${status}.`
1708
+ };
1709
+ }
1719
1710
  function createMountedCameraFrameSequencePlanFromApi(api, cameraKeys, options = {}) {
1720
1711
  return createMountedCameraFrameSequencePlan(cameraKeys, {
1721
1712
  ...options,
@@ -1819,8 +1810,8 @@ var _applyPoint = new Float64Array(3);
1819
1810
  var _rayPnt = new Float64Array(3);
1820
1811
  var _rayVec = new Float64Array(3);
1821
1812
  var _rayGeomId = new Int32Array(1);
1822
- var _projRaycaster = new THREE12.Raycaster();
1823
- var _projNdc = new THREE12.Vector2();
1813
+ var _projRaycaster = new THREE11.Raycaster();
1814
+ var _projNdc = new THREE11.Vector2();
1824
1815
  function waitForNextAnimationFrame2() {
1825
1816
  return new Promise((resolve) => {
1826
1817
  requestAnimationFrame(() => resolve());
@@ -1836,16 +1827,16 @@ function throwIfCameraSequenceAborted(signal) {
1836
1827
  function vector3FromArray(values, offset) {
1837
1828
  return [values[offset], values[offset + 1], values[offset + 2]];
1838
1829
  }
1839
- function quaternionFromArray(values, offset) {
1830
+ function quaternionFromMujocoQuat(values, offset) {
1840
1831
  return [
1841
- values[offset],
1842
1832
  values[offset + 1],
1843
1833
  values[offset + 2],
1844
- values[offset + 3]
1834
+ values[offset + 3],
1835
+ values[offset]
1845
1836
  ];
1846
1837
  }
1847
1838
  function quaternionFromXmat(values, offset) {
1848
- const matrix = new THREE12.Matrix4();
1839
+ const matrix = new THREE11.Matrix4();
1849
1840
  matrix.set(
1850
1841
  values[offset],
1851
1842
  values[offset + 1],
@@ -1864,7 +1855,7 @@ function quaternionFromXmat(values, offset) {
1864
1855
  0,
1865
1856
  1
1866
1857
  );
1867
- const quaternion = new THREE12.Quaternion().setFromRotationMatrix(matrix);
1858
+ const quaternion = new THREE11.Quaternion().setFromRotationMatrix(matrix);
1868
1859
  return [quaternion.x, quaternion.y, quaternion.z, quaternion.w];
1869
1860
  }
1870
1861
  function omitResolvedCameraSelectors(options) {
@@ -2537,7 +2528,7 @@ function MujocoSimProvider({
2537
2528
  bodyId: model.cam_bodyid?.[i] ?? -1,
2538
2529
  fov: model.cam_fovy?.[i] ?? null,
2539
2530
  position: model.cam_pos ? vector3FromArray(model.cam_pos, posOffset) : null,
2540
- quaternion: model.cam_quat ? quaternionFromArray(model.cam_quat, quatOffset) : null
2531
+ quaternion: model.cam_quat ? quaternionFromMujocoQuat(model.cam_quat, quatOffset) : null
2541
2532
  });
2542
2533
  }
2543
2534
  return result;
@@ -2556,7 +2547,7 @@ function MujocoSimProvider({
2556
2547
  throw new Error(`MuJoCo camera "${options.cameraName}" was not found.`);
2557
2548
  }
2558
2549
  const position = data.cam_xpos ? vector3FromArray(data.cam_xpos, cameraId * 3) : model.cam_pos ? vector3FromArray(model.cam_pos, cameraId * 3) : void 0;
2559
- const quaternion = data.cam_xmat ? quaternionFromXmat(data.cam_xmat, cameraId * 9) : model.cam_quat ? quaternionFromArray(model.cam_quat, cameraId * 4) : void 0;
2550
+ const quaternion = data.cam_xmat ? quaternionFromXmat(data.cam_xmat, cameraId * 9) : model.cam_quat ? quaternionFromMujocoQuat(model.cam_quat, cameraId * 4) : void 0;
2560
2551
  if (!position || !quaternion) {
2561
2552
  throw new Error(
2562
2553
  `MuJoCo camera "${options.cameraName}" does not expose a capture pose.`
@@ -2642,7 +2633,7 @@ function MujocoSimProvider({
2642
2633
  const geomId = _rayGeomId[0];
2643
2634
  const bodyId = geomId >= 0 ? model.geom_bodyid[geomId] : -1;
2644
2635
  return {
2645
- point: new THREE12.Vector3(
2636
+ point: new THREE11.Vector3(
2646
2637
  origin.x + dir.x * dist,
2647
2638
  origin.y + dir.y * dist,
2648
2639
  origin.z + dir.z * dist
@@ -2922,7 +2913,7 @@ function MujocoSimProvider({
2922
2913
  const cameraFrames = {};
2923
2914
  for (const { key, captureOptions, mountedSource, session } of captureSessions) {
2924
2915
  const resolvedCaptureOptions = resolveCameraCaptureOptions(captureOptions);
2925
- const cameraFrame = session.captureDataUrl({
2916
+ const cameraFrame = await session.captureDataUrlAsync({
2926
2917
  ...resolvedCaptureOptions,
2927
2918
  source: mountedSource ?? resolvedCaptureOptions.source
2928
2919
  });
@@ -2948,7 +2939,7 @@ function MujocoSimProvider({
2948
2939
  }
2949
2940
  const frame = {
2950
2941
  frameIndex,
2951
- time: getTime(),
2942
+ time: data.time,
2952
2943
  cameras: cameraFrames
2953
2944
  };
2954
2945
  if (retainFrames) {
@@ -3611,7 +3602,7 @@ function solve6x6(A, b, x) {
3611
3602
  }
3612
3603
 
3613
3604
  // src/hooks/useIkController.ts
3614
- var _syncMat4 = new THREE12.Matrix4();
3605
+ var _syncMat4 = new THREE11.Matrix4();
3615
3606
  function syncGizmoToSite(data, siteId, target) {
3616
3607
  if (siteId === -1) return;
3617
3608
  const sitePos = data.site_xpos.subarray(siteId * 3, siteId * 3 + 3);
@@ -3643,7 +3634,7 @@ var useIkController = createControllerHook(
3643
3634
  const { mjModelRef, mjDataRef, mujocoRef, resetCallbacks, status } = useMujocoContext();
3644
3635
  const ikEnabledRef = useRef(false);
3645
3636
  const ikCalculatingRef = useRef(false);
3646
- const ikTargetRef = useRef(new THREE12.Group());
3637
+ const ikTargetRef = useRef(new THREE11.Group());
3647
3638
  const siteIdRef = useRef(-1);
3648
3639
  const controlGroupRef = useRef(null);
3649
3640
  const genericIkRef = useRef(new GenericIK(mujocoRef.current));
@@ -3651,10 +3642,10 @@ var useIkController = createControllerHook(
3651
3642
  const needsInitialSync = useRef(true);
3652
3643
  const gizmoAnimRef = useRef({
3653
3644
  active: false,
3654
- startPos: new THREE12.Vector3(),
3655
- endPos: new THREE12.Vector3(),
3656
- startRot: new THREE12.Quaternion(),
3657
- endRot: new THREE12.Quaternion(),
3645
+ startPos: new THREE11.Vector3(),
3646
+ endPos: new THREE11.Vector3(),
3647
+ startRot: new THREE11.Quaternion(),
3648
+ endRot: new THREE11.Quaternion(),
3658
3649
  startTime: 0,
3659
3650
  duration: 1e3
3660
3651
  });
@@ -3799,8 +3790,8 @@ var useIkController = createControllerHook(
3799
3790
  const target = ikTargetRef.current;
3800
3791
  if (!target) return;
3801
3792
  const targetPos = pos.clone();
3802
- const targetRot = new THREE12.Quaternion().setFromEuler(
3803
- new THREE12.Euler(Math.PI, 0, 0)
3793
+ const targetRot = new THREE11.Quaternion().setFromEuler(
3794
+ new THREE11.Euler(Math.PI, 0, 0)
3804
3795
  );
3805
3796
  if (duration > 0) {
3806
3797
  const ga = gizmoAnimRef.current;
@@ -3825,7 +3816,7 @@ var useIkController = createControllerHook(
3825
3816
  if (!ikCalculatingRef.current || !target) return null;
3826
3817
  return {
3827
3818
  pos: target.position.clone(),
3828
- rot: new THREE12.Euler().setFromQuaternion(target.quaternion)
3819
+ rot: new THREE11.Euler().setFromQuaternion(target.quaternion)
3829
3820
  };
3830
3821
  },
3831
3822
  []
@@ -3921,10 +3912,10 @@ function Body({
3921
3912
  if (!hasChildren) return null;
3922
3913
  return /* @__PURE__ */ jsx("group", { ref: groupRef, children });
3923
3914
  }
3924
- var _mat4 = new THREE12.Matrix4();
3925
- var _pos = new THREE12.Vector3();
3926
- var _quat = new THREE12.Quaternion();
3927
- var _scale = new THREE12.Vector3(1, 1, 1);
3915
+ var _mat4 = new THREE11.Matrix4();
3916
+ var _pos = new THREE11.Vector3();
3917
+ var _quat = new THREE11.Quaternion();
3918
+ var _scale = new THREE11.Vector3(1, 1, 1);
3928
3919
  function IkGizmo({ controller, siteName, scale = 0.18, onDrag }) {
3929
3920
  const { mjModelRef, mjDataRef, status } = useMujocoContext();
3930
3921
  const { ikTargetRef, siteIdRef, ikEnabledRef, setIkEnabled } = controller;
@@ -3976,47 +3967,54 @@ function IkGizmo({ controller, siteName, scale = 0.18, onDrag }) {
3976
3967
  }
3977
3968
  });
3978
3969
  if (status !== "ready") return null;
3979
- return /* @__PURE__ */ jsx("group", { ref: wrapperRef, children: /* @__PURE__ */ jsx(
3980
- PivotControls,
3970
+ return /* @__PURE__ */ jsx(
3971
+ "group",
3981
3972
  {
3982
- ref: pivotRef,
3983
- autoTransform: true,
3984
- scale,
3985
- fixed: false,
3986
- depthTest: false,
3987
- disableScaling: true,
3988
- onDragStart: () => {
3989
- draggingRef.current = true;
3990
- if (!onDrag) {
3991
- if (!ikEnabledRef.current) setIkEnabled(true);
3992
- }
3993
- if (controls) controls.enabled = false;
3994
- },
3995
- onDragEnd: () => {
3996
- draggingRef.current = false;
3997
- if (pivotRef.current) {
3998
- pivotRef.current.matrix.identity();
3999
- pivotRef.current.matrixWorldNeedsUpdate = true;
4000
- }
4001
- if (controls) controls.enabled = true;
4002
- },
4003
- onDrag: (_l, _dl, world) => {
4004
- world.decompose(_pos, _quat, _scale);
4005
- if (onDrag) {
4006
- onDrag({ position: _pos.clone(), quaternion: _quat.clone() });
4007
- } else {
4008
- const target = ikTargetRef.current;
4009
- if (target) {
4010
- target.position.copy(_pos);
4011
- target.quaternion.copy(_quat);
4012
- }
3973
+ ref: wrapperRef,
3974
+ userData: { [CAPTURE_EXCLUDE_KEY]: true },
3975
+ children: /* @__PURE__ */ jsx(
3976
+ PivotControls,
3977
+ {
3978
+ ref: pivotRef,
3979
+ autoTransform: true,
3980
+ scale,
3981
+ fixed: false,
3982
+ depthTest: false,
3983
+ disableScaling: true,
3984
+ onDragStart: () => {
3985
+ draggingRef.current = true;
3986
+ if (!onDrag) {
3987
+ if (!ikEnabledRef.current) setIkEnabled(true);
3988
+ }
3989
+ if (controls) controls.enabled = false;
3990
+ },
3991
+ onDragEnd: () => {
3992
+ draggingRef.current = false;
3993
+ if (pivotRef.current) {
3994
+ pivotRef.current.matrix.identity();
3995
+ pivotRef.current.matrixWorldNeedsUpdate = true;
3996
+ }
3997
+ if (controls) controls.enabled = true;
3998
+ },
3999
+ onDrag: (_l, _dl, world) => {
4000
+ world.decompose(_pos, _quat, _scale);
4001
+ if (onDrag) {
4002
+ onDrag({ position: _pos.clone(), quaternion: _quat.clone() });
4003
+ } else {
4004
+ const target = ikTargetRef.current;
4005
+ if (target) {
4006
+ target.position.copy(_pos);
4007
+ target.quaternion.copy(_quat);
4008
+ }
4009
+ }
4010
+ },
4011
+ children: /* @__PURE__ */ jsx("mesh", { visible: false, children: /* @__PURE__ */ jsx("sphereGeometry", { args: [1e-3] }) })
4013
4012
  }
4014
- },
4015
- children: /* @__PURE__ */ jsx("mesh", { visible: false, children: /* @__PURE__ */ jsx("sphereGeometry", { args: [1e-3] }) })
4013
+ )
4016
4014
  }
4017
- ) });
4015
+ );
4018
4016
  }
4019
- var _dummy = new THREE12.Object3D();
4017
+ var _dummy = new THREE11.Object3D();
4020
4018
  function ContactMarkers({
4021
4019
  maxContacts = 100,
4022
4020
  radius = 8e-3,
@@ -4052,19 +4050,29 @@ function ContactMarkers({
4052
4050
  mesh.instanceMatrix.needsUpdate = true;
4053
4051
  });
4054
4052
  if (status !== "ready") return null;
4055
- return /* @__PURE__ */ jsx("group", { ...groupProps, children: /* @__PURE__ */ jsxs("instancedMesh", { ref: meshRef, args: [void 0, void 0, maxContacts], frustumCulled: false, renderOrder: 999, children: [
4056
- /* @__PURE__ */ jsx("sphereGeometry", { args: [radius, 8, 8] }),
4057
- /* @__PURE__ */ jsx("meshBasicMaterial", { color, depthTest: false })
4058
- ] }) });
4053
+ return /* @__PURE__ */ jsx(
4054
+ "group",
4055
+ {
4056
+ ...groupProps,
4057
+ userData: {
4058
+ ...groupProps.userData,
4059
+ [CAPTURE_EXCLUDE_KEY]: true
4060
+ },
4061
+ children: /* @__PURE__ */ jsxs("instancedMesh", { ref: meshRef, args: [void 0, void 0, maxContacts], frustumCulled: false, renderOrder: 999, children: [
4062
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [radius, 8, 8] }),
4063
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color, depthTest: false })
4064
+ ] })
4065
+ }
4066
+ );
4059
4067
  }
4060
4068
  var _force = new Float64Array(3);
4061
4069
  var _torque = new Float64Array(3);
4062
4070
  var _point = new Float64Array(3);
4063
- var _bodyPos = new THREE12.Vector3();
4064
- var _bodyQuat = new THREE12.Quaternion();
4065
- var _worldHit = new THREE12.Vector3();
4066
- var _raycaster = new THREE12.Raycaster();
4067
- var _mouse = new THREE12.Vector2();
4071
+ var _bodyPos = new THREE11.Vector3();
4072
+ var _bodyQuat = new THREE11.Quaternion();
4073
+ var _worldHit = new THREE11.Vector3();
4074
+ var _raycaster = new THREE11.Raycaster();
4075
+ var _mouse = new THREE11.Vector2();
4068
4076
  function DragInteraction({
4069
4077
  stiffness = 250,
4070
4078
  showArrow = true,
@@ -4075,19 +4083,20 @@ function DragInteraction({
4075
4083
  const draggingRef = useRef(false);
4076
4084
  const bodyIdRef = useRef(-1);
4077
4085
  const grabDistanceRef = useRef(0);
4078
- const localHitRef = useRef(new THREE12.Vector3());
4079
- const grabWorldRef = useRef(new THREE12.Vector3());
4080
- const mouseWorldRef = useRef(new THREE12.Vector3());
4086
+ const localHitRef = useRef(new THREE11.Vector3());
4087
+ const grabWorldRef = useRef(new THREE11.Vector3());
4088
+ const mouseWorldRef = useRef(new THREE11.Vector3());
4081
4089
  const arrowRef = useRef(null);
4082
4090
  const groupRef = useRef(null);
4083
4091
  useEffect(() => {
4084
4092
  if (!showArrow || !groupRef.current) return;
4085
- const arrow = new THREE12.ArrowHelper(
4086
- new THREE12.Vector3(0, 1, 0),
4087
- new THREE12.Vector3(),
4093
+ const arrow = new THREE11.ArrowHelper(
4094
+ new THREE11.Vector3(0, 1, 0),
4095
+ new THREE11.Vector3(),
4088
4096
  0.1,
4089
4097
  16729156
4090
4098
  );
4099
+ arrow.userData[CAPTURE_EXCLUDE_KEY] = true;
4091
4100
  arrow.visible = false;
4092
4101
  arrow.line.material.transparent = true;
4093
4102
  arrow.line.material.opacity = 0.6;
@@ -4266,7 +4275,7 @@ function useSceneLights(intensity = 1) {
4266
4275
  const dr = lightDiffuse ? lightDiffuse[3 * i] : 1;
4267
4276
  const dg = lightDiffuse ? lightDiffuse[3 * i + 1] : 1;
4268
4277
  const db = lightDiffuse ? lightDiffuse[3 * i + 2] : 1;
4269
- const color = new THREE12.Color(dr, dg, db);
4278
+ const color = new THREE11.Color(dr, dg, db);
4270
4279
  const px = lightPos[3 * i];
4271
4280
  const py = lightPos[3 * i + 1];
4272
4281
  const pz = lightPos[3 * i + 2];
@@ -4274,7 +4283,7 @@ function useSceneLights(intensity = 1) {
4274
4283
  const dy = lightDir[3 * i + 1];
4275
4284
  const dz = lightDir[3 * i + 2];
4276
4285
  if (isDirectional) {
4277
- const light = new THREE12.DirectionalLight(color, finalIntensity);
4286
+ const light = new THREE11.DirectionalLight(color, finalIntensity);
4278
4287
  light.position.set(px, py, pz);
4279
4288
  light.target.position.set(px + dx, py + dy, pz + dz);
4280
4289
  light.castShadow = castShadow;
@@ -4297,7 +4306,7 @@ function useSceneLights(intensity = 1) {
4297
4306
  const cutoff = lightCutoff ? lightCutoff[i] : 45;
4298
4307
  const exponent = lightExponent ? lightExponent[i] : 10;
4299
4308
  const angle = cutoff * Math.PI / 180;
4300
- const light = new THREE12.SpotLight(color, finalIntensity, 0, angle, exponent / 128);
4309
+ const light = new THREE11.SpotLight(color, finalIntensity, 0, angle, exponent / 128);
4301
4310
  light.position.set(px, py, pz);
4302
4311
  light.target.position.set(px + dx, py + dy, pz + dz);
4303
4312
  light.castShadow = castShadow;
@@ -4345,6 +4354,231 @@ function SceneLights({ intensity = 1 }) {
4345
4354
  useSceneLights(intensity);
4346
4355
  return null;
4347
4356
  }
4357
+ function SplatCollisionProxyPreview({
4358
+ collisionProxy,
4359
+ xmlText,
4360
+ fetchXml = fetchSplatCollisionProxyXml,
4361
+ color = "#60a5fa",
4362
+ opacity = 0.12,
4363
+ planeColor = "#94a3b8",
4364
+ planeOpacity = 0.08,
4365
+ children,
4366
+ ...groupProps
4367
+ }) {
4368
+ const { geoms } = useSplatCollisionProxyGeoms({
4369
+ collisionProxy,
4370
+ xmlText,
4371
+ fetchXml
4372
+ });
4373
+ if (geoms.length === 0 && !children) return null;
4374
+ return /* @__PURE__ */ jsxs(
4375
+ "group",
4376
+ {
4377
+ ...groupProps,
4378
+ userData: {
4379
+ kind: "splat-collision-proxy-preview",
4380
+ ...groupProps.userData
4381
+ },
4382
+ children: [
4383
+ geoms.map((geom) => /* @__PURE__ */ jsx(
4384
+ SplatCollisionProxyGeom,
4385
+ {
4386
+ geom,
4387
+ color,
4388
+ opacity,
4389
+ planeColor,
4390
+ planeOpacity
4391
+ },
4392
+ geom.id
4393
+ )),
4394
+ children
4395
+ ]
4396
+ }
4397
+ );
4398
+ }
4399
+ function useSplatCollisionProxyGeoms({
4400
+ collisionProxy,
4401
+ xmlText,
4402
+ fetchXml = fetchSplatCollisionProxyXml,
4403
+ enabled = true
4404
+ }) {
4405
+ const [loadedXmlText, setLoadedXmlText] = useState(null);
4406
+ const [status, setStatus] = useState("idle");
4407
+ const [error, setError] = useState(null);
4408
+ const xmlPath = collisionProxy?.xmlPath;
4409
+ useEffect(() => {
4410
+ let cancelled = false;
4411
+ if (!enabled) {
4412
+ setLoadedXmlText(null);
4413
+ setStatus("idle");
4414
+ setError(null);
4415
+ return void 0;
4416
+ }
4417
+ if (xmlText) {
4418
+ setLoadedXmlText(xmlText);
4419
+ setStatus("ready");
4420
+ setError(null);
4421
+ return void 0;
4422
+ }
4423
+ if (!xmlPath || !canFetchSplatCollisionProxyXml(xmlPath)) {
4424
+ setLoadedXmlText(null);
4425
+ setStatus("idle");
4426
+ setError(null);
4427
+ return void 0;
4428
+ }
4429
+ const fetchPath = xmlPath;
4430
+ async function loadProxyXml() {
4431
+ setStatus("loading");
4432
+ setError(null);
4433
+ try {
4434
+ const nextXmlText = await fetchXml(fetchPath);
4435
+ if (!cancelled) {
4436
+ setLoadedXmlText(nextXmlText);
4437
+ setStatus("ready");
4438
+ }
4439
+ } catch (nextError) {
4440
+ if (!cancelled) {
4441
+ setLoadedXmlText(null);
4442
+ setStatus("error");
4443
+ setError(
4444
+ nextError instanceof Error ? nextError : new Error("Unable to load collision proxy XML.")
4445
+ );
4446
+ }
4447
+ }
4448
+ }
4449
+ void loadProxyXml();
4450
+ return () => {
4451
+ cancelled = true;
4452
+ };
4453
+ }, [enabled, fetchXml, xmlPath, xmlText]);
4454
+ const geoms = useMemo(
4455
+ () => loadedXmlText ? parseSplatCollisionProxyGeoms(loadedXmlText) : [],
4456
+ [loadedXmlText]
4457
+ );
4458
+ return useMemo(
4459
+ () => ({
4460
+ geoms,
4461
+ status,
4462
+ error,
4463
+ xmlPath
4464
+ }),
4465
+ [error, geoms, status, xmlPath]
4466
+ );
4467
+ }
4468
+ async function fetchSplatCollisionProxyXml(xmlPath) {
4469
+ const response = await fetch(xmlPath);
4470
+ if (!response.ok) {
4471
+ throw new Error(`Unable to load collision proxy XML (${response.status}).`);
4472
+ }
4473
+ return response.text();
4474
+ }
4475
+ function canFetchSplatCollisionProxyXml(xmlPath) {
4476
+ return xmlPath.startsWith("/") || xmlPath.startsWith("http://") || xmlPath.startsWith("https://");
4477
+ }
4478
+ function parseSplatCollisionProxyGeoms(xmlText) {
4479
+ const parser = typeof DOMParser === "undefined" ? null : new DOMParser();
4480
+ if (!parser) return [];
4481
+ const document2 = parser.parseFromString(xmlText, "application/xml");
4482
+ if (document2.querySelector("parsererror")) return [];
4483
+ const bodyPositions = /* @__PURE__ */ new Map();
4484
+ for (const body of Array.from(document2.querySelectorAll("body"))) {
4485
+ const parentBody = body.parentElement?.closest("body");
4486
+ const parentPosition = parentBody ? bodyPositions.get(parentBody) ?? [0, 0, 0] : [0, 0, 0];
4487
+ bodyPositions.set(
4488
+ body,
4489
+ addProxyVectors(parentPosition, parseProxyVector(body.getAttribute("pos")))
4490
+ );
4491
+ }
4492
+ return Array.from(document2.querySelectorAll("geom")).map((geom, index) => {
4493
+ const type = getCollisionProxyGeomType(geom);
4494
+ if (!type) return null;
4495
+ const parentBody = geom.closest("body");
4496
+ const bodyPosition = parentBody ? bodyPositions.get(parentBody) ?? [0, 0, 0] : [0, 0, 0];
4497
+ const position = addProxyVectors(
4498
+ bodyPosition,
4499
+ parseProxyVector(geom.getAttribute("pos"))
4500
+ );
4501
+ const size = parseNumberList(geom.getAttribute("size"));
4502
+ return {
4503
+ id: geom.getAttribute("name") ?? `${type}-${index}`,
4504
+ type,
4505
+ position,
4506
+ size
4507
+ };
4508
+ }).filter((geom) => Boolean(geom));
4509
+ }
4510
+ function SplatCollisionProxyGeom({
4511
+ geom,
4512
+ color,
4513
+ opacity,
4514
+ planeColor,
4515
+ planeOpacity
4516
+ }) {
4517
+ if (geom.type === "sphere") {
4518
+ return /* @__PURE__ */ jsxs("mesh", { position: geom.position, children: [
4519
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [geom.size[0] ?? 0.1, 16, 8] }),
4520
+ /* @__PURE__ */ jsx(SplatCollisionProxyMaterial, { color, opacity })
4521
+ ] });
4522
+ }
4523
+ if (geom.type === "plane") {
4524
+ const width = geom.size[0] && geom.size[0] > 0 ? geom.size[0] * 2 : 4;
4525
+ const height = geom.size[1] && geom.size[1] > 0 ? geom.size[1] * 2 : 4;
4526
+ return /* @__PURE__ */ jsxs("mesh", { position: geom.position, children: [
4527
+ /* @__PURE__ */ jsx("boxGeometry", { args: [width, height, 0.02] }),
4528
+ /* @__PURE__ */ jsx(SplatCollisionProxyMaterial, { color: planeColor, opacity: planeOpacity })
4529
+ ] });
4530
+ }
4531
+ const size = getCollisionProxyBoxSize(geom);
4532
+ return /* @__PURE__ */ jsxs("mesh", { position: geom.position, children: [
4533
+ /* @__PURE__ */ jsx("boxGeometry", { args: size }),
4534
+ /* @__PURE__ */ jsx(SplatCollisionProxyMaterial, { color, opacity })
4535
+ ] });
4536
+ }
4537
+ function SplatCollisionProxyMaterial({
4538
+ color,
4539
+ opacity
4540
+ }) {
4541
+ return /* @__PURE__ */ jsx(
4542
+ "meshBasicMaterial",
4543
+ {
4544
+ color,
4545
+ transparent: true,
4546
+ opacity,
4547
+ wireframe: true
4548
+ }
4549
+ );
4550
+ }
4551
+ function getCollisionProxyGeomType(geom) {
4552
+ const type = geom.getAttribute("type") ?? "sphere";
4553
+ if (type === "box" || type === "plane" || type === "sphere" || type === "capsule" || type === "mesh") {
4554
+ return type;
4555
+ }
4556
+ return null;
4557
+ }
4558
+ function getCollisionProxyBoxSize(geom) {
4559
+ if (geom.type === "capsule") {
4560
+ const radius = geom.size[0] ?? 0.05;
4561
+ const halfLength = geom.size[1] ?? radius;
4562
+ return [radius * 2, radius * 2, Math.max(radius * 2, halfLength * 2)];
4563
+ }
4564
+ if (geom.type === "mesh") return [0.2, 0.2, 0.2];
4565
+ return [
4566
+ (geom.size[0] ?? 0.1) * 2,
4567
+ (geom.size[1] ?? geom.size[0] ?? 0.1) * 2,
4568
+ (geom.size[2] ?? geom.size[0] ?? 0.1) * 2
4569
+ ];
4570
+ }
4571
+ function parseProxyVector(value) {
4572
+ const values = parseNumberList(value);
4573
+ return [values[0] ?? 0, values[1] ?? 0, values[2] ?? 0];
4574
+ }
4575
+ function parseNumberList(value) {
4576
+ if (!value) return [];
4577
+ return value.trim().split(/\s+/).map((part) => Number(part)).filter((part) => Number.isFinite(part));
4578
+ }
4579
+ function addProxyVectors(a, b) {
4580
+ return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
4581
+ }
4348
4582
  var JOINT_COLORS = {
4349
4583
  0: 16711680,
4350
4584
  // free - red
@@ -4355,16 +4589,20 @@ var JOINT_COLORS = {
4355
4589
  3: 16776960
4356
4590
  // hinge - yellow
4357
4591
  };
4358
- var _v3a = new THREE12.Vector3();
4359
- new THREE12.Vector3();
4360
- var _quat2 = new THREE12.Quaternion();
4361
- var _contactPos = new THREE12.Vector3();
4362
- var _contactNormal = new THREE12.Vector3();
4592
+ var _v3a = new THREE11.Vector3();
4593
+ new THREE11.Vector3();
4594
+ var _quat2 = new THREE11.Quaternion();
4595
+ var _cameraMatrix = new THREE11.Matrix4();
4596
+ var _contactPos = new THREE11.Vector3();
4597
+ var _contactNormal = new THREE11.Vector3();
4363
4598
  var MAX_CONTACT_ARROWS = 50;
4599
+ var CAMERA_DEBUG_LENGTH = 0.12;
4600
+ var CAMERA_DEBUG_FRUSTUM_DEPTH = 0.08;
4364
4601
  function Debug({
4365
4602
  showGeoms = false,
4366
4603
  showSites = false,
4367
4604
  showJoints = false,
4605
+ showCameras = false,
4368
4606
  showContacts = false,
4369
4607
  showCOM = false,
4370
4608
  showInertia = false,
@@ -4380,6 +4618,7 @@ function Debug({
4380
4618
  const geoms = [];
4381
4619
  const sites = [];
4382
4620
  const joints = [];
4621
+ const cameras = [];
4383
4622
  const comMarkers = [];
4384
4623
  if (showGeoms) {
4385
4624
  for (let i = 0; i < model.ngeom; i++) {
@@ -4388,21 +4627,21 @@ function Debug({
4388
4627
  let geometry = null;
4389
4628
  switch (type) {
4390
4629
  case 2:
4391
- geometry = new THREE12.SphereGeometry(s[3 * i], 12, 8);
4630
+ geometry = new THREE11.SphereGeometry(s[3 * i], 12, 8);
4392
4631
  break;
4393
4632
  case 3:
4394
- geometry = new THREE12.CapsuleGeometry(s[3 * i], s[3 * i + 1] * 2, 6, 8);
4633
+ geometry = new THREE11.CapsuleGeometry(s[3 * i], s[3 * i + 1] * 2, 6, 8);
4395
4634
  break;
4396
4635
  case 5:
4397
- geometry = new THREE12.CylinderGeometry(s[3 * i], s[3 * i], s[3 * i + 1] * 2, 12);
4636
+ geometry = new THREE11.CylinderGeometry(s[3 * i], s[3 * i], s[3 * i + 1] * 2, 12);
4398
4637
  break;
4399
4638
  case 6:
4400
- geometry = new THREE12.BoxGeometry(s[3 * i] * 2, s[3 * i + 1] * 2, s[3 * i + 2] * 2);
4639
+ geometry = new THREE11.BoxGeometry(s[3 * i] * 2, s[3 * i + 1] * 2, s[3 * i + 2] * 2);
4401
4640
  break;
4402
4641
  }
4403
4642
  if (geometry) {
4404
- const mat = new THREE12.MeshBasicMaterial({ color: 65280, wireframe: true, transparent: true, opacity: 0.3 });
4405
- const mesh = new THREE12.Mesh(geometry, mat);
4643
+ const mat = new THREE11.MeshBasicMaterial({ color: 65280, wireframe: true, transparent: true, opacity: 0.3 });
4644
+ const mesh = new THREE11.Mesh(geometry, mat);
4406
4645
  mesh.userData.geomId = i;
4407
4646
  mesh.userData.bodyId = model.geom_bodyid[i];
4408
4647
  geoms.push(mesh);
@@ -4425,9 +4664,9 @@ function Debug({
4425
4664
  }
4426
4665
  if (maxGeomSize > 0) radius = maxGeomSize * 0.15;
4427
4666
  }
4428
- const geometry = new THREE12.OctahedronGeometry(radius);
4429
- const mat = new THREE12.MeshBasicMaterial({ color: 16711935, depthTest: false });
4430
- const mesh = new THREE12.Mesh(geometry, mat);
4667
+ const geometry = new THREE11.OctahedronGeometry(radius);
4668
+ const mat = new THREE11.MeshBasicMaterial({ color: 16711935, depthTest: false });
4669
+ const mesh = new THREE11.Mesh(geometry, mat);
4431
4670
  mesh.renderOrder = 999;
4432
4671
  mesh.frustumCulled = false;
4433
4672
  mesh.userData.siteId = i;
@@ -4439,9 +4678,9 @@ function Debug({
4439
4678
  ctx.font = "bold 36px monospace";
4440
4679
  ctx.textAlign = "center";
4441
4680
  ctx.fillText(getName(model, model.name_siteadr[i]), 128, 42);
4442
- const tex = new THREE12.CanvasTexture(canvas);
4443
- const spriteMat = new THREE12.SpriteMaterial({ map: tex, depthTest: false, transparent: true });
4444
- const sprite = new THREE12.Sprite(spriteMat);
4681
+ const tex = new THREE11.CanvasTexture(canvas);
4682
+ const spriteMat = new THREE11.SpriteMaterial({ map: tex, depthTest: false, transparent: true });
4683
+ const sprite = new THREE11.Sprite(spriteMat);
4445
4684
  const labelScale = radius * 15;
4446
4685
  sprite.scale.set(labelScale, labelScale * 0.25, 1);
4447
4686
  sprite.position.y = radius * 2;
@@ -4464,9 +4703,9 @@ function Debug({
4464
4703
  }
4465
4704
  }
4466
4705
  const arrowLen = Math.max(maxGeomSize * 0.8, 0.05);
4467
- const arrow = new THREE12.ArrowHelper(
4468
- new THREE12.Vector3(0, 0, 1),
4469
- new THREE12.Vector3(),
4706
+ const arrow = new THREE11.ArrowHelper(
4707
+ new THREE11.Vector3(0, 0, 1),
4708
+ new THREE11.Vector3(),
4470
4709
  arrowLen,
4471
4710
  color,
4472
4711
  arrowLen * 0.25,
@@ -4474,7 +4713,7 @@ function Debug({
4474
4713
  );
4475
4714
  arrow.renderOrder = 999;
4476
4715
  arrow.frustumCulled = false;
4477
- arrow.line.material = new THREE12.LineBasicMaterial({ color, depthTest: false });
4716
+ arrow.line.material = new THREE11.LineBasicMaterial({ color, depthTest: false });
4478
4717
  arrow.cone.material.depthTest = false;
4479
4718
  arrow.line.renderOrder = 999;
4480
4719
  arrow.line.frustumCulled = false;
@@ -4487,17 +4726,88 @@ function Debug({
4487
4726
  joints.push(arrow);
4488
4727
  }
4489
4728
  }
4729
+ if (showCameras && model.ncam && model.name_camadr) {
4730
+ for (let i = 0; i < model.ncam; i++) {
4731
+ const group = new THREE11.Group();
4732
+ group.userData.cameraId = i;
4733
+ group.renderOrder = 999;
4734
+ group.frustumCulled = false;
4735
+ const marker = new THREE11.Mesh(
4736
+ new THREE11.BoxGeometry(0.014, 9e-3, 6e-3),
4737
+ new THREE11.MeshBasicMaterial({ color: 3718648, depthTest: false })
4738
+ );
4739
+ marker.renderOrder = 999;
4740
+ marker.frustumCulled = false;
4741
+ group.add(marker);
4742
+ const forward = new THREE11.ArrowHelper(
4743
+ new THREE11.Vector3(0, 0, -1),
4744
+ new THREE11.Vector3(),
4745
+ CAMERA_DEBUG_LENGTH,
4746
+ 3718648,
4747
+ CAMERA_DEBUG_LENGTH * 0.24,
4748
+ CAMERA_DEBUG_LENGTH * 0.11
4749
+ );
4750
+ forward.renderOrder = 999;
4751
+ forward.frustumCulled = false;
4752
+ forward.line.material = new THREE11.LineBasicMaterial({
4753
+ color: 3718648,
4754
+ depthTest: false
4755
+ });
4756
+ forward.cone.material.depthTest = false;
4757
+ group.add(forward);
4758
+ const frustumGeometry = new THREE11.BufferGeometry();
4759
+ frustumGeometry.setAttribute(
4760
+ "position",
4761
+ new THREE11.Float32BufferAttribute(new Float32Array(8 * 2 * 3), 3)
4762
+ );
4763
+ const frustum = new THREE11.LineSegments(
4764
+ frustumGeometry,
4765
+ new THREE11.LineBasicMaterial({
4766
+ color: 3718648,
4767
+ transparent: true,
4768
+ opacity: 0.8,
4769
+ depthTest: false
4770
+ })
4771
+ );
4772
+ frustum.renderOrder = 999;
4773
+ frustum.frustumCulled = false;
4774
+ group.userData.frustum = frustum;
4775
+ group.add(frustum);
4776
+ const canvas = document.createElement("canvas");
4777
+ canvas.width = 256;
4778
+ canvas.height = 64;
4779
+ const ctx = canvas.getContext("2d");
4780
+ ctx.fillStyle = "#38bdf8";
4781
+ ctx.font = "bold 32px monospace";
4782
+ ctx.textAlign = "center";
4783
+ ctx.fillText(getName(model, model.name_camadr[i]), 128, 42);
4784
+ const texture = new THREE11.CanvasTexture(canvas);
4785
+ const sprite = new THREE11.Sprite(
4786
+ new THREE11.SpriteMaterial({
4787
+ map: texture,
4788
+ depthTest: false,
4789
+ transparent: true
4790
+ })
4791
+ );
4792
+ sprite.position.set(0, 0.014, 0.01);
4793
+ sprite.scale.set(0.04, 0.01, 1);
4794
+ sprite.renderOrder = 999;
4795
+ group.userData.label = sprite;
4796
+ group.add(sprite);
4797
+ cameras.push(group);
4798
+ }
4799
+ }
4490
4800
  if (showCOM) {
4491
4801
  for (let i = 1; i < model.nbody; i++) {
4492
- const geometry = new THREE12.SphereGeometry(5e-3, 6, 6);
4493
- const mat = new THREE12.MeshBasicMaterial({ color: 16711680 });
4494
- const mesh = new THREE12.Mesh(geometry, mat);
4802
+ const geometry = new THREE11.SphereGeometry(5e-3, 6, 6);
4803
+ const mat = new THREE11.MeshBasicMaterial({ color: 16711680 });
4804
+ const mesh = new THREE11.Mesh(geometry, mat);
4495
4805
  mesh.userData.bodyId = i;
4496
4806
  comMarkers.push(mesh);
4497
4807
  }
4498
4808
  }
4499
- return { geoms, sites, joints, comMarkers };
4500
- }, [status, mjModelRef, showGeoms, showSites, showJoints, showCOM]);
4809
+ return { geoms, sites, joints, cameras, comMarkers };
4810
+ }, [status, mjModelRef, showGeoms, showSites, showJoints, showCameras, showCOM]);
4501
4811
  useEffect(() => {
4502
4812
  const group = groupRef.current;
4503
4813
  if (!group || !debugGeometry) return;
@@ -4505,6 +4815,7 @@ function Debug({
4505
4815
  ...debugGeometry.geoms,
4506
4816
  ...debugGeometry.sites,
4507
4817
  ...debugGeometry.joints,
4818
+ ...debugGeometry.cameras,
4508
4819
  ...debugGeometry.comMarkers
4509
4820
  ];
4510
4821
  for (const obj of allObjects) group.add(obj);
@@ -4567,6 +4878,68 @@ function Debug({
4567
4878
  arrow.setDirection(_v3a);
4568
4879
  }
4569
4880
  }
4881
+ const camXpos = data.cam_xpos;
4882
+ const camXmat = data.cam_xmat;
4883
+ if (camXpos && camXmat) {
4884
+ for (const group of debugGeometry.cameras) {
4885
+ const cameraId = group.userData.cameraId;
4886
+ const i3 = cameraId * 3;
4887
+ const i9 = cameraId * 9;
4888
+ group.position.set(
4889
+ camXpos[i3],
4890
+ camXpos[i3 + 1],
4891
+ camXpos[i3 + 2]
4892
+ );
4893
+ _cameraMatrix.set(
4894
+ camXmat[i9],
4895
+ camXmat[i9 + 1],
4896
+ camXmat[i9 + 2],
4897
+ 0,
4898
+ camXmat[i9 + 3],
4899
+ camXmat[i9 + 4],
4900
+ camXmat[i9 + 5],
4901
+ 0,
4902
+ camXmat[i9 + 6],
4903
+ camXmat[i9 + 7],
4904
+ camXmat[i9 + 8],
4905
+ 0,
4906
+ 0,
4907
+ 0,
4908
+ 0,
4909
+ 1
4910
+ );
4911
+ group.quaternion.setFromRotationMatrix(_cameraMatrix);
4912
+ const fovy = model.cam_fovy?.[cameraId] ?? 45;
4913
+ const halfHeight = Math.tan(THREE11.MathUtils.degToRad(fovy) / 2) * CAMERA_DEBUG_FRUSTUM_DEPTH;
4914
+ const halfWidth = halfHeight * 4 / 3;
4915
+ const positions = group.userData.frustum.geometry.attributes.position;
4916
+ const array = positions.array;
4917
+ const points = [
4918
+ [0, 0, 0],
4919
+ [-halfWidth, halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4920
+ [0, 0, 0],
4921
+ [halfWidth, halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4922
+ [0, 0, 0],
4923
+ [halfWidth, -halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4924
+ [0, 0, 0],
4925
+ [-halfWidth, -halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4926
+ [-halfWidth, halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4927
+ [halfWidth, halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4928
+ [halfWidth, halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4929
+ [halfWidth, -halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4930
+ [halfWidth, -halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4931
+ [-halfWidth, -halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4932
+ [-halfWidth, -halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH],
4933
+ [-halfWidth, halfHeight, -CAMERA_DEBUG_FRUSTUM_DEPTH]
4934
+ ];
4935
+ for (let i = 0; i < points.length; i += 1) {
4936
+ array[i * 3] = points[i][0];
4937
+ array[i * 3 + 1] = points[i][1];
4938
+ array[i * 3 + 2] = points[i][2];
4939
+ }
4940
+ positions.needsUpdate = true;
4941
+ }
4942
+ }
4570
4943
  for (const mesh of debugGeometry.comMarkers) {
4571
4944
  const bid = mesh.userData.bodyId;
4572
4945
  const i3 = bid * 3;
@@ -4582,9 +4955,9 @@ function Debug({
4582
4955
  contactPoolInitRef.current = true;
4583
4956
  const pool = [];
4584
4957
  for (let i = 0; i < MAX_CONTACT_ARROWS; i++) {
4585
- const arrow = new THREE12.ArrowHelper(
4586
- new THREE12.Vector3(0, 1, 0),
4587
- new THREE12.Vector3(),
4958
+ const arrow = new THREE11.ArrowHelper(
4959
+ new THREE11.Vector3(0, 1, 0),
4960
+ new THREE11.Vector3(),
4588
4961
  0.1,
4589
4962
  16729156,
4590
4963
  0.03,
@@ -4634,14 +5007,24 @@ function Debug({
4634
5007
  }
4635
5008
  });
4636
5009
  if (status !== "ready") return null;
4637
- return /* @__PURE__ */ jsxs("group", { ...groupProps, children: [
4638
- /* @__PURE__ */ jsx("group", { ref: groupRef }),
4639
- showContacts && /* @__PURE__ */ jsx("group", { ref: contactGroupRef })
4640
- ] });
5010
+ return /* @__PURE__ */ jsxs(
5011
+ "group",
5012
+ {
5013
+ ...groupProps,
5014
+ userData: {
5015
+ ...groupProps.userData,
5016
+ [CAPTURE_EXCLUDE_KEY]: true
5017
+ },
5018
+ children: [
5019
+ /* @__PURE__ */ jsx("group", { ref: groupRef }),
5020
+ showContacts && /* @__PURE__ */ jsx("group", { ref: contactGroupRef })
5021
+ ]
5022
+ }
5023
+ );
4641
5024
  }
4642
- var DEFAULT_TENDON_COLOR = new THREE12.Color(0.3, 0.3, 0.8);
5025
+ var DEFAULT_TENDON_COLOR = new THREE11.Color(0.3, 0.3, 0.8);
4643
5026
  var DEFAULT_TENDON_WIDTH = 2e-3;
4644
- new THREE12.Vector3();
5027
+ new THREE11.Vector3();
4645
5028
  function TendonRenderer(props) {
4646
5029
  const { mjModelRef, mjDataRef, status } = useMujocoContext();
4647
5030
  const groupRef = useRef(null);
@@ -4655,7 +5038,7 @@ function TendonRenderer(props) {
4655
5038
  if (!model || !data || !group) return;
4656
5039
  const ntendon = model.ntendon ?? 0;
4657
5040
  if (ntendon === 0) return;
4658
- const material = new THREE12.MeshStandardMaterial({
5041
+ const material = new THREE11.MeshStandardMaterial({
4659
5042
  color: DEFAULT_TENDON_COLOR,
4660
5043
  roughness: 0.6,
4661
5044
  metalness: 0.1
@@ -4670,11 +5053,11 @@ function TendonRenderer(props) {
4670
5053
  curves.push(null);
4671
5054
  continue;
4672
5055
  }
4673
- const points = Array.from({ length: wrapNum }, () => new THREE12.Vector3());
4674
- const curve = new THREE12.CatmullRomCurve3(points, false);
5056
+ const points = Array.from({ length: wrapNum }, () => new THREE11.Vector3());
5057
+ const curve = new THREE11.CatmullRomCurve3(points, false);
4675
5058
  const segments = Math.max(wrapNum * 2, 4);
4676
- const geometry = new THREE12.TubeGeometry(curve, segments, DEFAULT_TENDON_WIDTH, 6, false);
4677
- const mesh = new THREE12.Mesh(geometry, material);
5059
+ const geometry = new THREE11.TubeGeometry(curve, segments, DEFAULT_TENDON_WIDTH, 6, false);
5060
+ const mesh = new THREE11.Mesh(geometry, material);
4678
5061
  mesh.frustumCulled = false;
4679
5062
  group.add(mesh);
4680
5063
  meshes.push(mesh);
@@ -4729,11 +5112,11 @@ function TendonRenderer(props) {
4729
5112
  if (curve.points.length !== validCount) {
4730
5113
  curve.points.length = validCount;
4731
5114
  while (curve.points.length < validCount) {
4732
- curve.points.push(new THREE12.Vector3());
5115
+ curve.points.push(new THREE11.Vector3());
4733
5116
  }
4734
5117
  }
4735
5118
  mesh.geometry.dispose();
4736
- mesh.geometry = new THREE12.TubeGeometry(
5119
+ mesh.geometry = new THREE11.TubeGeometry(
4737
5120
  curve,
4738
5121
  Math.max(validCount * 2, 4),
4739
5122
  DEFAULT_TENDON_WIDTH,
@@ -4760,24 +5143,24 @@ function FlexRenderer(props) {
4760
5143
  const vertAdr = model.flex_vertadr[f];
4761
5144
  const vertNum = model.flex_vertnum[f];
4762
5145
  if (vertNum === 0) continue;
4763
- const geometry = new THREE12.BufferGeometry();
5146
+ const geometry = new THREE11.BufferGeometry();
4764
5147
  const positions = new Float32Array(vertNum * 3);
4765
- geometry.setAttribute("position", new THREE12.BufferAttribute(positions, 3));
5148
+ geometry.setAttribute("position", new THREE11.BufferAttribute(positions, 3));
4766
5149
  geometry.computeVertexNormals();
4767
- let color = new THREE12.Color(0.5, 0.5, 0.5);
5150
+ let color = new THREE11.Color(0.5, 0.5, 0.5);
4768
5151
  if (model.flex_rgba) {
4769
- color = new THREE12.Color(
5152
+ color = new THREE11.Color(
4770
5153
  model.flex_rgba[4 * f],
4771
5154
  model.flex_rgba[4 * f + 1],
4772
5155
  model.flex_rgba[4 * f + 2]
4773
5156
  );
4774
5157
  }
4775
- const material = new THREE12.MeshStandardMaterial({
5158
+ const material = new THREE11.MeshStandardMaterial({
4776
5159
  color,
4777
5160
  roughness: 0.7,
4778
- side: THREE12.DoubleSide
5161
+ side: THREE11.DoubleSide
4779
5162
  });
4780
- const mesh = new THREE12.Mesh(geometry, material);
5163
+ const mesh = new THREE11.Mesh(geometry, material);
4781
5164
  mesh.userData.flexId = f;
4782
5165
  mesh.userData.vertAdr = vertAdr;
4783
5166
  mesh.userData.vertNum = vertNum;
@@ -4813,7 +5196,7 @@ function FlexRenderer(props) {
4813
5196
  return /* @__PURE__ */ jsx("group", { ...props, ref: groupRef });
4814
5197
  }
4815
5198
  var GEOM_TYPE_NAMES2 = ["plane", "hfield", "sphere", "capsule", "ellipsoid", "cylinder", "box", "mesh"];
4816
- var _matrix = new THREE12.Matrix4();
5199
+ var _matrix = new THREE11.Matrix4();
4817
5200
  function getGeomInfo(model, geomId) {
4818
5201
  const size = model.geom_size.subarray(geomId * 3, geomId * 3 + 3);
4819
5202
  const type = model.geom_type[geomId];
@@ -4835,10 +5218,10 @@ function geomSignature(model, geomId) {
4835
5218
  return [type, size, mat, data, rgba].join("|");
4836
5219
  }
4837
5220
  function firstMesh(object) {
4838
- if (object instanceof THREE12.Mesh) return object;
5221
+ if (object instanceof THREE11.Mesh) return object;
4839
5222
  let mesh = null;
4840
5223
  object.traverse((child) => {
4841
- if (!mesh && child instanceof THREE12.Mesh) mesh = child;
5224
+ if (!mesh && child instanceof THREE11.Mesh) mesh = child;
4842
5225
  });
4843
5226
  return mesh;
4844
5227
  }
@@ -5267,12 +5650,12 @@ function useActuators() {
5267
5650
  return actuators;
5268
5651
  }, [status, mjModelRef]);
5269
5652
  }
5270
- var _mat42 = new THREE12.Matrix4();
5653
+ var _mat42 = new THREE11.Matrix4();
5271
5654
  function useSitePosition(siteName) {
5272
5655
  const { mjModelRef, mjDataRef, status } = useMujocoContext();
5273
5656
  const siteIdRef = useRef(-1);
5274
- const positionRef = useRef(new THREE12.Vector3());
5275
- const quaternionRef = useRef(new THREE12.Quaternion());
5657
+ const positionRef = useRef(new THREE11.Vector3());
5658
+ const quaternionRef = useRef(new THREE11.Quaternion());
5276
5659
  useEffect(() => {
5277
5660
  const model = mjModelRef.current;
5278
5661
  if (!model || status !== "ready") {
@@ -5463,10 +5846,10 @@ function useJointState(name) {
5463
5846
  function useBodyState(name) {
5464
5847
  const { mjModelRef, status } = useMujocoContext();
5465
5848
  const bodyIdRef = useRef(-1);
5466
- const position = useRef(new THREE12.Vector3());
5467
- const quaternion = useRef(new THREE12.Quaternion());
5468
- const linearVelocity = useRef(new THREE12.Vector3());
5469
- const angularVelocity = useRef(new THREE12.Vector3());
5849
+ const position = useRef(new THREE11.Vector3());
5850
+ const quaternion = useRef(new THREE11.Quaternion());
5851
+ const linearVelocity = useRef(new THREE11.Vector3());
5852
+ const angularVelocity = useRef(new THREE11.Vector3());
5470
5853
  useEffect(() => {
5471
5854
  const model = mjModelRef.current;
5472
5855
  if (!model || status !== "ready") return;
@@ -5923,22 +6306,46 @@ function useMountedCameraSequenceRecorder(defaultOptions = {}) {
5923
6306
  const mujoco = useMujoco();
5924
6307
  const [status, setStatus] = useState("idle");
5925
6308
  const [error, setError] = useState(null);
6309
+ const [plan, setPlan] = useState(null);
6310
+ const [readiness, setReadiness] = useState(null);
6311
+ const [result, setResult] = useState(
6312
+ null
6313
+ );
5926
6314
  const reset = useCallback(() => {
5927
6315
  setStatus("idle");
5928
6316
  setError(null);
6317
+ setPlan(null);
6318
+ setReadiness(null);
6319
+ setResult(null);
5929
6320
  }, []);
5930
6321
  const createPlan = useCallback(
5931
6322
  (cameraKeys, options = {}) => {
5932
6323
  if (!mujoco.api) {
5933
6324
  throw new Error("MuJoCo scene is not ready for mounted camera sequence planning.");
5934
6325
  }
5935
- return createMountedCameraFrameSequencePlanFromApi(mujoco.api, cameraKeys, {
5936
- ...defaultOptions,
5937
- ...options
5938
- });
6326
+ const nextPlan = createMountedCameraFrameSequencePlanFromApi(
6327
+ mujoco.api,
6328
+ cameraKeys,
6329
+ {
6330
+ ...defaultOptions,
6331
+ ...options
6332
+ }
6333
+ );
6334
+ setPlan(nextPlan);
6335
+ setReadiness(null);
6336
+ return nextPlan;
5939
6337
  },
5940
6338
  [defaultOptions, mujoco.api]
5941
6339
  );
6340
+ const checkReadiness = useCallback(
6341
+ (cameraKeys, options = {}) => {
6342
+ const nextPlan = createPlan(cameraKeys, options);
6343
+ const nextReadiness = createMountedCameraFrameSequenceReadiness(nextPlan);
6344
+ setReadiness(nextReadiness);
6345
+ return nextReadiness;
6346
+ },
6347
+ [createPlan]
6348
+ );
5942
6349
  const record = useCallback(
5943
6350
  async (options) => {
5944
6351
  if (!mujoco.api) {
@@ -5946,13 +6353,17 @@ function useMountedCameraSequenceRecorder(defaultOptions = {}) {
5946
6353
  }
5947
6354
  setStatus("capturing");
5948
6355
  setError(null);
6356
+ setResult(null);
5949
6357
  try {
5950
- const result = await recordMountedCameraFrameSequence(mujoco.api, {
6358
+ const nextResult = await recordMountedCameraFrameSequence(mujoco.api, {
5951
6359
  ...defaultOptions,
5952
6360
  ...options
5953
6361
  });
6362
+ setPlan(nextResult.plan);
6363
+ setReadiness(nextResult.readiness);
6364
+ setResult(nextResult);
5954
6365
  setStatus("captured");
5955
- return result;
6366
+ return nextResult;
5956
6367
  } catch (nextError) {
5957
6368
  const error2 = nextError instanceof Error ? nextError : new Error("Unable to record the requested mounted camera sequence.");
5958
6369
  setError(error2);
@@ -5965,8 +6376,12 @@ function useMountedCameraSequenceRecorder(defaultOptions = {}) {
5965
6376
  return {
5966
6377
  status,
5967
6378
  error,
6379
+ plan,
6380
+ readiness,
6381
+ result,
5968
6382
  isRecording: status === "capturing",
5969
6383
  createPlan,
6384
+ checkReadiness,
5970
6385
  record,
5971
6386
  reset
5972
6387
  };
@@ -6022,7 +6437,7 @@ function useSelectionHighlight(bodyId, options = {}) {
6022
6437
  }
6023
6438
  }
6024
6439
  prevRef.current = [];
6025
- const highlightColor = new THREE12.Color(color);
6440
+ const highlightColor = new THREE11.Color(color);
6026
6441
  for (const mesh of meshes) {
6027
6442
  const mat = mesh.material;
6028
6443
  if (mat.emissive) {
@@ -6049,15 +6464,15 @@ function useSelectionHighlight(bodyId, options = {}) {
6049
6464
  }
6050
6465
  function useCameraAnimation() {
6051
6466
  const { camera } = useThree();
6052
- const orbitTargetRef = useRef(new THREE12.Vector3(0, 0, 0));
6467
+ const orbitTargetRef = useRef(new THREE11.Vector3(0, 0, 0));
6053
6468
  const cameraAnimRef = useRef({
6054
6469
  active: false,
6055
- startPos: new THREE12.Vector3(),
6056
- endPos: new THREE12.Vector3(),
6057
- startRot: new THREE12.Quaternion(),
6058
- endRot: new THREE12.Quaternion(),
6059
- startTarget: new THREE12.Vector3(),
6060
- endTarget: new THREE12.Vector3(),
6470
+ startPos: new THREE11.Vector3(),
6471
+ endPos: new THREE11.Vector3(),
6472
+ startRot: new THREE11.Quaternion(),
6473
+ endRot: new THREE11.Quaternion(),
6474
+ startTarget: new THREE11.Vector3(),
6475
+ endTarget: new THREE11.Vector3(),
6061
6476
  startTime: 0,
6062
6477
  duration: 0,
6063
6478
  resolve: null
@@ -6129,12 +6544,6 @@ function useCameraAnimation() {
6129
6544
  *
6130
6545
  * useFrameCapture — still-frame capture for canvas-backed MuJoCo/R3F scenes.
6131
6546
  */
6132
- /**
6133
- * @license
6134
- * SPDX-License-Identifier: Apache-2.0
6135
- *
6136
- * Offscreen camera-frame capture for R3F/MuJoCo scenes.
6137
- */
6138
6547
  /**
6139
6548
  * @license
6140
6549
  * SPDX-License-Identifier: Apache-2.0
@@ -6322,6 +6731,6 @@ function useCameraAnimation() {
6322
6731
  * useCameraAnimation — composable camera animation hook.
6323
6732
  */
6324
6733
 
6325
- export { Body, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkGizmo, InstancedGeomRenderer, MountedCameraFrameSequenceReadinessStatus, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights, TendonRenderer, TrajectoryPlayer, buildObservation, captureCameraFrame, captureCameraFrameBlob, captureFrame, captureFrameBlob, createCameraFrameCaptureSession, createContiguousControlGroup, createController, createControllerHook, createMountedCameraFrameSequencePlan, createMountedCameraFrameSequencePlanFromApi, createMountedCameraFrameSequenceReadiness, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getCameraFrameCaptureSourceTarget, getControlMap, getMountedCameraFrameCaptureSource, getName, isMountedCameraFrameCaptureSource, loadScene, recordMountedCameraFrameSequence, renderCameraFrameToCanvas, resolveControlGroup, resolveMountedCameraFrameSource, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useCameraFrameCapture, useCameraSequenceRecorder, useContactEvents, useContacts, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMountedCameraSequenceRecorder, useMujoco, useMujocoWasm, useObservation, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
6734
+ export { Body, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkGizmo, InstancedGeomRenderer, MountedCameraFrameSequenceManifestStatus, MountedCameraFrameSequenceReadinessStatus, MountedCameraFrameSourceSuggestionMatch, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights, SplatCollisionProxyPreview, TendonRenderer, TrajectoryPlayer, buildObservation, canFetchSplatCollisionProxyXml, captureFrame, captureFrameBlob, createContiguousControlGroup, createController, createControllerHook, createMountedCameraFrameSequenceManifest, createMountedCameraFrameSequencePlan, createMountedCameraFrameSequencePlanFromApi, createMountedCameraFrameSequenceReadiness, createMountedCameraFrameSourceSuggestions, fetchSplatCollisionProxyXml, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getCameraFrameCaptureSourceTarget, getControlMap, getMountedCameraFrameCaptureSource, getName, isMountedCameraFrameCaptureSource, loadScene, parseSplatCollisionProxyGeoms, recordMountedCameraFrameSequence, resolveControlGroup, resolveMountedCameraFrameSource, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useCameraFrameCapture, useCameraSequenceRecorder, useContactEvents, useContacts, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMountedCameraSequenceRecorder, useMujoco, useMujocoWasm, useObservation, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useSplatCollisionProxyGeoms, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
6326
6735
  //# sourceMappingURL=index.js.map
6327
6736
  //# sourceMappingURL=index.js.map