> ## Documentation Index
> Fetch the complete documentation index at: https://dadd.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# SplatEnvironment

> Composable Gaussian splat environment boundaries and optional Spark rendering

`mujoco-react` treats Gaussian splats as visual environments and MuJoCo XML as physics truth.
For realistic robot workflows, pair each `.spz`, `.ply`, or `.splat` visual asset with MJCF
collision geometry that provides contacts, friction, and task fixtures.

If a splat is intentionally visual-only, set `requiresCollisionProxy: false` on
the scenario. `useSparkSplatEnvironment` will still pass the visual `src` and
`format` to the renderer, while `withSplatEnvironment` leaves the MuJoCo
`sceneConfig` unchanged because there is no collision XML to add.

## Renderer-Agnostic Boundary

Use `useSplatSceneConfig` and `SplatEnvironment` from the main package when the
app owns the renderer or when you want metadata and collision proxy composition
without adding a splat renderer dependency. For scenario-driven apps, pass the
scenario directly; the hook resolves the visual asset and MJCF collision proxy
metadata without app-side prop reshaping.

```tsx theme={null}
import { MujocoCanvas, SplatEnvironment, useSplatSceneConfig } from "mujoco-react";

function Scene({ config, scenario }) {
  const splat = useSplatSceneConfig({ sceneConfig: config, scenario });

  return (
    <MujocoCanvas config={splat.sceneConfig}>
      {splat.environment ? (
        <SplatEnvironment
          environment={splat.environment}
          renderer="custom"
          collisionProxy={<LabCollisionPreview />}
        >
          <MySplatRenderer src={splat.environment.splat.src} />
        </SplatEnvironment>
      ) : null}
    </MujocoCanvas>
  );
}
```

Use `createSplatSceneConfig` for the same resolution behavior outside React,
such as import validators, codegen, backend handoff metadata, or tests:

```tsx theme={null}
import { createSplatSceneConfig } from "mujoco-react";

const splat = createSplatSceneConfig({
  sceneConfig: config,
  scenario,
  renderer: "spark",
});
```

`SplatEnvironment` writes stable `userData` onto its group:

* `role: "splat-environment"`
* `splatSrc`
* `splatFormat`
* `collisionProxyStatus`
* `collisionProxyXmlPath`
* `collisionProxyPrimitives`

## Visual Scenario Effects

Use `VisualScenarioEffects` next to `ScenarioLighting` to make visual scenario metadata
affect the actual Three scene. It applies camera exposure, optional background/fog, and
deterministic material variation without changing MuJoCo physics.

```tsx theme={null}
import {
  ScenarioLighting,
  VisualScenarioEffects,
} from "mujoco-react";

function Scene({ scenario }) {
  return (
    <MujocoCanvas config={config}>
      <VisualScenarioEffects
        scenario={scenario}
        applyBackground={!scenario.splat?.enabled}
        materialFilter={({ object }) => object.name.startsWith("prop_")}
      />
      <ScenarioLighting preset={scenario.lighting} />
    </MujocoCanvas>
  );
}
```

## Spark Renderer

Install Spark in apps that want first-class `.spz` rendering:

```bash theme={null}
npm install @sparkjsdev/spark
```

Then import the optional adapter from `mujoco-react/spark`:

```tsx theme={null}
import { MujocoCanvas } from "mujoco-react";
import {
  SparkSplatEnvironment,
  useSparkSplatEnvironment,
} from "mujoco-react/spark";

function Scene({ scenario }) {
  const splat = useSparkSplatEnvironment({ sceneConfig: config, scenario });

  return (
    <MujocoCanvas config={splat.sceneConfig} gl={{ preserveDrawingBuffer: true }}>
      {splat.props.src ? (
        <SparkSplatEnvironment hideGroundMeshes {...splat.props} />
      ) : null}
      <StatusBadge
        status={splat.lifecycle.status}
        error={splat.lifecycle.error}
      />
    </MujocoCanvas>
  );
}
```

`SparkSplatEnvironment` dynamically imports `@sparkjsdev/spark`, creates a `SparkRenderer`,
adds a `SplatMesh` to the same Three scene, and leaves MuJoCo bodies in the same render pass.
That mirrors the same-scene approach used by MuJoCo-GS-Web: splats provide visuals, while MJCF
continues to provide contacts and robot physics.

Spark rendering currently supports `.spz` assets. If a scenario points at `.ply` or `.splat`,
`SparkSplatEnvironment` reports `status: "error"` through `useSparkSplatLifecycle` so the app can
show a clear unsupported-format state. Keep using `SplatEnvironment` for renderer-agnostic metadata
or when integrating a different splat renderer.

Use `renderTuning` to adjust the live Spark renderer and `captureTuning` to
adjust offscreen camera-frame capture independently:

```tsx theme={null}
<SparkSplatEnvironment
  {...splat.props}
  renderTuning={{ lodSplatScale: 0.75, minSortIntervalMs: 50 }}
  captureTuning={{ lodSplatScale: 1.4, lodRenderScale: 0.45, maxWarmupFrames: 6 }}
/>
```

The default live tuning favors interactive frame rate. The default capture
tuning favors sharper snapshots and retries the first offscreen render if Spark
has not produced visible splats yet.

Use `useSparkSplatEnvironment` for the Spark path. It builds on
`useSplatSceneConfig`, adds paired collision proxy XML to the MuJoCo
`sceneConfig`, and returns lifecycle props for `SparkSplatEnvironment`. For
visual-only scenarios with `requiresCollisionProxy: false`, it returns the
original `sceneConfig` and passes `scenario`, `src`, and `format` through
`props` so the splat renderer can still load the visual layer.

`useSplatSceneConfig`, `useSparkSplatEnvironment`, and
`getSplatEnvironmentReadiness` expose the same readiness contract:

* `disabled`
* `missing-splat`
* `missing-collision-proxy`
* `unsupported-format`
* `ready`

Use this status for import screens and scenario editors instead of treating a
missing environment as a generic falsey value.

Use `createVisualScenarioExecutionContext()` when the app needs a serializable
record of the visual conditions used for a rollout, dataset episode, or training
handoff. The helper resolves camera exposure/noise/blur/jitter, material
randomization, splat source, collision proxy metadata, and readiness from the
same scenario object used by `SplatEnvironment`.

```tsx theme={null}
import { createVisualScenarioExecutionContext } from "mujoco-react";

const visualExecutionContext = createVisualScenarioExecutionContext({
  scenario,
  renderer: "spark",
  variantId,
});
```

Use `useSparkSplatLifecycle` directly when the app owns scene-config composition
but still needs status badges, loading affordances, or error messages around the
splat renderer. The hook returns:

* `status: "idle" | "loading" | "ready" | "error"`
* `error: Error | null`
* `isLoading`, `isReady`, and `isError`
* `props`, which can be spread onto `SparkSplatEnvironment`
* `reset()`, for retry flows

## Props

<ParamField body="src" type="string">
  URL for the visual splat asset.
</ParamField>

<ParamField body="format" type="&#x22;spz&#x22; | &#x22;ply&#x22; | &#x22;splat&#x22;" default="&#x22;spz&#x22;">
  Format metadata for the splat asset. `SparkSplatEnvironment` currently renders `.spz`.
</ParamField>

<ParamField body="collisionProxyMetadata" type="SplatCollisionProxyConfig">
  MJCF/XML collision proxy metadata to preserve alongside scene variants, rollouts, and datasets.
</ParamField>

<ParamField body="environment" type="PairedSplatEnvironmentConfig">
  Paired visual/physics environment config. Use `createPairedSplatEnvironment(scenario)`
  when the app stores splat data inside visual scenarios.
</ParamField>

<ParamField body="scenario" type="VisualScenarioConfig">
  Visual scenario metadata with an optional `splat` block. When present, this is enough
  for `SplatEnvironment` and `SparkSplatEnvironment` to resolve `src`, `format`, and
  collision proxy metadata.
</ParamField>

<ParamField body="collisionProxy" type="ReactNode">
  Optional R3F preview geometry for the collision proxy.
</ParamField>

<ParamField body="hideGroundMeshes" type="boolean" default="false">
  Hide meshes whose names include floor, ground, or plane while the splat is active.
</ParamField>

<ParamField body="onStatusChange" type="(status: &#x22;idle&#x22; | &#x22;loading&#x22; | &#x22;ready&#x22; | &#x22;error&#x22;) => void">
  Called as Spark loading progresses.
</ParamField>
