Gaussians From Point Cloud
Turn a bare point cloud into actual gaussians
- ply_path
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/bflow intof_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 writeslogit(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_filenameandoutput_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.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| ply_path | STRING | Path 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_filename | STRING | gaussians_from_pcd | Basename for the output PLY (no extension). |
| output_diropt | STRING | Directory to write the output PLY. Leave blank to use ComfyUI's output folder. | |
| init_scaleopt | FLOAT | 1.000.01–10 | Multiplier 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_opacityopt | FLOAT | 0.1000.001–0.999 | Sigmoid-space initial alpha per gaussian. The node applies logit(init_opacity) and writes that to `opacity`. 0.1 matches upstream 3DGS sfm-init. |
| knn_kopt | INT | 31–10 | k for the knn lookup. 3 matches upstream 3DGS (mean distance to the 3 nearest neighbors after skipping self). Larger k = smoother scale field. |
| subsample_maxopt | INT | 00–50000000 | Optional 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)
| Name | Type | Description |
|---|---|---|
| ply_path | STRING | — |