Rozdział 8 — Formaty eksportu


Co widać na obrazie (2 991 gaussianów, SH degree 3, syntetyczny bukiet Bjoerna z Blendera jako zestaw testowy bez problemów IP): Wartości rozmiaru pod każdą kartą formatu są obliczane na żywo z bieżącej liczby gaussianów i narzutu formatu — nie zakodowane sztywno. Z 2 991 gaussianów (SH degree 3) powstaje 742 KB PLY, 74 KB SPZ (współczynnik ~10× mniejszy dzięki kwantyzacji), 708 KB glTF (z rozszerzeniem KHR_gaussian_splatting, dlatego prawie równoważny PLY), 96 KB .splat (skompresowany format 24 bajty na gaussian). Orbit Video pokazuje „~Zero KB", ponieważ rozmiar jest znany dopiero po kodowaniu MP4. Web Viewer (133 KB) pakuje samodzielny plik HTML z osadzonym viewerem WebGL i skompresowanymi danymi splat — większy niż samo .splat z powodu narzutu viewera. Historia eksportu po prawej listuje już zakończony eksport PLY („training_20260527T211321Z.ply, 743 KB, 23:13") z pigułką formatu i akcją Reveal-w-Finderze.
Zakończony trening daje chmurę gaussianów — zbiór kilkuset tysięcy do milionów rozkładów Gaussa 3D, które razem rekonstruują scenę. RadianceKit zna dziesięć dróg zapisu tej chmury na dysk. Sześć z nich to czyste formaty danych 3D (PLY, Compressed PLY, SPZ, SOG, glTF, .splat), jeden pakuje chmurę wraz z gotowym viewerem HTML (Web Viewer), jeden renderuje plik MP4 z orbitalnej ścieżki kamery (Orbit Video), a dwa eksportują nie zawartość gaussianów, lecz tylko wynik SfM (pozy kamer i zgrubną chmurę punktów) do ponownego użycia w innych potokach treningu (transforms.json + workspace COLMAP).
Który format kiedy jest właściwy, zależy od celu. Do archiwizacji pełnych danych bez utraty jakości bierze się PLY. Do viewerów webowych na własnej stronie zwykle wystarcza .splat lub wbudowany Web Viewer. Gdy plik musi być minimalny, opłaca się SPZ lub SOG. Do ponownego użycia wyniku SfM w Nerfstudio, Postshot lub Brush właściwymi drogami są transforms.json i workspace COLMAP.
Wszystkie funkcje eksportu znajdują się w menu „Export" oraz w Trybie początkującym na ostatnim etapie kreatora. Większość formatów jest w pełni zgodna z sandboxem i działa w wersji App Store. Tylko SOG wymaga zewnętrznego pliku wykonywalnego (cwebp), który w buildzie App Store niekoniecznie jest dostępny — szczegóły w E4.
E1 — PLY (.ply)
GDZIE
Pasek menu → Export → 3D Formats → Export PLY... (⌘E). Tryb początkujący: krok kreatora Export → karta formatu „PLY". Rozmiar: typowo 100% (wartość referencyjna). Zgodny z: SuperSplat, PolyCam, wszystkie viewery 3DGS.
TECHNICZNIE
PLY jest kanonicznym formatem zapisu dla 3D Gaussian Splatting. RadianceKit zapisuje binarny plik Little-Endian ze standardowym układem właściwości 3DGS: na każdego gaussiana trójkomponentowa pozycja, trzy normalne stale ustawione na zero, trzy współczynniki SH DC (f_dc_0..2) dla bazowego koloru RGB, następnie do 45 dalszych współczynników SH (f_rest_0..44) w transponowanym układzie Channel-Major zdefiniowanym w artykule Kerbl 2023 (najpierw wszystkie współczynniki kanału R, potem wszystkie G, potem wszystkie B), za nimi opacity w postaci logit (surowe wartości pre-sigmoid), trzy skale w przestrzeni log oraz rotacja jako kwaternion wxyz. Maksymalny eksportowany stopień SH jest ograniczony do minimum z życzenia użytkownika i faktycznie wyuczonego stopnia; domyślnie 3 (45 reszt współczynników). Przed zapisem rozmiar payloadu jest obliczany w liczbach 64-bitowych, aby wychwycić przepełnienie przy ekstremalnie dużych chmurach. Plik zapisywany jest atomowo, co przy dużych chmurach przejściowo zajmuje podwójną ilość miejsca na dysku.
E2 — Compressed PLY (.ply)
GDZIE
Pasek menu → Export → 3D Formats → Export Compressed PLY... Tryb początkujący: karta formatu „Compressed PLY". Rozmiar: ok. 10–20% względem PLY (5- do 10-krotna kompresja). Zgodny z: SuperSplat, silnik PlayCanvas, viewery webowe.
TECHNICZNIE
Wariant formatu PLY od PlayCanvas z chunkowaną kwantyzacją. Gaussiany są grupowane w chunki po 256. Na chunk w nagłówku osobno zapisywane są granice Min/Max dla pozycji, skali i koloru; poszczególne gaussiany referencjonują swoje wartości względem tych granic i są kompresowane do po 32 bity: pozycja i skala z pakowaniem 11-10-11 bitów, rotacja jako kwaternion 2-10-10-10 bitów „Smallest-Three", kolor jako RGBA 8-8-8-8. Wyższe współczynniki SH są kwantyzowane tylko do 8 bitów na komponent (shCoeffCount * 3 uchar na gaussian). Sam format wciąż jest PLY z nagłówkiem ASCII i przez to zasadniczo walidowalny narzędziami PLY, ale właściwości wierzchołków są zadeklarowane jako pola uint. Stopień SH jest domyślnie 0 (brak współczynników reszty), aby maksymalizować kompresję — wyższe stopnie SH można jawnie wybrać.
E3 — SPZ (.spz)
GDZIE
Pasek menu → Export → 3D Formats → Export SPZ... Tryb początkujący: karta formatu „SPZ". Rozmiar: ok. 10% względem PLY (90% mniejszy). Zgodny z: Niantic Scaniverse, Niantic Spatial Fields, MetalSplatter.
TECHNICZNIE
Format SPZ-v2 od Niantica. Pozycje są pakowane jako 24-bitowy Fixed-Point (daje ok. 0,25 mm rozdzielczości), skale jako kwantyzacja 8-bitowa w przestrzeni log, rotacje jako 8-bitowy Smallest-Three (w v2 zapisywane są tylko xyz, w jest wyprowadzane przez dekoder z normy kwaternionu), opacity jako wartości 8-bitowe po sigmoidzie. SH DC jest zapisywany ze specyficznym dla SPZ wzorem pakowania (dc_raw * 0.15 * 255 + 0.5 * 255), wyższe pasma SH z 5 bitami (Band 1) lub 4 bitami (Band 2-3) na współczynnik. Cały zapakowany blob binarny jest następnie kompresowany standardowym gzip (RFC 1952), co daje format kontenera gzipped z magic bytes 1f 8b. RadianceKit wywołuje do tego systemowy gzip, ponieważ wbudowane API zlib firmy Apple generuje zastrzeżone framing Apple, które nie byłoby zgodne z czytnikami SPZ w Spatial Fields ani MetalSplatter. Systemowy gzip jest również wewnątrz sandboxa macOS możliwy do spawnowania.
E4 — SOG (.sog)
GDZIE
Pasek menu → Export → 3D Formats → Export SOG... Tryb początkujący: karta formatu „SOG". Rozmiar: ok. 5–6% względem PLY (15- do 20-krotna kompresja — najmniejsza opcja). Zgodny z: silnik PlayCanvas, edytor SuperSplat.
TECHNICZNIE
„Spatially Ordered Gaussians" — format PlayCanvas, który zapisuje chmurę gotową dla GPU w kilku obrazach WebP bezstratnych. Najpierw wszystkie gaussiany są przestrzennie sortowane kodem Morton 3D (30-bit Z-Order, po 10 bitów na oś), co zapewnia obrazom późniejszą lokalność cache w renderze. Następnie pozycje są symetryczną transformacją log (dla lepszego zakresu dynamicznego) kwantyzowane do wartości 16-bitowych i dzielone na dwa obrazy RGBA (means_l.webp dla dolnych 8 bitów, means_u.webp dla górnych). Rotacje są kodowane jako Smallest-Three z 3×8 bitami plus 2-bitowym trybem w jednym obrazie RGBA (tryb ląduje w alfa jako 252 + largest). Skale i SH DC są kwantyzowane każdy z 256-wpisowym codebookiem (rozproszonym percentylowo na wszystkich wartościach), indeksy lądują w scales.webp i sh0.webp. Pięć obrazów plus meta.json z codebookami i granicami pakowane jest do pliku ZIP (własny enkoder, ponieważ sandbox blokuje systemowy zip) i zapisywane z rozszerzeniem .sog.
Uwaga sandbox: SOG to jedyna opcja formatu wymagająca zewnętrznego pliku wykonywalnego. Etap enkodera WebP wywołuje cwebp z /usr/local/bin/cwebp lub /opt/homebrew/bin/cwebp. Jeśli żaden plik wykonywalny cwebp nie zostanie znaleziony, kod spada na surowe kodowanie PNG — ale: fallback PNG nie działa w SuperSplat. W wersji App Store oceniaj dostępność na podstawie wariantu builda; w wariancie deweloperskim cwebp musi być zainstalowane przez Homebrew (brew install webp).
E5 — glTF (.glb)
GDZIE
Pasek menu → Export → 3D Formats → Export glTF... Tryb początkujący: karta formatu „glTF". Rozmiar: porównywalny z PLY. Zgodny z: viewery glTF z rozszerzeniem KHR_gaussian_splatting (standard draft Khronos).
TECHNICZNIE
Zapisuje samowystarczalny plik binarny .glb (brak osobnego załącznika bin) zgodnie ze specyfikacją rozszerzenia KHR_gaussian_splatting. Pozycje są zapisywane jako zwykłe dane wierzchołków POSITION glTF (float3), wszystkie inne atrybuty (rotacja jako float4, skala jako float3, opacity jako float, współczynniki SH jako float3 × shCoeffCount) leżą w dodatkowych atrybutach wierzchołków i są referencjonowane przez rozszerzenie. Ważne: glTF używa praworęcznego układu Y-up, COLMAP/3DGS pracuje Y-down/Z-forward. Eksporter stosuje więc obrót o 180 stopni wokół osi X — pozycje są przepisywane jako (x, -y, -z), kwaterniony dostosowywane do (w, x, -y, -z). To daje geometrycznie poprawną, zgodną z ręcznością (nie odbitą lustrzanie) prezentację w viewerach glTF. Chunki JSON i binarne są paddingowane do wyrównania 4-bajtowego, jak wymaga standard GLB.
E6 — Splat (.splat)
GDZIE
Pasek menu → Export → 3D Formats → Export .splat... Tryb początkujący: karta formatu „.splat". Rozmiar: dokładnie 32 bajty na gaussiana. Zgodny z: gsplat.js, viewery webowe (referencja antimatter15), większość przeglądarkowych dem 3DGS.
TECHNICZNIE
Format .splat antimatter15 — 32 bajty na gaussiana, brak nagłówka, brak indyrekcji. Układ na wpis: 3 × float32 pozycja (współrzędne świata), 3 × float32 skala (po transformacji exp z przestrzeni log wewnętrznego bufora), 4 × uint8 kolor RGBA (współczynnik SH DC skalowany przez SH_C0 = 0.282... i ograniczony do [0,255]), 4 × uint8 kwaternion (w,x,y,z, znormalizowany i zakodowany w zakresie bajtu jako 128 + 128*q). Tylko SH DC jest zapisywane — wyższe pasma SH są odrzucane. To czyni format niezwykle zwartym, ale kosztuje zmiany koloru zależne od widoku, które występują przy odbiciach lub spekularnych refleksach. Kolejność zapisu to dokładnie kolejność indeksów chmury (bez sortowania przestrzennego), viewery webowe takie jak gsplat.js renderują od tego punktu wyjścia.

flowers-01.html otwarty bezpośrednio z Findera podwójnym kliknięciem w domyślnej przeglądarce — osadzony program WebGL2 renderuje chmurę gaussianów natychmiast, bez sieci ani serwera. Czarne znaczniki wokół bukietu to kamery treningowe, opcjonalnie wyświetlane. Przeciągnięcie myszką obraca, scroll zoomuje.E7 — Web Viewer (.html)
GDZIE
Pasek menu → Export → Media → Export Web Viewer... Tryb początkujący: karta formatu „Web Viewer". Rozmiar: dane splat kodowane base64 (≈ 4/3 narzutu) + ok. 5 KB powłoki HTML/JS. Zgodny z: każda nowoczesna przeglądarka z WebGL2 (wszystkie desktopy, iOS 15+, Android 5+).
TECHNICZNIE
Pakuje chmurę gaussianów wraz z w pełni inline zapisanym renderem WebGL2 w pojedynczy plik .html. Nie ma zależności od CDN, nie ma WASM, nie ma drugiego pliku. Chmura jest wewnętrznie najpierw kodowana jako binarna .splat (ta sama logika 32 bajtów jak E6), potem osadzana w base64, potem dekodowana w przeglądarce przez atob. Wbudowany renderer wykonuje własne sortowanie WebGL2, sterowanie orbitą myszy i sortowanie CPU na ramkę; cały kod JS (shadery, matematyka, pętla) jest widoczny w wyjściowym HTML. Konwencja osi na granicy zapis-do-renderera jest dokładnie taka sama jak w E5: pozycja (x, -y, -z), kwaternion (w, x, -y, -z). Opcjonalnie może być wyświetlany branding overlay (przełącznik Free Tier). Ponieważ wszystko jest inline, plik działa również bezpośrednio z protokołu file:// — brak lokalnego serwera WWW potrzebnego do testowania.

E8 — Orbit Video (.mp4/.mov)
GDZIE
Pasek menu → Viewport → Record Turntable Video LUB pasek menu → Export → Media → Export Orbit Video... Tryb początkujący: karta formatu „Orbit Video" z suwakiem czasu trwania 3–30 s. Rozmiar: zależnie od czasu trwania, rozdzielczości, bitrate. Zgodny z: wszystkie platformy (H.264 i HEVC to standard Apple).
TECHNICZNIE
Renderuje chmurę gaussianów wzdłuż parametrycznej orbitalnej ścieżki kamery i koduje każdą klatkę przez AVAssetWriter do pliku MP4 lub MOV. Konfiguracja orbity steruje liczbą obrotów (obroty), dystansem, elewacją, FOV, czasem trwania i współczynnikiem Ease-In/Out. Na klatkę macierz dopasowania świata (obliczana przez renderer, aby obrócić wewnętrzne współrzędne do orbitalnego świata Y-up) jest mnożona przez kamerę, następnie stosowane jest specyficzne dla MetalSplatter odbicie lustrzane Y. Cel renderingu offscreen jest przez IOSurface przyciągany do CVPixelBuffera dla enkodera. Enkoder wspiera H.264 i HEVC, konfigurowalny bitrate i rozdzielczość od 480p do 8K. Przed pierwszą klatką renderer czeka 200 ms, aby początkowe sortowanie splatów zostało ukończone. Ten eksport jest GPU-bound — przy 8K i milionach gaussianów czas renderowania na klatkę leży na poziomie kilku sekund, czyli całkowite czasy renderowania 10–30 minut dla 6 s wideo są możliwe.
E9 — Transforms SfM (transforms.json)
GDZIE
Pasek menu → Export → Photogrammetry → Export SfM (transforms.json)... Rozmiar: typowo 1–10 KB (tylko pozy + intrinsics, brak obrazów, brak gaussianów). Zgodny z: nerfstudio, Brush, gsplat, OpenSplat, Meshroom, wszystkie nowoczesne trenery 3DGS feed-forward.
TECHNICZNIE
Zapisuje format nerfstudio transforms.json z listą póz kamer plus dzielonymi intrinsics. Na kamerę macierz widoku (wewnętrznie w RadianceKit: World-to-Camera w konwencji COLMAP) jest odwracana, następnie kameralne wektory bazowe Y i Z są odbijane lustrzanie, aby przejść do konwencji nerfstudio (styl OpenGL, kamera patrzy wzdłuż -Z, +Y jest w górze). Finalna macierz 4×4 ląduje jako row-major zagnieżdżona tablica double w polu transform_matrix każdej klatki. Intrinsics są zapisywane na poziomie top-level (ogniskowa x/y, punkt główny x/y, szerokość/wysokość obrazu, camera_model = "OPENCV", plus współczynniki dystorsji k1, k2, p1, p2) — chyba że eksporter wykryje kilka różnych zestawów intrinsics, wtedy są zapisywane na klatkę. Ścieżki obrazów są zapisywane jako images/<filename> względem pliku JSON; użytkownik musi utworzyć siostrzany folder images/ z fotografiami treningowymi.
E10 — Workspace COLMAP (sparse/0/)
GDZIE
Pasek menu → Export → Photogrammetry → Export SfM (COLMAP Workspace)... Rozmiar: trzy pliki binarne razem typowo 4–8 MB — points3D.bin dominuje (jedna linia na punkt 3D chmury sparse), images.bin i cameras.bin są każdy znacznie poniżej 100 KB. Zgodny z: sam COLMAP, Nerfstudio, Postshot, Meshroom, wszystkie narzędzia oczekujące katalogu sparse/ COLMAP.
TECHNICZNIE
Zapisuje standardowy układ sparse/0/ COLMAP z trzema plikami binarnymi: cameras.bin, images.bin, points3D.bin. Referencja formatu to oficjalna dokumentacja COLMAP. cameras.bin zawiera zdeduplikowaną listę intrinsics (kamery z identycznymi intrinsics + rozmiarem obrazu są scalane do pojedynczego wpisu); używany model kamery to OPENCV (Model 4), z fx/fy/cx/cy plus czterema współczynnikami dystorsji k1/k2/p1/p2. images.bin listuje na obraz pozę jako kwaternion wxyz plus translację, za nimi ID kamery i nazwa pliku; nie są zapisywane korespondencje 2D-3D. points3D.bin zawiera chmurę punktów SfM z pozycją, kolorem (RGB 0-255) i wartościami domyślnymi dla reprojekcji i długości ścieżki. Wszystko zapisywane w Little-Endian. Re-import do RadianceKit działa przez menu File → „Import COLMAP/Metashape Workspace..." (zobacz Q3 w rozdziale o backendach SfM).
Który format kiedy?
| Cel | Format |
|---|---|
| Viewer webowy na własnej stronie | E7 Web Viewer (.html) |
Viewer webowy z gsplat.js | E6 Splat (.splat) |
| Reuse potoku w Postshot / Nerfstudio | E9 transforms.json + E10 Workspace COLMAP |
| Edycja w SuperSplat | E1 PLY lub E2 Compressed PLY |
| Niantic Scaniverse / Spatial Fields | E3 SPZ |
| Maksymalna kompresja | E4 SOG (wymagane cwebp) |
| Wideo marketingowe/społecznościowe | E8 Orbit Video |
Szybkie porównanie
| Format | Rozszerzenie | Sandbox | Rozmiar (1M Gauss) | Najlepsze użycie |
|---|---|---|---|---|
| E1 PLY | .ply | tak | ~250 MB | Archiwum, najwyższa zgodność |
| E2 Compressed PLY | .ply | tak | ~40 MB | Web + SuperSplat |
| E3 SPZ | .spz | tak (spawn gzip) | ~40 MB | Niantic + Mobile |
| E4 SOG | .sog | warunkowo (cwebp) | ~20 MB | Maksymalna kompresja |
| E5 glTF | .glb | tak | ~250 MB | Potok Khronos |
| E6 Splat | .splat | tak | ~32 MB | Viewer webowy gsplat.js |
| E7 Web Viewer | .html | tak | ~45 MB | Samodzielny plik przeglądarki |
| E8 Orbit Video | .mp4/.mov | tak | zmienny | Social/Marketing |
| E9 SfM Transforms | .json | tak | ~5 KB | Przekazanie póz |
| E10 Workspace COLMAP | Katalog | tak | ~4–8 MB | Przekazanie póz binarne |
Kolumna rozmiarów to przybliżone wartości referencyjne dla 1 mln gaussianów ze stopniem SH 3. Rzeczywiste wartości zmieniają się zależnie od kompresowalności sceny; stopień SH 0 redukuje PLY/glTF o współczynnik 4.