mujoco-react 10.2.1 → 10.4.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 +23 -1
- package/dist/{chunk-CYDGWNKQ.js → chunk-FBXXXPLQ.js} +169 -22
- package/dist/chunk-FBXXXPLQ.js.map +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +345 -40
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +1 -1
- package/dist/spark.js +4 -10
- package/dist/spark.js.map +1 -1
- package/dist/{types-B-J8fpPP.d.ts → types-CdFZCYmy.d.ts} +115 -1
- package/package.json +1 -1
- package/src/components/Debug.tsx +174 -3
- package/src/components/SceneRenderer.tsx +25 -6
- package/src/core/MujocoCanvas.tsx +8 -4
- package/src/core/MujocoPhysics.tsx +6 -4
- package/src/core/MujocoProvider.tsx +6 -4
- package/src/core/MujocoSimProvider.tsx +189 -9
- package/src/index.ts +1 -0
- package/src/rendering/GeomBuilder.ts +18 -2
- package/src/rendering/cameraFrameCapture.ts +229 -19
- package/src/spark.tsx +4 -12
- package/src/types.ts +121 -0
- package/dist/chunk-CYDGWNKQ.js.map +0 -1
|
@@ -80,6 +80,15 @@ type RendererState = {
|
|
|
80
80
|
clearColor: THREE.Color;
|
|
81
81
|
clearAlpha: number;
|
|
82
82
|
autoClear: boolean;
|
|
83
|
+
shadowMapEnabled: boolean;
|
|
84
|
+
toneMapping: THREE.WebGLRenderer['toneMapping'];
|
|
85
|
+
outputColorSpace: THREE.WebGLRenderer['outputColorSpace'];
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
type SceneVisualState = {
|
|
89
|
+
background: THREE.Scene['background'];
|
|
90
|
+
environment: THREE.Scene['environment'];
|
|
91
|
+
fog: THREE.Scene['fog'];
|
|
83
92
|
};
|
|
84
93
|
|
|
85
94
|
type VisibilityState = {
|
|
@@ -89,6 +98,107 @@ type VisibilityState = {
|
|
|
89
98
|
|
|
90
99
|
type CameraFrameCapturePreRender = () => void;
|
|
91
100
|
|
|
101
|
+
const isolatedRendererCache = new WeakMap<
|
|
102
|
+
THREE.WebGLRenderer,
|
|
103
|
+
Map<string, THREE.WebGLRenderer>
|
|
104
|
+
>();
|
|
105
|
+
|
|
106
|
+
function shouldUseRenderIsolation(
|
|
107
|
+
options: CameraFrameCaptureOptions
|
|
108
|
+
): boolean {
|
|
109
|
+
return options.renderIsolation === true || (
|
|
110
|
+
typeof options.renderIsolation === 'object' &&
|
|
111
|
+
options.renderIsolation.enabled !== false
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function getRenderIsolationOptions(
|
|
116
|
+
options: CameraFrameCaptureOptions
|
|
117
|
+
) {
|
|
118
|
+
return typeof options.renderIsolation === 'object'
|
|
119
|
+
? options.renderIsolation
|
|
120
|
+
: {};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function getRenderIsolationCacheKey(
|
|
124
|
+
width: number,
|
|
125
|
+
height: number,
|
|
126
|
+
options: CameraFrameCaptureOptions
|
|
127
|
+
) {
|
|
128
|
+
const isolation = getRenderIsolationOptions(options);
|
|
129
|
+
return JSON.stringify({
|
|
130
|
+
width,
|
|
131
|
+
height,
|
|
132
|
+
antialias: isolation.antialias ?? false,
|
|
133
|
+
alpha: isolation.alpha ?? false,
|
|
134
|
+
preserveDrawingBuffer: isolation.preserveDrawingBuffer ?? false,
|
|
135
|
+
powerPreference: isolation.powerPreference ?? null,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function createIsolatedRenderer(
|
|
140
|
+
sourceRenderer: THREE.WebGLRenderer,
|
|
141
|
+
width: number,
|
|
142
|
+
height: number,
|
|
143
|
+
options: CameraFrameCaptureOptions
|
|
144
|
+
): { renderer: THREE.WebGLRenderer; cached: boolean } | null {
|
|
145
|
+
if (!shouldUseRenderIsolation(options)) return null;
|
|
146
|
+
|
|
147
|
+
const isolation = getRenderIsolationOptions(options);
|
|
148
|
+
if (isolation.cache !== false) {
|
|
149
|
+
const cacheKey = getRenderIsolationCacheKey(width, height, options);
|
|
150
|
+
let rendererCache = isolatedRendererCache.get(sourceRenderer);
|
|
151
|
+
if (!rendererCache) {
|
|
152
|
+
rendererCache = new Map();
|
|
153
|
+
isolatedRendererCache.set(sourceRenderer, rendererCache);
|
|
154
|
+
}
|
|
155
|
+
const cachedRenderer = rendererCache.get(cacheKey);
|
|
156
|
+
if (cachedRenderer) {
|
|
157
|
+
cachedRenderer.outputColorSpace = sourceRenderer.outputColorSpace;
|
|
158
|
+
cachedRenderer.toneMapping = sourceRenderer.toneMapping;
|
|
159
|
+
cachedRenderer.shadowMap.enabled = false;
|
|
160
|
+
return { renderer: cachedRenderer, cached: true };
|
|
161
|
+
}
|
|
162
|
+
const createdRenderer = createUncachedIsolatedRenderer(
|
|
163
|
+
sourceRenderer,
|
|
164
|
+
width,
|
|
165
|
+
height,
|
|
166
|
+
options
|
|
167
|
+
);
|
|
168
|
+
rendererCache.set(cacheKey, createdRenderer);
|
|
169
|
+
return { renderer: createdRenderer, cached: true };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
renderer: createUncachedIsolatedRenderer(sourceRenderer, width, height, options),
|
|
174
|
+
cached: false,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function createUncachedIsolatedRenderer(
|
|
179
|
+
sourceRenderer: THREE.WebGLRenderer,
|
|
180
|
+
width: number,
|
|
181
|
+
height: number,
|
|
182
|
+
options: CameraFrameCaptureOptions
|
|
183
|
+
) {
|
|
184
|
+
const isolation = getRenderIsolationOptions(options);
|
|
185
|
+
const canvas = document.createElement('canvas');
|
|
186
|
+
const renderer = new THREE.WebGLRenderer({
|
|
187
|
+
canvas,
|
|
188
|
+
antialias: isolation.antialias ?? false,
|
|
189
|
+
alpha: isolation.alpha ?? false,
|
|
190
|
+
preserveDrawingBuffer: isolation.preserveDrawingBuffer ?? false,
|
|
191
|
+
powerPreference: isolation.powerPreference,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
renderer.setPixelRatio(1);
|
|
195
|
+
renderer.setSize(width, height, false);
|
|
196
|
+
renderer.outputColorSpace = sourceRenderer.outputColorSpace;
|
|
197
|
+
renderer.toneMapping = sourceRenderer.toneMapping;
|
|
198
|
+
renderer.shadowMap.enabled = false;
|
|
199
|
+
return renderer;
|
|
200
|
+
}
|
|
201
|
+
|
|
92
202
|
function toVector3(
|
|
93
203
|
value: CameraFrameCaptureVector3 | undefined,
|
|
94
204
|
fallback: THREE.Vector3
|
|
@@ -127,6 +237,19 @@ function applyCameraPose(
|
|
|
127
237
|
camera.updateMatrixWorld();
|
|
128
238
|
}
|
|
129
239
|
|
|
240
|
+
function applyProjectionMatrix(
|
|
241
|
+
camera: THREE.Camera,
|
|
242
|
+
projectionMatrix: CameraFrameCaptureOptions['projectionMatrix'] | undefined
|
|
243
|
+
) {
|
|
244
|
+
if (!projectionMatrix) return;
|
|
245
|
+
if (projectionMatrix instanceof THREE.Matrix4) {
|
|
246
|
+
camera.projectionMatrix.copy(projectionMatrix);
|
|
247
|
+
} else {
|
|
248
|
+
camera.projectionMatrix.fromArray(projectionMatrix);
|
|
249
|
+
}
|
|
250
|
+
camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
|
|
251
|
+
}
|
|
252
|
+
|
|
130
253
|
function createCaptureCamera(
|
|
131
254
|
options: CameraFrameCaptureOptions,
|
|
132
255
|
fallbackCamera: THREE.Camera,
|
|
@@ -146,6 +269,7 @@ function createCaptureCamera(
|
|
|
146
269
|
camera.far = options.far ?? camera.far;
|
|
147
270
|
camera.updateProjectionMatrix();
|
|
148
271
|
}
|
|
272
|
+
applyProjectionMatrix(camera, options.projectionMatrix);
|
|
149
273
|
|
|
150
274
|
applyCameraPose(camera, options, fallbackCamera);
|
|
151
275
|
return camera;
|
|
@@ -184,6 +308,7 @@ function prepareCaptureCamera(
|
|
|
184
308
|
camera.far = options.far ?? camera.far;
|
|
185
309
|
camera.updateProjectionMatrix();
|
|
186
310
|
}
|
|
311
|
+
applyProjectionMatrix(camera, options.projectionMatrix);
|
|
187
312
|
|
|
188
313
|
applyCameraPose(camera, options, fallbackCamera);
|
|
189
314
|
}
|
|
@@ -362,6 +487,9 @@ function saveRendererState(renderer: THREE.WebGLRenderer): RendererState {
|
|
|
362
487
|
clearColor,
|
|
363
488
|
clearAlpha: renderer.getClearAlpha(),
|
|
364
489
|
autoClear: renderer.autoClear,
|
|
490
|
+
shadowMapEnabled: renderer.shadowMap.enabled,
|
|
491
|
+
toneMapping: renderer.toneMapping,
|
|
492
|
+
outputColorSpace: renderer.outputColorSpace,
|
|
365
493
|
};
|
|
366
494
|
}
|
|
367
495
|
|
|
@@ -376,6 +504,64 @@ function restoreRendererState(
|
|
|
376
504
|
renderer.setScissorTest(state.scissorTest);
|
|
377
505
|
renderer.setClearColor(state.clearColor, state.clearAlpha);
|
|
378
506
|
renderer.autoClear = state.autoClear;
|
|
507
|
+
renderer.shadowMap.enabled = state.shadowMapEnabled;
|
|
508
|
+
renderer.toneMapping = state.toneMapping;
|
|
509
|
+
renderer.outputColorSpace = state.outputColorSpace;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function saveSceneVisualState(scene: THREE.Scene): SceneVisualState {
|
|
513
|
+
return {
|
|
514
|
+
background: scene.background,
|
|
515
|
+
environment: scene.environment,
|
|
516
|
+
fog: scene.fog,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function restoreSceneVisualState(scene: THREE.Scene, state: SceneVisualState) {
|
|
521
|
+
scene.background = state.background;
|
|
522
|
+
scene.environment = state.environment;
|
|
523
|
+
scene.fog = state.fog;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function hasOwn<T extends object>(object: T, key: keyof T) {
|
|
527
|
+
return Object.prototype.hasOwnProperty.call(object, key);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function applyCaptureVisualOverrides(
|
|
531
|
+
renderer: THREE.WebGLRenderer,
|
|
532
|
+
scene: THREE.Scene,
|
|
533
|
+
options: CameraFrameCaptureOptions
|
|
534
|
+
): SceneVisualState | null {
|
|
535
|
+
const overrides = options.visualOverrides;
|
|
536
|
+
if (!overrides) return null;
|
|
537
|
+
|
|
538
|
+
const previousSceneState = saveSceneVisualState(scene);
|
|
539
|
+
if (hasOwn(overrides, 'sceneBackground')) {
|
|
540
|
+
const background = overrides.sceneBackground;
|
|
541
|
+
scene.background = background === false ? null : (
|
|
542
|
+
typeof background === 'string' || typeof background === 'number'
|
|
543
|
+
? new THREE.Color(background)
|
|
544
|
+
: background ?? null
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
if (hasOwn(overrides, 'sceneEnvironment')) {
|
|
548
|
+
const environment = overrides.sceneEnvironment;
|
|
549
|
+
scene.environment = environment === false ? null : environment ?? null;
|
|
550
|
+
}
|
|
551
|
+
if (hasOwn(overrides, 'sceneFog')) {
|
|
552
|
+
const fog = overrides.sceneFog;
|
|
553
|
+
scene.fog = fog === false ? null : fog ?? null;
|
|
554
|
+
}
|
|
555
|
+
if (overrides.shadows !== undefined) {
|
|
556
|
+
renderer.shadowMap.enabled = overrides.shadows;
|
|
557
|
+
}
|
|
558
|
+
if (overrides.toneMapping !== undefined) {
|
|
559
|
+
renderer.toneMapping = overrides.toneMapping;
|
|
560
|
+
}
|
|
561
|
+
if (overrides.outputColorSpace !== undefined) {
|
|
562
|
+
renderer.outputColorSpace = overrides.outputColorSpace;
|
|
563
|
+
}
|
|
564
|
+
return previousSceneState;
|
|
379
565
|
}
|
|
380
566
|
|
|
381
567
|
function getCaptureRenderer(
|
|
@@ -410,6 +596,8 @@ export function createCameraFrameCaptureSession(
|
|
|
410
596
|
options: CameraFrameCaptureOptions = {}
|
|
411
597
|
): CameraFrameCaptureSession {
|
|
412
598
|
const { width, height } = getCaptureDimensions(renderer, options);
|
|
599
|
+
const isolatedRenderer = createIsolatedRenderer(renderer, width, height, options);
|
|
600
|
+
const sessionRenderer = isolatedRenderer?.renderer ?? renderer;
|
|
413
601
|
const camera = createCaptureCamera(options, fallbackCamera, width, height);
|
|
414
602
|
const target = new THREE.WebGLRenderTarget(width, height, {
|
|
415
603
|
format: THREE.RGBAFormat,
|
|
@@ -430,6 +618,13 @@ export function createCameraFrameCaptureSession(
|
|
|
430
618
|
|
|
431
619
|
function resolveCaptureOptions(nextOptions: CameraFrameCaptureOptions = {}) {
|
|
432
620
|
const captureOptions = { ...options, ...nextOptions };
|
|
621
|
+
if (
|
|
622
|
+
shouldUseRenderIsolation(captureOptions) !== shouldUseRenderIsolation(options)
|
|
623
|
+
) {
|
|
624
|
+
throw new Error(
|
|
625
|
+
'Camera frame capture sessions require stable renderIsolation settings.'
|
|
626
|
+
);
|
|
627
|
+
}
|
|
433
628
|
const nextDimensions = getCaptureDimensions(renderer, captureOptions);
|
|
434
629
|
if (
|
|
435
630
|
nextDimensions.width !== width ||
|
|
@@ -452,7 +647,12 @@ export function createCameraFrameCaptureSession(
|
|
|
452
647
|
}
|
|
453
648
|
|
|
454
649
|
function renderPreparedCapture(captureOptions: CameraFrameCaptureOptions) {
|
|
455
|
-
const previousState = saveRendererState(
|
|
650
|
+
const previousState = saveRendererState(sessionRenderer);
|
|
651
|
+
const previousSceneState = applyCaptureVisualOverrides(
|
|
652
|
+
sessionRenderer,
|
|
653
|
+
scene,
|
|
654
|
+
captureOptions
|
|
655
|
+
);
|
|
456
656
|
const hidden = [
|
|
457
657
|
...hideExcludedCaptureObjects(scene),
|
|
458
658
|
...hideCaptureGeomGroups(scene, captureOptions),
|
|
@@ -461,23 +661,23 @@ export function createCameraFrameCaptureSession(
|
|
|
461
661
|
runCapturePreRenderHooks(scene);
|
|
462
662
|
scene.updateMatrixWorld(true);
|
|
463
663
|
try {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
664
|
+
sessionRenderer.xr.enabled = false;
|
|
665
|
+
sessionRenderer.setRenderTarget(target);
|
|
666
|
+
sessionRenderer.setViewport(0, 0, width, height);
|
|
667
|
+
sessionRenderer.setScissor(0, 0, width, height);
|
|
668
|
+
sessionRenderer.setScissorTest(false);
|
|
469
669
|
if (captureOptions.background !== undefined) {
|
|
470
|
-
|
|
670
|
+
sessionRenderer.setClearColor(
|
|
471
671
|
new THREE.Color(captureOptions.background),
|
|
472
672
|
captureOptions.backgroundAlpha ?? previousState.clearAlpha
|
|
473
673
|
);
|
|
474
674
|
} else if (captureOptions.backgroundAlpha !== undefined) {
|
|
475
|
-
|
|
675
|
+
sessionRenderer.setClearColor(previousState.clearColor, captureOptions.backgroundAlpha);
|
|
476
676
|
}
|
|
477
|
-
|
|
478
|
-
|
|
677
|
+
sessionRenderer.clear();
|
|
678
|
+
sessionRenderer.render(scene, camera);
|
|
479
679
|
readRenderTargetToCanvas(
|
|
480
|
-
|
|
680
|
+
sessionRenderer,
|
|
481
681
|
target,
|
|
482
682
|
canvas,
|
|
483
683
|
drawContext,
|
|
@@ -485,7 +685,7 @@ export function createCameraFrameCaptureSession(
|
|
|
485
685
|
imageData,
|
|
486
686
|
width,
|
|
487
687
|
height,
|
|
488
|
-
|
|
688
|
+
sessionRenderer.outputColorSpace,
|
|
489
689
|
captureOptions.flipX ?? false
|
|
490
690
|
);
|
|
491
691
|
return {
|
|
@@ -497,7 +697,8 @@ export function createCameraFrameCaptureSession(
|
|
|
497
697
|
};
|
|
498
698
|
} finally {
|
|
499
699
|
restoreObjectVisibility(hidden);
|
|
500
|
-
|
|
700
|
+
if (previousSceneState) restoreSceneVisualState(scene, previousSceneState);
|
|
701
|
+
restoreRendererState(sessionRenderer, previousState);
|
|
501
702
|
}
|
|
502
703
|
}
|
|
503
704
|
|
|
@@ -511,23 +712,28 @@ export function createCameraFrameCaptureSession(
|
|
|
511
712
|
scene.updateMatrixWorld(true);
|
|
512
713
|
const captureRenderer = getCaptureRenderer(scene);
|
|
513
714
|
if (captureRenderer) {
|
|
514
|
-
const previousState = saveRendererState(
|
|
715
|
+
const previousState = saveRendererState(sessionRenderer);
|
|
716
|
+
const previousSceneState = applyCaptureVisualOverrides(
|
|
717
|
+
sessionRenderer,
|
|
718
|
+
scene,
|
|
719
|
+
captureOptions
|
|
720
|
+
);
|
|
515
721
|
const hidden = [
|
|
516
722
|
...hideExcludedCaptureObjects(scene),
|
|
517
723
|
...hideCaptureGeomGroups(scene, captureOptions),
|
|
518
724
|
];
|
|
519
725
|
try {
|
|
520
|
-
|
|
726
|
+
sessionRenderer.xr.enabled = false;
|
|
521
727
|
if (captureOptions.background !== undefined) {
|
|
522
|
-
|
|
728
|
+
sessionRenderer.setClearColor(
|
|
523
729
|
new THREE.Color(captureOptions.background),
|
|
524
730
|
captureOptions.backgroundAlpha ?? previousState.clearAlpha
|
|
525
731
|
);
|
|
526
732
|
} else if (captureOptions.backgroundAlpha !== undefined) {
|
|
527
|
-
|
|
733
|
+
sessionRenderer.setClearColor(previousState.clearColor, captureOptions.backgroundAlpha);
|
|
528
734
|
}
|
|
529
735
|
const captureResult = await captureRenderer({
|
|
530
|
-
renderer,
|
|
736
|
+
renderer: sessionRenderer,
|
|
531
737
|
scene,
|
|
532
738
|
camera,
|
|
533
739
|
target,
|
|
@@ -561,7 +767,8 @@ export function createCameraFrameCaptureSession(
|
|
|
561
767
|
}
|
|
562
768
|
} finally {
|
|
563
769
|
restoreObjectVisibility(hidden);
|
|
564
|
-
|
|
770
|
+
if (previousSceneState) restoreSceneVisualState(scene, previousSceneState);
|
|
771
|
+
restoreRendererState(sessionRenderer, previousState);
|
|
565
772
|
}
|
|
566
773
|
}
|
|
567
774
|
return renderPreparedCapture(captureOptions);
|
|
@@ -613,6 +820,9 @@ export function createCameraFrameCaptureSession(
|
|
|
613
820
|
},
|
|
614
821
|
dispose() {
|
|
615
822
|
target.dispose();
|
|
823
|
+
if (isolatedRenderer && !isolatedRenderer.cached) {
|
|
824
|
+
isolatedRenderer.renderer.dispose();
|
|
825
|
+
}
|
|
616
826
|
},
|
|
617
827
|
};
|
|
618
828
|
}
|
package/src/spark.tsx
CHANGED
|
@@ -381,6 +381,10 @@ export function SparkSplatEnvironment({
|
|
|
381
381
|
const onErrorRef = useRef(onError);
|
|
382
382
|
const [status, setStatus] = useState<SparkSplatStatus>('idle');
|
|
383
383
|
const { gl, invalidate } = useThree();
|
|
384
|
+
onStatusChangeRef.current = onStatusChange;
|
|
385
|
+
onLoadRef.current = onLoad;
|
|
386
|
+
onErrorRef.current = onError;
|
|
387
|
+
|
|
384
388
|
const metadata = useSplatEnvironment({
|
|
385
389
|
environment,
|
|
386
390
|
scenario,
|
|
@@ -413,18 +417,6 @@ export function SparkSplatEnvironment({
|
|
|
413
417
|
]
|
|
414
418
|
);
|
|
415
419
|
|
|
416
|
-
useEffect(() => {
|
|
417
|
-
onStatusChangeRef.current = onStatusChange;
|
|
418
|
-
}, [onStatusChange]);
|
|
419
|
-
|
|
420
|
-
useEffect(() => {
|
|
421
|
-
onLoadRef.current = onLoad;
|
|
422
|
-
}, [onLoad]);
|
|
423
|
-
|
|
424
|
-
useEffect(() => {
|
|
425
|
-
onErrorRef.current = onError;
|
|
426
|
-
}, [onError]);
|
|
427
|
-
|
|
428
420
|
useEffect(() => {
|
|
429
421
|
let disposed = false;
|
|
430
422
|
ensureSparkDisposeRejectionHandler();
|
package/src/types.ts
CHANGED
|
@@ -328,6 +328,9 @@ export interface MujocoModel {
|
|
|
328
328
|
cam_pos?: Float64Array;
|
|
329
329
|
cam_quat?: Float64Array;
|
|
330
330
|
cam_fovy?: Float64Array;
|
|
331
|
+
cam_intrinsic?: Float64Array;
|
|
332
|
+
cam_resolution?: Int32Array;
|
|
333
|
+
cam_sensorsize?: Float64Array;
|
|
331
334
|
|
|
332
335
|
// Tendon
|
|
333
336
|
ten_wrapadr: Int32Array;
|
|
@@ -723,6 +726,9 @@ export interface CameraInfo {
|
|
|
723
726
|
name: string;
|
|
724
727
|
bodyId: number;
|
|
725
728
|
fov: number | null;
|
|
729
|
+
resolution: [number, number] | null;
|
|
730
|
+
sensorSize: [number, number] | null;
|
|
731
|
+
intrinsic: [number, number, number, number] | null;
|
|
726
732
|
position: [number, number, number] | null;
|
|
727
733
|
quaternion: [number, number, number, number] | null;
|
|
728
734
|
}
|
|
@@ -1021,11 +1027,28 @@ export interface ObservationHandle {
|
|
|
1021
1027
|
|
|
1022
1028
|
// ---- Debug Component (spec 6.1) ----
|
|
1023
1029
|
|
|
1030
|
+
export interface DebugVirtualCamera {
|
|
1031
|
+
name?: string;
|
|
1032
|
+
position?: CameraFrameCaptureVector3;
|
|
1033
|
+
lookAt?: CameraFrameCaptureVector3;
|
|
1034
|
+
up?: CameraFrameCaptureVector3;
|
|
1035
|
+
quaternion?: THREE.Quaternion | readonly [number, number, number, number];
|
|
1036
|
+
fov?: number;
|
|
1037
|
+
width?: number;
|
|
1038
|
+
height?: number;
|
|
1039
|
+
frustumDepth?: number;
|
|
1040
|
+
markerScale?: number;
|
|
1041
|
+
color?: THREE.ColorRepresentation;
|
|
1042
|
+
aimColor?: THREE.ColorRepresentation;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1024
1045
|
export interface DebugProps {
|
|
1025
1046
|
showGeoms?: boolean;
|
|
1026
1047
|
showSites?: boolean;
|
|
1027
1048
|
showJoints?: boolean;
|
|
1028
1049
|
showCameras?: boolean;
|
|
1050
|
+
/** Additional explicit virtual camera poses to visualize alongside MuJoCo XML cameras. */
|
|
1051
|
+
virtualCameras?: readonly DebugVirtualCamera[];
|
|
1029
1052
|
showContacts?: boolean;
|
|
1030
1053
|
showCOM?: boolean;
|
|
1031
1054
|
showInertia?: boolean;
|
|
@@ -1505,6 +1528,51 @@ export type CameraFrameCaptureQuaternion =
|
|
|
1505
1528
|
| THREE.Quaternion
|
|
1506
1529
|
| readonly [number, number, number, number];
|
|
1507
1530
|
|
|
1531
|
+
export interface CameraFrameVisualOverrides {
|
|
1532
|
+
/**
|
|
1533
|
+
* Override `scene.background` for this capture only.
|
|
1534
|
+
* Use `null` or `false` to render without the viewer scene background.
|
|
1535
|
+
*/
|
|
1536
|
+
sceneBackground?: THREE.Scene['background'] | THREE.ColorRepresentation | null | false;
|
|
1537
|
+
/**
|
|
1538
|
+
* Override `scene.environment` for this capture only.
|
|
1539
|
+
* Use `null` or `false` to remove viewer environment lighting/maps.
|
|
1540
|
+
*/
|
|
1541
|
+
sceneEnvironment?: THREE.Scene['environment'] | null | false;
|
|
1542
|
+
/**
|
|
1543
|
+
* Override `scene.fog` for this capture only.
|
|
1544
|
+
* Use `null` or `false` to remove viewer fog.
|
|
1545
|
+
*/
|
|
1546
|
+
sceneFog?: THREE.Scene['fog'] | null | false;
|
|
1547
|
+
/** Override `renderer.shadowMap.enabled` while capturing. */
|
|
1548
|
+
shadows?: boolean;
|
|
1549
|
+
/** Override renderer tone mapping while capturing. */
|
|
1550
|
+
toneMapping?: THREE.WebGLRenderer['toneMapping'];
|
|
1551
|
+
/** Override renderer output color space while capturing. */
|
|
1552
|
+
outputColorSpace?: THREE.WebGLRenderer['outputColorSpace'];
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
export interface CameraFrameRenderIsolationOptions {
|
|
1556
|
+
/**
|
|
1557
|
+
* Use an independent offscreen WebGLRenderer for this capture.
|
|
1558
|
+
*
|
|
1559
|
+
* This prevents viewer renderer settings such as antialiasing, shadow-map
|
|
1560
|
+
* configuration, tone mapping, and environment setup from leaking into
|
|
1561
|
+
* policy/training images. Leave unset for the historical shared-renderer path.
|
|
1562
|
+
*/
|
|
1563
|
+
enabled?: boolean;
|
|
1564
|
+
/** Offscreen renderer antialiasing. Defaults to false for deterministic policy captures. */
|
|
1565
|
+
antialias?: boolean;
|
|
1566
|
+
/** Offscreen renderer alpha buffer. Defaults to false, matching Three.js WebGLRenderer. */
|
|
1567
|
+
alpha?: boolean;
|
|
1568
|
+
/** Offscreen renderer preserveDrawingBuffer flag. Defaults to false. */
|
|
1569
|
+
preserveDrawingBuffer?: boolean;
|
|
1570
|
+
/** Offscreen renderer power preference. Defaults to the browser's renderer default. */
|
|
1571
|
+
powerPreference?: WebGLPowerPreference;
|
|
1572
|
+
/** Reuse an offscreen renderer for matching capture dimensions/options. Defaults to true. */
|
|
1573
|
+
cache?: boolean;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1508
1576
|
export interface CameraFrameCaptureOptions {
|
|
1509
1577
|
/** Existing Three camera to clone before applying pose overrides. */
|
|
1510
1578
|
camera?: THREE.Camera;
|
|
@@ -1529,8 +1597,36 @@ export interface CameraFrameCaptureOptions {
|
|
|
1529
1597
|
fov?: number;
|
|
1530
1598
|
near?: number;
|
|
1531
1599
|
far?: number;
|
|
1600
|
+
/**
|
|
1601
|
+
* Explicit projection matrix for offscreen capture. This is useful when a
|
|
1602
|
+
* MuJoCo camera has calibrated intrinsics that cannot be represented by a
|
|
1603
|
+
* symmetric Three.js PerspectiveCamera fov alone.
|
|
1604
|
+
*/
|
|
1605
|
+
projectionMatrix?: THREE.Matrix4 | readonly number[];
|
|
1532
1606
|
/** Provenance for the camera pose used by the capture. Usually set by the MuJoCo provider. */
|
|
1533
1607
|
source?: CameraFrameCaptureSource;
|
|
1608
|
+
/**
|
|
1609
|
+
* When resolving a named MuJoCo camera, derive Three capture settings from
|
|
1610
|
+
* MuJoCo camera metadata where available: cam_resolution, cam_fovy,
|
|
1611
|
+
* cam_intrinsic/cam_sensorsize, and visual map near/far clipping.
|
|
1612
|
+
*/
|
|
1613
|
+
mujocoCameraCompatibility?: boolean | {
|
|
1614
|
+
useResolution?: boolean;
|
|
1615
|
+
useIntrinsics?: boolean;
|
|
1616
|
+
useClipping?: boolean;
|
|
1617
|
+
/**
|
|
1618
|
+
* When a MuJoCo camera has `resolution` metadata and the caller supplies
|
|
1619
|
+
* only width or only height, derive the missing dimension from the MuJoCo
|
|
1620
|
+
* camera aspect ratio.
|
|
1621
|
+
*/
|
|
1622
|
+
preserveAspect?: boolean;
|
|
1623
|
+
/**
|
|
1624
|
+
* Prefer the MuJoCo camera's configured resolution over width/height
|
|
1625
|
+
* provided by the caller. Leave false when a policy wants fixed-size
|
|
1626
|
+
* payloads while still preserving the camera aspect ratio.
|
|
1627
|
+
*/
|
|
1628
|
+
preferResolution?: boolean;
|
|
1629
|
+
};
|
|
1534
1630
|
/** Hide rendered Three objects whose MuJoCo geom group is in this list. */
|
|
1535
1631
|
hiddenGeomGroups?: readonly number[];
|
|
1536
1632
|
/** When provided, only rendered Three objects whose MuJoCo geom group is in this list are visible. */
|
|
@@ -1541,6 +1637,15 @@ export interface CameraFrameCaptureOptions {
|
|
|
1541
1637
|
background?: THREE.ColorRepresentation;
|
|
1542
1638
|
/** Optional clear alpha for this capture only. Defaults to the renderer's current clear alpha. */
|
|
1543
1639
|
backgroundAlpha?: number;
|
|
1640
|
+
/** Temporary scene/renderer visual overrides applied only for this offscreen capture. */
|
|
1641
|
+
visualOverrides?: CameraFrameVisualOverrides;
|
|
1642
|
+
/**
|
|
1643
|
+
* Render this capture with a separate offscreen WebGLRenderer.
|
|
1644
|
+
*
|
|
1645
|
+
* This is useful for policy or training captures that should remain canonical
|
|
1646
|
+
* while the interactive viewer uses richer visual effects.
|
|
1647
|
+
*/
|
|
1648
|
+
renderIsolation?: boolean | CameraFrameRenderIsolationOptions;
|
|
1544
1649
|
/** Mirror the captured image horizontally after rendering. Useful when matching policy datasets with mirrored camera frames. */
|
|
1545
1650
|
flipX?: boolean;
|
|
1546
1651
|
}
|
|
@@ -1658,6 +1763,21 @@ export interface CameraFrameSequenceRecorderAPI {
|
|
|
1658
1763
|
reset: () => void;
|
|
1659
1764
|
}
|
|
1660
1765
|
|
|
1766
|
+
export type MujocoMeshNormalSmoothing =
|
|
1767
|
+
| boolean
|
|
1768
|
+
| {
|
|
1769
|
+
/** Vertex merge tolerance used before recomputing mesh normals. Defaults to `1e-4`. */
|
|
1770
|
+
tolerance?: number;
|
|
1771
|
+
};
|
|
1772
|
+
|
|
1773
|
+
export interface MujocoRenderOptions {
|
|
1774
|
+
/**
|
|
1775
|
+
* Smooth mesh normals by welding duplicate vertices before recomputing normals.
|
|
1776
|
+
* Useful for faceted STL visuals; keep off for exact policy-render parity.
|
|
1777
|
+
*/
|
|
1778
|
+
meshNormalSmoothing?: MujocoMeshNormalSmoothing;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1661
1781
|
// ---- Canvas Props ----
|
|
1662
1782
|
|
|
1663
1783
|
export type MujocoCanvasProps = Omit<CanvasProps, 'onError'> & {
|
|
@@ -1675,6 +1795,7 @@ export type MujocoCanvasProps = Omit<CanvasProps, 'onError'> & {
|
|
|
1675
1795
|
paused?: boolean;
|
|
1676
1796
|
speed?: number;
|
|
1677
1797
|
interpolate?: boolean;
|
|
1798
|
+
renderOptions?: MujocoRenderOptions;
|
|
1678
1799
|
};
|
|
1679
1800
|
|
|
1680
1801
|
// ---- Hook Return Types ----
|