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

# Rendering Marble SPZ files in third-party engines

> Apply Marble splat scale metadata when rendering SPZ assets outside Marble.

Marble SPZ files are exported in the generated asset coordinate frame. When you
render them outside Marble, use `assets.splats.semantics_metadata` to convert
Gaussian centers and Gaussian sizes into metric, ground-aligned coordinates.

## Read the scale metadata

Completed world responses include SPZ URLs and scale metadata together:

```json theme={null}
{
  "assets": {
    "splats": {
      "spz_urls": {
        "500k": "<500k_spz_url>",
        "100k": "<100k_spz_url>",
        "full_res": "<full_res_spz_url>"
      },
      "semantics_metadata": {
        "metric_scale_factor": 1.23,
        "ground_plane_offset": 0.42
      }
    }
  }
}
```

The numeric values in this example are representative, not fixed constants. Use
the values returned with the world you are rendering.

`metric_scale_factor` converts raw generated asset units to meters.
`ground_plane_offset` places the metric ground plane at `y = 0`.

## Apply center and size scale

Apply scale to Gaussian centers and Gaussian sizes:

```python theme={null}
def to_metric_gaussian(center, linear_scale, semantics):
    scale = semantics["metric_scale_factor"]
    metric_center = center * scale
    metric_center[..., 1] -= semantics["ground_plane_offset"]

    metric_linear_scale = linear_scale * scale
    return metric_center, metric_linear_scale
```

The ground-plane offset applies only to Gaussian centers. Do not apply
`ground_plane_offset` to Gaussian sizes.

## Handle log-scale fields

Some Gaussian splat formats expose `scale_0`, `scale_1`, and `scale_2` as
log-space values. If your decoder gives you log scales, add the logarithm of the
metric scale instead of multiplying the log values directly:

```python theme={null}
import math


def to_metric_log_scale(log_scale, semantics):
    return log_scale + math.log(semantics["metric_scale_factor"])
```

Equivalently, convert to linear scale first:

```python theme={null}
import numpy as np


linear_scale = np.exp(log_scale)
metric_linear_scale = linear_scale * semantics["metric_scale_factor"]
metric_log_scale = np.log(metric_linear_scale)
```

Multiplying `scale_0`, `scale_1`, and `scale_2` directly is only correct if
your decoder exposes those fields as linear sizes.

## Convert renderer axes separately

`semantics_metadata` converts raw Marble SPZ coordinates to a metric,
ground-aligned frame. It does not include renderer-specific axis conversion.

Generated Marble SPZ assets use the `marble_raw_opencv` convention. If your
engine uses an OpenGL or Three.js-style frame, apply your engine's axis
conversion after applying metric scale and ground alignment. Marble's web
viewer applies a 180 degree rotation around the X axis for generated SPZ assets.
