Capítulo 8 — Formatos de exportação


O que aparece na imagem (2 991 Gaussians, SH degree 3, buquê sintético em Blender como conjunto de teste IP-clean): os tamanhos sob cada card de formato são calculados ao vivo a partir do número atual de Gaussians e do overhead do formato — não estão fixos. De 2 991 Gaussians (SH degree 3) saem 742 KB de PLY, 74 KB de SPZ (fator ~10× menor por quantização), 708 KB de glTF (com extensão KHR_gaussian_splatting, por isso quase equivalente ao PLY), 96 KB de .splat (formato compactado de 24 bytes por Gaussian). Orbit Video mostra „~Zero KB" porque o tamanho só é conhecido depois do encoding do MP4. Web Viewer (133 KB) empacota um arquivo HTML autônomo com viewer WebGL embutido e dados de splat comprimidos — maior que .splat puro por causa do overhead do viewer. Export History à direita lista um export de PLY já concluído („training_20260527T211321Z.ply, 743 KB, 23:13") com pill do formato e ação Reveal no Finder.
Um treinamento concluído entrega uma nuvem de Gaussians — uma coleção de algumas centenas de milhares a milhões de distribuições gaussianas 3D que juntas reconstroem a cena. O RadianceKit conhece dez formas de gravar essa nuvem em disco. Seis delas são formatos de dados 3D puros (PLY, Compressed PLY, SPZ, SOG, glTF, .splat); um empacota a nuvem junto com um viewer HTML pronto (Web Viewer); um renderiza um MP4 a partir de uma trajetória orbital (Orbit Video); e dois exportam não o conteúdo Gaussian em si, mas apenas o resultado de SfM (poses de câmera e nuvem de pontos grosseira) para reuso em outros pipelines de treinamento (transforms.json + COLMAP-Workspace).
Qual formato é o certo em cada momento depende do objetivo. Para arquivar dados completos sem perda de qualidade, use PLY. Para viewers web na sua própria página, geralmente basta .splat ou o Web Viewer embutido. Quando o arquivo precisa ser mínimo, vale SPZ ou SOG. Para reusar o resultado de SfM em Nerfstudio, Postshot ou Brush, os caminhos certos são transforms.json e o COLMAP-Workspace.
Todas as funções de exportação estão no menu „Export" e também no Modo Iniciante, no último passo do assistente. A maioria dos formatos é totalmente compatível com sandbox e funciona na versão da App Store. Só o SOG exige um binário externo (cwebp), que pode não estar disponível no build da App Store — detalhes em E4.
E1 — PLY (.ply)
ONDE
Barra de menus → Export → 3D Formats → Export PLY… (⌘E). Modo Iniciante: passo do assistente Export → card „PLY". Tamanho: tipicamente 100 % (valor de referência). Compatível com: SuperSplat, PolyCam, todos os viewers 3DGS.
TÉCNICO
PLY é o formato canônico de armazenamento para 3D Gaussian Splatting. O RadianceKit grava um arquivo binário little-endian com o layout padronizado de propriedades 3DGS: por Gaussian, posição de três componentes, três normais sempre em zero, três coeficientes DC-SH (f_dc_0..2) para a cor base RGB, depois até 45 coeficientes SH adicionais (f_rest_0..44) no arranjo channel-major transposto definido no artigo Kerbl-2023 (primeiro todos os coeficientes do canal R, depois G, depois B), seguidos de opacidade logit (valores pré-sigmoide brutos), três escalas em log space e uma quaternion wxyz de rotação. O grau SH máximo exportado é clampeado para o mínimo entre o desejado pelo usuário e o realmente aprendido; padrão é 3 (45 coeficientes de resto). Antes da escrita, o tamanho do payload é calculado em inteiros de 64 bits para capturar overflow em nuvens muito grandes. O arquivo é gravado de forma atômica, o que ocupa temporariamente o dobro de espaço em disco para nuvens grandes.
E2 — Compressed PLY (.ply)
ONDE
Barra de menus → Export → 3D Formats → Export Compressed PLY…. Modo Iniciante: card „Compressed PLY". Tamanho: cerca de 10–20 % do PLY (compressão de 5 a 10×). Compatível com: SuperSplat, engine PlayCanvas, viewers baseados em web.
TÉCNICO
A variante PlayCanvas do formato PLY com quantização em chunks. Os Gaussians são agrupados em chunks de 256. Por chunk são gravados no header bounds mín/máx separados para posição, escala e cor; os Gaussians individuais referenciam seus valores relativos a esses bounds e são comprimidos em 32 bits cada: posição e escala com packing 11-10-11 bits, rotação como quaternion „smallest three" 2-10-10-10 bits, cor como RGBA 8-8-8-8. Coeficientes SH mais altos são quantizados com apenas 8 bits por componente (shCoeffCount * 3 uchar por Gaussian). O formato em si ainda é PLY com header ASCII e portanto validável com ferramentas PLY, mas as propriedades de vertex são declaradas como campos uint. O grau SH padrão é 0 (sem coeficientes de resto), para maximizar a compressão — graus SH mais altos podem ser escolhidos explicitamente.
E3 — SPZ (.spz)
ONDE
Barra de menus → Export → 3D Formats → Export SPZ…. Modo Iniciante: card „SPZ". Tamanho: cerca de 10 % do PLY (90 % menor). Compatível com: Niantic Scaniverse, Niantic Spatial Fields, MetalSplatter.
TÉCNICO
Formato SPZ v2 da Niantic. Posições empacotadas como ponto fixo de 24 bits (resolução de cerca de 0,25 mm), escalas como quantização de 8 bits em log space, rotações como „smallest three" de 8 bits (em v2 só são gravados xyz, w é derivado pelo decoder a partir da norma do quaternion), opacidades como valores de 8 bits passados por sigmoide. DC-SH é gravado com uma fórmula de pack específica do SPZ (dc_raw * 0.15 * 255 + 0.5 * 255); bandas SH mais altas com 5 bits (banda 1) ou 4 bits (bandas 2–3) por coeficiente. Todo o blob binário empacotado é então comprimido com gzip padrão (RFC 1952), o que resulta em um contêiner gzipped com magic bytes 1f 8b. O RadianceKit chama o gzip do sistema porque a API zlib embutida da Apple gera um framing proprietário Apple que não seria compatível com os leitores SPZ em Spatial Fields ou MetalSplatter. O gzip do sistema permanece spawnável também dentro do sandbox macOS.
E4 — SOG (.sog)
ONDE
Barra de menus → Export → 3D Formats → Export SOG…. Modo Iniciante: card „SOG". Tamanho: cerca de 5–6 % do PLY (compressão de 15 a 20× — a menor opção). Compatível com: engine PlayCanvas, editor SuperSplat.
TÉCNICO
„Spatially Ordered Gaussians" — um formato PlayCanvas que armazena a nuvem GPU-ready em várias imagens WebP sem perda. Primeiro, todos os Gaussians são ordenados espacialmente por código Morton 3D (Z-Order de 30 bits, 10 bits por eixo), o que dá às imagens cache locality posterior no renderer. Depois, posições são quantizadas para 16 bits com transformação log simétrica (para melhor alcance dinâmico) e divididas em duas imagens RGBA (means_l.webp para os 8 bits inferiores, means_u.webp para os superiores). Rotações são codificadas como „smallest three" com 3×8 bits mais 2 bits de modo numa imagem RGBA (modo vai para alpha como 252 + largest). Escalas e DC-SH são quantizadas com um codebook de 256 entradas cada (baseado em percentis distribuído sobre todos os valores), os índices vão para scales.webp e sh0.webp. As cinco imagens mais um meta.json com codebooks e bounds são empacotadas num ZIP (encoder próprio, porque o sandbox bloqueia o zip do sistema) e salvas com a extensão .sog.
Atenção sandbox: SOG é a única opção de formato que exige um binário externo. O estágio de encoder WebP chama cwebp de /usr/local/bin/cwebp ou /opt/homebrew/bin/cwebp. Se nenhum binário cwebp for encontrado, o código cai para encoding PNG bruto — mas: o fallback PNG não funciona no SuperSplat. Na versão da App Store, avalia a disponibilidade pela variante de build; na variante de desenvolvimento, cwebp deve estar instalado via Homebrew (brew install webp).
E5 — glTF (.glb)
ONDE
Barra de menus → Export → 3D Formats → Export glTF…. Modo Iniciante: card „glTF". Tamanho: comparável ao PLY. Compatível com: viewers glTF com extensão KHR_gaussian_splatting (rascunho de padrão Khronos).
TÉCNICO
Grava um arquivo binário .glb autocontido (sem anexo separado de arquivo bin) conforme a especificação da extensão KHR_gaussian_splatting. Posições são gravadas como dados de vertex glTF POSITION regulares (float3); todos os demais atributos (rotação como float4, escala como float3, opacidade como float, coeficientes SH como float3 × shCoeffCount) ficam em atributos de vertex adicionais referenciados pela extensão. Importante: glTF usa sistema de coordenadas Y-up destrímano, enquanto COLMAP/3DGS trabalham Y-down/Z-forward. Por isso o exporter aplica uma rotação de 180° em torno do eixo X — posições são reescritas como (x, -y, -z); quaternions são ajustados para (w, x, -y, -z). Isso produz uma representação geometricamente correta e destrímana (não espelhada) em viewers glTF. Chunks JSON e binário são pad-ed para alinhamento de 4 bytes, como exigido pelo padrão GLB.
E6 — Splat (.splat)
ONDE
Barra de menus → Export → 3D Formats → Export .splat…. Modo Iniciante: card „.splat". Tamanho: exatamente 32 bytes por Gaussian. Compatível com: gsplat.js, viewers baseados em web (referência antimatter15), a maioria das demos de 3DGS em browser.
TÉCNICO
O formato .splat do antimatter15 — 32 bytes por Gaussian, sem header, sem indireção. Layout por entrada: 3 × float32 posição (coordenadas mundo), 3 × float32 escala (transformação exp a partir do log space do buffer interno), 4 × uint8 cor RGBA (coeficiente DC-SH escalado com SH_C0 = 0.282... e clampeado para [0,255]), 4 × uint8 quaternion (w,x,y,z, normalizado e codificado em byte como 128 + 128*q). Só o DC-SH é gravado — bandas SH mais altas são descartadas. Isso torna o formato extremamente compacto, mas custa as variações de cor dependentes de vista que aparecem em reflexões ou highlights especulares. A ordem de escrita é exatamente a ordem dos índices da nuvem (sem ordenação espacial); viewers web como gsplat.js renderizam a partir disso.

flowers-01.html aberto direto do Finder por duplo clique no browser padrão — o programa WebGL2 embutido renderiza a nuvem Gaussian imediatamente, sem rede ou servidor. Os marcadores pretos em volta do buquê são as câmeras de treinamento, opcionais de exibir. Drag do mouse rotaciona, scroll dá zoom.E7 — Web Viewer (.html)
ONDE
Barra de menus → Export → Media → Export Web Viewer…. Modo Iniciante: card „Web Viewer". Tamanho: dados de splat codificados em base64 (≈ overhead 4/3) + cerca de 5 KB de shell HTML/JS. Compatível com: qualquer browser moderno com WebGL2 (todos os desktops, iOS 15+, Android 5+).
TÉCNICO
Empacota a nuvem Gaussian junto com um renderer WebGL2 totalmente inline num único arquivo .html. Sem dependências de CDN, sem WASM, sem segundo arquivo. A nuvem é internamente codificada primeiro como binário .splat (mesma lógica de 32 bytes de E6), embutida em base64 e decodificada com atob no browser. O renderer embutido faz a sua própria ordenação WebGL2, controle orbital com mouse e ordenação CPU por frame; todo o código JS (shaders, matemática, loop) é visível no HTML de saída. A convenção de eixos na fronteira armazenamento-renderer é exatamente a mesma de E5: posição (x, -y, -z), quaternion (w, x, -y, -z). Opcionalmente pode aparecer uma sobreposição de branding (chave do free tier). Como tudo é inline, o arquivo funciona também direto do protocolo file:// — sem necessidade de servidor web local para testar.

E8 — Orbit Video (.mp4/.mov)
ONDE
Barra de menus → Viewport → Record Turntable Video OU barra de menus → Export → Media → Export Orbit Video…. Modo Iniciante: card „Orbit Video" com slider de duração 3–30 s. Tamanho: depende de duração, resolução, bitrate. Compatível com: todas as plataformas (H.264 e HEVC são padrão Apple).
TÉCNICO
Renderiza a nuvem Gaussian ao longo de uma trajetória orbital paramétrica e codifica cada frame via AVAssetWriter em arquivo MP4 ou MOV. A configuração orbital controla rotações (voltas), distância, elevação, FOV, duração e fator de ease in/out. Por frame, a matriz mundo-ajuste (calculada pelo renderer para girar as coordenadas internas para o sistema orbital Y-up) é multiplicada pela câmera; em seguida aplica-se o espelhamento Y específico do MetalSplatter. O alvo de render offscreen é puxado via IOSurface para um CVPixelBuffer para o encoder. O encoder suporta H.264 e HEVC, bitrate e resolução configuráveis de 480p a 8K. Antes do primeiro frame o renderer espera 200 ms para que a ordenação inicial dos splats termine. Esta exportação é GPU-bound — em 8K com milhões de Gaussians, o tempo de render por frame fica em vários segundos, ou seja, tempos totais de 10–30 minutos para um vídeo de 6 s são possíveis.
E9 — SfM Transforms (transforms.json)
ONDE
Barra de menus → Export → Photogrammetry → Export SfM (transforms.json)…. Tamanho: tipicamente 1–10 KB (só poses + intrínsecas, sem imagens, sem Gaussians). Compatível com: nerfstudio, Brush, gsplat, OpenSplat, Meshroom, todos os treinadores feed forward 3DGS modernos.
TÉCNICO
Grava o formato transforms.json do nerfstudio com uma lista de poses de câmera mais intrínsecas compartilhadas. Para cada câmera, a matriz de view (interno do RadianceKit: World-to-Camera em convenção COLMAP) é invertida; em seguida os vetores base Y e Z em coordenadas locais da câmera são espelhados para converter para a convenção do nerfstudio (estilo OpenGL, câmera olha ao longo de -Z, +Y para cima). A matriz 4×4 final vai como array aninhado row-major de doubles no campo transform_matrix de cada frame. As intrínsecas são gravadas em top level (focal x/y, principal point x/y, largura/altura da imagem, camera_model = "OPENCV", mais os coeficientes de distorção k1, k2, p1, p2) — exceto quando o exporter detecta vários conjuntos de intrínsecas diferentes; aí são gravados por frame. Caminhos de imagem são escritos como images/<filename> relativos ao JSON; o usuário deve criar uma pasta sibling images/ com as fotos de treinamento.
E10 — COLMAP Workspace (sparse/0/)
ONDE
Barra de menus → Export → Photogrammetry → Export SfM (COLMAP Workspace)…. Tamanho: três arquivos binários, no total tipicamente 4–8 MB — points3D.bin domina (uma linha por ponto 3D da sparse cloud), images.bin e cameras.bin cada um bem abaixo de 100 KB. Compatível com: o próprio COLMAP, Nerfstudio, Postshot, Meshroom, todas as ferramentas que esperam um diretório sparse/ do COLMAP.
TÉCNICO
Grava o layout padrão COLMAP sparse/0/ com três arquivos binários: cameras.bin, images.bin, points3D.bin. A referência de formato é a documentação oficial do COLMAP. cameras.bin contém a lista deduplicada de intrínsecas (câmeras com intrínsecas + tamanho de imagem idênticos viram uma única entrada); o modelo de câmera usado é OPENCV (modelo 4), com fx/fy/cx/cy mais os quatro coeficientes de distorção k1/k2/p1/p2. images.bin lista por imagem a pose como quaternion wxyz mais translation, seguida do ID da câmera e do nome do arquivo; sem correspondências 2D-3D armazenadas. points3D.bin contém a nuvem de pontos SfM com posição, cor (RGB 0-255) e valores padrão para reprojeção e track length. Tudo é gravado em little-endian. O reimport no RadianceKit funciona pelo menu File → „Import COLMAP/Metashape Workspace…" (ver Q3 no capítulo de backends de SfM).
Qual formato, quando?
| Objetivo | Formato |
|---|---|
| Viewer web na própria página | E7 Web Viewer (.html) |
Viewer web com gsplat.js | E6 Splat (.splat) |
| Reuso no pipeline Postshot / Nerfstudio | E9 transforms.json + E10 COLMAP Workspace |
| Edição no SuperSplat | E1 PLY ou E2 Compressed PLY |
| Niantic Scaniverse / Spatial Fields | E3 SPZ |
| Compressão máxima | E4 SOG (cwebp necessário) |
| Vídeo de marketing / redes | E8 Orbit Video |
Comparação rápida
| Formato | Extensão | Sandbox | Tamanho (1M Gauss) | Melhor uso |
|---|---|---|---|---|
| E1 PLY | .ply | sim | ~250 MB | Arquivo, maior compatibilidade |
| E2 Compressed PLY | .ply | sim | ~40 MB | Web + SuperSplat |
| E3 SPZ | .spz | sim (spawn de gzip) | ~40 MB | Niantic + mobile |
| E4 SOG | .sog | condicional (cwebp) | ~20 MB | Compressão máxima |
| E5 glTF | .glb | sim | ~250 MB | Pipeline Khronos |
| E6 Splat | .splat | sim | ~32 MB | Viewer web gsplat.js |
| E7 Web Viewer | .html | sim | ~45 MB | Arquivo standalone para browser |
| E8 Orbit Video | .mp4/.mov | sim | variável | Redes/marketing |
| E9 SfM Transforms | .json | sim | ~5 KB | Repasse de poses |
| E10 COLMAP Workspace | diretório | sim | ~4–8 MB | Repasse de poses binário |
A coluna de tamanho são valores aproximados para 1 milhão de Gaussians com grau SH 3. Valores reais variam conforme a compressibilidade da cena; grau SH 0 reduz PLY/glTF por um fator de 4.