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/README.md +155 -15
- package/dist/{chunk-T3GVZJ4F.js → chunk-6MOK6ZWB.js} +501 -33
- package/dist/chunk-6MOK6ZWB.js.map +1 -0
- package/dist/index.d.ts +129 -7
- package/dist/index.js +846 -437
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +27 -3
- package/dist/spark.js +156 -3
- package/dist/spark.js.map +1 -1
- package/dist/{types-oxbxOkAx.d.ts → types-BDB9QT6Z.d.ts} +42 -3
- package/dist/vite.js +8 -4
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ContactMarkers.tsx +8 -1
- package/src/components/Debug.tsx +154 -3
- package/src/components/DragInteraction.tsx +2 -0
- package/src/components/IkGizmo.tsx +5 -1
- package/src/components/SplatCollisionProxyPreview.tsx +350 -0
- package/src/components/VisualScenario.tsx +140 -41
- package/src/core/MujocoSimProvider.tsx +6 -6
- package/src/hooks/useMountedCameraSequenceRecorder.ts +54 -6
- package/src/index.ts +32 -0
- package/src/rendering/cameraFrameCapture.ts +259 -28
- package/src/rendering/cameraFrameSource.ts +382 -2
- package/src/spark.tsx +241 -1
- package/src/types.ts +45 -2
- package/src/vite.ts +9 -4
- package/dist/chunk-T3GVZJ4F.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useThree } from '@react-three/fiber';
|
|
2
|
-
import { useEffect, useMemo } from 'react';
|
|
3
1
|
import * as THREE from 'three';
|
|
2
|
+
import { useThree } from '@react-three/fiber';
|
|
3
|
+
import { useMemo, useEffect } from 'react';
|
|
4
4
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/types.ts
|
|
@@ -85,6 +85,393 @@ var SplatEnvironmentReadinessStatus = {
|
|
|
85
85
|
UnsupportedFormat: "unsupported-format",
|
|
86
86
|
Ready: "ready"
|
|
87
87
|
};
|
|
88
|
+
var CAMERA_FRAME_CAPTURE_RENDER_USER_DATA_KEY = "mujocoReactCameraFrameCaptureRender";
|
|
89
|
+
var CAPTURE_EXCLUDE_KEY = "mujoco.capture.exclude";
|
|
90
|
+
function toVector3(value, fallback) {
|
|
91
|
+
if (!value) return fallback.clone();
|
|
92
|
+
return value instanceof THREE.Vector3 ? value.clone() : new THREE.Vector3(value[0], value[1], value[2]);
|
|
93
|
+
}
|
|
94
|
+
function applyCameraPose(camera, options, fallbackCamera) {
|
|
95
|
+
camera.position.copy(toVector3(options.position, fallbackCamera.position));
|
|
96
|
+
camera.up.copy(toVector3(options.up, fallbackCamera.up));
|
|
97
|
+
if (options.quaternion) {
|
|
98
|
+
if (options.quaternion instanceof THREE.Quaternion) {
|
|
99
|
+
camera.quaternion.copy(options.quaternion);
|
|
100
|
+
} else {
|
|
101
|
+
camera.quaternion.set(
|
|
102
|
+
options.quaternion[0],
|
|
103
|
+
options.quaternion[1],
|
|
104
|
+
options.quaternion[2],
|
|
105
|
+
options.quaternion[3]
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
} else if (options.lookAt) {
|
|
109
|
+
camera.lookAt(toVector3(options.lookAt, new THREE.Vector3()));
|
|
110
|
+
} else {
|
|
111
|
+
camera.quaternion.copy(fallbackCamera.quaternion);
|
|
112
|
+
}
|
|
113
|
+
camera.updateMatrixWorld();
|
|
114
|
+
}
|
|
115
|
+
function createCaptureCamera(options, fallbackCamera, width, height) {
|
|
116
|
+
const camera = options.camera ? options.camera.clone() : fallbackCamera instanceof THREE.PerspectiveCamera ? fallbackCamera.clone() : new THREE.PerspectiveCamera(45, width / height, 0.01, 100);
|
|
117
|
+
if (camera instanceof THREE.PerspectiveCamera) {
|
|
118
|
+
camera.aspect = width / height;
|
|
119
|
+
camera.fov = options.fov ?? camera.fov;
|
|
120
|
+
camera.near = options.near ?? camera.near;
|
|
121
|
+
camera.far = options.far ?? camera.far;
|
|
122
|
+
camera.updateProjectionMatrix();
|
|
123
|
+
}
|
|
124
|
+
applyCameraPose(camera, options, fallbackCamera);
|
|
125
|
+
return camera;
|
|
126
|
+
}
|
|
127
|
+
function getCaptureDimensions(renderer, options) {
|
|
128
|
+
const width = Math.max(
|
|
129
|
+
1,
|
|
130
|
+
Math.floor(options.width ?? renderer.domElement.width)
|
|
131
|
+
);
|
|
132
|
+
const height = Math.max(
|
|
133
|
+
1,
|
|
134
|
+
Math.floor(options.height ?? renderer.domElement.height)
|
|
135
|
+
);
|
|
136
|
+
return { width, height };
|
|
137
|
+
}
|
|
138
|
+
function prepareCaptureCamera(camera, options, fallbackCamera, width, height) {
|
|
139
|
+
if (options.camera) {
|
|
140
|
+
camera.copy(options.camera);
|
|
141
|
+
}
|
|
142
|
+
if (camera instanceof THREE.PerspectiveCamera) {
|
|
143
|
+
camera.aspect = width / height;
|
|
144
|
+
camera.fov = options.fov ?? camera.fov;
|
|
145
|
+
camera.near = options.near ?? camera.near;
|
|
146
|
+
camera.far = options.far ?? camera.far;
|
|
147
|
+
camera.updateProjectionMatrix();
|
|
148
|
+
}
|
|
149
|
+
applyCameraPose(camera, options, fallbackCamera);
|
|
150
|
+
}
|
|
151
|
+
function readRenderTargetToCanvas(renderer, target, canvas, context, pixels, imageData, width, height, outputColorSpace) {
|
|
152
|
+
renderer.readRenderTargetPixels(target, 0, 0, width, height, pixels);
|
|
153
|
+
const rowBytes = width * 4;
|
|
154
|
+
const encodeSrgb = outputColorSpace === THREE.SRGBColorSpace;
|
|
155
|
+
for (let y = 0; y < height; y += 1) {
|
|
156
|
+
const sourceStart = (height - y - 1) * rowBytes;
|
|
157
|
+
const targetStart = y * rowBytes;
|
|
158
|
+
const row = pixels.subarray(sourceStart, sourceStart + rowBytes);
|
|
159
|
+
if (!encodeSrgb) {
|
|
160
|
+
imageData.data.set(row, targetStart);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
for (let x = 0; x < rowBytes; x += 4) {
|
|
164
|
+
const pixelOffset = targetStart + x;
|
|
165
|
+
imageData.data[pixelOffset] = linearByteToSrgbByte(row[x]);
|
|
166
|
+
imageData.data[pixelOffset + 1] = linearByteToSrgbByte(row[x + 1]);
|
|
167
|
+
imageData.data[pixelOffset + 2] = linearByteToSrgbByte(row[x + 2]);
|
|
168
|
+
imageData.data[pixelOffset + 3] = row[x + 3];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
context.putImageData(imageData, 0, 0);
|
|
172
|
+
return canvas;
|
|
173
|
+
}
|
|
174
|
+
function linearByteToSrgbByte(value) {
|
|
175
|
+
const normalized = value / 255;
|
|
176
|
+
const encoded = normalized <= 31308e-7 ? normalized * 12.92 : 1.055 * Math.pow(normalized, 1 / 2.4) - 0.055;
|
|
177
|
+
return Math.min(255, Math.max(0, Math.round(encoded * 255)));
|
|
178
|
+
}
|
|
179
|
+
function readPixelsToCanvas(pixels, context, imageData, width, height, flipY = true) {
|
|
180
|
+
const rowBytes = width * 4;
|
|
181
|
+
for (let y = 0; y < height; y += 1) {
|
|
182
|
+
const sourceY = flipY ? height - y - 1 : y;
|
|
183
|
+
const sourceStart = sourceY * rowBytes;
|
|
184
|
+
const targetStart = y * rowBytes;
|
|
185
|
+
imageData.data.set(
|
|
186
|
+
pixels.subarray(sourceStart, sourceStart + rowBytes),
|
|
187
|
+
targetStart
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
context.putImageData(imageData, 0, 0);
|
|
191
|
+
}
|
|
192
|
+
function hideExcludedCaptureObjects(scene) {
|
|
193
|
+
const hidden = [];
|
|
194
|
+
scene.traverse((object) => {
|
|
195
|
+
if (!object.visible) return;
|
|
196
|
+
if (!object.userData[CAPTURE_EXCLUDE_KEY]) return;
|
|
197
|
+
hidden.push({ object, visible: object.visible });
|
|
198
|
+
object.visible = false;
|
|
199
|
+
});
|
|
200
|
+
return hidden;
|
|
201
|
+
}
|
|
202
|
+
function restoreObjectVisibility(hidden) {
|
|
203
|
+
for (const { object, visible } of hidden) {
|
|
204
|
+
object.visible = visible;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function getCameraFrameCaptureSource(options) {
|
|
208
|
+
if (options.source) return options.source;
|
|
209
|
+
if (options.cameraName) {
|
|
210
|
+
return { kind: "mujoco-camera", cameraName: options.cameraName };
|
|
211
|
+
}
|
|
212
|
+
if (options.siteName) {
|
|
213
|
+
return { kind: "mujoco-site", siteName: options.siteName };
|
|
214
|
+
}
|
|
215
|
+
if (options.bodyName) {
|
|
216
|
+
return { kind: "mujoco-body", bodyName: options.bodyName };
|
|
217
|
+
}
|
|
218
|
+
if (options.camera) return { kind: "custom-camera" };
|
|
219
|
+
if (options.position || options.lookAt || options.quaternion) {
|
|
220
|
+
return { kind: "explicit-pose" };
|
|
221
|
+
}
|
|
222
|
+
return { kind: "fallback-camera" };
|
|
223
|
+
}
|
|
224
|
+
function saveRendererState(renderer) {
|
|
225
|
+
const viewport = new THREE.Vector4();
|
|
226
|
+
const scissor = new THREE.Vector4();
|
|
227
|
+
const clearColor = new THREE.Color();
|
|
228
|
+
renderer.getViewport(viewport);
|
|
229
|
+
renderer.getScissor(scissor);
|
|
230
|
+
renderer.getClearColor(clearColor);
|
|
231
|
+
return {
|
|
232
|
+
target: renderer.getRenderTarget(),
|
|
233
|
+
xrEnabled: renderer.xr.enabled,
|
|
234
|
+
viewport,
|
|
235
|
+
scissor,
|
|
236
|
+
scissorTest: renderer.getScissorTest(),
|
|
237
|
+
clearColor,
|
|
238
|
+
clearAlpha: renderer.getClearAlpha(),
|
|
239
|
+
autoClear: renderer.autoClear
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function restoreRendererState(renderer, state) {
|
|
243
|
+
renderer.setRenderTarget(state.target);
|
|
244
|
+
renderer.xr.enabled = state.xrEnabled;
|
|
245
|
+
renderer.setViewport(state.viewport);
|
|
246
|
+
renderer.setScissor(state.scissor);
|
|
247
|
+
renderer.setScissorTest(state.scissorTest);
|
|
248
|
+
renderer.setClearColor(state.clearColor, state.clearAlpha);
|
|
249
|
+
renderer.autoClear = state.autoClear;
|
|
250
|
+
}
|
|
251
|
+
function getCaptureRenderer(scene) {
|
|
252
|
+
const renderers = [];
|
|
253
|
+
scene.traverse((object) => {
|
|
254
|
+
if (renderers.length) return;
|
|
255
|
+
const render = object.userData[CAMERA_FRAME_CAPTURE_RENDER_USER_DATA_KEY];
|
|
256
|
+
if (typeof render === "function") renderers.push(render);
|
|
257
|
+
});
|
|
258
|
+
return renderers[0] ?? null;
|
|
259
|
+
}
|
|
260
|
+
function createCameraFrameCaptureSession(renderer, scene, fallbackCamera, options = {}) {
|
|
261
|
+
const { width, height } = getCaptureDimensions(renderer, options);
|
|
262
|
+
const camera = createCaptureCamera(options, fallbackCamera, width, height);
|
|
263
|
+
const target = new THREE.WebGLRenderTarget(width, height, {
|
|
264
|
+
format: THREE.RGBAFormat,
|
|
265
|
+
type: THREE.UnsignedByteType
|
|
266
|
+
});
|
|
267
|
+
const canvas = document.createElement("canvas");
|
|
268
|
+
canvas.width = width;
|
|
269
|
+
canvas.height = height;
|
|
270
|
+
const context = canvas.getContext("2d");
|
|
271
|
+
if (!context) {
|
|
272
|
+
target.dispose();
|
|
273
|
+
throw new Error("Unable to create a 2D canvas for camera frame capture.");
|
|
274
|
+
}
|
|
275
|
+
const drawContext = context;
|
|
276
|
+
const pixels = new Uint8Array(width * height * 4);
|
|
277
|
+
const imageData = drawContext.createImageData(width, height);
|
|
278
|
+
function resolveCaptureOptions(nextOptions = {}) {
|
|
279
|
+
const captureOptions = { ...options, ...nextOptions };
|
|
280
|
+
const nextDimensions = getCaptureDimensions(renderer, captureOptions);
|
|
281
|
+
if (nextDimensions.width !== width || nextDimensions.height !== height) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
"Camera frame capture sessions require stable width and height."
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
prepareCaptureCamera(
|
|
287
|
+
camera,
|
|
288
|
+
captureOptions,
|
|
289
|
+
fallbackCamera,
|
|
290
|
+
width,
|
|
291
|
+
height
|
|
292
|
+
);
|
|
293
|
+
return captureOptions;
|
|
294
|
+
}
|
|
295
|
+
function renderPreparedCapture(captureOptions) {
|
|
296
|
+
const previousState = saveRendererState(renderer);
|
|
297
|
+
const hidden = hideExcludedCaptureObjects(scene);
|
|
298
|
+
scene.updateMatrixWorld(true);
|
|
299
|
+
try {
|
|
300
|
+
renderer.xr.enabled = false;
|
|
301
|
+
renderer.setRenderTarget(target);
|
|
302
|
+
renderer.setViewport(0, 0, width, height);
|
|
303
|
+
renderer.setScissor(0, 0, width, height);
|
|
304
|
+
renderer.setScissorTest(false);
|
|
305
|
+
renderer.clear();
|
|
306
|
+
renderer.render(scene, camera);
|
|
307
|
+
readRenderTargetToCanvas(
|
|
308
|
+
renderer,
|
|
309
|
+
target,
|
|
310
|
+
canvas,
|
|
311
|
+
drawContext,
|
|
312
|
+
pixels,
|
|
313
|
+
imageData,
|
|
314
|
+
width,
|
|
315
|
+
height,
|
|
316
|
+
renderer.outputColorSpace
|
|
317
|
+
);
|
|
318
|
+
return {
|
|
319
|
+
canvas,
|
|
320
|
+
camera,
|
|
321
|
+
width,
|
|
322
|
+
height,
|
|
323
|
+
source: getCameraFrameCaptureSource(captureOptions)
|
|
324
|
+
};
|
|
325
|
+
} finally {
|
|
326
|
+
restoreObjectVisibility(hidden);
|
|
327
|
+
restoreRendererState(renderer, previousState);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function capture(nextOptions = {}) {
|
|
331
|
+
return renderPreparedCapture(resolveCaptureOptions(nextOptions));
|
|
332
|
+
}
|
|
333
|
+
async function captureAsync(nextOptions = {}) {
|
|
334
|
+
const captureOptions = resolveCaptureOptions(nextOptions);
|
|
335
|
+
scene.updateMatrixWorld(true);
|
|
336
|
+
const captureRenderer = getCaptureRenderer(scene);
|
|
337
|
+
if (captureRenderer) {
|
|
338
|
+
const previousState = saveRendererState(renderer);
|
|
339
|
+
const hidden = hideExcludedCaptureObjects(scene);
|
|
340
|
+
try {
|
|
341
|
+
renderer.xr.enabled = false;
|
|
342
|
+
const captureResult = await captureRenderer({
|
|
343
|
+
renderer,
|
|
344
|
+
scene,
|
|
345
|
+
camera,
|
|
346
|
+
target,
|
|
347
|
+
width,
|
|
348
|
+
height
|
|
349
|
+
});
|
|
350
|
+
if (captureResult) {
|
|
351
|
+
const captureWidth = captureResult.width ?? width;
|
|
352
|
+
const captureHeight = captureResult.height ?? height;
|
|
353
|
+
if (captureWidth !== width || captureHeight !== height) {
|
|
354
|
+
throw new Error(
|
|
355
|
+
"Camera frame capture renderer returned unexpected dimensions."
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
readPixelsToCanvas(
|
|
359
|
+
captureResult.pixels,
|
|
360
|
+
drawContext,
|
|
361
|
+
imageData,
|
|
362
|
+
width,
|
|
363
|
+
height,
|
|
364
|
+
captureResult.flipY ?? true
|
|
365
|
+
);
|
|
366
|
+
return {
|
|
367
|
+
canvas,
|
|
368
|
+
camera,
|
|
369
|
+
width,
|
|
370
|
+
height,
|
|
371
|
+
source: getCameraFrameCaptureSource(captureOptions)
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
} finally {
|
|
375
|
+
restoreObjectVisibility(hidden);
|
|
376
|
+
restoreRendererState(renderer, previousState);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return renderPreparedCapture(captureOptions);
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
width,
|
|
383
|
+
height,
|
|
384
|
+
capture,
|
|
385
|
+
captureAsync,
|
|
386
|
+
captureDataUrl(nextOptions = {}) {
|
|
387
|
+
const type = nextOptions.type ?? options.type ?? "image/png";
|
|
388
|
+
const result = capture(nextOptions);
|
|
389
|
+
return {
|
|
390
|
+
...result,
|
|
391
|
+
dataUrl: result.canvas.toDataURL(
|
|
392
|
+
type,
|
|
393
|
+
nextOptions.quality ?? options.quality
|
|
394
|
+
),
|
|
395
|
+
type
|
|
396
|
+
};
|
|
397
|
+
},
|
|
398
|
+
async captureDataUrlAsync(nextOptions = {}) {
|
|
399
|
+
const type = nextOptions.type ?? options.type ?? "image/png";
|
|
400
|
+
const result = await captureAsync(nextOptions);
|
|
401
|
+
return {
|
|
402
|
+
...result,
|
|
403
|
+
dataUrl: result.canvas.toDataURL(
|
|
404
|
+
type,
|
|
405
|
+
nextOptions.quality ?? options.quality
|
|
406
|
+
),
|
|
407
|
+
type
|
|
408
|
+
};
|
|
409
|
+
},
|
|
410
|
+
async captureBlob(nextOptions = {}) {
|
|
411
|
+
const type = nextOptions.type ?? options.type ?? "image/png";
|
|
412
|
+
const result = await captureAsync(nextOptions);
|
|
413
|
+
const blob = await new Promise((resolve, reject) => {
|
|
414
|
+
result.canvas.toBlob(
|
|
415
|
+
(nextBlob) => {
|
|
416
|
+
if (nextBlob) resolve(nextBlob);
|
|
417
|
+
else reject(new Error("Camera frame capture did not produce a Blob."));
|
|
418
|
+
},
|
|
419
|
+
type,
|
|
420
|
+
nextOptions.quality ?? options.quality
|
|
421
|
+
);
|
|
422
|
+
});
|
|
423
|
+
return { ...result, blob, type };
|
|
424
|
+
},
|
|
425
|
+
dispose() {
|
|
426
|
+
target.dispose();
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function renderCameraFrameToCanvas(renderer, scene, fallbackCamera, options = {}) {
|
|
431
|
+
const session = createCameraFrameCaptureSession(
|
|
432
|
+
renderer,
|
|
433
|
+
scene,
|
|
434
|
+
fallbackCamera,
|
|
435
|
+
options
|
|
436
|
+
);
|
|
437
|
+
try {
|
|
438
|
+
return session.capture();
|
|
439
|
+
} finally {
|
|
440
|
+
session.dispose();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async function captureCameraFrame(renderer, scene, fallbackCamera, options = {}) {
|
|
444
|
+
const type = options.type ?? "image/png";
|
|
445
|
+
const session = createCameraFrameCaptureSession(
|
|
446
|
+
renderer,
|
|
447
|
+
scene,
|
|
448
|
+
fallbackCamera,
|
|
449
|
+
options
|
|
450
|
+
);
|
|
451
|
+
try {
|
|
452
|
+
const result = await session.captureAsync();
|
|
453
|
+
return {
|
|
454
|
+
...result,
|
|
455
|
+
dataUrl: result.canvas.toDataURL(type, options.quality),
|
|
456
|
+
type
|
|
457
|
+
};
|
|
458
|
+
} finally {
|
|
459
|
+
session.dispose();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async function captureCameraFrameBlob(renderer, scene, fallbackCamera, options = {}) {
|
|
463
|
+
const session = createCameraFrameCaptureSession(
|
|
464
|
+
renderer,
|
|
465
|
+
scene,
|
|
466
|
+
fallbackCamera,
|
|
467
|
+
options
|
|
468
|
+
);
|
|
469
|
+
try {
|
|
470
|
+
return await session.captureBlob();
|
|
471
|
+
} finally {
|
|
472
|
+
session.dispose();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
88
475
|
var DEFAULT_BACKGROUND = "#181a1f";
|
|
89
476
|
function ScenarioLighting({
|
|
90
477
|
preset = "studio",
|
|
@@ -160,6 +547,75 @@ function getScenarioCameraPosition(basePosition, scenario) {
|
|
|
160
547
|
Number((z + jitter * 0.25).toFixed(3))
|
|
161
548
|
];
|
|
162
549
|
}
|
|
550
|
+
function useVisualScenarioExecutionContext({
|
|
551
|
+
scenario,
|
|
552
|
+
environment,
|
|
553
|
+
renderer,
|
|
554
|
+
variantId,
|
|
555
|
+
enabled
|
|
556
|
+
}) {
|
|
557
|
+
return useMemo(
|
|
558
|
+
() => createVisualScenarioExecutionContext({
|
|
559
|
+
scenario,
|
|
560
|
+
environment,
|
|
561
|
+
renderer,
|
|
562
|
+
variantId,
|
|
563
|
+
enabled
|
|
564
|
+
}),
|
|
565
|
+
[enabled, environment, renderer, scenario, variantId]
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
function createVisualScenarioExecutionContext({
|
|
569
|
+
scenario,
|
|
570
|
+
environment,
|
|
571
|
+
renderer,
|
|
572
|
+
variantId,
|
|
573
|
+
enabled = true
|
|
574
|
+
}) {
|
|
575
|
+
const pairedEnvironment = environment ?? (scenario ? createPairedSplatEnvironment(scenario, { renderer }) : void 0);
|
|
576
|
+
const splat = scenario?.splat;
|
|
577
|
+
const collisionProxy = pairedEnvironment?.collisionProxy ?? splat?.collisionProxy ?? void 0;
|
|
578
|
+
const readiness = getSplatEnvironmentReadiness({
|
|
579
|
+
environment: pairedEnvironment,
|
|
580
|
+
scenario,
|
|
581
|
+
renderer,
|
|
582
|
+
enabled
|
|
583
|
+
});
|
|
584
|
+
const format = pairedEnvironment?.splat.format ?? splat?.format ?? readiness.format ?? "spz";
|
|
585
|
+
return {
|
|
586
|
+
scenarioId: scenario?.id ?? pairedEnvironment?.id ?? "visual-scenario",
|
|
587
|
+
scenarioLabel: scenario?.label ?? pairedEnvironment?.label ?? "Visual scenario",
|
|
588
|
+
variantId,
|
|
589
|
+
seed: scenario?.seed ?? 0,
|
|
590
|
+
lighting: scenario?.lighting ?? "studio",
|
|
591
|
+
environment: scenario?.environment,
|
|
592
|
+
camera: {
|
|
593
|
+
jitter: scenario?.camera?.jitter ?? 0,
|
|
594
|
+
exposure: scenario?.camera?.exposure ?? 1,
|
|
595
|
+
noise: scenario?.camera?.noise ?? 0,
|
|
596
|
+
blur: scenario?.camera?.blur ?? 0
|
|
597
|
+
},
|
|
598
|
+
materials: {
|
|
599
|
+
randomizeObjectColors: Boolean(
|
|
600
|
+
scenario?.materials?.randomizeObjectColors
|
|
601
|
+
),
|
|
602
|
+
randomizeTableMaterial: Boolean(
|
|
603
|
+
scenario?.materials?.randomizeTableMaterial
|
|
604
|
+
),
|
|
605
|
+
roughness: scenario?.materials?.roughness,
|
|
606
|
+
metalness: scenario?.materials?.metalness
|
|
607
|
+
},
|
|
608
|
+
splatEnabled: Boolean(splat?.enabled || pairedEnvironment),
|
|
609
|
+
splatSrc: pairedEnvironment?.splat.src ?? splat?.src,
|
|
610
|
+
splatFormat: format,
|
|
611
|
+
splatRenderer: renderer ?? pairedEnvironment?.splat.renderer,
|
|
612
|
+
collisionProxyXmlPath: collisionProxy?.xmlPath,
|
|
613
|
+
collisionProxyStatus: collisionProxy?.status,
|
|
614
|
+
collisionProxyPrimitives: collisionProxy?.primitives ?? [],
|
|
615
|
+
readiness,
|
|
616
|
+
transformSource: "visualScenario.camera"
|
|
617
|
+
};
|
|
618
|
+
}
|
|
163
619
|
function VisualScenarioEffects(props) {
|
|
164
620
|
useVisualScenarioEffects(props);
|
|
165
621
|
return null;
|
|
@@ -335,33 +791,39 @@ function useSplatSceneConfig({
|
|
|
335
791
|
enabled = true,
|
|
336
792
|
renderer
|
|
337
793
|
}) {
|
|
338
|
-
const resolvedEnvironment = useMemo(
|
|
339
|
-
() => enabled ? environment ?? (scenario ? createPairedSplatEnvironment(scenario, { renderer }) : void 0) : void 0,
|
|
340
|
-
[enabled, environment, renderer, scenario]
|
|
341
|
-
);
|
|
342
|
-
const readiness = useMemo(
|
|
343
|
-
() => getSplatEnvironmentReadiness({
|
|
344
|
-
environment: resolvedEnvironment,
|
|
345
|
-
scenario,
|
|
346
|
-
renderer,
|
|
347
|
-
enabled
|
|
348
|
-
}),
|
|
349
|
-
[enabled, renderer, resolvedEnvironment, scenario]
|
|
350
|
-
);
|
|
351
|
-
const resolvedSceneConfig = useMemo(
|
|
352
|
-
() => resolvedEnvironment ? withSplatEnvironment(sceneConfig, resolvedEnvironment) : sceneConfig,
|
|
353
|
-
[resolvedEnvironment, sceneConfig]
|
|
354
|
-
);
|
|
355
794
|
return useMemo(
|
|
356
|
-
() => ({
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
795
|
+
() => createSplatSceneConfig({
|
|
796
|
+
sceneConfig,
|
|
797
|
+
scenario,
|
|
798
|
+
environment,
|
|
799
|
+
enabled,
|
|
800
|
+
renderer
|
|
361
801
|
}),
|
|
362
|
-
[enabled,
|
|
802
|
+
[enabled, environment, renderer, scenario, sceneConfig]
|
|
363
803
|
);
|
|
364
804
|
}
|
|
805
|
+
function createSplatSceneConfig({
|
|
806
|
+
sceneConfig,
|
|
807
|
+
scenario,
|
|
808
|
+
environment,
|
|
809
|
+
enabled = true,
|
|
810
|
+
renderer
|
|
811
|
+
}) {
|
|
812
|
+
const resolvedEnvironment = enabled ? environment ?? (scenario ? createPairedSplatEnvironment(scenario, { renderer }) : void 0) : void 0;
|
|
813
|
+
const readiness = getSplatEnvironmentReadiness({
|
|
814
|
+
environment: resolvedEnvironment,
|
|
815
|
+
scenario,
|
|
816
|
+
renderer,
|
|
817
|
+
enabled
|
|
818
|
+
});
|
|
819
|
+
const resolvedSceneConfig = resolvedEnvironment ? withSplatEnvironment(sceneConfig, resolvedEnvironment, { renderer }) : sceneConfig;
|
|
820
|
+
return {
|
|
821
|
+
environment: resolvedEnvironment,
|
|
822
|
+
sceneConfig: resolvedSceneConfig,
|
|
823
|
+
enabled: enabled && readiness.status !== SplatEnvironmentReadinessStatus.Disabled,
|
|
824
|
+
readiness
|
|
825
|
+
};
|
|
826
|
+
}
|
|
365
827
|
function getSplatEnvironmentReadiness({
|
|
366
828
|
environment,
|
|
367
829
|
scenario,
|
|
@@ -434,7 +896,7 @@ function getSplatEnvironmentReadiness({
|
|
|
434
896
|
function createPairedSplatEnvironment(scenario, options = {}) {
|
|
435
897
|
const splat = scenario.splat;
|
|
436
898
|
const collisionProxy = splat?.collisionProxy;
|
|
437
|
-
if (!splat?.enabled || !splat.src
|
|
899
|
+
if (!splat?.enabled || !splat.src) {
|
|
438
900
|
return void 0;
|
|
439
901
|
}
|
|
440
902
|
return {
|
|
@@ -446,14 +908,14 @@ function createPairedSplatEnvironment(scenario, options = {}) {
|
|
|
446
908
|
format: splat.format ?? "spz",
|
|
447
909
|
renderer: options.renderer
|
|
448
910
|
},
|
|
449
|
-
collisionProxy: {
|
|
911
|
+
collisionProxy: collisionProxy?.xmlPath ? {
|
|
450
912
|
...collisionProxy,
|
|
451
913
|
xmlPath: collisionProxy.xmlPath
|
|
452
|
-
}
|
|
914
|
+
} : void 0
|
|
453
915
|
};
|
|
454
916
|
}
|
|
455
917
|
function isPairedSplatEnvironment(input) {
|
|
456
|
-
return !!input && "
|
|
918
|
+
return !!input && "splat" in input && !!input.splat && !("enabled" in input.splat);
|
|
457
919
|
}
|
|
458
920
|
function sceneRelativePath(sceneConfig, path) {
|
|
459
921
|
const src = sceneConfig.src;
|
|
@@ -474,7 +936,7 @@ function uniquePaths(paths) {
|
|
|
474
936
|
}
|
|
475
937
|
function withSplatEnvironment(sceneConfig, input, options = {}) {
|
|
476
938
|
const environment = isPairedSplatEnvironment(input) ? input : input ? createPairedSplatEnvironment(input, options) : void 0;
|
|
477
|
-
const xmlPath = environment?.collisionProxy
|
|
939
|
+
const xmlPath = environment?.collisionProxy?.xmlPath;
|
|
478
940
|
if (!xmlPath) return sceneConfig;
|
|
479
941
|
return {
|
|
480
942
|
...sceneConfig,
|
|
@@ -608,7 +1070,13 @@ function clamp01(value) {
|
|
|
608
1070
|
* @license
|
|
609
1071
|
* SPDX-License-Identifier: Apache-2.0
|
|
610
1072
|
*/
|
|
1073
|
+
/**
|
|
1074
|
+
* @license
|
|
1075
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
1076
|
+
*
|
|
1077
|
+
* Offscreen camera-frame capture for R3F/MuJoCo scenes.
|
|
1078
|
+
*/
|
|
611
1079
|
|
|
612
|
-
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, withContacts, withSplatEnvironment };
|
|
613
|
-
//# sourceMappingURL=chunk-
|
|
614
|
-
//# sourceMappingURL=chunk-
|
|
1080
|
+
export { CAMERA_FRAME_CAPTURE_RENDER_USER_DATA_KEY, 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, withContacts, withSplatEnvironment };
|
|
1081
|
+
//# sourceMappingURL=chunk-6MOK6ZWB.js.map
|
|
1082
|
+
//# sourceMappingURL=chunk-6MOK6ZWB.js.map
|