diff --git a/docs/tutorials/gaussian-splat-streaming-lod.md b/docs/tutorials/gaussian-splat-streaming-lod.md index 05d44330aa0..0f5648e1bd4 100644 --- a/docs/tutorials/gaussian-splat-streaming-lod.md +++ b/docs/tutorials/gaussian-splat-streaming-lod.md @@ -1,13 +1,13 @@ --- -title: '3D Gaussian Splat Streaming LOD' -description: Stream huge Gaussian splat scenes with spatial LOD and SOG ordering so large environments load progressively. +title: '3D Gaussian Splat Streamed SOG' +description: Stream huge Gaussian splat scenes with Streamed SOG so large environments load progressively. tags: [gaussiansplatting, tutorial] thumb: https://s3-eu-west-1.amazonaws.com/images.playcanvas.com/projects/12/1408991/3CA651-image-75.jpg --- import Link from '@docusaurus/Link'; -An example project showing how to use PlayCanvas' streaming LOD format based on [SOG](/user-manual/gaussian-splatting/formats/sog) (Spatially Ordered Gaussians). The environment being streamed is the Church of Saints Peter and Paul. +An example project showing how to use PlayCanvas' [Streamed SOG](/user-manual/gaussian-splatting/formats/streamed-sog) format, based on [SOG](/user-manual/gaussian-splatting/formats/sog) (Spatially Ordered Gaussians). The environment being streamed is the Church of Saints Peter and Paul.
diff --git a/docs/user-manual/gaussian-splatting/building/lod-streaming.md b/docs/user-manual/gaussian-splatting/building/lod-streaming.md index 2114a6748f0..2a172b226dc 100644 --- a/docs/user-manual/gaussian-splatting/building/lod-streaming.md +++ b/docs/user-manual/gaussian-splatting/building/lod-streaming.md @@ -1,49 +1,49 @@ --- -title: LOD Streaming -description: "LOD streaming for large splat scenes: octree layout, generating lod-meta data, examples, and performance guidance." +title: Streamed SOG +description: "Streamed SOG for large splat scenes: spatial tree layout, generating lod-meta data, examples, and performance guidance." --- -LOD (Level of Detail) Streaming enables efficient rendering of large Gaussian splat scenes by dynamically loading appropriate levels of detail based on the camera's distance. This feature dramatically reduces memory usage and improves rendering performance for large-scale splat scenes. +Streamed SOG enables efficient rendering of large Gaussian splat scenes by dynamically loading appropriate levels of detail (LOD) based on the camera's distance. This dramatically reduces memory usage and improves rendering performance for large-scale splat scenes. ## How It Works -LOD streaming works by: +Streamed SOG works by: 1. Pre-generating multiple versions of your splat at different detail levels -2. Organizing them into an octree structure for efficient streaming +2. Organizing them into a spatial tree structure for efficient streaming 3. Dynamically loading and unloading detail levels based on camera distance 4. Rendering only the appropriate level of detail for each region of the scene This approach allows you to render massive splat scenes that would otherwise be impossible due to memory constraints. -## Creating LOD Streaming Data +## Creating Streamed SOG Data -To use LOD streaming, you need to generate the streaming format — an octree-based `lod-meta.json` structure that organizes multiple levels of detail for efficient streaming. There are two ways to obtain the LOD levels: +To use Streamed SOG, you need to generate the format — a `lod-meta.json` spatial tree structure that organizes multiple levels of detail for efficient streaming (see the [Streamed SOG Format Specification](/user-manual/gaussian-splatting/formats/streamed-sog)). There are two ways to obtain the LOD levels: - **Provide your own LOD levels** — supply multiple splat files at progressively lower detail (LOD 0 = highest detail, higher numbers = lower detail), for example produced during training or exported separately. - **Generate them with SplatTransform** — use [SplatTransform](/user-manual/splat-transform) to decimate a single high-quality splat into lower-detail levels, so you don't have to author them yourself. -Once you have the LOD levels, SplatTransform bundles them into the streaming-optimized format. See the [Generating LOD Format](/user-manual/splat-transform#generating-lod-format) section in the SplatTransform documentation for detailed instructions. +Once you have the LOD levels, SplatTransform bundles them into the Streamed SOG format. See the [Generating Streamed SOG](/user-manual/splat-transform#generating-lod-format) section in the SplatTransform documentation for detailed instructions. ## Live Examples -Explore these live examples to see LOD streaming in action: +Explore these live examples to see Streamed SOG in action: -- LOD Streaming (Basic) - Demonstrates basic LOD streaming with different detail levels +- Streamed SOG (Basic) - Demonstrates basic streaming with different detail levels - + -- LOD Streaming with Spherical Harmonics - Shows LOD streaming with spherical harmonic data +- Streamed SOG with Spherical Harmonics - Shows streaming with spherical harmonic data - + -## Enabling LOD Streaming +## Enabling Streamed SOG -LOD streaming is enabled simply by loading a streaming LOD format asset (`lod-meta.json`) onto a GSplat component — no additional configuration is required. +Streaming is enabled simply by loading a Streamed SOG asset (`lod-meta.json`) onto a GSplat component — no additional configuration is required. ## Controlling LOD Behavior -You can control and fine-tune LOD streaming using the following APIs: +You can control and fine-tune streaming behavior using the following APIs: ### Component-Level Control @@ -54,7 +54,7 @@ entity.gsplat.lodBaseDistance = 10; // distance for the first LOD transition entity.gsplat.lodMultiplier = 2; // each successive threshold is 2x farther ``` -The default multiplier of 2 gives perceptually uniform transitions under perspective projection. The system also compensates for camera FOV automatically. +The multiplier defaults to 3 (and is clamped to a minimum of 1.2) — each LOD transition happens at three times the previous distance. The system also compensates for camera FOV automatically. ### Scene-Level Control @@ -73,32 +73,32 @@ const gsplatSettings = app.scene.gsplat; // (See API documentation for available properties) ``` -The most important scene-level setting for LOD streaming is the global splat budget, which automatically balances detail across all GSplat assets to hit a target splat count. See [Global Splat Budget](/user-manual/gaussian-splatting/building/performance#global-splat-budget) in the Performance section for details. +The most important scene-level setting for Streamed SOG is the global splat budget, which automatically balances detail across all GSplat assets to hit a target splat count. See [Global Splat Budget](/user-manual/gaussian-splatting/building/performance#global-splat-budget) in the Performance section for details. -## Using LOD Streaming in the Editor +## Using Streamed SOG in the Editor -Native support for LOD streaming in the PlayCanvas Editor will be added in the near future. In the meantime, you can use the Engine API in scripts to enable streaming LOD functionality in your Editor projects. +Native support for Streamed SOG in the PlayCanvas Editor will be added in the near future. In the meantime, you can use the Engine API in scripts to enable Streamed SOG functionality in your Editor projects. ### Sample Project -We've created a sample project that demonstrates how to use streaming LOD with Gaussian splats in the PlayCanvas Editor: +We've created a sample project that demonstrates how to use Streamed SOG with Gaussian splats in the PlayCanvas Editor: **[Church of Saints Peter and Paul](https://playcanvas.com/project/1408991/overview/church-of-saints-peter-and-paul)** -This project showcases a large-scale Gaussian splat scene with LOD streaming, including custom reveal shader effects. +This project showcases a large-scale Gaussian splat scene with Streamed SOG, including custom reveal shader effects. ### Using the Streamed GSplat Script -The sample project includes a `streamed-gsplat.mjs` script that can be added to any Entity to enable LOD streaming: +The sample project includes a `streamed-gsplat.mjs` script that can be added to any Entity to enable Streamed SOG: #### Setup Steps 1. Add the script to an Entity in your scene -2. Configure the `splatUrl` property to point to an externally hosted LOD splat format file +2. Configure the `splatUrl` property to point to an externally hosted Streamed SOG file :::note External Hosting -Currently, the LOD splat data needs to be hosted externally (not as an Editor asset). This limitation will be removed in the future when native Editor support for streaming LOD format is added. +Currently, the Streamed SOG data needs to be hosted externally (not as an Editor asset). This limitation will be removed in the future when native Editor support for Streamed SOG is added. ::: @@ -125,15 +125,15 @@ This demonstrates the flexibility of the PlayCanvas Engine's shader system for c ### Future Editor Improvements -As native Editor support for streaming LOD is added, the following improvements are planned: +As native Editor support for Streamed SOG is added, the following improvements are planned: -- **Direct Asset Import**: Upload LOD splat files directly as Editor assets (no external hosting needed) +- **Direct Asset Import**: Upload Streamed SOG files directly as Editor assets (no external hosting needed) - **Visual Configuration**: Configure LOD settings through the Editor UI instead of script properties -- **Preview in Editor**: View and test streaming LOD behavior directly in the Editor viewport +- **Preview in Editor**: View and test streaming behavior directly in the Editor viewport ## Benefits -- **Better Performance**: LOD streaming reduces memory usage and improves rendering performance for large scenes +- **Better Performance**: Streamed SOG reduces memory usage and improves rendering performance for large scenes - **Scalability**: Enables rendering of much larger Gaussian splat scenes by dynamically loading appropriate detail levels - **Flexibility**: Provides fine-grained control over LOD distances and streaming behavior - **Optimized Loading**: Only loads the data needed for the current view @@ -143,6 +143,7 @@ As native Editor support for streaming LOD is added, the following improvements - [GSplatComponent API](https://api.playcanvas.com/engine/classes/GSplatComponent.html) - [Scene.gsplat API](https://api.playcanvas.com/engine/classes/Scene.html#gsplat) - [SplatTransform CLI Tool](/user-manual/splat-transform) -- [Generating LOD Format](/user-manual/splat-transform#generating-lod-format) +- [Generating Streamed SOG](/user-manual/splat-transform#generating-lod-format) +- [Streamed SOG Format Specification](/user-manual/gaussian-splatting/formats/streamed-sog) - [Splat Rendering Architecture](/user-manual/gaussian-splatting/rendering-architecture) - [Custom Shaders](/user-manual/gaussian-splatting/building/custom-shaders) diff --git a/docs/user-manual/gaussian-splatting/building/performance.md b/docs/user-manual/gaussian-splatting/building/performance.md index 109471ebe85..250cc3f5bcb 100644 --- a/docs/user-manual/gaussian-splatting/building/performance.md +++ b/docs/user-manual/gaussian-splatting/building/performance.md @@ -1,6 +1,6 @@ --- title: Performance -description: "Performance tips for splat scenes: splat counts, fill rate, scene settings, LOD streaming budgets, and optimization strategies." +description: "Performance tips for splat scenes: splat counts, fill rate, scene settings, Streamed SOG budgets, and optimization strategies." --- Rendering splats can be expensive on both the CPU and GPU. Here are some strategies to achieve good performance: @@ -9,7 +9,7 @@ Rendering splats can be expensive on both the CPU and GPU. Here are some strateg Be mindful of the number of Gaussians in your scene since every Gaussian is sorted on camera depth every frame. You can check the number contained within a particular GSplat asset by using the [SPLAT DATA Panel](/user-manual/supersplat/editor/data-panel/) in the [SuperSplat Editor](/user-manual/supersplat/editor/). Use SuperSplat to trim unwanted Gaussians from your PLY files. -For large scenes, consider using [LOD Streaming](/user-manual/gaussian-splatting/building/lod-streaming) which dynamically loads appropriate levels of detail based on camera distance. This significantly reduces the number of active Gaussians at any given time while maintaining visual quality where it matters most. +For large scenes, consider using [Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming) which dynamically loads appropriate levels of detail based on camera distance. This significantly reduces the number of active Gaussians at any given time while maintaining visual quality where it matters most. ## Fill Rate Considerations @@ -30,13 +30,13 @@ Given the fragment-heavy nature of Gaussian splatting, these settings have a sig Both settings help reduce the fragment processing load, which is the primary bottleneck in 3DGS rendering. -## LOD Streaming Configuration +## Streamed SOG Configuration -When using [LOD Streaming](/user-manual/gaussian-splatting/building/lod-streaming), you have several options to control quality and performance. The recommended approach is to use the **global splat budget** which automatically manages LOD selection across all GSplat assets in your scene. +When using [Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming), you have several options to control quality and performance. The recommended approach is to use the **global splat budget** which automatically manages LOD selection across all GSplat assets in your scene. ### Global Splat Budget -The global splat budget is the primary way to control rendering performance for LOD streaming. Set it via: +The global splat budget is the primary way to control rendering performance for Streamed SOG. Set it via: ```javascript app.scene.gsplat.splatBudget = 4000000; // 4 million splats max @@ -47,7 +47,7 @@ When a budget is set, the engine automatically adjusts LOD levels across all GSp - **Budget = 0**: Disables budget enforcement, using only distance-based LOD selection - **Budget > 0**: Enforces the specified maximum splat count across all GSplat assets -The budget system accounts for all GSplat assets in the scene, including both LOD-streaming assets (with multiple detail levels) and fixed assets (single detail level). +The budget system accounts for all GSplat assets in the scene, including both Streamed SOG assets (with multiple detail levels) and fixed assets (single detail level). ### LOD Distances @@ -88,7 +88,7 @@ The approach has two steps: ```javascript const gsplatSystem = app.systems.gsplat; -// `entity` has a gsplat component using a loaded LOD-streaming asset +// `entity` has a gsplat component using a loaded Streamed SOG asset const gsplat = entity.gsplat; // 1. Start with the lowest (coarsest) LOD only, for the fastest first frame @@ -113,7 +113,7 @@ const onFrameReady = (camera, layer, ready, loadingCount) => { gsplatSystem.on('frame:ready', onFrameReady); ``` -This technique is demonstrated in the live [LOD Streaming example](/user-manual/gaussian-splatting/building/lod-streaming#live-examples). +This technique is demonstrated in the live [Streamed SOG example](/user-manual/gaussian-splatting/building/lod-streaming#live-examples). ### Recommended Configuration diff --git a/docs/user-manual/gaussian-splatting/formats/index.md b/docs/user-manual/gaussian-splatting/formats/index.md index 953b4fa0a15..02842d3236d 100644 --- a/docs/user-manual/gaussian-splatting/formats/index.md +++ b/docs/user-manual/gaussian-splatting/formats/index.md @@ -1,9 +1,9 @@ --- title: Splat File Formats -description: "Compare PLY and SOG splat formats for editing versus web delivery, size and quality trade-offs, and typical conversion workflows." +description: "Compare PLY, SOG and Streamed SOG splat formats for editing versus web delivery, size and quality trade-offs, and typical conversion workflows." --- -PlayCanvas supports two formats for 3D Gaussian Splat data: +PlayCanvas supports three formats for 3D Gaussian Splat data: ## [PLY Format](./ply.md) - Source & Interchange @@ -21,17 +21,26 @@ Compressed format optimized for web delivery. 15-20× smaller than PLY with loss - **File size**: Small (compressed) - **Quality**: Visually optimized +## [Streamed SOG Format](./streamed-sog.md) - Large-Scene Streaming + +SOG chunks organized into a spatial tree with multiple levels of detail. Viewers stream in only the chunks and detail levels needed for the current camera. + +- **Use for**: Very large scenes (tens of millions of Gaussians), progressive loading +- **File size**: Small per chunk, loaded on demand +- **Quality**: Visually optimized, view-dependent detail + ## Quick Comparison -| | PLY | SOG | -|---|---|---| -| **Size** | Large | Small (15-20× compression) | -| **Quality** | Lossless | Lossy | -| **Use** | Source/editing | Runtime/delivery | -| **Speed** | Slow loading | Fast loading | +| | PLY | SOG | Streamed SOG | +|---|---|---|---| +| **Size** | Large | Small (15-20× compression) | Small (SOG chunks, loaded on demand) | +| **Quality** | Lossless | Lossy | Lossy, view-dependent detail | +| **Use** | Source/editing | Runtime/delivery | Very large scenes | +| **Speed** | Slow loading | Fast loading | Progressive streaming | ## Workflow 1. Train and edit with **PLY** 2. Convert to **SOG** for production using [SplatTransform](/user-manual/splat-transform/) -3. Deploy SOG files for optimal performance +3. For very large scenes, convert to **Streamed SOG** instead +4. Deploy for optimal performance diff --git a/docs/user-manual/gaussian-splatting/formats/sog.md b/docs/user-manual/gaussian-splatting/formats/sog.md index 5530a8f46c4..36ce073b044 100644 --- a/docs/user-manual/gaussian-splatting/formats/sog.md +++ b/docs/user-manual/gaussian-splatting/formats/sog.md @@ -76,7 +76,7 @@ interface Meta { generator?: string; // e.g. "splat-transform v1.2.3" }; count: number; // Number of gaussians (<= W*H of the images) - antialias: boolean; // True iff scene was trained with anti-aliasing + antialias?: boolean; // Optional. True iff scene was trained with anti-aliasing. Default: false means: { // Ranges for decoding *log-transformed* positions (see §3.1). @@ -86,7 +86,7 @@ interface Meta { }; scales: { - codebook: number[]; // 256 floats; see §3.3 + codebook: number[]; // 256 floats (log-domain); see §3.3 files: ["scales.webp"]; }; @@ -114,7 +114,7 @@ interface Meta { :::note -* The scales codebook contains linear-space values. The sh0 codebook contains gamma-space DC coefficients. The shN codebook contains gamma-space AC coefficients. +* The scales codebook contains log-space values that must be passed through `exp()` to recover linear sizes (§3.3). The sh0 codebook contains gamma-space DC coefficients. The shN codebook contains gamma-space AC coefficients. * Image data **must** be treated as raw 8-bit integers (no gamma conversion). * Unless otherwise stated, channels not mentioned are ignored. * Filenames in `files` arrays are arbitrary, but the order is significant. @@ -158,8 +158,10 @@ const p = { Quaternions are encoded with **3×8-bit components + 2-bit mode** (total **26 bits**) using the standard *smallest-three* scheme. -* **R,G,B** store the three kept (signed) components, uniformly quantized to `[-√2/2, +√2/2]`. -* **A** stores the **mode** in the range **252..255**. The mode is `A - 252` ∈ {0,1,2,3} and identifies which of the four components was the **largest by magnitude** (and therefore omitted from the stream and reconstructed). +Quaternion components are ordered **(w, x, y, z)** throughout. + +* **R,G,B** store the three kept (signed) components in **(w, x, y, z)** order, uniformly quantized to `[-√2/2, +√2/2]`. +* **A** stores the **mode** in the range **252..255**. The mode is `A - 252` ∈ {0,1,2,3} and identifies which of the four components — in **(w, x, y, z)** order — was the **largest by magnitude** (and therefore omitted from the stream and reconstructed): mode 0 = w, 1 = x, 2 = y, 3 = z. * Let `norm = Math.SQRT2` (i.e., √2). ```ts @@ -170,19 +172,19 @@ const a = toComp(quats.r); const b = toComp(quats.g); const c = toComp(quats.b); -const mode = quats.a - 252; // 0..3 (R,G,B,A is one of the four components) +const mode = quats.a - 252; // 0..3 → omitted component is w, x, y or z respectively // Reconstruct the omitted component so that ||q|| = 1 and w.l.o.g. the omitted one is non-negative const t = a*a + b*b + c*c; const d = Math.sqrt(Math.max(0, 1 - t)); -// Place components according to mode +// Place components according to mode; q is ordered [w, x, y, z] let q: [number, number, number, number]; switch (mode) { - case 0: q = [d, a, b, c]; break; // omitted = x - case 1: q = [a, d, b, c]; break; // omitted = y - case 2: q = [a, b, d, c]; break; // omitted = z - case 3: q = [a, b, c, d]; break; // omitted = w + case 0: q = [d, a, b, c]; break; // omitted = w + case 1: q = [a, d, b, c]; break; // omitted = x + case 2: q = [a, b, d, c]; break; // omitted = y + case 3: q = [a, b, c, d]; break; // omitted = z default: throw new Error("Invalid quaternion mode"); } ``` @@ -195,15 +197,15 @@ switch (mode) { > `scales.webp` (RGB via codebook) -Per-axis sizes are **codebook indices**: +Per-axis sizes are **codebook indices**. The codebook stores **log-domain** values, so decoding requires an exponential: ```ts -const sx = meta.scales.codebook[scales.r]; // 0..255 -const sy = meta.scales.codebook[scales.g]; -const sz = meta.scales.codebook[scales.b]; +const sx = Math.exp(meta.scales.codebook[scales.r]); // r,g,b are 0..255 +const sy = Math.exp(meta.scales.codebook[scales.g]); +const sz = Math.exp(meta.scales.codebook[scales.b]); ``` -Interpretation (e.g., principal axis standard deviations vs. full extents) follows the source training setup; values are in **scene units**. +Interpretation (e.g., principal axis standard deviations vs. full extents) follows the source training setup; decoded (post-`exp`) values are in **scene units**. ### 3.4 Base color + opacity (DC) diff --git a/docs/user-manual/gaussian-splatting/formats/streamed-sog.md b/docs/user-manual/gaussian-splatting/formats/streamed-sog.md new file mode 100644 index 00000000000..164e973d3bd --- /dev/null +++ b/docs/user-manual/gaussian-splatting/formats/streamed-sog.md @@ -0,0 +1,158 @@ +--- +title: The Streamed SOG Format +description: "Streamed SOG specification: lod-meta.json layout, spatial tree, LOD chunk references, and environment splats." +sidebar_label: Streamed SOG +--- + +**Streamed SOG** splits a Gaussian splat scene into spatial chunks at multiple levels of detail (LOD). A viewer walks a spatial tree to decide which chunks and detail levels to load for the current camera, allowing very large scenes (tens of millions of Gaussians) to load progressively and stay interactive. + +You can create Streamed SOG datasets with **[SplatTransform](https://github.com/playcanvas/splat-transform)** — see [Generating Streamed SOG](/user-manual/splat-transform/#generating-lod-format) for a step-by-step walkthrough. Individual chunks are standard [SOG](./sog.md) datasets. + +This document is the format specification. It describes **version 1**. + +## 1. File set + +A Streamed SOG dataset is a directory containing a single index file plus one subdirectory per chunk: + +```none +scene/ +├── lod-meta.json # index: scene info + spatial tree (this spec) +├── 0_0/ # LOD 0, chunk 0 — unbundled SOG (meta.json + .webp textures) +│ ├── meta.json +│ └── *.webp +├── 0_1/ # LOD 0, chunk 1 +├── 1_0/ # LOD 1, chunk 0 +├── … # one directory per {lod}_{chunk} +└── env/ # optional environment splats — unbundled SOG +``` + +* The index file is always named `lod-meta.json`. Loaders identify the format by this filename. +* Each chunk is a standard **unbundled** [SOG](./sog.md) dataset (a `meta.json` plus WebP texture files). Bundled (single-archive) SOG chunks are not part of this format. +* All paths in `lod-meta.json` are relative to the directory containing `lod-meta.json`. + +:::note[Chunk naming] + +The `{lod}_{chunk}/` directory naming is a convention of the writer. Readers **must** resolve chunk locations through the `filenames` array, not the naming pattern. + +::: + +--- + +## 2. `lod-meta.json` + +```ts +interface LodMeta { + version: 1; // File format version (integer) + asset?: { // Optional tool/version metadata + generator?: string; // e.g. "splat-transform v2.5.2" + }; + count: number; // Total gaussians across all LOD levels (excludes environment) + counts: number[]; // Gaussians per LOD level; index = LOD level, length = lodLevels + lodLevels: number; // Number of LOD levels + environment?: string; // Relative path to the environment SOG's meta.json; omitted if none + filenames: string[]; // Relative paths to chunk SOG meta.json files, referenced by index + tree: Node; // Root of the spatial tree +} + +interface Node { + bound: { + min: [number, number, number]; // AABB minimum [x, y, z] + max: [number, number, number]; // AABB maximum [x, y, z] + }; + children?: [Node, Node]; // Interior node: exactly two child nodes + lods?: { + [lodLevel: string]: { // Leaf node: map of LOD level → splat range + file: number; // Index into filenames + offset: number; // Index of the first splat within the chunk + count: number; // Number of consecutive splats + }; + }; +} +``` + +--- + +## 3. The spatial tree + +`tree` is a binary spatial subdivision of the scene. Every node carries an axis-aligned bounding box and is either an **interior node** (has `children`, always exactly two) or a **leaf node** (has `lods`) — never both. + +* A leaf's `bound` encloses the full extents of every Gaussian assigned to it — each Gaussian's position expanded by its rotated, scaled ellipsoid — not just the Gaussian centers. +* An interior node's `bound` is the union of its children's bounds. +* Bounds are expressed in the same coordinate frame as the splat positions stored in the chunk SOG files. + +### 3.1 LOD levels + +LOD level `0` is the highest detail; higher levels are progressively coarser. A leaf's `lods` object is keyed by the decimal string form of the LOD level (`"0"` … `"lodLevels - 1"`). A missing key means the leaf has no splats at that level. + +All LOD levels of a leaf cover the same spatial region — a viewer selects exactly one level per leaf based on, for example, distance to camera. + +### 3.2 Chunk references + +Each `lods` entry addresses a contiguous run of splats within one chunk: + +* `file` is an index into the top-level `filenames` array. +* `offset` and `count` select splats `[offset, offset + count)` in the chunk's storage order (splat indices, not bytes). In the chunk's SOG textures, storage order is row-major pixel order, so splat `i` lives at pixel `(i % W, floor(i / W))`. + +A chunk file's contents are exactly the concatenation of the leaf runs that reference it: the runs are non-overlapping and cover the chunk completely. Within each run, splats are sorted in Morton order for spatial locality; no ordering holds across run boundaries. A chunk only ever contains splats of a single LOD level. + +--- + +## 4. Environment + +The optional `environment` field points to a standard unbundled [SOG](./sog.md) dataset containing splats that are not part of the LOD/chunk streaming scheme — typically far-field background such as sky. A viewer **should** load and render the environment unconditionally, independent of the spatial tree. + +--- + +## 5. Precision + +Non-integer numbers in `lod-meta.json` are quantized to 7 significant digits (approximately 32-bit float precision). + +--- + +## 6. Example `lod-meta.json` + +A two-level scene with an environment, split into one interior node with two leaves: + +```json +{ + "version": 1, + "asset": { "generator": "splat-transform v2.5.2" }, + "count": 1500000, + "counts": [1000000, 500000], + "lodLevels": 2, + "environment": "env/meta.json", + "filenames": [ + "0_0/meta.json", + "1_0/meta.json" + ], + "tree": { + "bound": { "min": [-10, 0, -10], "max": [10, 5, 10] }, + "children": [ + { + "bound": { "min": [-10, 0, -10], "max": [0.5, 5, 10] }, + "lods": { + "0": { "file": 0, "offset": 0, "count": 600000 }, + "1": { "file": 1, "offset": 0, "count": 300000 } + } + }, + { + "bound": { "min": [0.5, 0, -10], "max": [10, 4.5, 10] }, + "lods": { + "0": { "file": 0, "offset": 600000, "count": 400000 }, + "1": { "file": 1, "offset": 300000, "count": 200000 } + } + } + ] + } +} +``` + +--- + +## 7. Versioning & compatibility + +* Files conforming to this specification have `version: 1`. Readers **should** reject files with a greater major version. +* Files produced before the format was versioned omit `version`, `asset`, `count` and `counts`, and may contain `"environment": null`. Readers that wish to support them **should** treat a missing `version` as pre-release and `environment: null` as no environment. +* Unknown fields **should** be ignored, allowing minor additive evolution without a version bump. + +--- diff --git a/docs/user-manual/gaussian-splatting/rendering-architecture/index.md b/docs/user-manual/gaussian-splatting/rendering-architecture/index.md index 2a50c086d48..b2a0d326cb3 100644 --- a/docs/user-manual/gaussian-splatting/rendering-architecture/index.md +++ b/docs/user-manual/gaussian-splatting/rendering-architecture/index.md @@ -3,7 +3,7 @@ title: Splat Rendering Architecture description: "How PlayCanvas renders Gaussian splats: the work buffer pipeline, global sorting across components, and access to advanced features." --- -PlayCanvas renders Gaussian splats through a shared pipeline that sorts all splats from every GSplat component together. This global sorting ensures correct rendering order across the entire scene and provides access to advanced features like procedural splats, LOD streaming, and GPU-based splat processing. +PlayCanvas renders Gaussian splats through a shared pipeline that sorts all splats from every GSplat component together. This global sorting ensures correct rendering order across the entire scene and provides access to advanced features like procedural splats, Streamed SOG, and GPU-based splat processing. ## Global Sorting @@ -43,7 +43,7 @@ flowchart LR GSplat resources are the source data for splats. They come in two forms: -1. **Loaded splats**: Imported from files (`.ply`, `.sog`) or streamed via [LOD streaming](/user-manual/gaussian-splatting/building/lod-streaming) +1. **Loaded splats**: Imported from files (`.ply`, `.sog`) or streamed via [Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming) 2. **Procedural splats**: Created programmatically using [GSplatContainer](/user-manual/gaussian-splatting/building/procedural-splats/) Each resource stores splat data in GPU textures according to a [data format](/user-manual/gaussian-splatting/rendering-architecture/splat-data-format). @@ -73,7 +73,7 @@ The Global Sorting example demonstrates how sorting all splats together eliminat - **Improved Visual Quality**: Eliminates artifacts when rendering multiple overlapping splat components - **Consistent Rendering**: Maintains correct depth sorting regardless of camera position - **Better Scene Composition**: Enables complex scenes with many splat components -- **Advanced Features**: Unlocks procedural splats, LOD streaming, and GPU processing +- **Advanced Features**: Unlocks procedural splats, Streamed SOG, and GPU processing ## Advanced Features @@ -81,7 +81,7 @@ The following features build on this rendering pipeline: - [Splat Data Format](/user-manual/gaussian-splatting/rendering-architecture/splat-data-format) - Custom texture formats for splat data - [Procedural Splats](/user-manual/gaussian-splatting/building/procedural-splats/) - Create splats programmatically -- [LOD Streaming](/user-manual/gaussian-splatting/building/lod-streaming) - Dynamic level-of-detail loading +- [Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming) - Dynamic level-of-detail loading - [Splat Processing](/user-manual/gaussian-splatting/rendering-architecture/splat-processing) - GPU-based splat manipulation ## See Also diff --git a/docs/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md b/docs/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md index 65a375b271f..8c91d1f0dd3 100644 --- a/docs/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md +++ b/docs/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md @@ -97,7 +97,7 @@ You can add extra streams to a resource's format to store custom per-splat data. :::note -Extra streams are not supported for LOD streaming resources. LOD resources dynamically load and unload data as needed, and custom extra streams cannot be preserved across these operations. +Extra streams are not supported for Streamed SOG resources. These resources dynamically load and unload data as needed, and custom extra streams cannot be preserved across these operations. ::: diff --git a/docs/user-manual/splat-transform/collision.md b/docs/user-manual/splat-transform/collision.md index 6a3579ea203..905db4d9ac4 100644 --- a/docs/user-manual/splat-transform/collision.md +++ b/docs/user-manual/splat-transform/collision.md @@ -11,7 +11,7 @@ For uploading or generating voxel collision through the SuperSplat web UI instea Two outputs are produced from the same voxelization pass: -- **`.voxel.json` / `.voxel.bin`** — sparse voxel octree (SVO) for raycasts and broad-phase collision queries. This is the format consumed by the [SuperSplat Viewer](/user-manual/supersplat/viewer/) for runtime collision detection. +- **`.voxel.json` / `.voxel.bin`** — sparse voxel octree (SVO) for raycasts and broad-phase collision queries. This is the format consumed by the [SuperSplat Viewer](/user-manual/supersplat/viewer/) for runtime collision detection. The on-disk structure is specified in the [Voxel Format](/user-manual/splat-transform/voxel-format) specification. - **`.collision.glb`** — triangulated mesh built from the voxel grid (only when `-K` / `--collision-mesh` is passed). A typical pipeline runs four stages, with the latter two being optional depending on the scene type: @@ -223,6 +223,7 @@ splat-transform input.ply \ ## See also +- [Voxel Format](/user-manual/splat-transform/voxel-format) — the on-disk format of `.voxel.json` / `.voxel.bin` output. - [splat-transform CLI reference](/user-manual/splat-transform/) — full option reference including Voxel Output Options. - [Docker Backend](/user-manual/splat-transform/docker) — running the GPU-only voxel/collision features in a container. - [Studio → Collision](/user-manual/supersplat/studio/collision) — uploading or generating voxel collision through the SuperSplat web UI. diff --git a/docs/user-manual/splat-transform/index.md b/docs/user-manual/splat-transform/index.md index eae1b675402..ffa425dc18e 100644 --- a/docs/user-manual/splat-transform/index.md +++ b/docs/user-manual/splat-transform/index.md @@ -189,7 +189,7 @@ Apply when reading `.lcc` files. ## LOD Output Options -Apply when writing `lod-meta.json` (multi-LOD streaming SOG bundle). +Apply when writing `lod-meta.json` ([Streamed SOG](/user-manual/gaussian-splatting/formats/streamed-sog) output). ```none -C, --lod-chunk-count Approximate number of Gaussians per LOD chunk in K. Default: 512 @@ -452,9 +452,9 @@ splat-transform \ complete_scene.ply ``` -### Generating LOD Format {#generating-lod-format} +### Generating Streamed SOG {#generating-lod-format} -The LOD (Level of Detail) format enables efficient streaming and rendering of large Gaussian splat scenes. SplatTransform builds an optimized streaming format with an octree structure for progressive download from a set of LOD levels, where each level has progressively fewer Gaussians (LOD 0 = highest detail, higher numbers = lower detail). +The [Streamed SOG](/user-manual/gaussian-splatting/formats/streamed-sog) format enables efficient streaming and rendering of large Gaussian splat scenes. SplatTransform builds an optimized streaming format with a spatial tree structure for progressive download from a set of LOD (Level of Detail) levels, where each level has progressively fewer Gaussians (LOD 0 = highest detail, higher numbers = lower detail). You can obtain those LOD levels in two ways: @@ -465,7 +465,7 @@ You can obtain those LOD levels in two ways: The output filename determines the format. These are **not** arbitrary names: -- **`lod-meta.json`** — generates LOD streaming format (multiple SOG chunks with an octree structure for progressive loading) +- **`lod-meta.json`** — generates Streamed SOG format (multiple SOG chunks with a spatial tree structure for progressive loading) - **`meta.json`** — generates unbundled SOG format (a single SOG file, no streaming) The output filename must be exactly `lod-meta.json` or `meta.json` — only the directory path before it can vary. For example: `output/lod-meta.json`, `my-scene/lod-meta.json`. @@ -473,7 +473,7 @@ The output filename must be exactly `lod-meta.json` or `meta.json` — only the ::: ```bash -# Generate LOD streaming format from multiple input files +# Generate Streamed SOG format from multiple input files # Each input file represents a different detail level (LOD 0 is highest quality) splat-transform \ lod0.ply -l 0 \ @@ -489,7 +489,7 @@ splat-transform \ splat-transform source.ply -F 50% lod1.ply splat-transform source.ply -F 25% lod2.ply splat-transform source.ply -F 10% lod3.ply -# Step 2: bundle the full-detail source and the decimated levels into a streaming LOD format +# Step 2: bundle the full-detail source and the decimated levels into Streamed SOG format splat-transform \ source.ply -l 0 \ lod1.ply -l 1 \ @@ -518,7 +518,7 @@ node --max-old-space-size=32000 node_modules/.bin/splat-transform \ --filter-nan \ --filter-harmonics 0 -# Generate LOD streaming format directly from an LCC file +# Generate Streamed SOG format directly from an LCC file # (LCC files already contain multiple LOD levels) splat-transform scene.lcc output/lod-meta.json ``` diff --git a/docs/user-manual/splat-transform/voxel-format.md b/docs/user-manual/splat-transform/voxel-format.md new file mode 100644 index 00000000000..9a0126eb80b --- /dev/null +++ b/docs/user-manual/splat-transform/voxel-format.md @@ -0,0 +1,169 @@ +--- +title: Voxel Format +description: "Voxel format specification: the on-disk structure of .voxel.json / .voxel.bin sparse voxel octrees written by splat-transform." +sidebar_label: Voxel Format +--- + +This document specifies version 1.1 of the **voxel** format. It describes the on-disk structure written by [splat-transform](/user-manual/splat-transform/) when the output path ends in `.voxel.json` and consumed by runtimes such as the [SuperSplat Viewer](/user-manual/supersplat/viewer/) for collision detection and raycasts. + +The format stores a solid/empty voxelization of a Gaussian splat scene as a sparse voxel octree (SVO) in the Laine–Karras node layout: a JSON header describing the grid, plus a compact binary file holding the tree. + +For a step-by-step guide to generating this format (voxelization, exterior fill, nav carving, collision meshes), see the [Collision Mesh](/user-manual/splat-transform/collision) guide. + +## File set + +A voxel dataset is a pair of files with a shared stem, plus an optional collision mesh: + +```none +scene.voxel.json # header: bounds, resolution, tree statistics (this spec) +scene.voxel.bin # binary octree data (nodes + leafData) +scene.collision.glb # optional triangle mesh extracted from the voxels +``` + +- The header is always named `*.voxel.json`. Writers and readers derive the binary filename by replacing the `.voxel.json` suffix with `.voxel.bin`; the header does not reference it explicitly. +- The `.collision.glb` (written only when collision mesh generation is requested) is a standard glTF binary and is not described further here. + +## `*.voxel.json` + +```ts +interface VoxelMeta { + version: string; // file format version, decimal string, e.g. "1.1" + asset?: { + generator?: string; // tool/version that produced the file, e.g. "splat-transform v2.5.2" + }; + gridBounds: { // AABB of the voxel grid, aligned to 4-voxel block boundaries + min: number[]; // [x, y, z] — world position of the min corner of voxel (0, 0, 0) + max: number[]; // [x, y, z] + }; + sceneBounds: { // AABB of the source Gaussians (informational) + min: number[]; + max: number[]; + }; + voxelResolution: number; // edge length of one voxel, world units + leafSize: number; // voxels per leaf-block edge; always 4 + treeDepth: number; // subdivision levels from the root cube down to leaf blocks (>= 1) + numInteriorNodes: number; // number of interior nodes in `nodes` + numMixedLeaves: number; // number of mixed leaves in `nodes` + nodeCount: number; // total uint32 entries in the `nodes` array + leafDataCount: number; // total uint32 entries in the `leafData` array (= 2 * numMixedLeaves) +} +``` + +- `gridBounds` is the authoritative frame for the voxel data: voxel `(vx, vy, vz)` occupies the world-space box from `gridBounds.min + (vx, vy, vz) · voxelResolution` to `gridBounds.min + (vx+1, vy+1, vz+1) · voxelResolution`. Each axis spans a whole number of 4×4×4-voxel blocks: `nb = round((max − min) / (4 · voxelResolution))`. +- `sceneBounds` records the bounds of the source Gaussian scene (each Gaussian's position expanded by its rotated, scaled extents at the renderer's sigma cutoff). It is informational; depending on fill/carve/crop options, `gridBounds` may be larger or smaller than `sceneBounds`. +- `nodeCount` = `numInteriorNodes` + `numMixedLeaves` + the number of solid leaves (not stored separately). + +### Coordinate space + +All bounds are expressed in the PlayCanvas engine's coordinate frame — the frame the splat scene renders in. This differs from the source PLY's coordinate frame by the engine's standard splat import transform (a 180° rotation about the Z axis). + +## `*.voxel.bin` + +The binary file is two concatenated little-endian `uint32` arrays with no header or padding: + +| Offset (bytes) | Length (bytes) | Contents | +| --- | --- | --- | +| `0` | `nodeCount * 4` | `nodes` array | +| `nodeCount * 4` | `leafDataCount * 4` | `leafData` array | + +The total file size is exactly `(nodeCount + leafDataCount) * 4` bytes. A scene with no solid voxels has `nodeCount = 0`, `leafDataCount = 0` and an empty binary file. + +## The octree + +The tree subdivides a cube of `2^treeDepth` blocks per axis (each block being `leafSize`³ = 4×4×4 voxels), anchored at `gridBounds.min`. Where the per-axis block counts are not equal powers of two, the root cube extends beyond `gridBounds.max`; that excess region is always empty (such octants are simply absent from their parents' child masks). + +Nodes at depth `treeDepth` are **leaf blocks** covering 4×4×4 voxels. `nodes[0]` is the root. + +### Octant numbering + +An interior node's eight octants are numbered by axis halves, X least significant: + +```none +oct = x | (y << 1) | (z << 2) // x, y, z = 0 for the lower half, 1 for the upper half +``` + +This matches Morton order: the path from the root to a leaf block at block coordinates `(bx, by, bz)` consumes the coordinates' bits from most to least significant — at depth `d` (root = 0), `oct = ((bx >> s) & 1) | (((by >> s) & 1) << 1) | (((bz >> s) & 1) << 2)` where `s = treeDepth − 1 − d`. + +### Node words + +Each entry of `nodes` is one `uint32`, decoded as follows (test in order): + +| Condition | Node kind | Meaning | +| --- | --- | --- | +| `word == 0xFF000000` | **Solid leaf** | The node's entire volume is solid. No children, no leaf data. May appear at any depth (a collapsed fully-solid subtree). | +| `(word >>> 24) == 0` | **Mixed leaf** | `word` is an index `i` into `leafData` pairs: the node's voxel mask is `leafData[2i]` (lo) and `leafData[2i + 1]` (hi). Only appears at depth `treeDepth`. | +| otherwise | **Interior** | `childMask = word >>> 24` (8 bits, one per octant); `firstChild = word & 0xFFFFFF` (index into `nodes`). | + +The two leaf encodings are unambiguous: + +- An interior node always has at least one child, so its `childMask` is never `0` — a zero top byte uniquely identifies a mixed leaf. +- Nodes are emitted in breadth-first order with children always following their parent, so an interior node's `firstChild` is never `0` — `0xFF000000` uniquely identifies a solid leaf. + +### Children + +An interior node's present children (set bits of `childMask`) are stored contiguously starting at `nodes[firstChild]`, ordered by ascending octant index. The child for octant `oct` (when `childMask & (1 << oct)` is set) is at: + +```none +nodes[firstChild + popcount(childMask & ((1 << oct) - 1))] +``` + +A clear bit in `childMask` means that octant's entire volume is empty; no node is stored for it. + +### Mixed-leaf voxel masks + +A mixed leaf's 4×4×4 = 64 voxels are stored as a 64-bit occupancy mask split across two `uint32`s. For the voxel at local coordinates `(lx, ly, lz)`, each in `[0, 4)`: + +```none +bit = lx + (ly << 2) + (lz << 4) +solid = bit < 32 ? (lo >>> bit) & 1 : (hi >>> (bit - 32)) & 1 +``` + +`leafData[2i]` holds bits 0–31 (`lo`), `leafData[2i + 1]` holds bits 32–63 (`hi`). A set bit means the voxel is solid. A mixed leaf's mask is never all-zero or all-one — such blocks are encoded as an absent octant or a solid leaf instead. + +### Query domain + +Queries outside `gridBounds` are outside the format's domain, and the appropriate convention depends on the use case. Navigation/collision consumers (e.g. the [SuperSplat Viewer](/user-manual/supersplat/viewer/)) treat out-of-grid space as **solid**; outputs produced with the nav options (exterior fill, floor fill, carve) rely on this — the writer crops away fully-solid blocks beyond the navigable region precisely because the runtime treats everything outside the grid as solid anyway. + +## Limits + +`firstChild` and the mixed-leaf `leafData` index are 24-bit values, capping the format at 16,777,216 node entries and 16,777,216 mixed leaves. The writer fails with an error rather than exceed either limit. + +## Example `*.voxel.json` + +A 32 × 14 × 32-block grid at 5 cm resolution (block size 0.2): + +```json +{ + "version": "1.1", + "asset": { + "generator": "splat-transform v2.5.2" + }, + "gridBounds": { + "min": [-3.2, -0.2, -3.2], + "max": [3.2, 2.6, 3.2] + }, + "sceneBounds": { + "min": [-3.13, -0.08, -3.07], + "max": [3.11, 2.49, 3.08] + }, + "voxelResolution": 0.05, + "leafSize": 4, + "treeDepth": 5, + "numInteriorNodes": 1201, + "numMixedLeaves": 5678, + "nodeCount": 9232, + "leafDataCount": 11356 +} +``` + +## Versioning & compatibility + +- `version` is a decimal `"major.minor"` string. Files conforming to this specification have `version: "1.1"`. Readers should reject files with a greater major version. +- **1.0 → 1.1**: version 1.0 files store bounds and voxel data in the source PLY coordinate frame; 1.1 voxelizes in the PlayCanvas engine frame (see [Coordinate space](#coordinate-space)). The binary layout is unchanged. +- The `asset` block was added after 1.1 shipped and may be absent from older 1.1 files. +- Unknown fields should be ignored, allowing minor additive evolution without a version bump. + +## See also + +- [Collision Mesh](/user-manual/splat-transform/collision) — generating voxel and collision data with splat-transform. +- [splat-transform CLI reference](/user-manual/splat-transform/) — full option reference including Voxel Output Options. diff --git a/docs/user-manual/supersplat/index.md b/docs/user-manual/supersplat/index.md index 95303a279db..ed713267743 100644 --- a/docs/user-manual/supersplat/index.md +++ b/docs/user-manual/supersplat/index.md @@ -47,7 +47,7 @@ If you already have a clean splat file, you don't need to use the Editor. Hit th | **[Viewer](viewer/)** | The open-source web viewer that powers scene pages and Editor HTML exports. Embed in your own page or self-host. | npm `@playcanvas/supersplat-viewer`, [GitHub](https://github.com/playcanvas/supersplat-viewer) | | **[Convert](convert)** | Web frontend to the [splat-transform](/user-manual/splat-transform/) CLI: convert formats, transform, and filter in the browser. | [superspl.at/convert](https://superspl.at/convert) | -Behind the scenes, every published splat is compressed to the SOG format, and large splats (over 1 million Gaussians) are automatically LOD-streamed for fast loading on any device — see [Streaming & Performance](streaming). +Behind the scenes, every published splat is compressed to the SOG format, and large splats (over 1 million Gaussians) are automatically converted to Streamed SOG for fast loading on any device — see [Streaming & Performance](streaming). ## Open source vs hosted diff --git a/docs/user-manual/supersplat/streaming.md b/docs/user-manual/supersplat/streaming.md index f16b72b80d7..8d28a9f7072 100644 --- a/docs/user-manual/supersplat/streaming.md +++ b/docs/user-manual/supersplat/streaming.md @@ -1,22 +1,22 @@ --- title: Streaming & Performance -description: "How SuperSplat compresses published splats to SOG, generates level-of-detail streaming for large scenes, and enforces a runtime Gaussian budget." +description: "How SuperSplat compresses published splats to SOG, generates Streamed SOG for large scenes, and enforces a runtime Gaussian budget." --- -When you [publish from the Editor](/user-manual/supersplat/editor/publishing) or [directly upload](/user-manual/supersplat/upload) a splat, SuperSplat compresses it to the **SOG** family of formats for fast delivery. Large splats are automatically given **level-of-detail (LOD) streaming** so they load quickly and run smoothly on any device. +When you [publish from the Editor](/user-manual/supersplat/editor/publishing) or [directly upload](/user-manual/supersplat/upload) a splat, SuperSplat compresses it to the **SOG** family of formats for fast delivery. Large splats are automatically converted to **Streamed SOG** so they load quickly and run smoothly on any device. ## How your splat is compressed Your splat's Gaussian count determines the format: - **Fewer than 1 million Gaussians** — the splat is compressed to a single, non-streamed **`.sog`** file. -- **1 million Gaussians or more** — SuperSplat generates a set of **levels of detail (LODs)** using [splat-transform](/user-manual/splat-transform/), halving the Gaussian count at each level (decimation), and compresses them into a **streamed SOG** bundle: a `lod-meta.json` index plus per-LOD `.sog` chunks. Larger splats produce more levels, so expect some extra back-end processing time after upload. +- **1 million Gaussians or more** — SuperSplat generates a set of **levels of detail (LODs)** using [splat-transform](/user-manual/splat-transform/), halving the Gaussian count at each level (decimation), and compresses them into a **Streamed SOG** bundle: a `lod-meta.json` index plus per-LOD `.sog` chunks. Larger splats produce more levels, so expect some extra back-end processing time after upload. When you [directly upload](/user-manual/supersplat/upload) a PLY, this choice appears as an **Auto generate LODs** checkbox, ticked automatically at 1 million Gaussians or more; you can override it before publishing. Splats uploaded as a pre-built LCC or SSOG archive are always streamed. ## Near-instant loads and the Gaussian budget -A streamed SOG loads **progressively**: the viewer shows the scene as soon as the lowest level of detail is ready, then fills in finer detail as it streams in. This gives near-instant time-to-first-frame even for very large scenes. +A Streamed SOG splat loads **progressively**: the viewer shows the scene as soon as the lowest level of detail is ready, then fills in finer detail as it streams in. This gives near-instant time-to-first-frame even for very large scenes. At runtime the viewer enforces a **Gaussian budget** — a cap on how many Gaussians are drawn at once — so the scene stays within a sensible amount of memory and renders at a good frame rate. The budget depends on the device and the viewer's **Performance Mode** setting (a toggle in the viewer's settings menu): @@ -29,7 +29,7 @@ As the camera moves, the viewer raises and lowers the level of detail across the ## Bringing your own LODs -Advanced users can skip the automatic step and supply a pre-built streamed SOG: +Advanced users can skip the automatic step and supply a pre-built Streamed SOG bundle: - Generate one with the [splat-transform](/user-manual/splat-transform/) CLI (use `--decimate` to build the LOD levels), then [directly upload](/user-manual/supersplat/upload) the resulting bundle. - Or produce LOD-capable output from the [Convert](/user-manual/supersplat/convert) utility. @@ -37,5 +37,5 @@ Advanced users can skip the automatic step and supply a pre-built streamed SOG: ## See also - [Direct Upload](/user-manual/supersplat/upload) — upload a ready-made splat -- [splat-transform](/user-manual/splat-transform/) — generate streamed SOG / LOD bundles yourself -- [LOD streaming (developer guide)](/user-manual/gaussian-splatting/building/lod-streaming) — using LOD streaming in your own PlayCanvas apps +- [splat-transform](/user-manual/splat-transform/) — generate Streamed SOG bundles yourself +- [Streamed SOG (developer guide)](/user-manual/gaussian-splatting/building/lod-streaming) — using Streamed SOG in your own PlayCanvas apps diff --git a/docs/user-manual/supersplat/upload.md b/docs/user-manual/supersplat/upload.md index f79c90aa794..cb2b8439785 100644 --- a/docs/user-manual/supersplat/upload.md +++ b/docs/user-manual/supersplat/upload.md @@ -31,7 +31,7 @@ Drag and drop, or pick from your filesystem. The dialog accepts: |--------|----------------|---------------------| | **PLY** | `.ply` | Starts with a PLY header and declares an ASCII or binary format. | | **SOG** | `.sog` | Contains one `meta.json` file and the expected SOG WebP payload files. | -| **LOD streaming bundle (SSOG)** | `.zip` | Contains `lod-meta.json` and one or more SOG chunk folders. See [Streaming & Performance](/user-manual/supersplat/streaming). | +| **Streamed SOG bundle (SSOG)** | `.zip` | Contains `lod-meta.json` and one or more SOG chunk folders. See [Streaming & Performance](/user-manual/supersplat/streaming). | | **LCC** | `.zip` | Contains exactly one `.lcc` file with sibling `index.bin` and `data.bin` files. | The file contents are validated after selection. Direct Upload does not accept `.compressed.ply`, `.ksplat`, `.splat`, or `.spz` files directly; use the [Convert](/user-manual/supersplat/convert) utility or the [splat-transform CLI](/user-manual/splat-transform/) to convert those first. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/tutorials/gaussian-splat-streaming-lod.md b/i18n/ja/docusaurus-plugin-content-docs/current/tutorials/gaussian-splat-streaming-lod.md index fca51464be8..0868cf59daf 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/tutorials/gaussian-splat-streaming-lod.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/tutorials/gaussian-splat-streaming-lod.md @@ -1,13 +1,13 @@ --- -title: '3DガウシアンスプラットストリーミングLOD' +title: '3DガウシアンスプラットStreamed SOG' tags: [gaussiansplatting, tutorial] thumb: https://s3-eu-west-1.amazonaws.com/images.playcanvas.com/projects/12/1408991/3CA651-image-75.jpg -description: 空間 LOD と SOG 順序で巨大な Gaussian splat Scene をストリーミングし、大規模環境を段階的に読み込みます。 +description: Streamed SOGで巨大なGaussian splatシーンをストリーミングし、大規模環境を段階的に読み込みます。 --- import Link from '@docusaurus/Link'; -[SOG](/user-manual/gaussian-splatting/formats/sog)(空間的に順序付けられたガウシアン)に基づくPlayCanvasのストリーミングLODフォーマットの使用方法を示すサンプルプロジェクト。ストリーミングされる環境は聖ペテロ・パウロ教会です。 +[SOG](/user-manual/gaussian-splatting/formats/sog)(空間的に順序付けられたガウシアン)に基づくPlayCanvasの[Streamed SOG](/user-manual/gaussian-splatting/formats/streamed-sog)フォーマットの使用方法を示すサンプルプロジェクト。ストリーミングされる環境は聖ペテロ・パウロ教会です。
diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/lod-streaming.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/lod-streaming.md index 6e77f4edd22..2e2922f8676 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/lod-streaming.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/lod-streaming.md @@ -1,59 +1,61 @@ --- -title: LODストリーミング -description: "大規模スプラットシーン向けLODストリーミング:オクツリー構成、lod-metaデータの生成、例、パフォーマンス指針です。" +title: Streamed SOG +description: "大規模スプラットシーン向けStreamed SOG:空間ツリー構成、lod-metaデータの生成、例、パフォーマンス指針です。" --- -LOD(Level of Detail)ストリーミングは、カメラの距離に基づいて適切な詳細レベルを動的にロードすることで、大規模なGaussian splatシーンの効率的なレンダリングを可能にします。この機能により、大規模なスプラットシーンのメモリ使用量を大幅に削減し、レンダリングパフォーマンスを向上させます。 +Streamed SOGは、カメラの距離に基づいて適切な詳細レベル(LOD)を動的にロードすることで、大規模なGaussian splatシーンの効率的なレンダリングを可能にします。これにより、大規模なスプラットシーンのメモリ使用量を大幅に削減し、レンダリングパフォーマンスを向上させます。 ## 仕組み -LODストリーミングは以下のように動作します: +Streamed SOGは以下のように動作します: 1. スプラットの複数のバージョンを異なる詳細レベルで事前生成 -2. 効率的なストリーミングのためにオクツリー構造に整理 +2. 効率的なストリーミングのために空間ツリー構造に整理 3. カメラ距離に基づいて詳細レベルを動的にロードおよびアンロード 4. シーンの各領域に適切な詳細レベルのみをレンダリング このアプローチにより、メモリ制約により不可能だった大規模なスプラットシーンをレンダリングできます。 -## LODストリーミングデータの作成 +## Streamed SOGデータの作成 -LODストリーミングを使用するには、ストリーミング形式(複数の詳細レベルを効率的なストリーミングのためにオクツリー構造で整理した`lod-meta.json`)を生成する必要があります。LODレベルを用意する方法は2つあります: +Streamed SOGを使用するには、その形式(複数の詳細レベルを効率的なストリーミングのために空間ツリー構造で整理した`lod-meta.json`)を生成する必要があります([Streamed SOGフォーマット仕様](/user-manual/gaussian-splatting/formats/streamed-sog)を参照)。LODレベルを用意する方法は2つあります: - **独自のLODレベルを用意する** — 詳細度を段階的に下げた複数のスプラットファイル(LOD 0 = 最高詳細、数字が大きいほど詳細が低い)を、例えばトレーニング時に生成したものや個別にエクスポートしたものとして用意します。 - **SplatTransformで生成する** — [SplatTransform](/user-manual/splat-transform)を使用して、1つの高品質スプラットをデシメート(簡略化)し、詳細度の低いレベルを生成できます。自分で用意する必要はありません。 -LODレベルが揃ったら、SplatTransformがそれらをストリーミング最適化形式にまとめます。詳細については、SplatTransformドキュメントの[LOD形式の生成](/user-manual/splat-transform#generating-lod-format)セクションを参照してください。 +LODレベルが揃ったら、SplatTransformがそれらをStreamed SOG形式にまとめます。詳細については、SplatTransformドキュメントの[Streamed SOGの生成](/user-manual/splat-transform#generating-lod-format)セクションを参照してください。 ## ライブサンプル -LODストリーミングの動作を確認するには、以下のライブサンプルを参照してください: +Streamed SOGの動作を確認するには、以下のライブサンプルを参照してください: -- LODストリーミング(基本) - 異なる詳細レベルでの基本的なLODストリーミングを示します +- Streamed SOG(基本) - 異なる詳細レベルでの基本的なストリーミングを示します - + -- 球面調和関数付きLODストリーミング - 球面調和データを含むLODストリーミングを示します +- 球面調和関数付きStreamed SOG - 球面調和データを含むストリーミングを示します - + -## LODストリーミングの有効化 +## Streamed SOGの有効化 -LODストリーミングは、ストリーミングLOD形式アセット(`lod-meta.json`)をGSplatコンポーネントにロードするだけで有効になります。追加の設定は必要ありません。 +ストリーミングは、Streamed SOGアセット(`lod-meta.json`)をGSplatコンポーネントにロードするだけで有効になります。追加の設定は必要ありません。 ## LOD動作の制御 -以下のAPIを使用してLODストリーミングを制御および微調整できます: +以下のAPIを使用してストリーミング動作を制御および微調整できます: ### コンポーネントレベルの制御 -[`lodDistances`](https://api.playcanvas.com/engine/classes/GSplatComponent.html#loddistances)プロパティを使用して、LODレベル間の切り替え距離しきい値を設定します: +[`lodBaseDistance`](https://api.playcanvas.com/engine/classes/GSplatComponent.html#lodBaseDistance)と[`lodMultiplier`](https://api.playcanvas.com/engine/classes/GSplatComponent.html#lodMultiplier)を使用して、LODの距離しきい値を制御します。しきい値は等比数列に従います:`lodBaseDistance * lodMultiplier^i` ```javascript -// LOD距離しきい値を設定(ワールド単位) -entity.gsplat.lodDistances = [10, 20, 40, 80]; +entity.gsplat.lodBaseDistance = 10; // 最初のLOD遷移の距離 +entity.gsplat.lodMultiplier = 2; // 後続のしきい値はそれぞれ2倍遠くなる ``` +乗数のデフォルトは3で(最小1.2にクランプされます)、各LOD遷移は前の遷移の3倍の距離で発生します。システムはカメラのFOVも自動的に補正します。 + ### シーンレベルの制御 [`Scene.gsplat`](https://api.playcanvas.com/engine/classes/Scene.html#gsplat)プロパティは、gsplatレンダリングのシーン全体の設定へのアクセスを提供します。これには以下のオプションが含まれます: @@ -71,32 +73,32 @@ const gsplatSettings = app.scene.gsplat; // (利用可能なプロパティについてはAPIドキュメントを参照) ``` -LODストリーミングで最も重要なシーンレベルの設定はグローバルスプラット予算で、すべてのGSplatアセット全体で目標スプラット数に収まるよう詳細度を自動的に調整します。詳細については、パフォーマンスセクションの[グローバルスプラット予算](/user-manual/gaussian-splatting/building/performance#global-splat-budget)を参照してください。 +Streamed SOGで最も重要なシーンレベルの設定はグローバルスプラット予算で、すべてのGSplatアセット全体で目標スプラット数に収まるよう詳細度を自動的に調整します。詳細については、パフォーマンスセクションの[グローバルスプラット予算](/user-manual/gaussian-splatting/building/performance#global-splat-budget)を参照してください。 -## エディターでのLODストリーミングの使用 +## エディターでのStreamed SOGの使用 -PlayCanvas EditorでのLODストリーミングのネイティブサポートは近い将来追加される予定です。それまでの間、Editorプロジェクトでストリーミングロード機能を有効にするには、スクリプト内でEngine APIを使用できます。 +PlayCanvas EditorでのStreamed SOGのネイティブサポートは近い将来追加される予定です。それまでの間、EditorプロジェクトでStreamed SOG機能を有効にするには、スクリプト内でEngine APIを使用できます。 ### サンプルプロジェクト -PlayCanvas EditorでGaussian splatsとストリーミングLODを使用する方法を示すサンプルプロジェクトを作成しました: +PlayCanvas EditorでGaussian splatsとStreamed SOGを使用する方法を示すサンプルプロジェクトを作成しました: **[Church of Saints Peter and Paul](https://playcanvas.com/project/1408991/overview/church-of-saints-peter-and-paul)** -このプロジェクトは、カスタムリビールシェーダーエフェクトを含むLODストリーミングを使用した大規模なGaussian splatシーンを紹介しています。 +このプロジェクトは、カスタムリビールシェーダーエフェクトを含むStreamed SOGを使用した大規模なGaussian splatシーンを紹介しています。 ### Streamed GSplatスクリプトの使用 -サンプルプロジェクトには、LODストリーミングを有効にするために任意のエンティティに追加できる`streamed-gsplat.mjs`スクリプトが含まれています: +サンプルプロジェクトには、Streamed SOGを有効にするために任意のエンティティに追加できる`streamed-gsplat.mjs`スクリプトが含まれています: #### セットアップ手順 1. シーン内のエンティティにスクリプトを追加 -2. `splatUrl`プロパティを外部でホストされているLODスプラット形式ファイルを指すように設定 +2. `splatUrl`プロパティを外部でホストされているStreamed SOGファイルを指すように設定 :::note 外部ホスティング -現在、LODスプラットデータは外部でホストする必要があります(Editorアセットとしてではなく)。この制限は、ストリーミングLOD形式のネイティブEditorサポートが追加される将来に解除される予定です。 +現在、Streamed SOGデータは外部でホストする必要があります(Editorアセットとしてではなく)。この制限は、Streamed SOGのネイティブEditorサポートが追加される将来に解除される予定です。 ::: @@ -123,15 +125,15 @@ PlayCanvas EditorでGaussian splatsとストリーミングLODを使用する方 ### 将来のエディター改善 -ストリーミングLODのネイティブEditorサポートが追加されると、以下の改善が計画されています: +Streamed SOGのネイティブEditorサポートが追加されると、以下の改善が計画されています: -- **直接アセットインポート**:LODスプラットファイルをEditorアセットとして直接アップロード(外部ホスティング不要) +- **直接アセットインポート**:Streamed SOGファイルをEditorアセットとして直接アップロード(外部ホスティング不要) - **ビジュアル設定**:スクリプトプロパティではなくEditor UIを通じてLOD設定を構成 -- **エディターでのプレビュー**:Editorビューポートで直接ストリーミングLOD動作を表示およびテスト +- **エディターでのプレビュー**:Editorビューポートで直接ストリーミング動作を表示およびテスト ## メリット -- **パフォーマンス向上**:LODストリーミングは大規模シーンのメモリ使用量を削減し、レンダリングパフォーマンスを向上 +- **パフォーマンス向上**:Streamed SOGは大規模シーンのメモリ使用量を削減し、レンダリングパフォーマンスを向上 - **スケーラビリティ**:適切な詳細レベルを動的にロードすることで、はるかに大規模なGaussian splatシーンのレンダリングを可能に - **柔軟性**:LOD距離とストリーミング動作の細かい制御を提供 - **最適化されたロード**:現在のビューに必要なデータのみをロード @@ -141,6 +143,7 @@ PlayCanvas EditorでGaussian splatsとストリーミングLODを使用する方 - [GSplatComponent API](https://api.playcanvas.com/engine/classes/GSplatComponent.html) - [Scene.gsplat API](https://api.playcanvas.com/engine/classes/Scene.html#gsplat) - [SplatTransform CLIツール](/user-manual/splat-transform) -- [LOD形式の生成](/user-manual/splat-transform#generating-lod-format) +- [Streamed SOGの生成](/user-manual/splat-transform#generating-lod-format) +- [Streamed SOGフォーマット仕様](/user-manual/gaussian-splatting/formats/streamed-sog) - [スプラットレンダリングアーキテクチャ](/user-manual/gaussian-splatting/rendering-architecture) - [カスタムシェーダー](/user-manual/gaussian-splatting/building/custom-shaders) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/performance.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/performance.md index df915436dfb..dfb178f5789 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/performance.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/building/performance.md @@ -1,6 +1,6 @@ --- title: パフォーマンス -description: "スプラットシーンのパフォーマンスのヒント:スプラット数、フィルレート、Scene設定、LODストリーミングの予算、最適化の方針です。" +description: "スプラットシーンのパフォーマンスのヒント:スプラット数、フィルレート、Scene設定、Streamed SOGの予算、最適化の方針です。" --- スプラットのレンダリングは、CPUとGPUの両方で負荷が高くなる場合があります。良好なパフォーマンスを達成するための戦略をいくつか紹介します: @@ -9,7 +9,7 @@ description: "スプラットシーンのパフォーマンスのヒント:ス シーン内のGaussian数に注意してください。すべてのGaussianは毎フレームカメラの深度でソートされます。特定のGSplatアセットに含まれる数は、[SuperSplat Editor](/user-manual/supersplat/editor/)の[SPLAT DATA Panel](/user-manual/supersplat/editor/data-panel/)を使用して確認できます。SuperSplatを使用して、PLYファイルから不要なGaussianをトリミングしてください。 -大規模なシーンでは、カメラ距離に基づいて適切な詳細レベルを動的にロードする[LODストリーミング](/user-manual/gaussian-splatting/building/lod-streaming)の使用を検討してください。これにより、最も重要な場所で視覚品質を維持しながら、任意の時点でアクティブなGaussian数を大幅に削減できます。 +大規模なシーンでは、カメラ距離に基づいて適切な詳細レベルを動的にロードする[Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming)の使用を検討してください。これにより、最も重要な場所で視覚品質を維持しながら、任意の時点でアクティブなGaussian数を大幅に削減できます。 ## フィルレートの考慮事項 @@ -30,13 +30,13 @@ Gaussian splattingのフラグメント重視の性質を考えると、これ 両方の設定は、3DGSレンダリングの主なボトルネックであるフラグメント処理負荷の削減に役立ちます。 -## LODストリーミング設定 +## Streamed SOG設定 -[LODストリーミング](/user-manual/gaussian-splatting/building/lod-streaming)を使用する場合、品質とパフォーマンスを制御するためのいくつかのオプションがあります。推奨されるアプローチは、シーン内のすべてのGSplatアセットのLOD選択を自動的に管理する**グローバルスプラットバジェット**を使用することです。 +[Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming)を使用する場合、品質とパフォーマンスを制御するためのいくつかのオプションがあります。推奨されるアプローチは、シーン内のすべてのGSplatアセットのLOD選択を自動的に管理する**グローバルスプラットバジェット**を使用することです。 -### グローバルスプラットバジェット +### グローバルスプラットバジェット {#global-splat-budget} -グローバルスプラットバジェットは、LODストリーミングのレンダリングパフォーマンスを制御する主要な方法です。以下のように設定します: +グローバルスプラットバジェットは、Streamed SOGのレンダリングパフォーマンスを制御する主要な方法です。以下のように設定します: ```javascript app.scene.gsplat.splatBudget = 4000000; // 最大400万スプラット @@ -47,7 +47,7 @@ app.scene.gsplat.splatBudget = 4000000; // 最大400万スプラット - **バジェット = 0**:バジェット適用を無効にし、距離ベースのLOD選択のみを使用 - **バジェット > 0**:すべてのGSplatアセットに対して指定された最大スプラット数を適用 -バジェットシステムは、LODストリーミングアセット(複数の詳細レベルを持つ)と固定アセット(単一の詳細レベル)の両方を含む、シーン内のすべてのGSplatアセットを考慮します。 +バジェットシステムは、Streamed SOGアセット(複数の詳細レベルを持つ)と固定アセット(単一の詳細レベル)の両方を含む、シーン内のすべてのGSplatアセットを考慮します。 ### LOD距離 @@ -87,7 +87,7 @@ app.scene.gsplat.lodRangeMax = 3; // LOD 3より低くはしない ```javascript const gsplatSystem = app.systems.gsplat; -// `entity` は、ロード済みのLODストリーミングアセットを使用する gsplat コンポーネントを持ちます +// `entity` は、ロード済みのStreamed SOGアセットを使用する gsplat コンポーネントを持ちます const gsplat = entity.gsplat; // 1. 最初のフレームを最速にするため、最も低い(最も粗い)LODのみで開始 @@ -112,7 +112,7 @@ const onFrameReady = (camera, layer, ready, loadingCount) => { gsplatSystem.on('frame:ready', onFrameReady); ``` -この手法は、ライブの[LODストリーミングサンプル](/user-manual/gaussian-splatting/building/lod-streaming)で実演されています。 +この手法は、ライブの[Streamed SOGサンプル](/user-manual/gaussian-splatting/building/lod-streaming)で実演されています。 ### 推奨設定 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/index.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/index.md index 282a3ef7519..e26f215a5f2 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/index.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/index.md @@ -1,9 +1,9 @@ --- title: Splat ファイル形式 -description: 編集とWeb配信向けにPLYとSOGのスプラット形式を比較し、サイズと品質のトレードオフ、代表的な変換ワークフローを説明します。 +description: 編集とWeb配信向けにPLY、SOG、Streamed SOGのスプラット形式を比較し、サイズと品質のトレードオフ、代表的な変換ワークフローを説明します。 --- -PlayCanvasは、3D Gaussian Splatデータ用に2つの形式をサポートしています。 +PlayCanvasは、3D Gaussian Splatデータ用に3つの形式をサポートしています。 ## [PLY 形式](./ply.md) - ソース & 交換用 @@ -21,17 +21,26 @@ Gaussian splatデータの業界標準です。非圧縮、高精度、普遍的 - **ファイルサイズ**: 小 (圧縮済み) - **品質**: 視覚的に最適化 +## [Streamed SOG 形式](./streamed-sog.md) - 大規模シーンのストリーミング用 + +複数の詳細度(LOD)を持つSOGチャンクを空間ツリーに編成した形式です。ビューアは、現在のカメラに必要なチャンクと詳細度のみをストリーミングします。 + +- **用途**: 非常に大きなシーン(数千万のGaussian)、プログレッシブ読み込み +- **ファイルサイズ**: チャンクごとに小、オンデマンドで読み込み +- **品質**: 視覚的に最適化、視点依存の詳細度 + ## 簡易比較 -| | PLY | SOG | -|---|---|---| -| **サイズ** | 大 | 小 (15~20倍に圧縮) | -| **品質** | ロスレス | ロッシー | -| **用途** | ソース/編集 | ランタイム/配信 | -| **速度** | 読み込みが遅い | 読み込みが速い | +| | PLY | SOG | Streamed SOG | +|---|---|---|---| +| **サイズ** | 大 | 小 (15~20倍に圧縮) | 小 (SOGチャンク、オンデマンド読み込み) | +| **品質** | ロスレス | ロッシー | ロッシー、視点依存の詳細度 | +| **用途** | ソース/編集 | ランタイム/配信 | 非常に大きなシーン | +| **速度** | 読み込みが遅い | 読み込みが速い | プログレッシブストリーミング | ## ワークフロー 1. **PLY**でトレーニングと編集を行う 2. [SplatTransform](/user-manual/splat-transform/)を使用して、本番用に**SOG**に変換する -3. 最適なパフォーマンスを得るためにSOGファイルをデプロイする +3. 非常に大きなシーンの場合は、代わりに**Streamed SOG**に変換する +4. 最適なパフォーマンスを得るためにデプロイする diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/sog.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/sog.md index 888c03faf68..78bfad88a30 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/sog.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/sog.md @@ -72,8 +72,11 @@ SOGデータセットは、画像セットとメタデータファイルで構 ```ts interface Meta { version: 2; // ファイルフォーマットのバージョン (整数) + asset?: { // オプションのツール/バージョンメタデータ + generator?: string; // 例: "splat-transform v1.2.3" + }; count: number; // ガウス分布の数 (画像のW*H以下) - antialias: boolean; // シーンがアンチエイリアシングで学習された場合に真 + antialias?: boolean; // オプション。シーンがアンチエイリアシングで学習された場合に真。デフォルト: false means: { // *対数変換された*位置をデコードするための範囲 (3.1節参照)。 @@ -83,7 +86,7 @@ interface Meta { }; scales: { - codebook: number[]; // 256個の浮動小数点数; 3.3節参照 + codebook: number[]; // 256個の浮動小数点数 (対数領域); 3.3節参照 files: ["scales.webp"]; }; @@ -111,7 +114,7 @@ interface Meta { :::note -* scalesコードブックは線形空間の値を含みます。sh0およびshNコードブックはガンマ空間のDC係数を含みます。 +* scalesコードブックは対数空間の値を含みます。線形のサイズを得るには `exp()` を適用しなければなりません(3.3節参照)。sh0コードブックはガンマ空間のDC係数を、shNコードブックはガンマ空間のAC係数を含みます。 * 画像データは、生の8ビット整数として扱われなければ**なりません**(ガンマ変換なし)。 * 特に記載がない限り、言及されていないチャンネルは無視されます。 * `files`配列内のファイル名は任意ですが、順序は重要です。 @@ -155,8 +158,10 @@ const p = { クォータニオンは、標準的な*smallest-three*スキームを使用して、**3×8ビットコンポーネント + 2ビットモード**(合計**26ビット**)でエンコードされます。 -* **R,G,B** は、保持される3つの(符号付き)コンポーネントを格納し、`[-√2/2, +√2/2]` に一様に量子化されます。 -* **A** は、範囲**252..255**の**モード**を格納します。モードは `A - 252` ∈ {0,1,2,3} であり、4つのコンポーネントのうち**絶対値が最も大きかった**(そのためストリームから省略され、再構築される)ものを識別します。 +クォータニオンのコンポーネントは、全体を通して **(w, x, y, z)** の順序です。 + +* **R,G,B** は、保持される3つの(符号付き)コンポーネントを **(w, x, y, z)** の順序で格納し、`[-√2/2, +√2/2]` に一様に量子化されます。 +* **A** は、範囲**252..255**の**モード**を格納します。モードは `A - 252` ∈ {0,1,2,3} であり、4つのコンポーネント(**(w, x, y, z)** の順)のうち**絶対値が最も大きかった**(そのためストリームから省略され、再構築される)ものを識別します。モード 0 = w、1 = x、2 = y、3 = z です。 * `norm = Math.SQRT2` (つまり √2) とします。 ```ts @@ -167,19 +172,19 @@ const a = toComp(quats.r); const b = toComp(quats.g); const c = toComp(quats.b); -const mode = quats.a - 252; // 0..3 (R,G,B,A は4つのコンポーネントのいずれか) +const mode = quats.a - 252; // 0..3 → 省略されたコンポーネントはそれぞれ w, x, y, z // ||q|| = 1 となるように省略されたコンポーネントを再構築し、w.l.o.g. で省略されたものが非負になるようにする const t = a*a + b*b + c*c; const d = Math.sqrt(Math.max(0, 1 - t)); -// モードに従ってコンポーネントを配置する +// モードに従ってコンポーネントを配置する; q の順序は [w, x, y, z] let q: [number, number, number, number]; switch (mode) { - case 0: q = [d, a, b, c]; break; // 省略されたのはx - case 1: q = [a, d, b, c]; break; // 省略されたのはy - case 2: q = [a, b, d, c]; break; // 省略されたのはz - case 3: q = [a, b, c, d]; break; // 省略されたのはw + case 0: q = [d, a, b, c]; break; // 省略されたのはw + case 1: q = [a, d, b, c]; break; // 省略されたのはx + case 2: q = [a, b, d, c]; break; // 省略されたのはy + case 3: q = [a, b, c, d]; break; // 省略されたのはz default: throw new Error("Invalid quaternion mode"); // 無効なクォータニオンモード } ``` @@ -192,15 +197,15 @@ switch (mode) { > `scales.webp` (RGB via codebook) -軸ごとのサイズは**コードブックのインデックス**です。 +軸ごとのサイズは**コードブックのインデックス**です。コードブックは**対数領域**の値を格納するため、デコードには指数関数が必要です。 ```ts -const sx = meta.scales.codebook[scales.r]; // 0..255 -const sy = meta.scales.codebook[scales.g]; -const sz = meta.scales.codebook[scales.b]; +const sx = Math.exp(meta.scales.codebook[scales.r]); // r,g,b は 0..255 +const sy = Math.exp(meta.scales.codebook[scales.g]); +const sz = Math.exp(meta.scales.codebook[scales.b]); ``` -解釈(例えば、主軸の標準偏差と全範囲)は、ソースのトレーニング設定に従います。値は**シーン単位**です。 +解釈(例えば、主軸の標準偏差と全範囲)は、ソースのトレーニング設定に従います。デコード後(`exp` 適用後)の値は**シーン単位**です。 ### 3.4 基本色 + 不透明度 (DC) @@ -268,6 +273,7 @@ const index = shN_labels.r + (shN_labels.g << 8); ```json { "version": 2, + "asset": { "generator": "splat-transform v1.2.3" }, "count": 187543, "antialias": true, "means": { diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/streamed-sog.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/streamed-sog.md new file mode 100644 index 00000000000..6118f0be3d0 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/formats/streamed-sog.md @@ -0,0 +1,158 @@ +--- +title: Streamed SOGフォーマット +sidebar_label: Streamed SOG +description: "Streamed SOGの仕様:lod-meta.jsonの構成、空間ツリー、LODチャンク参照、環境スプラットです。" +--- + +**Streamed SOG** は、Gaussian Splatシーンを複数の詳細度(LOD)の空間チャンクに分割します。ビューアは空間ツリーを走査して、現在のカメラに対して読み込むチャンクと詳細度を決定します。これにより、非常に大きなシーン(数千万のGaussian)をプログレッシブに読み込み、インタラクティブ性を維持できます。 + +**[SplatTransform](https://github.com/playcanvas/splat-transform)** を使用してStreamed SOGデータセットを作成できます。手順については[Streamed SOGの生成](/user-manual/splat-transform/#generating-lod-format)を参照してください。個々のチャンクは標準の[SOG](./sog.md)データセットです。 + +このドキュメントはフォーマット仕様です。**バージョン1**について説明します。 + +## 1. ファイルセット + +Streamed SOGデータセットは、単一のインデックスファイルとチャンクごとのサブディレクトリを含むディレクトリです。 + +```none +scene/ +├── lod-meta.json # インデックス: シーン情報 + 空間ツリー (本仕様) +├── 0_0/ # LOD 0, チャンク0 — unbundled SOG (meta.json + .webpテクスチャ) +│ ├── meta.json +│ └── *.webp +├── 0_1/ # LOD 0, チャンク1 +├── 1_0/ # LOD 1, チャンク0 +├── … # {lod}_{chunk} ごとに1ディレクトリ +└── env/ # オプションの環境スプラット — unbundled SOG +``` + +* インデックスファイルの名前は常に `lod-meta.json` です。ローダーはこのファイル名でフォーマットを識別します。 +* 各チャンクは標準の **unbundled** な[SOG](./sog.md)データセット(`meta.json` とWebPテクスチャファイル)です。バンドルされた(単一アーカイブの)SOGチャンクはこのフォーマットには含まれません。 +* `lod-meta.json` 内のすべてのパスは、`lod-meta.json` を含むディレクトリからの相対パスです。 + +:::note[チャンクの命名] + +`{lod}_{chunk}/` というディレクトリ名はライターの慣例です。リーダーは命名パターンではなく、`filenames` 配列を通じてチャンクの場所を解決**しなければなりません**。 + +::: + +--- + +## 2. `lod-meta.json` + +```ts +interface LodMeta { + version: 1; // ファイルフォーマットのバージョン (整数) + asset?: { // オプションのツール/バージョンメタデータ + generator?: string; // 例: "splat-transform v2.5.2" + }; + count: number; // 全LODレベルにわたるGaussianの総数 (環境を除く) + counts: number[]; // LODレベルごとのGaussian数; インデックス = LODレベル, 長さ = lodLevels + lodLevels: number; // LODレベルの数 + environment?: string; // 環境SOGのmeta.jsonへの相対パス; 存在しない場合は省略 + filenames: string[]; // チャンクSOGのmeta.jsonへの相対パス。インデックスで参照される + tree: Node; // 空間ツリーのルート +} + +interface Node { + bound: { + min: [number, number, number]; // AABBの最小値 [x, y, z] + max: [number, number, number]; // AABBの最大値 [x, y, z] + }; + children?: [Node, Node]; // 内部ノード: 常にちょうど2つの子ノード + lods?: { + [lodLevel: string]: { // リーフノード: LODレベル → スプラット範囲のマップ + file: number; // filenamesへのインデックス + offset: number; // チャンク内の最初のスプラットのインデックス + count: number; // 連続するスプラットの数 + }; + }; +} +``` + +--- + +## 3. 空間ツリー + +`tree` はシーンの二分空間分割です。すべてのノードは軸並行境界ボックス(AABB)を持ち、**内部ノード**(`children` を持つ。常にちょうど2つ)または**リーフノード**(`lods` を持つ)のいずれかです。両方を持つことはありません。 + +* リーフの `bound` は、割り当てられたすべてのGaussianの完全な広がりを囲みます。Gaussianの中心位置だけでなく、回転・スケールされた楕円体で拡張された範囲です。 +* 内部ノードの `bound` は、子ノードのboundの和集合です。 +* boundは、チャンクSOGファイルに格納されたスプラット位置と同じ座標系で表現されます。 + +### 3.1 LODレベル + +LODレベル `0` が最高詳細度で、レベルが上がるほど粗くなります。リーフの `lods` オブジェクトのキーは、LODレベルの10進文字列表現(`"0"` … `"lodLevels - 1"`)です。キーが存在しない場合、そのリーフはそのレベルにスプラットを持ちません。 + +リーフのすべてのLODレベルは同じ空間領域をカバーします。ビューアは、例えばカメラからの距離に基づいて、リーフごとに1つのレベルを選択します。 + +### 3.2 チャンク参照 + +各 `lods` エントリは、1つのチャンク内の連続したスプラット範囲を指します。 + +* `file` はトップレベルの `filenames` 配列へのインデックスです。 +* `offset` と `count` は、チャンクの格納順におけるスプラット `[offset, offset + count)` を選択します(バイトではなくスプラットインデックス)。チャンクのSOGテクスチャでは、格納順は行優先のピクセル順であり、スプラット `i` はピクセル `(i % W, floor(i / W))` に位置します。 + +チャンクファイルの内容は、それを参照するリーフ範囲を連結したものと正確に一致します。範囲は重複せず、チャンク全体をカバーします。各範囲内では、空間的局所性のためにスプラットはモートン順にソートされています。範囲の境界を越えた順序は保証されません。1つのチャンクには単一のLODレベルのスプラットのみが含まれます。 + +--- + +## 4. 環境 + +オプションの `environment` フィールドは、LOD/チャンクストリーミングの対象外のスプラット(通常は空などの遠景)を含む標準のunbundledな[SOG](./sog.md)データセットを指します。ビューアは、空間ツリーとは無関係に、環境を無条件に読み込んでレンダリング**すべきです**。 + +--- + +## 5. 精度 + +`lod-meta.json` 内の非整数値は、有効数字7桁(約32ビット浮動小数点精度)に量子化されます。 + +--- + +## 6. `lod-meta.json` の例 + +環境を持つ2レベルのシーンを、1つの内部ノードと2つのリーフに分割した例: + +```json +{ + "version": 1, + "asset": { "generator": "splat-transform v2.5.2" }, + "count": 1500000, + "counts": [1000000, 500000], + "lodLevels": 2, + "environment": "env/meta.json", + "filenames": [ + "0_0/meta.json", + "1_0/meta.json" + ], + "tree": { + "bound": { "min": [-10, 0, -10], "max": [10, 5, 10] }, + "children": [ + { + "bound": { "min": [-10, 0, -10], "max": [0.5, 5, 10] }, + "lods": { + "0": { "file": 0, "offset": 0, "count": 600000 }, + "1": { "file": 1, "offset": 0, "count": 300000 } + } + }, + { + "bound": { "min": [0.5, 0, -10], "max": [10, 4.5, 10] }, + "lods": { + "0": { "file": 0, "offset": 600000, "count": 400000 }, + "1": { "file": 1, "offset": 300000, "count": 200000 } + } + } + ] + } +} +``` + +--- + +## 7. バージョン管理と互換性 + +* この仕様に準拠するファイルは `version: 1` を持ちます。リーダーはより大きなメジャーバージョンのファイルを拒否**すべきです**。 +* フォーマットがバージョン管理される前に生成されたファイルは、`version`、`asset`、`count`、`counts` を省略しており、`"environment": null` を含む場合があります。これらをサポートするリーダーは、`version` の欠落をプレリリースとして扱い、`environment: null` を環境なしとして扱う**べきです**。 +* 未知のフィールドは無視される**べきです**。これにより、バージョンを上げずに小規模な追加的変更が可能になります。 + +--- diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/index.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/index.md index 0a4c008bdf7..bcd56259d70 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/index.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/index.md @@ -3,7 +3,7 @@ title: スプラットレンダリングアーキテクチャ description: "PlayCanvasがGaussian splatsをレンダリングする仕組み:ワークバッファパイプライン、コンポーネント間のグローバルソート、高度な機能へのアクセスです。" --- -PlayCanvasは、すべてのGSplatコンポーネントのすべてのスプラットを一緒にソートする共有パイプラインを通じてGaussian splatsをレンダリングします。このグローバルソートにより、シーン全体で正しいレンダリング順序が保証され、プロシージャルスプラット、LODストリーミング、GPUベースのスプラット処理などの高度な機能へのアクセスが提供されます。 +PlayCanvasは、すべてのGSplatコンポーネントのすべてのスプラットを一緒にソートする共有パイプラインを通じてGaussian splatsをレンダリングします。このグローバルソートにより、シーン全体で正しいレンダリング順序が保証され、プロシージャルスプラット、Streamed SOG、GPUベースのスプラット処理などの高度な機能へのアクセスが提供されます。 ## グローバルソート @@ -43,7 +43,7 @@ flowchart LR GSplatリソースはスプラットのソースデータです。2つの形式があります: -1. **ロードされたスプラット**:ファイル(`.ply`、`.sog`)からインポートされるか、[LODストリーミング](/user-manual/gaussian-splatting/building/lod-streaming)経由でストリーミングされます +1. **ロードされたスプラット**:ファイル(`.ply`、`.sog`)からインポートされるか、[Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming)経由でストリーミングされます 2. **プロシージャルスプラット**:[GSplatContainer](/user-manual/gaussian-splatting/building/procedural-splats/)を使用してプログラムで作成されます 各リソースは[データフォーマット](/user-manual/gaussian-splatting/rendering-architecture/splat-data-format)に従ってGPUテクスチャにスプラットデータを格納します。 @@ -73,7 +73,7 @@ Global Sortingサンプルでは、すべてのスプラットを一緒にソー - **視覚品質の向上**:複数の重なり合うスプラットコンポーネントをレンダリングする際のアーティファクトを排除 - **一貫したレンダリング**:カメラ位置に関係なく正しい深度ソートを維持 - **より良いシーン構成**:多くのスプラットコンポーネントを持つ複雑なシーンを可能に -- **高度な機能**:プロシージャルスプラット、LODストリーミング、GPU処理をアンロック +- **高度な機能**:プロシージャルスプラット、Streamed SOG、GPU処理をアンロック ## 高度な機能 @@ -81,7 +81,7 @@ Global Sortingサンプルでは、すべてのスプラットを一緒にソー - [スプラットデータフォーマット](/user-manual/gaussian-splatting/rendering-architecture/splat-data-format) - スプラットデータのカスタムテクスチャフォーマット - [プロシージャルスプラット](/user-manual/gaussian-splatting/building/procedural-splats/) - プログラムによるスプラットの作成 -- [LODストリーミング](/user-manual/gaussian-splatting/building/lod-streaming) - 動的な詳細レベルのロード +- [Streamed SOG](/user-manual/gaussian-splatting/building/lod-streaming) - 動的な詳細レベルのロード - [スプラット処理](/user-manual/gaussian-splatting/rendering-architecture/splat-processing) - GPUベースのスプラット操作 ## 関連項目 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md index 5833bda2a11..e950cd8a350 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/gaussian-splatting/rendering-architecture/splat-data-format.md @@ -97,7 +97,7 @@ const format = entity.gsplat.resource.format; :::note -追加ストリームはLODストリーミングリソースではサポートされていません。LODリソースは必要に応じてデータを動的にロードおよびアンロードするため、カスタム追加ストリームはこれらの操作間で保持できません。 +追加ストリームはStreamed SOGリソースではサポートされていません。これらのリソースは必要に応じてデータを動的にロードおよびアンロードするため、カスタム追加ストリームはこれらの操作間で保持できません。 ::: diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/collision.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/collision.md index fa63751ba55..5e2fd34c89d 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/collision.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/collision.md @@ -11,7 +11,7 @@ CLI ではなく SuperSplat の Web UI を介してボクセルコリジョン 同じボクセル化パスから2つの出力が生成されます: -- **`.voxel.json` / `.voxel.bin`** — レイキャストおよびブロードフェーズのコリジョンクエリ用のスパースボクセルオクツリー (SVO)。これはランタイムコリジョン検出のために [SuperSplat ビューア](/user-manual/supersplat/viewer/) で使用されるフォーマットです。 +- **`.voxel.json` / `.voxel.bin`** — レイキャストおよびブロードフェーズのコリジョンクエリ用のスパースボクセルオクツリー (SVO)。これはランタイムコリジョン検出のために [SuperSplat ビューア](/user-manual/supersplat/viewer/) で使用されるフォーマットです。ディスク上の構造は[ボクセルフォーマット](/user-manual/splat-transform/voxel-format)仕様で規定されています。 - **`.collision.glb`** — ボクセルグリッドから構築された三角形メッシュ(`-K` / `--collision-mesh` を渡した場合のみ)。 典型的なパイプラインは4つのステージで構成され、後者の2つはシーンタイプに応じて任意です: @@ -223,6 +223,7 @@ splat-transform input.ply \ ## 関連項目 +- [ボクセルフォーマット](/user-manual/splat-transform/voxel-format) — `.voxel.json` / `.voxel.bin` 出力のディスク上のフォーマット。 - [splat-transform CLI リファレンス](/user-manual/splat-transform/) — ボクセル出力オプションを含む完全なオプションリファレンス。 - [Docker バックエンド](/user-manual/splat-transform/docker) — コンテナで GPU 専用のボクセル/コリジョン機能を実行する方法。 - [Studio → コリジョン](/user-manual/supersplat/studio/collision) — SuperSplat の Web UI を介してボクセルコリジョンをアップロードまたは生成する方法。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/index.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/index.md index 3ad9f6c41d0..9cc901db01a 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/index.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/index.md @@ -189,7 +189,7 @@ SOG圧縮および GPU ボクセル化(`--filter-cluster`、`--filter-floaters ## LOD出力オプション -`lod-meta.json`(マルチLODストリーミングSOGバンドル)を書き込む際に適用されます。 +`lod-meta.json`([Streamed SOG](/user-manual/gaussian-splatting/formats/streamed-sog)出力)を書き込む際に適用されます。 ```none -C, --lod-chunk-count Approximate number of Gaussians per LOD chunk in K. Default: 512 @@ -452,9 +452,9 @@ splat-transform \ complete_scene.ply ``` -### LOD形式の生成 {#generating-lod-format} +### Streamed SOGの生成 {#generating-lod-format} -LOD (Level of Detail) 形式は、大きなガウシアンスプラットシーンの効率的なストリーミングとレンダリングを可能にします。SplatTransformは、段階的にガウシアンが少なくなる一連のLODレベル(LOD 0 = 最高詳細、数字が大きいほど詳細度が低い)から、プログレッシブダウンロードのためにオクツリー構造を持つ最適化されたストリーミング形式を構築します。 +[Streamed SOG](/user-manual/gaussian-splatting/formats/streamed-sog)形式は、大きなガウシアンスプラットシーンの効率的なストリーミングとレンダリングを可能にします。SplatTransformは、段階的にガウシアンが少なくなる一連のLOD (Level of Detail) レベル(LOD 0 = 最高詳細、数字が大きいほど詳細度が低い)から、プログレッシブダウンロードのために空間ツリー構造を持つ最適化されたストリーミング形式を構築します。 LODレベルは次の2つの方法で用意できます: @@ -465,7 +465,7 @@ LODレベルは次の2つの方法で用意できます: 出力ファイル名がフォーマットを決定します。これらは**任意の名前ではありません**: -- **`lod-meta.json`** — LODストリーミング形式を生成(プログレッシブローディング用のオクツリー構造を持つ複数のSOGチャンク) +- **`lod-meta.json`** — Streamed SOG形式を生成(プログレッシブローディング用の空間ツリー構造を持つ複数のSOGチャンク) - **`meta.json`** — 非バンドル版SOG形式を生成(単一のSOGファイル、ストリーミングなし) 出力ファイル名は正確に `lod-meta.json` または `meta.json` である必要があります。変更できるのはその前のディレクトリパスのみです。例:`output/lod-meta.json`、`my-scene/lod-meta.json`。 @@ -473,7 +473,7 @@ LODレベルは次の2つの方法で用意できます: ::: ```bash -# 複数の入力ファイルからLODストリーミング形式を生成 +# 複数の入力ファイルからStreamed SOG形式を生成 # 各入力ファイルは異なる詳細レベルを表します(LOD 0は最高品質) splat-transform \ lod0.ply -l 0 \ @@ -489,7 +489,7 @@ splat-transform \ splat-transform source.ply -F 50% lod1.ply splat-transform source.ply -F 25% lod2.ply splat-transform source.ply -F 10% lod3.ply -# ステップ2: フル詳細のソースとデシメートしたレベルをストリーミングLOD形式にまとめる +# ステップ2: フル詳細のソースとデシメートしたレベルをStreamed SOG形式にまとめる splat-transform \ source.ply -l 0 \ lod1.ply -l 1 \ @@ -518,7 +518,7 @@ node --max-old-space-size=32000 node_modules/.bin/splat-transform \ --filter-nan \ --filter-harmonics 0 -# LCCファイルから直接LODストリーミング形式を生成 +# LCCファイルから直接Streamed SOG形式を生成 # (LCCファイルには複数のLODレベルが既に含まれています) splat-transform scene.lcc output/lod-meta.json ``` diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/voxel-format.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/voxel-format.md new file mode 100644 index 00000000000..702e2389cb7 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/splat-transform/voxel-format.md @@ -0,0 +1,169 @@ +--- +title: ボクセルフォーマット +description: "ボクセルフォーマット仕様:splat-transformが書き出す .voxel.json / .voxel.bin スパースボクセルオクツリーのディスク上の構造です。" +sidebar_label: ボクセルフォーマット +--- + +このドキュメントは、**ボクセル**フォーマットのバージョン1.1の仕様です。出力パスが `.voxel.json` で終わる場合に[splat-transform](/user-manual/splat-transform/)が書き出し、[SuperSplat ビューア](/user-manual/supersplat/viewer/)などのランタイムがコリジョン検出やレイキャストのために使用する、ディスク上の構造を記述します。 + +このフォーマットは、Gaussian splatシーンのソリッド/空のボクセル化を、Laine–Karrasノードレイアウトのスパースボクセルオクツリー(SVO)として格納します。グリッドを記述するJSONヘッダと、ツリーを保持するコンパクトなバイナリファイルで構成されます。 + +このフォーマットの生成手順(ボクセル化、外部フィル、ナビゲーション領域のカーブ、コリジョンメッシュ)については、[コリジョンメッシュ](/user-manual/splat-transform/collision)ガイドを参照してください。 + +## ファイルセット + +ボクセルデータセットは、共通の語幹を持つファイルのペアと、オプションのコリジョンメッシュで構成されます: + +```none +scene.voxel.json # ヘッダ: 境界、解像度、ツリー統計 (本仕様) +scene.voxel.bin # バイナリオクツリーデータ (nodes + leafData) +scene.collision.glb # オプション。ボクセルから抽出された三角形メッシュ +``` + +- ヘッダの名前は常に `*.voxel.json` です。ライターとリーダーは、`.voxel.json` サフィックスを `.voxel.bin` に置き換えてバイナリファイル名を導出します。ヘッダはバイナリファイルを明示的に参照しません。 +- `.collision.glb`(コリジョンメッシュ生成が要求された場合のみ書き出されます)は標準のglTFバイナリであり、本仕様ではこれ以上説明しません。 + +## `*.voxel.json` + +```ts +interface VoxelMeta { + version: string; // ファイルフォーマットのバージョン。10進文字列、例: "1.1" + asset?: { + generator?: string; // ファイルを生成したツール/バージョン。例: "splat-transform v2.5.2" + }; + gridBounds: { // ボクセルグリッドのAABB。4ボクセルブロック境界にアラインされる + min: number[]; // [x, y, z] — ボクセル (0, 0, 0) の最小コーナーのワールド座標 + max: number[]; // [x, y, z] + }; + sceneBounds: { // ソースGaussianのAABB (参考情報) + min: number[]; + max: number[]; + }; + voxelResolution: number; // ボクセル1個の辺の長さ (ワールド単位) + leafSize: number; // リーフブロックの1辺あたりのボクセル数。常に4 + treeDepth: number; // ルートキューブからリーフブロックまでの分割レベル数 (>= 1) + numInteriorNodes: number; // `nodes` 内の内部ノードの数 + numMixedLeaves: number; // `nodes` 内の混合リーフの数 + nodeCount: number; // `nodes` 配列のuint32エントリの総数 + leafDataCount: number; // `leafData` 配列のuint32エントリの総数 (= 2 * numMixedLeaves) +} +``` + +- `gridBounds` はボクセルデータの基準となるフレームです。ボクセル `(vx, vy, vz)` は、`gridBounds.min + (vx, vy, vz) · voxelResolution` から `gridBounds.min + (vx+1, vy+1, vz+1) · voxelResolution` までのワールド空間のボックスを占めます。各軸は4×4×4ボクセルブロックの整数個分の範囲です:`nb = round((max − min) / (4 · voxelResolution))`。 +- `sceneBounds` は、ソースGaussianシーンの境界(各Gaussianの位置を、レンダラーのシグマカットオフにおける回転・スケールされた広がりで拡張したもの)を記録します。これは参考情報です。フィル/カーブ/クロップのオプションによっては、`gridBounds` が `sceneBounds` より大きい場合も小さい場合もあります。 +- `nodeCount` = `numInteriorNodes` + `numMixedLeaves` + ソリッドリーフの数(個別には格納されません)。 + +### 座標空間 + +すべての境界は、PlayCanvasエンジンの座標系 — スプラットシーンがレンダリングされるフレーム — で表現されます。これは、エンジンの標準的なスプラットインポート変換(Z軸まわりの180°回転)の分だけ、ソースPLYの座標系と異なります。 + +## `*.voxel.bin` + +バイナリファイルは、ヘッダもパディングもなく連結された、2つのリトルエンディアン `uint32` 配列です: + +| オフセット (バイト) | 長さ (バイト) | 内容 | +| --- | --- | --- | +| `0` | `nodeCount * 4` | `nodes` 配列 | +| `nodeCount * 4` | `leafDataCount * 4` | `leafData` 配列 | + +ファイルの合計サイズは正確に `(nodeCount + leafDataCount) * 4` バイトです。ソリッドボクセルのないシーンは `nodeCount = 0`、`leafDataCount = 0` で、バイナリファイルは空になります。 + +## オクツリー + +ツリーは、`gridBounds.min` を起点とし、1軸あたり `2^treeDepth` ブロック(各ブロックは `leafSize`³ = 4×4×4ボクセル)のキューブを分割します。軸ごとのブロック数が同じ2のべき乗でない場合、ルートキューブは `gridBounds.max` を超えて広がります。その超過領域は常に空です(そのようなオクタントは親のチャイルドマスクから単に欠落します)。 + +深さ `treeDepth` のノードは、4×4×4ボクセルをカバーする**リーフブロック**です。`nodes[0]` がルートです。 + +### オクタント番号 + +内部ノードの8つのオクタントは、Xを最下位として軸の半分ごとに番号付けされます: + +```none +oct = x | (y << 1) | (z << 2) // x, y, z = 下半分なら0、上半分なら1 +``` + +これはモートン順と一致します。ルートからブロック座標 `(bx, by, bz)` のリーフブロックまでのパスは、座標のビットを最上位から最下位へ消費します — 深さ `d`(ルート = 0)において、`oct = ((bx >> s) & 1) | (((by >> s) & 1) << 1) | (((bz >> s) & 1) << 2)`、ここで `s = treeDepth − 1 − d` です。 + +### ノードワード + +`nodes` の各エントリは1つの `uint32` で、以下のようにデコードされます(順番に判定します): + +| 条件 | ノード種別 | 意味 | +| --- | --- | --- | +| `word == 0xFF000000` | **ソリッドリーフ** | ノードの全体積がソリッドです。子もリーフデータもありません。任意の深さに現れる可能性があります(完全にソリッドなサブツリーの折りたたみ)。 | +| `(word >>> 24) == 0` | **混合リーフ** | `word` は `leafData` ペアへのインデックス `i` です。ノードのボクセルマスクは `leafData[2i]`(lo)と `leafData[2i + 1]`(hi)です。深さ `treeDepth` にのみ現れます。 | +| それ以外 | **内部ノード** | `childMask = word >>> 24`(8ビット、オクタントごとに1ビット)、`firstChild = word & 0xFFFFFF`(`nodes` へのインデックス)。 | + +2つのリーフエンコーディングは曖昧さなく区別できます: + +- 内部ノードは常に少なくとも1つの子を持つため、その `childMask` が `0` になることはありません — 上位バイトがゼロであることは混合リーフを一意に識別します。 +- ノードは、子が常に親の後に続く幅優先順で出力されるため、内部ノードの `firstChild` が `0` になることはありません — `0xFF000000` はソリッドリーフを一意に識別します。 + +### 子ノード + +内部ノードの存在する子(`childMask` のセットされたビット)は、`nodes[firstChild]` から始まる連続領域に、オクタントインデックスの昇順で格納されます。オクタント `oct` の子(`childMask & (1 << oct)` がセットされている場合)は次の位置にあります: + +```none +nodes[firstChild + popcount(childMask & ((1 << oct) - 1))] +``` + +`childMask` のクリアされたビットは、そのオクタントの全体積が空であることを意味します。そのオクタントのノードは格納されません。 + +### 混合リーフのボクセルマスク + +混合リーフの4×4×4 = 64ボクセルは、2つの `uint32` に分割された64ビットの占有マスクとして格納されます。ローカル座標 `(lx, ly, lz)`(それぞれ `[0, 4)`)のボクセルについて: + +```none +bit = lx + (ly << 2) + (lz << 4) +solid = bit < 32 ? (lo >>> bit) & 1 : (hi >>> (bit - 32)) & 1 +``` + +`leafData[2i]` がビット0–31(`lo`)を、`leafData[2i + 1]` がビット32–63(`hi`)を保持します。セットされたビットはボクセルがソリッドであることを意味します。混合リーフのマスクがすべてゼロまたはすべて1になることはありません — そのようなブロックは、欠落オクタントまたはソリッドリーフとしてエンコードされます。 + +### クエリ範囲 + +`gridBounds` の外側へのクエリはフォーマットの対象範囲外であり、適切な規約はユースケースによって異なります。ナビゲーション/コリジョンのコンシューマ(例:[SuperSplat ビューア](/user-manual/supersplat/viewer/))は、グリッド外の空間を**ソリッド**として扱います。ナビゲーションオプション(外部フィル、フロアフィル、カーブ)で生成された出力はこれに依存しています — ランタイムがグリッド外をすべてソリッドとして扱うからこそ、ライターはナビゲーション可能領域の外側にある完全にソリッドなブロックをクロップして除去します。 + +## 制限 + +`firstChild` と混合リーフの `leafData` インデックスは24ビット値であり、フォーマットの上限はノードエントリ16,777,216個、混合リーフ16,777,216個です。ライターはいずれかの制限を超える代わりにエラーで失敗します。 + +## `*.voxel.json` の例 + +5cm解像度(ブロックサイズ0.2)の32 × 14 × 32ブロックのグリッド: + +```json +{ + "version": "1.1", + "asset": { + "generator": "splat-transform v2.5.2" + }, + "gridBounds": { + "min": [-3.2, -0.2, -3.2], + "max": [3.2, 2.6, 3.2] + }, + "sceneBounds": { + "min": [-3.13, -0.08, -3.07], + "max": [3.11, 2.49, 3.08] + }, + "voxelResolution": 0.05, + "leafSize": 4, + "treeDepth": 5, + "numInteriorNodes": 1201, + "numMixedLeaves": 5678, + "nodeCount": 9232, + "leafDataCount": 11356 +} +``` + +## バージョン管理と互換性 + +- `version` は10進の `"major.minor"` 文字列です。この仕様に準拠するファイルは `version: "1.1"` を持ちます。リーダーはより大きなメジャーバージョンのファイルを拒否すべきです。 +- **1.0 → 1.1**:バージョン1.0のファイルは、境界とボクセルデータをソースPLYの座標系で格納します。1.1はPlayCanvasエンジンのフレームでボクセル化します([座標空間](#座標空間)を参照)。バイナリレイアウトは変わりません。 +- `asset` ブロックは1.1の出荷後に追加されたため、古い1.1ファイルには存在しない場合があります。 +- 未知のフィールドは無視されるべきです。これにより、バージョンを上げずに小規模な追加的変更が可能になります。 + +## 関連項目 + +- [コリジョンメッシュ](/user-manual/splat-transform/collision) — splat-transformによるボクセルおよびコリジョンデータの生成。 +- [splat-transform CLIリファレンス](/user-manual/splat-transform/) — ボクセル出力オプションを含む全オプションのリファレンス。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/index.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/index.md index a717e9d4f7c..d4491df0d3e 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/index.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/index.md @@ -47,7 +47,7 @@ flowchart TB | **[Viewer](viewer/)** | シーンページとEditorのHTMLエクスポートを動かしているオープンソースのウェブビューア。自分のページに埋め込むか、セルフホストできます。 | npm `@playcanvas/supersplat-viewer`、[GitHub](https://github.com/playcanvas/supersplat-viewer) | | **[Convert](convert)** | [splat-transform](/user-manual/splat-transform/) CLIのウェブフロントエンド:ブラウザ上で形式変換、トランスフォーム、フィルタを実行します。 | [superspl.at/convert](https://superspl.at/convert) | -舞台裏では、公開されたすべてのスプラットはSOG形式に圧縮され、大きなスプラット(100万ガウシアンを超えるもの)は、どのデバイスでも高速に読み込めるよう自動的にLODストリーミングされます — [ストリーミングとパフォーマンス](streaming)を参照してください。 +舞台裏では、公開されたすべてのスプラットはSOG形式に圧縮され、大きなスプラット(100万ガウシアンを超えるもの)は、どのデバイスでも高速に読み込めるよう自動的にStreamed SOGへ変換されます — [ストリーミングとパフォーマンス](streaming)を参照してください。 ## オープンソース vs ホスト型 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/streaming.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/streaming.md index a48f7b85fd4..64a1b436908 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/streaming.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/streaming.md @@ -1,22 +1,22 @@ --- title: ストリーミングとパフォーマンス -description: "SuperSplatが公開済みスプラットをSOGに圧縮し、大規模なシーンにLODストリーミングを生成し、ランタイムのガウシアンバジェットを適用する仕組み。" +description: "SuperSplatが公開済みスプラットをSOGに圧縮し、大規模なシーンにStreamed SOGを生成し、ランタイムのガウシアンバジェットを適用する仕組み。" --- -[Editorから公開](/user-manual/supersplat/editor/publishing)するか、スプラットを[直接アップロード](/user-manual/supersplat/upload)すると、SuperSplatは高速配信のために**SOG**系フォーマットへ圧縮します。大きなスプラットには自動的に**レベルオブディテール(LOD)ストリーミング**が付与され、どのデバイスでも素早く読み込まれ、滑らかに動作します。 +[Editorから公開](/user-manual/supersplat/editor/publishing)するか、スプラットを[直接アップロード](/user-manual/supersplat/upload)すると、SuperSplatは高速配信のために**SOG**系フォーマットへ圧縮します。大きなスプラットは自動的に**Streamed SOG**へ変換され、どのデバイスでも素早く読み込まれ、滑らかに動作します。 ## スプラットの圧縮方法 スプラットのガウシアン数によってフォーマットが決まります: - **100万ガウシアン未満** — スプラットは単一の非ストリーミング**`.sog`**ファイルに圧縮されます。 -- **100万ガウシアン以上** — SuperSplatが[splat-transform](/user-manual/splat-transform/)を使って一連の**レベルオブディテール(LOD)**を生成し、各レベルでガウシアン数を半分にしていき(デシメーション)、それらを**ストリーミングSOG**バンドル — `lod-meta.json`インデックスと、LODごとの`.sog`チャンク — に圧縮します。スプラットが大きいほどレベル数も増えるため、アップロード後にバックエンドでの処理時間が多少かかります。 +- **100万ガウシアン以上** — SuperSplatが[splat-transform](/user-manual/splat-transform/)を使って一連の**レベルオブディテール(LOD)**を生成し、各レベルでガウシアン数を半分にしていき(デシメーション)、それらを**Streamed SOG**バンドル — `lod-meta.json`インデックスと、LODごとの`.sog`チャンク — に圧縮します。スプラットが大きいほどレベル数も増えるため、アップロード後にバックエンドでの処理時間が多少かかります。 PLYを[直接アップロード](/user-manual/supersplat/upload)する場合、この選択は**Auto generate LODs**チェックボックスとして表示され、100万ガウシアン以上では自動的にオンになります(公開前に切り替え可能です)。事前にビルドされたLCCまたはSSOGアーカイブとしてアップロードされたスプラットは、常にストリーミングされます。 ## ほぼ瞬時の読み込みとガウシアンバジェット -ストリーミングSOGは**段階的に**読み込まれます。ビューアは最も低いレベルオブディテールが用意でき次第シーンを表示し、ストリーミングが進むにつれて細部を補完します。これにより、非常に大規模なシーンでもほぼ瞬時に最初のフレームが表示されます。 +Streamed SOGスプラットは**段階的に**読み込まれます。ビューアは最も低いレベルオブディテールが用意でき次第シーンを表示し、ストリーミングが進むにつれて細部を補完します。これにより、非常に大規模なシーンでもほぼ瞬時に最初のフレームが表示されます。 ランタイムでは、ビューアが**ガウシアンバジェット** — 一度に描画されるガウシアン数の上限 — を適用するため、シーンは妥当なメモリ内に収まり、良好なフレームレートでレンダリングされます。バジェットはデバイスと、ビューアの**Performance Mode**設定(ビューアの設定メニューにあるトグル)によって決まります: @@ -29,7 +29,7 @@ PLYを[直接アップロード](/user-manual/supersplat/upload)する場合、 ## 独自のLODを用意する -上級ユーザーは自動処理を省略し、事前にビルドしたストリーミングSOGを用意できます: +上級ユーザーは自動処理を省略し、事前にビルドしたStreamed SOGバンドルを用意できます: - [splat-transform](/user-manual/splat-transform/) CLIで生成し(`--decimate`でLODレベルをビルド)、できたバンドルを[直接アップロード](/user-manual/supersplat/upload)します。 - または[Convert](/user-manual/supersplat/convert)ユーティリティからLOD対応の出力を生成します。 @@ -37,5 +37,5 @@ PLYを[直接アップロード](/user-manual/supersplat/upload)する場合、 ## 関連項目 - [Direct Upload](/user-manual/supersplat/upload) — 完成済みのスプラットをアップロードする -- [splat-transform](/user-manual/splat-transform/) — ストリーミングSOG / LODバンドルを自分で生成する -- [LODストリーミング(開発者ガイド)](/user-manual/gaussian-splatting/building/lod-streaming) — 独自のPlayCanvasアプリでLODストリーミングを使う +- [splat-transform](/user-manual/splat-transform/) — Streamed SOGバンドルを自分で生成する +- [Streamed SOG(開発者ガイド)](/user-manual/gaussian-splatting/building/lod-streaming) — 独自のPlayCanvasアプリでStreamed SOGを使う diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/upload.md b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/upload.md index ffa3d6d81c3..5aee08f718b 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/upload.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/user-manual/supersplat/upload.md @@ -31,7 +31,7 @@ Upload Splatダイアログを開く方法は3つあります: |--------|----------------|---------------------| | **PLY** | `.ply` | PLYヘッダで始まり、ASCIIまたはバイナリのフォーマットを宣言していること。 | | **SOG** | `.sog` | 1つの`meta.json`ファイルと、期待されるSOGのWebPペイロードファイルを含むこと。 | -| **LODストリーミングバンドル (SSOG)** | `.zip` | `lod-meta.json`と1つ以上のSOGチャンクフォルダを含むこと。[ストリーミングとパフォーマンス](/user-manual/supersplat/streaming)を参照してください。 | +| **Streamed SOGバンドル (SSOG)** | `.zip` | `lod-meta.json`と1つ以上のSOGチャンクフォルダを含むこと。[ストリーミングとパフォーマンス](/user-manual/supersplat/streaming)を参照してください。 | | **LCC** | `.zip` | 正確に1つの`.lcc`ファイルと、隣接する`index.bin`および`data.bin`ファイルを含むこと。 | ファイルの内容は選択後に検証されます。Direct Uploadは`.compressed.ply`、`.ksplat`、`.splat`、`.spz`ファイルを直接受け付けません。これらは[Convert](/user-manual/supersplat/convert)ユーティリティまたは[splat-transform CLI](/user-manual/splat-transform/)で先に変換してください。 diff --git a/sidebars.js b/sidebars.js index 12b8191dc70..0fc827ddf2e 100644 --- a/sidebars.js +++ b/sidebars.js @@ -606,6 +606,7 @@ const sidebars = { }, items: [ 'user-manual/splat-transform/collision', + 'user-manual/splat-transform/voxel-format', 'user-manual/splat-transform/docker', ], }, @@ -859,6 +860,7 @@ const sidebars = { items: [ 'user-manual/gaussian-splatting/formats/ply', 'user-manual/gaussian-splatting/formats/sog', + 'user-manual/gaussian-splatting/formats/streamed-sog', ], }, {