pv.PolyData(points) adds one VERT cell per point, so n_cells became
verts+lines+polys and cell_data (lines+polys only) mismatched. Build the
PolyData empty then assign points/faces/lines -> no verts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
edge_value = reduce(face_field[A], face_field[B]); face_normals+angle =
dihedral. Thresholded edges + surface written to an ASCII .vtp and shown
in the shared VTK.js viewer (viewer_vtk.html) in-node. Face field is a
string (face_normals or any face_attributes key; available ones logged).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recreating the EGL render window per mesh dominated per-mesh time. Keep a
single plotter alive and clear()+redraw between meshes (recreate only
after a failure). Refactored render into _make_plotter/_prep_poly/
_draw_into/_screenshot_arr; titles use named add_text so they replace on
reuse. No decimation. Workers (software path) still one-shot.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Y/Z swap is a reflection: deep-copy the wrapped mesh (never mutate the
upstream trimesh), flip_normals to restore winding/lighting, and call
reset_camera so the view re-frames the transformed bounds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lazy-imported comfy.utils.ProgressBar, advanced per mesh in both the
process-pool and serial paths.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fix: len(m.faces or []) raised "ambiguous truth value" on the numpy
faces array, crashing the whole load. Use a safe _n_faces() helper.
- Threads barely helped (trimesh OBJ parsing is GIL-bound Python); switch
to a ProcessPoolExecutor for true CPU-parallel parsing, with a serial
fallback on error.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When use_gpu is off and >1 mesh, render across CPU cores via a process
pool (software rasterisation is embarrassingly parallel). Parent starts
Xvfb without a GL context (fork-safe); workers reload from file_path when
available to avoid pickling big meshes. Shared _render_mesh_array used by
serial + worker paths. GPU path unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
use_multithreading toggle loads files via a ThreadPoolExecutor (workers =
cpu_count); mesh I/O + numpy OBJ parsing release the GIL so big batches
load much faster. Order preserved; live per-mesh logging.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- revert_yz_flip: swap Y/Z axes
- three_plane: 2x2 grid (iso(random) + XY/YZ/XZ)
- mesh_opacity + show_edges with conditional edge_opacity (hidden until edges on, via web_src JS)
- show_connected_components: color by pyvista connectivity() RegionId
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Upgrade the batch renderer (was Render Mesh Batch): optional GPU/native
EGL offscreen with software fallback, tqdm + ComfyUI progress bars, and
the filename drawn via plotter.add_title. Renamed to Preview Mesh Batch
Render (node_id GeomPackPreviewMeshBatchRender).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Native <datalist> never opens inside ComfyUI transformed DOM widgets;
replace with a body-attached floating dropdown (fixed-positioned under the
input), click-to-descend into folders, fed by /gpack/getpath.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Inspired by VHS Load Video (Path), but GeometryPack-owned: register
/gpack/getpath in __init__ (main process, after PromptServer exists) to
list directory contents, and a web_src widget that replaces folder_path
with an <input>+<datalist> showing live FOLDER suggestions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Three.js viewer.html OBJLoader chokes on some OBJs; viewer_vtk.html
uses VTK readers (same LOAD_MESH protocol) and shows the download bar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Just-uploaded meshes are added to the file_path combo client-side but are
not in the backend cached INPUT_TYPES options, so queueing hit a 400
"Value not in list". validate_inputs(**kwargs)->True skips that combo
check; execute() still resolves the path and raises if truly missing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Switch upload from fetch to XHR for upload progress, show a bar on the
node during upload. Top-level log to confirm the extension loads.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Load Mesh: drop/upload meshes (reuses /upload/image, subfolder=3d, like
the official Load Image) + a "view 3d" toggle that mounts the shared
vtk.js viewer inline. Frontend source in tracked web_src/, copied to the
generated web/js at prestartup.
- Render Mesh Batch: offscreen pyvista render per mesh, titled by name.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deletes mesh faces/points by a scalar field value via pyvista's threshold filter,
reusing the existing trimesh<->pyvista bridge. Keep modes above/below/between/equal,
on vertex (point) or face (cell) data (auto-prefers face data), with all_scalars for
point fields. E.g. field='viewed', keep='above', value=0.5 -> keep only the faces
Pixal3D's view actually saw. Output mesh retains surviving fields + a summary.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>