Commit Graph
43 Commits
Author SHA1 Message Date
PozzettiAndrea dbfe9ebfc3 Trigger CI 2026-05-16 20:46:43 +02:00
PozzettiAndrea 9188ac555a Merge dev into main: workflows, comfy-env removal, gallery link 2026-05-16 20:33:08 +02:00
PozzettiAndrea 5d7672c34f Add .github/workflows/ — pr-gate, publish, run-tests
Three standard comfy-test scaffolding workflows, lifted verbatim from
ComfyUI-TRELLIS2 (identical across TRELLIS2/CADabra/HYWM2/GeometryPack
— no per-repo customization needed; they reference
PozzettiAndrea/comfy-test/.github/workflows/* and GitHub injects the
repo context):

- pr-gate.yml     PR + push-to-main + manual: runs comfy-test gate,
                  publishes results to gh-pages, screenshots the
                  gallery index at 1200x700 to gh-pages/gallery-preview.png
- publish.yml     pyproject.toml changes -> publish to Comfy registry
- run-tests.yml   push-to-dev -> runs the test matrix from comfy-test.toml

Closes the gap that made the README's gallery thumbnail 404 — it
points at https://pozzettiandrea.github.io/ComfyUI-GaussianPack/
gallery-preview.png, which now gets generated on each pr-gate run.
2026-05-16 20:32:17 +02:00
Andrea Pozzetti e439634477 Update README with new asset link
Removed an outdated link and added a new one.
2026-05-16 20:24:21 +02:00
Andrea Pozzetti f50a0f4952 Merge pull request #2 from PozzettiAndrea/dev
Dev
2026-05-16 20:11:48 +02:00
PozzettiAndrea b8de26b68c Drop comfy-env dependency: stdlib + relative import only
User wants GaussianPack fully self-contained — no comfy-env in the
runtime path. Three swaps + one orphan deletion:

1. prestartup_script.py: `comfy_env.copy_files(src, dst)` -> stdlib
   shutil.copy2 loop. Same semantics (top-level files, non-clobbering),
   6 lines. Fixes the NameError that snuck in earlier when the
   `from comfy_env import copy_files` line was removed without
   replacement; in the test workspace `apple.ply` actually lands in
   `input/` now.

2. __init__.py: `comfy_env.register_nodes()` -> `from .nodes import
   NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS`. That's literally
   what register_nodes() boils down to when no nodes/comfy-env.toml is
   present (the no-isolation branch). Hyphenated parent package names
   are fine for relative imports — verified earlier in this session
   with a Foo-Bar fixture via importlib.import_module.

3. nodes/__init__.py: docstring update — drop the "calls
   comfy_env.register_nodes()" mention now that the root does the
   relative import directly.

4. comfy-env-root.toml: deleted. The [node_reqs] section only had
   meaning for comfy-env's isolation discovery; with no comfy-env in
   play it was dead metadata.

`comfy-test.toml` stays (that's a different tool — comfy-test, not
comfy-env). `requirements.txt` stays (numpy + plyfile + NanoGS git).

`grep -rn comfy_env` across the repo returns 0 hits. Import smoke
test in the worker pixi env resolves all 5 nodes
(PreviewGaussians, GaussianMerge, LoadPLY, GaussianAnalysis,
GaussianExport).
2026-05-16 19:55:52 +02:00
PozzettiAndrea a279c930f8 Add gh-pages test-gallery link to README
Same pattern as ComfyUI-TRELLIS2: centered clickable thumbnail +
"View Live Test Gallery →" link, pointing at
https://pozzettiandrea.github.io/ComfyUI-GaussianPack/

Assumes the standard gh-pages publish path that comfy-test writes to
on push (gallery-preview.png lives at the page root). If no run has
been published yet, the image 404s harmlessly and the text link still
works.
2026-05-16 19:51:50 +02:00
PozzettiAndrea dc6909a94e recurse glob 2026-05-16 16:18:40 +02:00
PozzettiAndrea 006259f0b2 ms 2026-05-16 16:12:57 +02:00
PozzettiAndrea 93bc2e3775 LoadPLY: switch to LoadImage idiom — bare filenames + get_annotated_filepath
Previous design scanned input/ AND output/ and stored prefixed combo
entries like 'input/apple.ply'. When comfy-test ran the workflow, the
saved value 'input/apple.ply' didn't match anything the node could
resolve, and VALIDATE_INPUTS rejected the prompt:

  Custom validation failed for node: ply_file -
  LoadPLY: 'input/apple.ply' is not a known PLY in input/ or output/

Refactor to mirror ComfyUI's stock LoadImage node:
- INPUT_TYPES lists ONLY input/, bare filenames (no folder prefix)
- IS_CHANGED uses folder_paths.get_annotated_filepath(name)
- VALIDATE_INPUTS uses folder_paths.exists_annotated_filepath(name)
- load() returns folder_paths.get_annotated_filepath(name)

`get_annotated_filepath` understands `[input]/name`, `[temp]/name`,
and `[output]/name` annotations transparently, so power users can
type those into the combo if they need output/ access — same as
LoadImage. The default UX is "pick from input/".

Output-side PLYs from upstream nodes (GaussianMerge, GaussianExport,
LiToExportPLY) are wired directly into PreviewGaussians via the
STRING output — no LoadPLY needed.

workflows/merge_splats.json: rewrite widgets_values from
"input/apple.ply" -> "apple.ply" to match the new bare-filename
convention.
2026-05-16 16:06:21 +02:00
PozzettiAndrea cdbff35038 Run all 5 levels: syntax, install, registration, instantiation, execution 2026-05-16 16:04:02 +02:00
PozzettiAndrea cda2ef417c Match comfy-test.toml shape to ComfyUI-TRELLIS2
User asked for the test config to mirror TRELLIS2's. Changes:

- levels: ["syntax", "install", "registration", "instantiation"]
       -> ["syntax", "install", "execution"]
  Drops the two intermediate levels (execution implies them) and
  adds `execution` so the actual workflow runs. Without `execution`
  the test was passing vacuously without ever loading the workflow
  JSON.
- publish: true -> 'true' (string, matching TRELLIS2's spelling)
- [test.platforms]: dropped macos_desktop / windows_desktop keys
  to match TRELLIS2's key set. Kept CPU rows enabled and GPU rows
  disabled (inverse of TRELLIS2 since GaussianPack is pure-Python).

[test.workflows] unchanged: cpu = ["merge_splats"], gpu = [].
2026-05-16 16:02:06 +02:00
PozzettiAndrea bbe103e24f Broaden register_routes except clause; unblocks comfy-test instantiation
comfy-test's instantiation level was passing with 0 nodes instead of
the 5 we register, because nodes/__init__.py crashed at module-load:

  nodes/__init__.py:17           _register_spz_route()
  nodes/spz_route.py             from server import PromptServer
  ComfyUI/server.py:8            import nodes
  ComfyUI/nodes.py:26            import comfy.diffusers_load
  comfy/sd.py:7                  from comfy import model_management
  comfy/model_management.py:254  total_vram = get_total_memory(get_torch_device())
  RuntimeError: Cannot access accelerator device when none is available.

ComfyUI's model_management.py evaluates `torch.device(torch.cuda.
current_device())` at module-import time. comfy-test's test
subprocess monkey-patches torch.cuda.{is_available,device_count,
current_device} but `torch.device(0)` still crashes on CPU-only.

Our `except ImportError` clause missed the RuntimeError, so the
exception escaped and nodes/__init__.py never completed →
register_nodes() returned 0 → test "passes" vacuously with
`All 0 node(s) instantiated successfully!`.

Fix: catch `Exception` instead of `ImportError`. Real ComfyUI
startup is unaffected — by the time custom_nodes load, `server` is
already in sys.modules so the import is a no-op lookup with no
transitive imports.

Verified locally:
  [comfy-env] Importing nodes (root)...
  WARNING SPZ route not registered (RuntimeError: Cannot access accelerator device...)
  [comfy-env] Imported nodes root: 5 nodes
  [comfy-env] Registered 5 total nodes
  MAPPINGS: ['PreviewGaussians', 'GaussianMerge', 'LoadPLY', 'GaussianAnalysis', 'GaussianExport']

Next `cds test gaussianpack` should now print
`All 5 node(s) instantiated successfully!`.
2026-05-16 15:59:32 +02:00
PozzettiAndrea d1b617b112 workflow definition 2026-05-16 15:42:15 +02:00
PozzettiAndrea 1bf075ac52 good toggles for comfy test 2026-05-16 15:40:53 +02:00
PozzettiAndrea eee3bee6ba new workflow 2026-05-16 15:40:07 +02:00
PozzettiAndrea 99606e0144 Expand k tooltip on GaussianMerge with actual guidance
The widget's tooltip was just `"kNN candidate count for the merge
graph."` — technically correct but didn't tell the user whether
higher means better or worse, what to set it to, or what it costs.

Three lines now explain:
- What k does (search breadth for candidate merge pairs).
- The trade-off (higher = better selector choice, O(N*k) memory).
- Pragmatic defaults: 16 = sweet spot, 8 = fast draft, 24-32 on
  specular-heavy scenes, 32+ wasted.

No behavior change.
2026-05-16 15:38:50 +02:00
PozzettiAndrea cdb36341ee Resolve PLY → /view params via folder_paths (live), not common.py cache
User feedback: the path → (filename, subfolder, kind) resolution
should read folder_paths directly rather than relying on
COMFYUI_INPUT_FOLDER / COMFYUI_OUTPUT_FOLDER captured in common.py
at module import.

Folded the two-base scan into `folder_paths.get_directory_by_type(t)`
(folder_paths.py:214) over ("output", "input", "temp") in priority
order. Three benefits:

- Picks up runtime config: --input-directory CLI flag, mid-session
  setattr on folder_paths, etc. The previous version froze at first
  import of common.py.
- Adds "temp" coverage for free.
- Single source of truth — common.py no longer needs to mirror
  folder_paths constants for this codepath.

The COMFYUI_INPUT_FOLDER / COMFYUI_OUTPUT_FOLDER definitions in
common.py stay (the other nodes still import them for their own
defaults); only preview_gaussian.py stops using them.
2026-05-16 15:34:14 +02:00
PozzettiAndrea d4be0bda1d Fix /view 404 for PLYs under input/; remove Spark heartbeat log
Two paper cuts spotted while wiring LoadPLY through PreviewGaussians:

## 1. Hardcoded `type=output` in the /view fetch

Repro: LoadPLY hands /home/work/.../ComfyUI/input/apple.ply to
PreviewGaussians. The JS fetches `/view?filename=apple.ply&type=output
&subfolder=` and gets 404 because the file lives in input/, not
output/. PLYs produced by GaussianMerge/GaussianExport/LiToExportPLY
(under output/) worked because the hardcoded `type=output` matched.

Fix is two-sided:

- Python (nodes/preview_gaussian.py): new `_resolve_for_view()`
  walks the abs path against folder_paths.get_{output,input}_directory()
  and returns (filename, subfolder, folder_kind). The kind is shipped
  as a new UI field `ply_type` ("input" | "output"), plus
  `ply_subfolder` for nested locations.

- JS (web/js/gaussian_preview.js): reads `ply_type` / `ply_subfolder`
  off the onExecuted message and substitutes them into both URLs —
  `/view?type=<kind>&subfolder=<sub>` for raw PLY transport, and
  `/gaussianpack/spz?type=<kind>&subfolder=<sub>` for the SPZ
  transcode route. The Python SPZ route already accepts both
  type=input and type=output (spz_route.py:53-56), so no server-side
  change needed.

Files truly outside ComfyUI's input/output trees still 404 (the
fallback returns type=output + bare basename), which matches the
prior behavior — the previewer can't serve arbitrary disk paths.

## 2. Spark heartbeat log spam

Every 120 frames (~2 s) the iframe printed
"[Spark] heartbeat: N frames" to the console. Useful while bringing
up the rendering loop, noise now that everything works. Dropped the
line; the "first frame rendered" trace stays as the smoke test.
2026-05-16 15:24:22 +02:00
PozzettiAndrea 4974530084 Add GaussianAnalysis + GaussianExport nodes
## GaussianAnalysis (viewer/Gaussian Analysis)

Header-only PLY inspector — instant even for hundreds-of-MB scenes.
Reports:
  - splat count + file size + bytes/splat
  - PLY encoding (ascii vs binary little/big endian)
  - SH degree (derived from f_rest_* count: 0/9/24/45 -> 0/1/2/3)
  - precision (float32 all / uint8 all / mixed)
  - feature flags: has f_dc_*, has RGB uchar, has opacity, has scale_*,
    has rot_*
  - flavor heuristic: "raw 3DGS PLY (SH degree N)" / "SH-stripped"
    / "RGB-baked" / "compressed / packed"

OUTPUT_NODE: the report is also dumped into the node body via the `ui`
payload, while a STRING is returned so it can be chained into a Note
or printed downstream.

Sanity-tested against the bundled assets/apple.ply (200,000 splats,
47.30 MB, raw 3DGS SH=3, float32 all).

## GaussianExport (viewer/Gaussian Export)

PLY -> PLY (or PLY -> SPZ) reformatter. Three modes:

  ply         passthrough copy (just rename).
  ply_no_sh   strip f_rest_* (view-dependent SH coefficients). Keeps
              the DC term (f_dc_0/1/2 = base color) so the splat still
              looks right; loses specular highlights. ~3-5x smaller.
              Pure Python via plyfile.
  spz         SPZ v2 (gzipped) via the vendored ply_to_spz.mjs (same
              Node subprocess spz_route.py uses for the in-flight
              viewer transcode). ~9x smaller; SH quantizes to 4 bits.
              Requires Node on PATH.

Output is the absolute path to the produced file, so the node chains
into PreviewGaussians / GaussianMerge directly.

Typical use:
  LoadPLY -> GaussianMerge(target=200k) -> GaussianExport(ply_no_sh)
          -> PreviewGaussians

That gets you ~50 MB scenes from ~225 MB raw outputs without losing
view-independent appearance.
2026-05-16 15:19:44 +02:00
PozzettiAndrea 1a638ac662 Add prestartup_script.py to seed ComfyUI/input/ with bundled assets
Mirrors LiTo's prestartup pattern: on each ComfyUI startup, copies
files from this repo's `assets/` directory (currently apple.ply, ~50MB)
into the host ComfyUI's `input/` directory.

Uses `comfy_env.copy_files`, which is non-clobbering — pre-existing
files in input/ are left alone, so user edits and uploads survive
restarts. Skipped if assets/ is missing (e.g. fresh shallow clone).
2026-05-16 15:12:49 +02:00
PozzettiAndrea 11323079d2 added workflow 2026-05-16 15:08:00 +02:00
PozzettiAndrea abd1838e37 add nanogs 2026-05-16 15:01:43 +02:00
PozzettiAndrea e843d5bef0 Replace nodes/comfy-env.toml with a plain root requirements.txt
GaussianPack only needs three pure-Python deps (no CUDA, no conda-side
wheels), so the comfy-env pixi spec was overkill. requirements.txt at
the root is the standard custom-node convention and ComfyUI-Manager
auto-installs it on first launch.

Translation:

  [dependencies]
  numpy = ">=1.24"             ->  numpy>=1.24
  plyfile = "*"                ->  plyfile

  [pypi-dependencies]
  nanogs = { git = "..." }     ->  git+https://github.com/saliteta/NanoGS.git

Without `nodes/comfy-env.toml`, comfy_env.register_nodes() falls back
to its main-process branch (imports nodes/__init__.py normally — no
subprocess isolation), which is exactly what we want for these pure-
Python nodes.
2026-05-16 15:00:43 +02:00
PozzettiAndrea 6bac79935e Reorganize: python in nodes/, non-python in web/, root __init__ uses register_nodes
Match LiTo's project layout. Net file moves:

  spz_route.py             -> nodes/spz_route.py
  install.py               -> root (was briefly in nodes/)
  server_tools/            -> web/server_tools/    (Node JS subprocess
                                                    tool — non-python
                                                    asset, sits next to
                                                    browser-served web/)

Root and nodes/ now mirror ComfyUI-LiTo:

  Root: __init__.py, install.py, pyproject.toml, comfy-env-root.toml,
        comfy-test.toml, README.md, LICENSE, web/, scripts/, nodes/
  nodes/: __init__.py, comfy-env.toml, common.py, preview_gaussian.py,
          merge_gaussians.py, load_ply.py, spz_route.py

## Root __init__.py — LiTo-style

  import logging
  log = logging.getLogger("comfyui-gaussianpack")
  from comfy_env import register_nodes
  NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS = register_nodes()
  WEB_DIRECTORY = "./web"

Delegates node discovery to `comfy_env.register_nodes()`, which scans
`nodes/__init__.py` for the mappings. WEB_DIRECTORY stays at root
(points at top-level web/) so ComfyUI's static handler doesn't have to
walk into nodes/.

## nodes/__init__.py — clean child package

Imports PreviewGaussians, GaussianMerge, LoadPLY from sibling modules,
calls register_routes() for the SPZ HTTP route, exposes the two
mapping dicts. Dropped `WEB_DIRECTORY` (it belongs at root).

## nodes/comfy-env.toml — pixi env declaration

numpy + plyfile + nanogs (git pip). Same content as before — was
previously at root, where comfy-env's discovery wouldn't pick it up
for isolation purposes. Now lives where comfy-env expects.

## spz_route.py — path fix

NODE_SCRIPT was `THIS_DIR / "server_tools" / "ply_to_spz.mjs"` when the
file was at root. Now at nodes/ with server_tools moved to web/, so:

  NODE_SCRIPT = THIS_DIR.parent / "web" / "server_tools" / "ply_to_spz.mjs"

Smoke test (worker pixi env):
  PYTHONPATH=.../ComfyUI:. python -c "import nodes; print(nodes.NODE_CLASS_MAPPINGS)"
  -> {'PreviewGaussians': ..., 'GaussianMerge': ..., 'LoadPLY': ...}
2026-05-16 14:49:10 +02:00
PozzettiAndrea 0ce11ce8a4 Add LoadPLY file-picker node
User asked to "copy the Load PLY node from HallettVisual/comfyui-
GaussianViewer". After cloning + reading the source, that repo doesn't
ship a LoadPLY node — every PLY input there is forceInput-only
(GaussianViewer / GeomPackRenderGaussian / ExtrinsicsToPose). So
writing one from scratch in the spirit of the request.

`load_ply.py` scans both ComfyUI's input/ AND output/ directories
recursively for .ply files; the combo entries are prefixed with the
folder kind ("input/foo.ply", "output/lito_output.ply") to disambiguate
collisions. LiTo's LiToExportPLY writes to output/, so its files appear
in the dropdown directly — no manual copying.

Implements:
- INPUT_TYPES re-scans on each schema evaluation (no stale lists).
- IS_CHANGED keys on the picked file's mtime so re-runs catch edits.
- VALIDATE_INPUTS rejects entries that disappeared between schema
  fetch and execute.

Output is a STRING `ply_path` (absolute), so it slots directly into
PreviewGaussians / GaussianMerge's `ply_path` forceInput. Lets users
preview an arbitrary PLY without re-running LiTo, or pipe a
hand-edited PLY into GaussianMerge.
2026-05-15 18:32:25 +02:00
PozzettiAndrea 9137508fba Re-add GaussianMerge + Lito structure; rename to GaussianPack; trackball camera
The prior commit (6908dbe) was lost when the local repo was re-cloned
before its push could land. Redoing the full GaussianPack-side work
in one pass, plus two new asks from this session:

1. Display name: "Preview Gaussians Turntable" -> "Preview Gaussians".
2. Camera: OrbitControls -> TrackballControls. ParaView-style free
   rotation — no fixed up vector, no gimbal lock at the poles, can
   roll the camera. Replaces the "bound at azimuth and bottom" feel.

## Rename (mechanical sed pass)

  ComfyUI-GSViewer -> ComfyUI-GaussianPack
  GSViewer         -> GaussianPack         (log tags, extension name)
  gsviewer         -> gaussianpack         (route path, logger name)
  GSVIEWER         -> GAUSSIANPACK

Hit __init__.py, spz_route.py, pyproject.toml, comfyui_extension.json,
README.md, web/js/gaussian_preview.js.

## LiTo-style project structure

- comfy-test.toml       — test matrix; workflow-level testing
                           happens downstream in ComfyUI-LiTo.
- comfy-env-root.toml   — empty [node_reqs]; GaussianPack has no
                           downstream custom-node deps.
- comfy-env.toml        — numpy + plyfile + NanoGS via pypi-git.
- install.py            — two-liner mirroring LiTo's.
- requirements.txt      — DELETED, superseded by comfy-env.toml.

## GaussianMerge node

merge_gaussians.py: takes a 3DGS .ply + target_count, writes a slimmer
.ply via NanoGS pairwise merging (MPMM — same algorithm
@playcanvas/splat-transform's `--decimate` uses). Pure Python, CPU only;
the upstream paper notes a CUDA port as future work. ~10-30s for 1M ->
200K splats.

Lazy-imports nanogs.simplification + nanogs.utils.params inside the
merge method to keep import cost off ComfyUI startup. Caches via
mtime + (target_count, opacity_threshold, k) sidecar — re-running with
the same inputs is a no-op.

Pass-through if target >= input. ratio is clamped to NanoGS's required
open (0, 1) interval.

Node parameters:
  ply_path           STRING, forceInput
  target_count       INT, default 200_000
  output_filename    STRING, default "merged"
  opacity_threshold  FLOAT, default 0.1
  k                  INT, default 16

## Camera: TrackballControls

Vendored web/js/TrackballControls.js (three@0.169.0, ~18 KB) +
importmap entry alongside OrbitControls. The viewer now constructs
TrackballControls with rotateSpeed=3.5, zoomSpeed=1.2, panSpeed=0.8,
staticMoving=true (no inertia drift). ResizeObserver now calls
controls.handleResize() so mouse-to-NDC mapping stays correct after
canvas resize. .target / .update() / .enabled API surface is identical
between OrbitControls and TrackballControls — no callsite changes
needed in gaussian_preview.js.

OrbitControls.js stays vendored (still in importmap) for any future
node that wants the constrained "preserve up" behavior.

Workflow chain (LiTo apple):
  LoadImage -> LiToImageTo3D -> LiToExportPLY (~225 MB raw)
                                       |
                               GaussianMerge(target=200_000)
                                       |
                               PreviewGaussians (~50 MB)
2026-05-15 18:28:38 +02:00
PozzettiAndrea 5d5371937e Mirror widget values to node.properties to survive ComfyUI's widgets_values strip
ComfyUI's widgetInputs extension strips the first entry from
info.widgets_values for forceInput-bound STRING inputs (ply_path),
silently shifting every other widget's value left by one. The
in-memory info we receive in onConfigure is already lossy — the
original fov_degrees value is gone before our code can see it.

Solution: persist every named widget into properties["Widget Values"]
on each change (same pattern we already use for "Camera Config"). On
load, prefer properties over info.widgets_values. For old workflows
without Widget Values, fall back to Camera Config.fov so at least
that survives.
2026-05-15 08:43:38 +02:00
PozzettiAndrea 336780c65b Debug logging in onConfigure to trace widget reconciliation 2026-05-15 08:29:51 +02:00
PozzettiAndrea 5bb9c03fa1 better ordering in js 2026-05-15 08:18:29 +02:00
PozzettiAndrea b60d7f5b8d Rename to ComfyUI-GSViewer; robust onConfigure migration
* Bulk rename "ComfyUI-TurntableGSViewer" -> "ComfyUI-GSViewer" across
  package metadata, route prefix (/turntablegsviewer/spz ->
  /gsviewer/spz), logger name, extension id, and all console-log tags.
* Extend onConfigure to defend against stale workflow schemas: rescues
  stranded camera-state JSON into properties["Camera Config"] and
  resets combo widgets whose value isn't in the option list. Fixes the
  validator-reject when an old-schema basic.json (camera state glued
  into widgets_values[3]) is loaded against today's renderer combo.
2026-05-14 15:07:22 +02:00
PozzettiAndrea 0f48ff93d2 spz route 2026-05-14 14:23:25 +02:00
PozzettiAndrea d20556eb29 playcanvas/spark dual backend 2026-05-14 13:02:34 +02:00
PozzettiAndrea 2839459333 add spz option 2026-05-13 13:26:00 +02:00
PozzettiAndrea 6738e39769 javascript firing at right timeg 2026-05-13 01:02:48 +02:00
PozzettiAndrea a2504f2c22 fix crash 2026-05-13 00:44:12 +02:00
PozzettiAndrea 24c8f0a101 sync pos with json 2026-05-13 00:01:53 +02:00
PozzettiAndrea 5e6b102b2d save coords in json 2026-05-13 00:00:18 +02:00
Andrea Pozzetti 92227bd0a0 Update README with user attachments link
Added a link to user attachments in the README.
2026-05-12 23:42:42 +02:00
PozzettiAndrea 3ca0ff019f gitignored 2026-05-12 23:35:50 +02:00
PozzettiAndreaandClaude Opus 4.7 21957052a8 rename display name to "Preview Gaussians Turntable"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:23:24 +02:00
PozzettiAndreaandClaude Opus 4.7 f452fc506e single PreviewGaussians node + tiny readme
Collapse the 4-node PlyPreview surface to one node:
- PreviewGaussians: takes ply_path (STRING, forceInput) plus camera-
  intrinsics widgets (fov_degrees, image_width, image_height) directly
  on the node. NODE_CLASS_MAPPINGS = {"PreviewGaussians": ...}.
- Drop load_gaussian_ply.py, load_gaussian_ply_path.py,
  process_gaussian_ply.py and the /plypreview/files refresh route.
- common.py stays — get_default_intrinsics + get_default_extrinsics
  are reused.
- Frontend JS unchanged except the preview block targets
  "PreviewGaussians". The LoadPLY-dropdown refresh block is left in
  place as harmless dead code in case the loader node comes back.
- requirements.txt cleared (no Python deps; PLY parsing is in the
  browser via gsplat.js).
- README slimmed to a few lines.
- Removed Figure1/2 + image/ + README.en.md + README.zh-CN.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:19:47 +02:00
PozzettiAndreaandClaude Opus 4.7 1dd817b154 initial copy from comfyui-PlyPreview as ComfyUI-TurntableGSViewer base
Copy of XuanYu-github/comfyui-PlyPreview (GPL-3.0) repackaged under
new name and ownership. Metadata changes only:
- pyproject.toml: project name + URLs + tool.comfy.DisplayName
- comfyui_extension.json: name / author / repo
- removed .github/workflows/publish_action.yml (upstream's auto-publish)

Internal class names, NODE_CLASS_MAPPINGS keys, CATEGORY strings,
and source code are intact for further customization.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 21:12:59 +02:00