Nodes/ComfyUI-TurntableGSViewer/Gaussians From Point Cloud
ComfyUI Node

Gaussians From Point Cloud

Turn a bare point cloud into actual gaussians

By PozzettiAndrea·Created 4 months ago·Updated 7 days ago· 6
Gaussians From Point Cloud
    • ply_path
    ply_path
    output_filenamegaussians_from_pcd
    output_dir
    init_scale1.00
    init_opacity0.100
    knn_k3
    subsample_max0

    Most of the 3D stuff you generate in ComfyUI doesn't come out as gaussian splats. It comes out as a point cloud - a PLY with just x/y/z and maybe r/g/b. Fine for a point viewer, useless for a gaussian-splat pipeline, because 3DGS needs a whole set of per-point fields: rot_*, scale_*, opacity, and f_dc_* color. Feed a bare point cloud into a splat trainer or a viewer without those fields and you get either a rejection or degenerate defaults - the classic failure being every gaussian collapsed to a 1 mm sphere, which then takes forever to train out of.

    GaussiansFromPointCloud is the bridge. It takes any PLY - plain point cloud or an existing 3DGS PLY - and emits a properly-initialized gaussian PLY that downstream trainers and viewers actually like. It's part of the GaussianPack family (repo ComfyUI-TurntableGSViewer, same author as the HyWorld2 and TRELLIS.2 wrappers) and lives in the "GaussianPack" menu category.

    How it works

    The key is that scales aren't just guessed - they're derived the same way upstream 3DGS does its SfM initialization. The node runs a k-nearest-neighbors lookup (via sklearn's KDTree) and sets each gaussian's scale to log(mean distance to its k nearest neighbors × init_scale). Dense regions get small gaussians, sparse regions get big ones. That's exactly the initialization a real trainer would converge from, so a later training pass starts from a sane place instead of a soup of 1 mm spheres.

    The rest of the fields follow sensibly:

    • colors from the PLY's r/g/b flow into f_dc_* via the standard inverse transform
    • rotations start as identity quaternions (training deforms them)
    • opacity starts at logit(init_opacity), default 0.1 - which matches the upstream SfM init

    Inputs that matter

    • ply_path - input PLY. Plain point clouds get the full treatment; existing 3DGS PLYs have all fields read and missing ones defaulted. Note: knn-derived scales override whatever scales the input already had.
    • init_scale (default 1.0) - multiplier on the knn distance. Below 1 gives sharper but possibly under-covered gaussians; above 1 gives smoother but blurrier ones. 1.0 is the honest default.
    • init_opacity (default 0.1) - the sigmoid-space initial alpha. The node writes logit(init_opacity) to the opacity field.
    • knn_k (default 3) - neighbors used for scale estimation, matching upstream. Larger k = smoother scale field.
    • subsample_max (default 0) - optional random cap on output count. 0 means write every point. If a downstream node OOMs on a giant cloud, cap it at something like 2,000,000; the seed is deterministic from the input count.
    • output_filename and output_dir - filename, and where to write (leave the dir blank for ComfyUI's output folder).

    The single output, ply_path, is the absolute path of the new PLY - ready for a viewer, merge, export, or a trainer.

    Installing it

    cd ComfyUI/custom_nodes
    git clone https://github.com/PozzettiAndrea/ComfyUI-TurntableGSViewer.git
    cd ComfyUI-TurntableGSViewer
    pip install -r requirements.txt --upgrade
    python install.py
    

    Restart ComfyUI. Manager users: search "GaussianPack". Remember the experimental comfy-env dependency pulls in pixi on first install. No weights to download; the pack auto-copies sample PLYs into input/.

    When you'll use it

    Any time your upstream is point-cloud-flavored - a depth-to-pointcloud node, a colmap export, a panorama-stitched scene - and your downstream expects real gaussians. It's also a handy sanity fix for an existing 3DGS PLY whose scales are garbage. One thing to watch: a 7M-point cloud takes a few seconds and a couple hundred MB of RAM for the knn pass, so don't be alarmed if it's not instant.

    CategoryGaussianPack

    Inputs (7)

    NameTypeDefaultDescription
    ply_pathSTRINGPath to an input PLY. Can be a plain point cloud (x/y/z + optional r/g/b) or an existing 3DGS PLY (in which case all fields are read; missing ones get sensible defaults). knn-derived scales OVERRIDE whatever scales the input had.
    output_filenameSTRINGgaussians_from_pcdBasename for the output PLY (no extension).
    output_diroptSTRINGDirectory to write the output PLY. Leave blank to use ComfyUI's output folder.
    init_scaleoptFLOAT1.000.01–10Multiplier on the knn distance when computing initial scales. 1.0 = exactly the mean distance to k nearest neighbors. <1 = smaller gaussians (sharper but possibly under-covered). >1 = larger (smoother but blurrier).
    init_opacityoptFLOAT0.1000.001–0.999Sigmoid-space initial alpha per gaussian. The node applies logit(init_opacity) and writes that to `opacity`. 0.1 matches upstream 3DGS sfm-init.
    knn_koptINT31–10k for the knn lookup. 3 matches upstream 3DGS (mean distance to the 3 nearest neighbors after skipping self). Larger k = smoother scale field.
    subsample_maxoptINT00–50000000Optional random cap on the gaussian count. 0 = no cap (write every input point). Set a positive value (e.g. 2_000_000) if a downstream node OOMs at huge counts. Deterministic seed = N_in.

    Outputs (1)

    NameTypeDescription
    ply_pathSTRING