Skip to content

Conversation

@prodigious-diego
Copy link

Adds support for exporting 3D Gaussians to SPLAT and SOG formats, enabling compatibility with popular Gaussian splatting viewers and tools.

Changes

  • Add --export-format option to predict.py CLI (ply, splat, sog)
  • Implement export_splat() and export_sog() utilities in gaussians.py

Testing

Verified these output correctly and load into SuperSplat (splat and sog) and Antimatter (splat)

image

@ftaghiyev
Copy link

Hi @prodigious-diego,

Thanks for PR, LGTM. The only tiny concern I have is that per-element loop is not fundamentally required because the critical path can be expressed in vectorized or batched NumPy operations, with only limited control-flow logic remaining.

"quats": {"files": ["quats.webp"]},
"sh0": {"codebook": sh0_codebook.tolist(), "files": ["sh0.webp"]},
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. TypeScript (core technology – đáng chú ý nhất)
    Không chỉ là “viết bằng TypeScript”, mà là TypeScript có kỷ luật thiết kế:
    Type annotations rõ ràng (SerializedBlock, DAGEdge, NodeMetadata)
    Dùng private → class-based OOP chuẩn
    Type đóng vai trò hợp đồng (contract) cho dữ liệu DAG
    Codebase lớn hoặc phức tạp
    Ưu tiên độ an toàn khi refactor và khả năng mở rộng

  2. ES Modules + Path Alias (@/...)
    Công nghệ liên quan:
    tsconfig.json → paths
    Bundler: Vite / Webpack / ts-node / esbuild
    Ý nghĩa kiến trúc:
    Không phải project nhỏ, cấu trúc thư mục được thiết kế từ đầu
    Dùng alias để:
    Tránh relative import dài dòng
    Dễ tái cấu trúc module
    Đây là dấu hiệu của codebase enterprise / production-grade

  3. DAG / Workflow Engine (Domain-specific technology)
    Đây là điểm rất đáng chú ý về mặt kiến trúc, không phải công nghệ phổ thông.
    Các khái niệm xuất hiện:
    DAG (Directed Acyclic Graph)
    nodes / edges
    loops / parallelConfigs
    sentinel nodes
    validateSubflowStructure
    Điều này cho thấy:
    Hệ thống là workflow engine / rule engine / pipeline engine
    Có thể tương tự:
    Temporal / Airflow (ở mức ý tưởng)
    Node-based automation (Zapier / n8n / Prefect style)
    Đây không phải CRUD app thông thường.

  4. Defensive Validation Pattern
    Kỹ thuật nổi bật:
    Validation được tách thành function riêng
    Check cấu trúc DAG trước khi execute
    Fail fast bằng throw Error(...)
    Đây là:
    Defensive programming
    Design-by-contract (ở mức ứng dụng)
    Rất đáng học nếu bạn làm hệ thống:
    Workflow
    Plugin system
    User-defined graph/config

  5. Sentinel Nodes (kỹ thuật nâng cao)
    buildSentinelStartId, extractBaseBlockId
    Đây không phải công nghệ, mà là kỹ thuật mô hình hóa:
    Sentinel node = node giả để:
    Chuẩn hóa entry/exit
    Tránh edge case
    ID manipulation → cho thấy blockId mang semantic
    Đây là dấu hiệu:
    Người viết code có kinh nghiệm xử lý graph phức tạp
    Tối ưu cho thuật toán hơn là UI

  6. Logging Library (Pino / Winston / Bunyan style)
    logger.info(...) cho thấy:
    Không dùng console.log
    Có logging abstraction
    Điều này thường đi kèm:
    Production environment
    Observability / debugging workflow execution

  7. JavaScript Collection API được dùng “đúng cách”
    Map thay vì object
    Array.from(iterator)
    .some() cho short-circuit logic
    Dấu hiệu:
    Developer nắm vững ES6+
    Code hướng đến readability + performance

Comment on lines +510 to +516
with open(path, "wb") as f:
for i in sort_idx:
f.write(xyz[i].astype(np.float32).tobytes())
f.write(scales[i].astype(np.float32).tobytes())
rgba = np.concatenate([colors_rgb[i], [opacities[i]]])
f.write((rgba * 255).clip(0, 255).astype(np.uint8).tobytes())
f.write((quats[i] * 128 + 128).clip(0, 255).astype(np.uint8).tobytes())
Copy link

@Enter-tainer Enter-tainer Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to gaussians, sharp's save_ply function also saves many metadata, such as image size, camera intrinsic/extrinsic and colorspace. These information are important for rendering

if path.suffix.lower() != ".sog":
path = path.with_suffix(".sog")

with zipfile.ZipFile(path, "w", zipfile.ZIP_DEFLATED) as zf:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does ZIP_DEFLATED make sense for lossless webp?



@torch.no_grad()
def save_sog(
Copy link

@Enter-tainer Enter-tainer Dec 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linear to srgb transform is missing so the color of sog is very dark Sorry I got it wrong, sog does use linear srgb

Typically 15-20x smaller than PLY. The format stores data in a ZIP archive
containing WebP images for positions, rotations, scales, and colors.
Reference: https://github.com/aras-p/sog-format
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Reference: https://github.com/aras-p/sog-format
Reference: https://developer.playcanvas.com/user-manual/gaussian-splatting/formats/sog/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants