Capítulo 8 — Formatos de exportación


Lo que se ve en la imagen (2 991 Gaussianos, grado SH 3, ramo sintético de Blender libre de IP como conjunto de prueba): Las cifras de tamaño bajo cada tarjeta de formato se calculan en vivo a partir del número actual de Gaussianos y el overhead del formato — no están fijadas. Con 2 991 Gaussianos (grado SH 3) obtienes 742 KB de PLY, 74 KB de SPZ (factor ~10× más pequeño por la cuantización), 708 KB de glTF (con extensión KHR_gaussian_splatting, por eso casi equivalente al PLY), 96 KB de .splat (formato comprimido de 24 bytes por Gaussiano). Orbit Video muestra "~Zero KB" porque el tamaño solo se conoce tras codificar el MP4. Web Viewer (133 KB) empaqueta un archivo HTML autónomo con visor WebGL embebido y datos de splat comprimidos — más grande que el .splat puro por el overhead del visor. El historial de exportación a la derecha enumera la exportación PLY ya completada ("training_20260527T211321Z.ply, 743 KB, 23:13") con la insignia de formato y la acción Reveal in Finder.
Un entrenamiento terminado entrega una nube de Gaussianos — una colección de unos pocos cientos de miles a millones de distribuciones Gaussianas 3D que en conjunto reconstruyen la escena. RadianceKit conoce diez formas de escribir esa nube a disco. Seis son formatos de datos 3D puros (PLY, Compressed PLY, SPZ, SOG, glTF, .splat), uno empaqueta la nube junto con un visor HTML listo (Web Viewer), uno renderiza un archivo MP4 desde una trayectoria de cámara orbital (Orbit Video) y dos no exportan contenido Gaussiano sino solo el resultado de SfM (poses de cámara y nube de puntos gruesa) para reutilizar en otras pipelines de entrenamiento (transforms.json + COLMAP Workspace).
Qué formato es el adecuado en cada caso depende del objetivo. Para archivar todos los datos sin pérdida de calidad usas PLY. Para visores web en tu propia página, .splat o el Web Viewer integrado suelen bastar. Si el archivo tiene que ser mínimo, vale la pena SPZ o SOG. Para reutilizar el resultado de SfM en Nerfstudio, Postshot o Brush, transforms.json y el COLMAP Workspace son las vías correctas.
Todas las funciones de exportación están en el menú "Export", así como en el modo principiante en la última etapa del asistente. La mayoría de los formatos son totalmente compatibles con el sandbox y funcionan en la versión de App Store. Solo SOG requiere un binario externo (cwebp) que no está necesariamente presente en el build de App Store — detalles en E4.
E1 — PLY (.ply)
DÓNDE
Barra de menús → Export → 3D Formats → Export PLY… (⌘E). Modo principiante: paso del asistente Export → tarjeta de formato "PLY". Tamaño: típicamente 100 % (valor de referencia). Compatible con: SuperSplat, PolyCam, todos los visores 3DGS.
TÉCNICO
PLY es el formato de almacenamiento canónico para 3D Gaussian Splatting. RadianceKit escribe un archivo binario little-endian con el layout de propiedades 3DGS estandarizado: por Gaussiano, posición de tres componentes, tres normales siempre a cero, tres coeficientes SH DC (f_dc_0..2) para el color RGB base, seguidos de hasta 45 coeficientes SH adicionales (f_rest_0..44) en la disposición canal-mayor transpuesta definida por el paper de Kerbl 2023 (primero todos los coeficientes del canal R, luego todos los de G y luego todos los de B), seguido por la opacidad logit (valores brutos previos al sigmoide), tres escalas en espacio logarítmico y una rotación cuaternión wxyz. El grado SH máximo exportado se acota al mínimo entre el deseo del usuario y el grado realmente aprendido; el predeterminado es 3 (45 coeficientes rest). Antes de escribir, el tamaño del payload se calcula en entero de 64 bits para detectar overflow en nubes extremadamente grandes. El archivo se escribe de forma atómica, lo que en nubes grandes ocupa brevemente el doble de espacio en disco.
E2 — PLY comprimido (.ply)
DÓNDE
Barra de menús → Export → 3D Formats → Export Compressed PLY…. Modo principiante: tarjeta de formato "Compressed PLY". Tamaño: aprox. 10–20 % vs. PLY (compresión de 5 a 10 veces). Compatible con: SuperSplat, motor PlayCanvas, visores basados en web.
TÉCNICO
La variante PlayCanvas del formato PLY con cuantización por chunks. Los Gaussianos se agrupan en chunks de 256. Por chunk se almacenan en la cabecera, por separado, los límites min/max para posición, escala y color; los Gaussianos individuales referencian sus valores relativos a esos límites y se comprimen a 32 bits cada uno: posición y escala con empaquetado 11-10-11 bits, rotación como cuaternión "Smallest-Three" 2-10-10-10 bits, color como RGBA 8-8-8-8. Los coeficientes SH superiores se cuantizan con solo 8 bits por componente (shCoeffCount * 3 uchar por Gaussiano). El formato en sí sigue siendo PLY con cabecera ASCII y por tanto en principio validable con herramientas de PLY, pero las propiedades de vértice están declaradas como campos uint. El grado SH es por defecto 0 (sin coeficientes rest) para maximizar la compresión — se pueden seleccionar grados SH superiores de forma explícita.
E3 — SPZ (.spz)
DÓNDE
Barra de menús → Export → 3D Formats → Export SPZ…. Modo principiante: tarjeta de formato "SPZ". Tamaño: aprox. 10 % vs. PLY (90 % más pequeño). Compatible con: Niantic Scaniverse, Niantic Spatial Fields, MetalSplatter.
TÉCNICO
El formato SPZ v2 de Niantic. Las posiciones se empaquetan como fixed-point de 24 bits (lo que da una resolución de aprox. 0,25 mm), las escalas como cuantización de 8 bits en espacio logarítmico, las rotaciones como Smallest-Three de 8 bits (en v2 solo se almacena xyz, w se deriva en el decoder a partir de la norma del cuaternión), las opacidades como valores sigmoideados de 8 bits. El SH DC se almacena con una fórmula de empaquetado específica de SPZ (dc_raw * 0.15 * 255 + 0.5 * 255), las bandas SH superiores con 5 bits (banda 1) o 4 bits (banda 2-3) por coeficiente. Todo el blob binario empaquetado se comprime después con gzip estándar (RFC 1952), lo que da un formato contenedor gzipped con bytes mágicos 1f 8b. RadianceKit invoca para ello el gzip del sistema, porque la API zlib integrada de Apple genera un framing propio de Apple que no sería compatible con los lectores SPZ de Spatial Fields o MetalSplatter. El gzip del sistema también sigue siendo lanzable dentro del sandbox de macOS.
E4 — SOG (.sog)
DÓNDE
Barra de menús → Export → 3D Formats → Export SOG…. Modo principiante: tarjeta de formato "SOG". Tamaño: aprox. 5–6 % vs. PLY (compresión de 15 a 20 veces — la opción más pequeña). Compatible con: motor PlayCanvas, editor SuperSplat.
TÉCNICO
"Spatially Ordered Gaussians" — un formato PlayCanvas que almacena la nube lista para GPU en varias imágenes WebP sin pérdida. Primero, todos los Gaussianos se ordenan espacialmente mediante código Morton 3D (Z-order de 30 bits, 10 bits por eje), lo que da más adelante a las imágenes localidad de caché en el renderer. Luego las posiciones se cuantizan a valores de 16 bits con transformación logarítmica simétrica (para un mejor rango dinámico) y se dividen en dos imágenes RGBA (means_l.webp para los 8 bits bajos, means_u.webp para los altos). Las rotaciones se codifican como Smallest-Three con 3×8 bits más modo de 2 bits en una imagen RGBA (el modo aterriza en alfa como 252 + largest). Las escalas y el SH DC se cuantizan, cada uno, con un codebook de 256 entradas (distribuido por percentiles sobre todos los valores); los índices acaban en scales.webp y sh0.webp. Las cinco imágenes más un meta.json con codebooks y bounds se empaquetan en un archivo ZIP (encoder propio porque el sandbox bloquea el zip del sistema) y se guardan con la extensión .sog.
Aviso de sandbox: SOG es la única opción de formato que requiere un binario externo. La etapa del encoder WebP llama a cwebp desde /usr/local/bin/cwebp o /opt/homebrew/bin/cwebp. Si no se encuentra el binario cwebp, el código recurre a la codificación PNG cruda — pero: el fallback PNG no funciona en SuperSplat. En la versión de App Store, evalúa la disponibilidad según la variante del build; en la variante de desarrollador, cwebp debe instalarse mediante Homebrew (brew install webp).
E5 — glTF (.glb)
DÓNDE
Barra de menús → Export → 3D Formats → Export glTF…. Modo principiante: tarjeta de formato "glTF". Tamaño: comparable al PLY. Compatible con: visores glTF con extensión KHR_gaussian_splatting (borrador de estándar Khronos).
TÉCNICO
Escribe un archivo binario .glb autocontenido (sin archivo bin separado adjunto) conforme a la especificación de la extensión KHR_gaussian_splatting. Las posiciones se almacenan como datos de vértice POSITION regulares de glTF (float3); todos los demás atributos (rotación como float4, escala como float3, opacidad como float, coeficientes SH como float3 × shCoeffCount) están en atributos de vértice adicionales y se referencian mediante la extensión. Importante: glTF usa un sistema de coordenadas right-handed Y-up, COLMAP/3DGS trabaja en Y-down/Z-forward. Por eso, el exportador aplica una rotación de 180 grados alrededor del eje X — las posiciones se reescriben como (x, -y, -z), los cuaterniones se ajustan a (w, x, -y, -z). Esto da una visualización geométricamente correcta y con handedness (no espejada) en los visores glTF. Los chunks JSON y binarios se rellenan con padding a alineación de 4 bytes como exige el estándar GLB.
E6 — Splat (.splat)
DÓNDE
Barra de menús → Export → 3D Formats → Export .splat…. Modo principiante: tarjeta de formato ".splat". Tamaño: exactamente 32 bytes por Gaussiano. Compatible con: gsplat.js, visores basados en web (referencia antimatter15), la mayoría de las demos 3DGS en navegador.
TÉCNICO
El formato .splat de antimatter15 — 32 bytes por Gaussiano, sin cabecera, sin indirección. Layout por entrada: 3 × float32 posición (coordenadas mundo), 3 × float32 escala (transformada con exp desde el espacio logarítmico del buffer interno), 4 × uint8 color RGBA (coeficiente SH DC escalado con SH_C0 = 0.282... y clamped a [0,255]), 4 × uint8 cuaternión (w,x,y,z, normalizado y codificado en el rango de bytes como 128 + 128*q). Solo se almacena el SH DC — las bandas SH superiores se descartan. Eso hace al formato extremadamente compacto, pero cuesta los cambios de color dependientes de la vista que se dan con reflejos o brillos especulares. El orden de escritura es exactamente el orden de índice de la nube (sin ordenación espacial); los visores web como gsplat.js renderizan basándose en ese supuesto.

flowers-01.html autónomo abierto directamente desde el Finder con doble clic en el navegador por defecto — el programa WebGL2 embebido renderiza la nube Gaussiana de inmediato, sin red ni servidor. Los marcadores negros alrededor del ramo son las cámaras de entrenamiento, opcionalmente conmutables. Arrastrar con el ratón rota, scroll hace zoom.E7 — Visor web (.html)
DÓNDE
Barra de menús → Export → Media → Export Web Viewer…. Modo principiante: tarjeta de formato "Web Viewer". Tamaño: datos de splat codificados en base64 (≈ 4/3 de overhead) + aprox. 5 KB de envoltorio HTML/JS. Compatible con: cualquier navegador moderno con WebGL2 (todos los escritorios, iOS 15+, Android 5+).
TÉCNICO
Empaqueta la nube Gaussiana junto con un renderer WebGL2 escrito totalmente inline en un único archivo .html. No hay dependencias de CDN, ni WASM, ni segundo archivo. La nube se codifica internamente primero como binario .splat (misma lógica de 32 bytes que E6), después se incrusta en base64 y luego se decodifica con atob en el navegador. El renderer integrado hace su propia ordenación WebGL2, controles de órbita con ratón y ordenación por CPU por frame; todo el código JS (shader, matemáticas, bucle) es visible en el HTML de salida. La convención de ejes en la frontera almacenamiento–renderer es exactamente la misma que en E5: posición (x, -y, -z), cuaternión (w, x, -y, -z). Opcionalmente se puede mostrar un overlay de branding (conmutador del free-tier). Como todo es inline, el archivo también funciona directamente desde el protocolo file:// — no se necesita servidor web local para probarlo.

E8 — Vídeo orbital (.mp4/.mov)
DÓNDE
Barra de menús → Viewport → Record Turntable Video O bien Barra de menús → Export → Media → Export Orbit Video…. Modo principiante: tarjeta de formato "Orbit Video" con deslizador de duración 3–30 s. Tamaño: depende de duración, resolución, bitrate. Compatible con: todas las plataformas (H.264 y HEVC son estándar de Apple).
TÉCNICO
Renderiza la nube Gaussiana a lo largo de una trayectoria de cámara orbital paramétrica y codifica cada fotograma mediante AVAssetWriter en un archivo MP4 o MOV. La configuración de la órbita controla la velocidad de rotación (vueltas), distancia, elevación, FOV, duración y factor de ease-in/out. Por fotograma, la matriz de ajuste mundial (calculada por el renderer para rotar las coordenadas internas al mundo orbital Y-up) se multiplica con la cámara, tras lo cual se aplica el espejado en Y específico de MetalSplatter. El render target offscreen se extrae mediante IOSurface a un CVPixelBuffer para el encoder. El encoder soporta H.264 y HEVC, bitrate y resolución configurables de 480p a 8K. Antes del primer fotograma, el renderer espera 200 ms para que se complete la ordenación inicial de splats. Esta exportación está limitada por GPU — a 8K y millones de Gaussianos, el tiempo de renderizado por fotograma es de varios segundos, así que son posibles tiempos totales de renderizado de 10–30 minutos para un vídeo de 6 s.
E9 — SfM Transforms (transforms.json)
DÓNDE
Barra de menús → Export → Photogrammetry → Export SfM (transforms.json)…. Tamaño: típicamente 1–10 KB (solo poses + intrínsecos, sin imágenes, sin Gaussianos). Compatible con: nerfstudio, Brush, gsplat, OpenSplat, Meshroom, todos los entrenadores 3DGS feed-forward modernos.
TÉCNICO
Escribe el formato transforms.json de nerfstudio con una lista de poses de cámara más intrínsecos compartidos. Por cámara, la matriz de vista (interna de RadianceKit: World-to-Camera en convención COLMAP) se invierte, tras lo cual los vectores base Y y Z local de cámara se espejan para pasar a la convención nerfstudio (estilo OpenGL, la cámara mira a lo largo de -Z, +Y es arriba). La matriz 4×4 final aterriza como array anidado row-major de doubles en el campo transform_matrix de cada frame. Los intrínsecos se almacenan en el nivel superior (focal x/y, punto principal x/y, ancho/alto de imagen, camera_model = "OPENCV", más los coeficientes de distorsión k1, k2, p1, p2) — excepto cuando el exportador detecta varios conjuntos de intrínsecos distintos, caso en que se escriben por frame. Las rutas de imagen se escriben como images/<filename> relativas al archivo JSON; el usuario debe crear una carpeta hermana images/ con las fotos de entrenamiento.
E10 — COLMAP Workspace (sparse/0/)
DÓNDE
Barra de menús → Export → Photogrammetry → Export SfM (COLMAP Workspace)…. Tamaño: tres archivos binarios juntos típicamente 4–8 MB — points3D.bin domina (una línea por punto 3D de la nube sparse), images.bin y cameras.bin están cada uno notablemente por debajo de 100 KB. Compatible con: el propio COLMAP, Nerfstudio, Postshot, Meshroom, todas las herramientas que esperan un directorio sparse/ de COLMAP.
TÉCNICO
Escribe el layout estándar sparse/0/ de COLMAP con tres archivos binarios: cameras.bin, images.bin, points3D.bin. La referencia de formato es la documentación oficial de COLMAP. cameras.bin contiene la lista de intrínsecos deduplicados (las cámaras con intrínsecos idénticos + tamaño de imagen se fusionan en una sola entrada); el modelo de cámara usado es OPENCV (modelo 4), con fx/fy/cx/cy más los cuatro coeficientes de distorsión k1/k2/p1/p2. images.bin lista por imagen la pose como cuaternión wxyz más traslación, seguidos del ID de cámara y el nombre de archivo; no se almacenan correspondencias 2D-3D. points3D.bin contiene la nube de puntos SfM con posición, color (RGB 0-255) y valores predeterminados para reproyección y longitud de track. Todo se escribe en little-endian. La reimportación en RadianceKit funciona a través del menú File → "Import COLMAP/Metashape Workspace…" (véase Q3 en el capítulo de backends SfM).
¿Qué formato en cada caso?
| Objetivo | Formato |
|---|---|
| Visor web en tu propia página | E7 Web Viewer (.html) |
Visor web con gsplat.js | E6 Splat (.splat) |
| Reutilización de pipeline en Postshot / Nerfstudio | E9 transforms.json + E10 COLMAP Workspace |
| Edición en SuperSplat | E1 PLY o E2 Compressed PLY |
| Niantic Scaniverse / Spatial Fields | E3 SPZ |
| Máxima compresión | E4 SOG (cwebp requerido) |
| Vídeo de marketing/redes | E8 Orbit Video |
Comparativa rápida
| Formato | Extensión | Sandbox | Tamaño (1M Gauss) | Mejor uso |
|---|---|---|---|---|
| E1 PLY | .ply | sí | ~250 MB | Archivo, máxima compatibilidad |
| E2 Compressed PLY | .ply | sí | ~40 MB | Web + SuperSplat |
| E3 SPZ | .spz | sí (spawn de gzip) | ~40 MB | Niantic + móvil |
| E4 SOG | .sog | condicional (cwebp) | ~20 MB | Máxima compresión |
| E5 glTF | .glb | sí | ~250 MB | Pipeline Khronos |
| E6 Splat | .splat | sí | ~32 MB | Visor web gsplat.js |
| E7 Web Viewer | .html | sí | ~45 MB | Archivo autónomo para navegador |
| E8 Vídeo orbital | .mp4/.mov | sí | variable | Redes/marketing |
| E9 SfM Transforms | .json | sí | ~5 KB | Traspaso de poses |
| E10 COLMAP Workspace | Directorio | sí | ~4–8 MB | Traspaso de poses binario |
La columna de tamaño son valores de referencia aproximados para 1 millón de Gaussianos con grado SH 3. Los valores reales varían según la compresibilidad de la escena; el grado SH 0 reduce PLY/glTF por un factor de 4.