mujoco-react 8.11.0 → 9.1.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 +34 -17
- package/dist/{chunk-SEWQULWO.js → chunk-33CV6HSV.js} +3 -3
- package/dist/chunk-33CV6HSV.js.map +1 -0
- package/dist/index.d.ts +13 -41
- package/dist/index.js +185 -152
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +1 -1
- package/dist/spark.js +1 -1
- package/dist/{types-BmneHLBM.d.ts → types-C5gTvR7b.d.ts} +83 -13
- package/package.json +1 -1
- package/src/components/DragInteraction.tsx +1 -1
- package/src/components/IkGizmo.tsx +2 -2
- package/src/components/SceneRenderer.tsx +1 -1
- package/src/components/TrajectoryPlayer.tsx +4 -1
- package/src/components/VisualScenario.tsx +1 -1
- package/src/core/MujocoPhysics.tsx +10 -4
- package/src/core/MujocoSimProvider.tsx +42 -13
- package/src/core/createController.tsx +2 -2
- package/src/hooks/useBodyState.ts +1 -1
- package/src/hooks/useContacts.ts +1 -1
- package/src/hooks/useCtrlNoise.ts +1 -1
- package/src/hooks/useFrameCapture.ts +8 -42
- package/src/hooks/useGamepad.ts +1 -1
- package/src/hooks/useGravityCompensation.ts +1 -1
- package/src/hooks/useIkController.ts +22 -13
- package/src/hooks/useJointState.ts +1 -1
- package/src/hooks/useKeyboardTeleop.ts +1 -1
- package/src/hooks/usePolicy.ts +1 -1
- package/src/hooks/useSensor.ts +1 -1
- package/src/hooks/useTrajectoryPlayer.ts +4 -4
- package/src/hooks/useTrajectoryRecorder.ts +1 -1
- package/src/index.ts +18 -9
- package/src/types.ts +106 -18
- package/dist/chunk-SEWQULWO.js.map +0 -1
|
@@ -59,7 +59,7 @@ export function useJointState(name: Joints): JointStateResult {
|
|
|
59
59
|
jointIdRef.current = -1;
|
|
60
60
|
}, [name, status, mjModelRef]);
|
|
61
61
|
|
|
62
|
-
useAfterPhysicsStep((
|
|
62
|
+
useAfterPhysicsStep(({ data }) => {
|
|
63
63
|
if (jointIdRef.current < 0) return;
|
|
64
64
|
const qa = qposAdrRef.current;
|
|
65
65
|
const da = dofAdrRef.current;
|
|
@@ -70,7 +70,7 @@ export function useKeyboardTeleop(config: KeyboardTeleopConfig) {
|
|
|
70
70
|
}, []);
|
|
71
71
|
|
|
72
72
|
// Apply bindings each physics frame
|
|
73
|
-
useBeforePhysicsStep((
|
|
73
|
+
useBeforePhysicsStep(({ data }) => {
|
|
74
74
|
if (!enabledRef.current) return;
|
|
75
75
|
const bindings = bindingsRef.current;
|
|
76
76
|
const cache = actuatorCacheRef.current;
|
package/src/hooks/usePolicy.ts
CHANGED
|
@@ -28,7 +28,7 @@ export function usePolicy(config: PolicyConfig) {
|
|
|
28
28
|
configRef.current = config;
|
|
29
29
|
isRunningRef.current = config.enabled ?? isRunningRef.current;
|
|
30
30
|
|
|
31
|
-
useBeforePhysicsStep((model, data) => {
|
|
31
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
32
32
|
if (!isRunningRef.current) return;
|
|
33
33
|
|
|
34
34
|
const cfg = configRef.current;
|
package/src/hooks/useSensor.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function useSensor(name: Sensors): SensorHandle {
|
|
|
39
39
|
}, [name, status, mjModelRef]);
|
|
40
40
|
|
|
41
41
|
// Update every frame after physics step
|
|
42
|
-
useAfterPhysicsStep((
|
|
42
|
+
useAfterPhysicsStep(({ data }) => {
|
|
43
43
|
if (sensorIdRef.current < 0) return;
|
|
44
44
|
const adr = sensorAdrRef.current;
|
|
45
45
|
const dim = sensorDimRef.current;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { useCallback, useRef } from 'react';
|
|
9
9
|
import { useFrame } from '@react-three/fiber';
|
|
10
10
|
import { useMujocoContext, useBeforePhysicsStep } from '../core/MujocoSimProvider';
|
|
11
|
-
import type { PlaybackState, TrajectoryFrame, TrajectoryInput } from '../types';
|
|
11
|
+
import type { PlaybackState, TrajectoryStateChangeInput, TrajectoryFrame, TrajectoryInput } from '../types';
|
|
12
12
|
|
|
13
13
|
export interface TrajectoryPlayerOptions {
|
|
14
14
|
fps?: number;
|
|
@@ -16,7 +16,7 @@ export interface TrajectoryPlayerOptions {
|
|
|
16
16
|
loop?: boolean;
|
|
17
17
|
mode?: 'kinematic' | 'physics';
|
|
18
18
|
onComplete?: () => void;
|
|
19
|
-
onStateChange?: (
|
|
19
|
+
onStateChange?: (input: TrajectoryStateChangeInput) => void;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/** Check if input is TrajectoryFrame[] (vs number[][]) */
|
|
@@ -74,7 +74,7 @@ export function useTrajectoryPlayer(
|
|
|
74
74
|
const setState = useCallback((next: PlaybackState) => {
|
|
75
75
|
if (stateRef.current === next) return;
|
|
76
76
|
stateRef.current = next;
|
|
77
|
-
optionsRef.current.onStateChange?.(next);
|
|
77
|
+
optionsRef.current.onStateChange?.({ state: next });
|
|
78
78
|
}, []);
|
|
79
79
|
|
|
80
80
|
const play = useCallback(() => {
|
|
@@ -181,7 +181,7 @@ export function useTrajectoryPlayer(
|
|
|
181
181
|
});
|
|
182
182
|
|
|
183
183
|
// --- Physics mode: set ctrl values each physics step ---
|
|
184
|
-
useBeforePhysicsStep((model, data) => {
|
|
184
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
185
185
|
if (stateRef.current !== 'playing') return;
|
|
186
186
|
if ((optionsRef.current.mode ?? 'kinematic') !== 'physics') return;
|
|
187
187
|
|
|
@@ -22,7 +22,7 @@ export function useTrajectoryRecorder(options: RecorderOptions = {}) {
|
|
|
22
22
|
const framesRef = useRef<TrajectoryFrame[]>([]);
|
|
23
23
|
const fields = options.fields ?? ['qpos'];
|
|
24
24
|
|
|
25
|
-
useAfterPhysicsStep((
|
|
25
|
+
useAfterPhysicsStep(({ data }) => {
|
|
26
26
|
if (!recordingRef.current) return;
|
|
27
27
|
|
|
28
28
|
const frame: TrajectoryFrame = {
|
package/src/index.ts
CHANGED
|
@@ -82,15 +82,6 @@ export {
|
|
|
82
82
|
captureFrameBlob,
|
|
83
83
|
useFrameCapture,
|
|
84
84
|
} from './hooks/useFrameCapture';
|
|
85
|
-
export type {
|
|
86
|
-
FrameCaptureAPI,
|
|
87
|
-
FrameCaptureBlobResult,
|
|
88
|
-
FrameCaptureOptions,
|
|
89
|
-
FrameCaptureResult,
|
|
90
|
-
FrameCaptureStatus,
|
|
91
|
-
FrameCaptureTarget,
|
|
92
|
-
FrameCaptureTargetRef,
|
|
93
|
-
} from './hooks/useFrameCapture';
|
|
94
85
|
export { useCtrlNoise } from './hooks/useCtrlNoise';
|
|
95
86
|
export { useBodyMeshes } from './hooks/useBodyMeshes';
|
|
96
87
|
export { useSelectionHighlight } from './hooks/useSelectionHighlight';
|
|
@@ -110,8 +101,14 @@ export type {
|
|
|
110
101
|
IkConfig,
|
|
111
102
|
IkContextValue,
|
|
112
103
|
IKSolveFn,
|
|
104
|
+
IkSolveInput,
|
|
113
105
|
// Callbacks
|
|
114
106
|
PhysicsStepCallback,
|
|
107
|
+
PhysicsStepInput,
|
|
108
|
+
ResetCallbackInput,
|
|
109
|
+
ReadyCallbackInput,
|
|
110
|
+
StepCallbackInput,
|
|
111
|
+
SelectionCallbackInput,
|
|
115
112
|
// State management
|
|
116
113
|
StateSnapshot,
|
|
117
114
|
// Model introspection
|
|
@@ -155,6 +152,7 @@ export type {
|
|
|
155
152
|
// Component props
|
|
156
153
|
BodyProps,
|
|
157
154
|
IkGizmoProps,
|
|
155
|
+
IkGizmoDragInput,
|
|
158
156
|
DragInteractionProps,
|
|
159
157
|
DebugProps,
|
|
160
158
|
SceneLightsProps,
|
|
@@ -175,13 +173,24 @@ export type {
|
|
|
175
173
|
ScenarioMaterialConfig,
|
|
176
174
|
SplatEnvironmentProps,
|
|
177
175
|
VisualScenarioEffectsProps,
|
|
176
|
+
VisualScenarioMaterialFilterInput,
|
|
178
177
|
TrajectoryPlayerProps,
|
|
178
|
+
TrajectoryFrameCallbackInput,
|
|
179
|
+
TrajectoryStateChangeInput,
|
|
179
180
|
ContactListenerProps,
|
|
180
181
|
// API
|
|
181
182
|
MujocoSimAPI,
|
|
183
|
+
MujocoFrameCaptureOptions,
|
|
182
184
|
MujocoCanvasProps,
|
|
183
185
|
MujocoContextValue,
|
|
184
186
|
// Hook return types
|
|
187
|
+
FrameCaptureAPI,
|
|
188
|
+
FrameCaptureBlobResult,
|
|
189
|
+
FrameCaptureOptions,
|
|
190
|
+
FrameCaptureResult,
|
|
191
|
+
FrameCaptureStatus,
|
|
192
|
+
FrameCaptureTarget,
|
|
193
|
+
FrameCaptureTargetRef,
|
|
185
194
|
SitePositionResult,
|
|
186
195
|
SensorResult,
|
|
187
196
|
CtrlHandle,
|
package/src/types.ts
CHANGED
|
@@ -450,7 +450,7 @@ export interface LoadFromFilesOptions {
|
|
|
450
450
|
homeJoints?: number[];
|
|
451
451
|
xmlPatches?: XmlPatch[];
|
|
452
452
|
sceneObjects?: SceneObject[];
|
|
453
|
-
onReset?: (
|
|
453
|
+
onReset?: (input: ResetCallbackInput) => void;
|
|
454
454
|
}
|
|
455
455
|
|
|
456
456
|
export interface SceneConfig {
|
|
@@ -471,7 +471,7 @@ export interface SceneConfig {
|
|
|
471
471
|
sceneObjects?: SceneObject[];
|
|
472
472
|
homeJoints?: number[];
|
|
473
473
|
xmlPatches?: XmlPatch[];
|
|
474
|
-
onReset?: (
|
|
474
|
+
onReset?: (input: ResetCallbackInput) => void;
|
|
475
475
|
}
|
|
476
476
|
|
|
477
477
|
// ---- IK Controller Config ----
|
|
@@ -513,7 +513,7 @@ export interface IkContextValue {
|
|
|
513
513
|
setIkEnabled: (enabled: boolean) => void;
|
|
514
514
|
moveTarget: (pos: THREE.Vector3, duration?: number) => void;
|
|
515
515
|
syncTargetToSite: () => void;
|
|
516
|
-
solveIK: (
|
|
516
|
+
solveIK: (input: IkSolveInput) => number[] | null;
|
|
517
517
|
getGizmoStats: () => { pos: THREE.Vector3; rot: THREE.Euler } | null;
|
|
518
518
|
}
|
|
519
519
|
|
|
@@ -536,12 +536,16 @@ export interface PhysicsConfig {
|
|
|
536
536
|
// ---- IK ----
|
|
537
537
|
|
|
538
538
|
export type IKSolveFn = (
|
|
539
|
-
|
|
540
|
-
quat: THREE.Quaternion,
|
|
541
|
-
currentQ: number[],
|
|
542
|
-
context?: IKSolveContext
|
|
539
|
+
input: IkSolveInput
|
|
543
540
|
) => number[] | null;
|
|
544
541
|
|
|
542
|
+
export interface IkSolveInput {
|
|
543
|
+
position: THREE.Vector3;
|
|
544
|
+
quaternion: THREE.Quaternion;
|
|
545
|
+
currentQ: number[];
|
|
546
|
+
context?: IKSolveContext;
|
|
547
|
+
}
|
|
548
|
+
|
|
545
549
|
export interface IKSolveContext {
|
|
546
550
|
model: MujocoModel;
|
|
547
551
|
data: MujocoData;
|
|
@@ -551,10 +555,29 @@ export interface IKSolveContext {
|
|
|
551
555
|
|
|
552
556
|
// ---- Callbacks ----
|
|
553
557
|
|
|
554
|
-
export
|
|
555
|
-
model: MujocoModel
|
|
556
|
-
data: MujocoData
|
|
557
|
-
|
|
558
|
+
export interface PhysicsStepInput {
|
|
559
|
+
model: MujocoModel;
|
|
560
|
+
data: MujocoData;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
export interface ResetCallbackInput extends PhysicsStepInput {}
|
|
564
|
+
|
|
565
|
+
export interface ReadyCallbackInput {
|
|
566
|
+
api: MujocoSimAPI;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export interface StepCallbackInput {
|
|
570
|
+
time: number;
|
|
571
|
+
model: MujocoModel;
|
|
572
|
+
data: MujocoData;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
export interface SelectionCallbackInput {
|
|
576
|
+
bodyId: number;
|
|
577
|
+
name: string;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
export type PhysicsStepCallback = (input: PhysicsStepInput) => void;
|
|
558
581
|
|
|
559
582
|
// ---- State Management (spec 4.1) ----
|
|
560
583
|
|
|
@@ -808,7 +831,12 @@ export interface IkGizmoProps {
|
|
|
808
831
|
controller: IkContextValue;
|
|
809
832
|
siteName?: string;
|
|
810
833
|
scale?: number;
|
|
811
|
-
onDrag?: (
|
|
834
|
+
onDrag?: (input: IkGizmoDragInput) => void;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
export interface IkGizmoDragInput {
|
|
838
|
+
position: THREE.Vector3;
|
|
839
|
+
quaternion: THREE.Quaternion;
|
|
812
840
|
}
|
|
813
841
|
|
|
814
842
|
export interface DragInteractionProps {
|
|
@@ -940,7 +968,12 @@ export interface VisualScenarioEffectsProps {
|
|
|
940
968
|
background?: THREE.ColorRepresentation;
|
|
941
969
|
fogNear?: number;
|
|
942
970
|
fogFar?: number;
|
|
943
|
-
materialFilter?: (
|
|
971
|
+
materialFilter?: (input: VisualScenarioMaterialFilterInput) => boolean;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
export interface VisualScenarioMaterialFilterInput {
|
|
975
|
+
object: THREE.Object3D;
|
|
976
|
+
material: THREE.Material;
|
|
944
977
|
}
|
|
945
978
|
|
|
946
979
|
export type TrajectoryInput = TrajectoryFrame[] | number[][];
|
|
@@ -952,9 +985,18 @@ export interface TrajectoryPlayerProps {
|
|
|
952
985
|
loop?: boolean;
|
|
953
986
|
playing?: boolean;
|
|
954
987
|
mode?: 'kinematic' | 'physics';
|
|
955
|
-
onFrame?: (
|
|
988
|
+
onFrame?: (input: TrajectoryFrameCallbackInput) => void;
|
|
956
989
|
onComplete?: () => void;
|
|
957
|
-
onStateChange?: (
|
|
990
|
+
onStateChange?: (input: TrajectoryStateChangeInput) => void;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
export interface TrajectoryFrameCallbackInput {
|
|
994
|
+
frameIndex: number;
|
|
995
|
+
frame: TrajectoryFrame | number[] | undefined;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
export interface TrajectoryStateChangeInput {
|
|
999
|
+
state: PlaybackState;
|
|
958
1000
|
}
|
|
959
1001
|
|
|
960
1002
|
export interface SelectionHighlightProps {
|
|
@@ -1058,7 +1100,10 @@ export interface MujocoSimAPI {
|
|
|
1058
1100
|
recompile(patches?: XmlPatch[]): Promise<void>;
|
|
1059
1101
|
|
|
1060
1102
|
// Canvas
|
|
1103
|
+
getCanvas(): HTMLCanvasElement | null;
|
|
1061
1104
|
getCanvasSnapshot(width?: number, height?: number, mimeType?: string): string;
|
|
1105
|
+
captureFrame(options?: MujocoFrameCaptureOptions): Promise<FrameCaptureResult>;
|
|
1106
|
+
captureFrameBlob(options?: MujocoFrameCaptureOptions): Promise<FrameCaptureBlobResult>;
|
|
1062
1107
|
project2DTo3D(
|
|
1063
1108
|
x: number,
|
|
1064
1109
|
y: number,
|
|
@@ -1076,16 +1121,59 @@ export interface MujocoSimAPI {
|
|
|
1076
1121
|
readonly mjDataRef: React.RefObject<MujocoData | null>;
|
|
1077
1122
|
}
|
|
1078
1123
|
|
|
1124
|
+
export type FrameCaptureStatus = 'idle' | 'capturing' | 'captured' | 'error';
|
|
1125
|
+
|
|
1126
|
+
export type FrameCaptureTarget =
|
|
1127
|
+
| HTMLCanvasElement
|
|
1128
|
+
| HTMLElement
|
|
1129
|
+
| null
|
|
1130
|
+
| undefined;
|
|
1131
|
+
|
|
1132
|
+
export type FrameCaptureTargetRef =
|
|
1133
|
+
React.RefObject<HTMLCanvasElement | HTMLElement | null>;
|
|
1134
|
+
|
|
1135
|
+
export interface FrameCaptureOptions {
|
|
1136
|
+
target?: FrameCaptureTarget | FrameCaptureTargetRef;
|
|
1137
|
+
type?: string;
|
|
1138
|
+
quality?: number;
|
|
1139
|
+
waitForAnimationFrame?: boolean;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
export type MujocoFrameCaptureOptions = Omit<FrameCaptureOptions, 'target'>;
|
|
1143
|
+
|
|
1144
|
+
export interface FrameCaptureResult {
|
|
1145
|
+
canvas: HTMLCanvasElement;
|
|
1146
|
+
dataUrl: string;
|
|
1147
|
+
type: string;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
export interface FrameCaptureBlobResult {
|
|
1151
|
+
canvas: HTMLCanvasElement;
|
|
1152
|
+
blob: Blob;
|
|
1153
|
+
type: string;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
export interface FrameCaptureAPI {
|
|
1157
|
+
status: FrameCaptureStatus;
|
|
1158
|
+
error: Error | null;
|
|
1159
|
+
isCapturing: boolean;
|
|
1160
|
+
capture: (options?: FrameCaptureOptions) => Promise<FrameCaptureResult>;
|
|
1161
|
+
captureBlob: (
|
|
1162
|
+
options?: FrameCaptureOptions
|
|
1163
|
+
) => Promise<FrameCaptureBlobResult>;
|
|
1164
|
+
reset: () => void;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1079
1167
|
// ---- Canvas Props ----
|
|
1080
1168
|
|
|
1081
1169
|
export type MujocoCanvasProps = Omit<CanvasProps, 'onError'> & {
|
|
1082
1170
|
config: SceneConfig;
|
|
1083
1171
|
/** R3F content rendered while the MuJoCo WASM module is still loading. */
|
|
1084
1172
|
loadingFallback?: ReactNode;
|
|
1085
|
-
onReady?: (
|
|
1173
|
+
onReady?: (input: ReadyCallbackInput) => void;
|
|
1086
1174
|
onError?: (error: Error) => void;
|
|
1087
|
-
onStep?: (
|
|
1088
|
-
onSelection?: (
|
|
1175
|
+
onStep?: (input: StepCallbackInput) => void;
|
|
1176
|
+
onSelection?: (input: SelectionCallbackInput) => void;
|
|
1089
1177
|
// Declarative physics config (spec 1.1)
|
|
1090
1178
|
gravity?: [number, number, number];
|
|
1091
1179
|
timestep?: number;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/VisualScenario.tsx"],"names":[],"mappings":"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","file":"chunk-SEWQULWO.js","sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { useThree } from '@react-three/fiber';\nimport type { ThreeElements } from '@react-three/fiber';\nimport type { ReactNode } from 'react';\nimport { useEffect, useMemo } from 'react';\nimport * as THREE from 'three';\nimport type {\n PairedSplatEnvironmentConfig,\n ScenarioMaterialConfig,\n SceneConfig,\n SplatCollisionProxyConfig,\n SplatEnvironmentMetadata,\n SplatEnvironmentMetadataInput,\n SplatFormat,\n SplatRendererKind,\n SplatSceneInput,\n ScenarioLightingPreset,\n ScenarioLightingProps,\n SplatEnvironmentProps,\n VisualScenarioConfig,\n VisualScenarioEffectsProps,\n} from '../types';\n\nconst DEFAULT_BACKGROUND = '#181a1f';\n\nexport function ScenarioLighting({\n preset = 'studio',\n castShadow = true,\n intensity = 1,\n}: ScenarioLightingProps) {\n if (preset === 'warehouse') {\n return (\n <>\n <ambientLight intensity={0.18 * intensity} />\n <directionalLight\n position={[3.5, -2, 5]}\n intensity={2.2 * intensity}\n castShadow={castShadow}\n />\n <directionalLight position={[-2, 1.5, 2.5]} intensity={0.25 * intensity} />\n </>\n );\n }\n\n if (preset === 'low-light') {\n return (\n <>\n <ambientLight intensity={0.08 * intensity} />\n <directionalLight\n position={[2, -2, 3]}\n intensity={0.75 * intensity}\n castShadow={castShadow}\n />\n <pointLight position={[-0.5, -0.8, 1.3]} intensity={0.6 * intensity} />\n </>\n );\n }\n\n if (preset === 'splat') {\n return (\n <>\n <ambientLight intensity={0.42 * intensity} />\n <directionalLight\n position={[1.8, -2.4, 3.5]}\n intensity={1.2 * intensity}\n castShadow={castShadow}\n />\n <pointLight position={[0.4, 0.2, 1.4]} intensity={0.35 * intensity} />\n </>\n );\n }\n\n return (\n <>\n <ambientLight intensity={0.35 * intensity} />\n <directionalLight\n position={[2.5, -3, 4]}\n intensity={1.6 * intensity}\n castShadow={castShadow}\n />\n </>\n );\n}\n\nexport function getScenarioBackground(\n preset: ScenarioLightingPreset | undefined,\n fallback = DEFAULT_BACKGROUND\n) {\n if (preset === 'warehouse') return '#20242b';\n if (preset === 'low-light') return '#0f1115';\n if (preset === 'splat') return '#1b1f24';\n return fallback;\n}\n\nexport function getScenarioCameraPosition(\n basePosition: readonly [number, number, number],\n scenario?: Pick<VisualScenarioConfig, 'camera'>\n): [number, number, number] {\n const [x, y, z] = basePosition;\n const jitter = scenario?.camera?.jitter ?? 0;\n\n return [\n Number((x + jitter * 0.6).toFixed(3)),\n Number((y - jitter * 0.4).toFixed(3)),\n Number((z + jitter * 0.25).toFixed(3)),\n ];\n}\n\nexport function VisualScenarioEffects(props: VisualScenarioEffectsProps) {\n useVisualScenarioEffects(props);\n return null;\n}\n\nexport function useVisualScenarioEffects({\n scenario,\n enabled = true,\n applyBackground = true,\n applyFog = true,\n applyRenderer = true,\n applyMaterials = true,\n background,\n fogNear,\n fogFar,\n materialFilter,\n}: VisualScenarioEffectsProps) {\n const { gl, scene, invalidate } = useThree();\n\n useEffect(() => {\n if (!enabled || !scenario) {\n return undefined;\n }\n\n const previousExposure = gl.toneMappingExposure;\n const previousBackground = scene.background;\n const previousFog = scene.fog;\n const materialSnapshots = new Map<\n THREE.Material,\n {\n color?: THREE.Color;\n roughness?: number;\n metalness?: number;\n }\n >();\n\n if (applyRenderer) {\n gl.toneMappingExposure = scenario.camera?.exposure ?? 1;\n }\n\n if (applyBackground) {\n scene.background = new THREE.Color(\n background ?? getScenarioBackground(scenario.lighting)\n );\n }\n\n if (applyFog) {\n scene.fog = createScenarioFog(scenario, background, fogNear, fogFar);\n }\n\n if (applyMaterials && scenario.materials) {\n applyScenarioMaterials(scene, scenario, materialSnapshots, materialFilter);\n }\n\n invalidate();\n\n return () => {\n gl.toneMappingExposure = previousExposure;\n scene.background = previousBackground;\n scene.fog = previousFog;\n\n for (const [material, snapshot] of materialSnapshots) {\n const mutable = getMutableScenarioMaterial(material);\n if (!mutable) continue;\n if (snapshot.color) mutable.color.copy(snapshot.color);\n if (typeof snapshot.roughness === 'number') {\n mutable.roughness = snapshot.roughness;\n }\n if (typeof snapshot.metalness === 'number') {\n mutable.metalness = snapshot.metalness;\n }\n mutable.needsUpdate = true;\n }\n\n invalidate();\n };\n }, [\n applyBackground,\n applyFog,\n applyMaterials,\n applyRenderer,\n background,\n enabled,\n fogFar,\n fogNear,\n gl,\n invalidate,\n materialFilter,\n scenario,\n scene,\n ]);\n}\n\n/**\n * Renderer-agnostic Gaussian splat environment boundary.\n *\n * This component intentionally does not import a specific 3DGS renderer. Pass a\n * Spark/GaussianSplats3D object as `children` once the app chooses a renderer,\n * and pass MuJoCo/MJCF collision proxy visuals via `collisionProxy`.\n */\nexport function SplatEnvironment({\n environment,\n scenario,\n renderer,\n src,\n format,\n collisionProxy,\n collisionProxyMetadata,\n children,\n showPlaceholder = true,\n ...groupProps\n}: SplatEnvironmentProps) {\n const metadata = useSplatEnvironment({\n environment,\n scenario,\n renderer,\n src,\n format,\n collisionProxy: collisionProxyMetadata,\n });\n const existingUserData =\n typeof groupProps.userData === 'object' && groupProps.userData !== null\n ? groupProps.userData\n : {};\n\n return (\n <group\n {...groupProps}\n userData={{\n ...existingUserData,\n ...metadata.userData,\n }}\n >\n {children}\n {children || !showPlaceholder ? null : <SplatPlaceholder />}\n {collisionProxy}\n </group>\n );\n}\n\nexport function useSplatEnvironment({\n environment,\n scenario,\n renderer,\n src,\n format,\n collisionProxy,\n}: SplatEnvironmentMetadataInput): SplatEnvironmentMetadata {\n const scenarioEnvironment = useMemo(\n () =>\n environment ??\n (scenario\n ? createPairedSplatEnvironment(scenario, { renderer })\n : undefined),\n [environment, renderer, scenario]\n );\n const resolvedSrc = src ?? scenarioEnvironment?.splat.src ?? scenario?.splat?.src;\n const resolvedFormat =\n format ??\n scenarioEnvironment?.splat.format ??\n scenario?.splat?.format ??\n 'spz';\n const resolvedCollisionProxy =\n collisionProxy ??\n scenarioEnvironment?.collisionProxy ??\n scenario?.splat?.collisionProxy ??\n undefined;\n\n return useMemo(\n () => ({\n src: resolvedSrc,\n format: resolvedFormat,\n collisionProxy: resolvedCollisionProxy,\n userData: createSplatEnvironmentUserData({\n environment: scenarioEnvironment,\n src: resolvedSrc,\n format: resolvedFormat,\n collisionProxy: resolvedCollisionProxy,\n }),\n }),\n [scenarioEnvironment, resolvedSrc, resolvedFormat, resolvedCollisionProxy]\n );\n}\n\n/**\n * Convert a generic visual scenario splat block into a paired visual/physics\n * environment config. Returns undefined until both the splat asset and MJCF\n * collision proxy are present.\n */\nexport function createPairedSplatEnvironment(\n scenario: Pick<VisualScenarioConfig, 'id' | 'label' | 'environment' | 'splat'>,\n options: {\n id?: string;\n label?: string;\n description?: string;\n renderer?: SplatRendererKind;\n } = {}\n): PairedSplatEnvironmentConfig | undefined {\n const splat = scenario.splat;\n const collisionProxy = splat?.collisionProxy;\n\n if (!splat?.enabled || !splat.src || !collisionProxy?.xmlPath) {\n return undefined;\n }\n\n return {\n id: options.id ?? scenario.id ?? 'splat-environment',\n label: options.label ?? scenario.label ?? 'Gaussian splat environment',\n description:\n options.description ??\n (scenario.environment\n ? `Visual ${scenario.environment} splat paired with MJCF collision proxy.`\n : undefined),\n splat: {\n src: splat.src,\n format: splat.format ?? 'spz',\n renderer: options.renderer,\n },\n collisionProxy: {\n ...collisionProxy,\n xmlPath: collisionProxy.xmlPath,\n },\n };\n}\n\nfunction isPairedSplatEnvironment(input: SplatSceneInput): input is PairedSplatEnvironmentConfig {\n return !!input && 'collisionProxy' in input && 'splat' in input;\n}\n\nfunction sceneRelativePath(sceneConfig: SceneConfig, path: string): string {\n const src = sceneConfig.src;\n if (!src) return path;\n\n const base = src.endsWith('/') ? src : src + '/';\n if (path.startsWith(base)) return path.slice(base.length);\n return path;\n}\n\nfunction uniquePaths(paths: readonly string[]): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n for (const path of paths) {\n if (seen.has(path)) continue;\n seen.add(path);\n result.push(path);\n }\n return result;\n}\n\n/**\n * Compose a MuJoCo scene config with a paired splat collision proxy.\n *\n * This keeps the common hybrid setup declarative:\n * robot XML remains `sceneFile`, the `.spz` remains a visual-only layer, and\n * the paired MJCF collision proxy is added to `environmentFiles`.\n */\nexport function withSplatEnvironment(\n sceneConfig: SceneConfig,\n input: SplatSceneInput,\n options: { renderer?: SplatRendererKind } = {}\n): SceneConfig {\n const environment = isPairedSplatEnvironment(input)\n ? input\n : input\n ? createPairedSplatEnvironment(input, options)\n : undefined;\n const xmlPath = environment?.collisionProxy.xmlPath;\n if (!xmlPath) return sceneConfig;\n\n return {\n ...sceneConfig,\n environmentFiles: uniquePaths([\n ...(sceneConfig.environmentFiles ?? []),\n sceneRelativePath(sceneConfig, xmlPath),\n ]),\n };\n}\n\nexport function createSplatEnvironmentUserData({\n environment,\n src,\n format = 'spz',\n collisionProxy,\n}: {\n environment?: PairedSplatEnvironmentConfig;\n src?: string;\n format?: SplatFormat;\n collisionProxy?: SplatCollisionProxyConfig;\n}) {\n return {\n role: 'splat-environment',\n environmentId: environment?.id,\n environmentLabel: environment?.label,\n splatSrc: src,\n splatFormat: format,\n splatRenderer: environment?.splat.renderer,\n collisionProxyStatus: collisionProxy?.status ?? 'missing',\n collisionProxyXmlPath: collisionProxy?.xmlPath,\n collisionProxyPrimitives: collisionProxy?.primitives ?? [],\n };\n}\n\nexport function createSparkSplatViewerUrl({\n viewerUrl,\n splatSrc,\n}: {\n viewerUrl: string;\n splatSrc: string;\n}) {\n const url = new URL(viewerUrl, 'http://mujoco-react.local');\n url.searchParams.set('splat', splatSrc);\n return viewerUrl.startsWith('http') ? url.toString() : `${url.pathname}${url.search}`;\n}\n\nfunction SplatPlaceholder() {\n return (\n <group>\n <mesh position={[0, 0, 1.2]}>\n <boxGeometry args={[2.4, 2.4, 2.4]} />\n <meshBasicMaterial\n color=\"#8b8b8b\"\n transparent\n opacity={0.06}\n wireframe\n side={THREE.DoubleSide}\n />\n </mesh>\n </group>\n );\n}\n\nfunction createScenarioFog(\n scenario: VisualScenarioConfig,\n background: THREE.ColorRepresentation | undefined,\n fogNear: number | undefined,\n fogFar: number | undefined\n) {\n if (scenario.lighting === 'low-light') {\n return new THREE.Fog(\n background ?? getScenarioBackground(scenario.lighting),\n fogNear ?? 2.5,\n fogFar ?? 9\n );\n }\n\n if (scenario.lighting === 'warehouse') {\n return new THREE.Fog(\n background ?? getScenarioBackground(scenario.lighting),\n fogNear ?? 5,\n fogFar ?? 16\n );\n }\n\n return null;\n}\n\nfunction applyScenarioMaterials(\n scene: THREE.Scene,\n scenario: VisualScenarioConfig,\n snapshots: Map<\n THREE.Material,\n {\n color?: THREE.Color;\n roughness?: number;\n metalness?: number;\n }\n >,\n materialFilter: VisualScenarioEffectsProps['materialFilter']\n) {\n const materials = scenario.materials;\n if (!materials) return;\n\n scene.traverse((object) => {\n if (!(object instanceof THREE.Mesh)) {\n return;\n }\n\n for (const material of normalizeMaterials(object.material)) {\n const mutable = getMutableScenarioMaterial(material);\n if (!mutable) continue;\n if (materialFilter && !materialFilter(object, material)) continue;\n\n if (!snapshots.has(material)) {\n snapshots.set(material, {\n color: mutable.color.clone(),\n roughness: mutable.roughness,\n metalness: mutable.metalness,\n });\n }\n\n applyScenarioMaterial(mutable, object, scenario, materials);\n }\n });\n}\n\nfunction applyScenarioMaterial(\n material: THREE.MeshStandardMaterial | THREE.MeshPhysicalMaterial,\n object: THREE.Object3D,\n scenario: VisualScenarioConfig,\n materials: ScenarioMaterialConfig\n) {\n const seed = scenario.seed ?? 0;\n const objectKey = `${scenario.id ?? 'scenario'}:${object.name}:${material.name}:${seed}`;\n const variation = hashToUnitInterval(objectKey);\n\n if (materials.randomizeObjectColors) {\n material.color.setHSL(variation, 0.38, 0.42);\n }\n\n if (materials.randomizeTableMaterial) {\n material.roughness = clamp01(\n materials.roughness ?? 0.35 + variation * 0.45\n );\n material.metalness = clamp01(\n materials.metalness ?? variation * 0.12\n );\n }\n\n material.needsUpdate = true;\n}\n\nfunction normalizeMaterials(\n material: THREE.Material | THREE.Material[]\n): THREE.Material[] {\n return Array.isArray(material) ? material : [material];\n}\n\nfunction getMutableScenarioMaterial(\n material: THREE.Material\n): THREE.MeshStandardMaterial | THREE.MeshPhysicalMaterial | null {\n if (\n material instanceof THREE.MeshStandardMaterial ||\n material instanceof THREE.MeshPhysicalMaterial\n ) {\n return material;\n }\n\n return null;\n}\n\nfunction hashToUnitInterval(value: string) {\n let hash = 2166136261;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0) / 4294967295;\n}\n\nfunction clamp01(value: number) {\n return Math.max(0, Math.min(1, value));\n}\n\nexport type SplatCollisionProxy = ReactNode | ThreeElements['group'];\n"]}
|