Commit Graph
524 Commits
Author SHA1 Message Date
PozzettiAndreaandClaude Opus 4.8 7fac4f40ba Sharpen Guided Normal: add neighborhood_rings knob
Exposes the face-neighborhood (k-ring) size used for both guidance and
filtering, previously hardcoded to the vertex 1-ring. Higher rings widen the
filter footprint so each pass hits harder / reaches farther -- a genuinely
stronger lever than just adding iterations. _build_vertex_based_face_neighbors
grows the patch by ring expansion (rings=1 reproduces the old 1-ring exactly, so
existing callers are unchanged). Wired through CPU + GPU paths and the dispatcher
(default 1, max 4; cost/memory grow ~rings^2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 20:57:40 +02:00
PozzettiAndreaandClaude Opus 4.8 57e09d6c43 Sharpen Guided Normal: sigma_r in degrees + method description
- sigma_r is now entered in DEGREES (angle between normals at which they stop
  blending), converted internally to the unit-normal chord 2*sin(theta/2).
  Default 20 deg == the previous 0.35 default, so behavior is unchanged.
- Clarified sigma_s / sigma_r tooltips (spatial vs range scale).
- Added a node-level description to Sharpen Mesh explaining the pipeline and the
  guided-normal method (renders as ComfyUI's node help on hover).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 20:32:32 +02:00
PozzettiAndreaandClaude Opus 4.8 b98cfd33d8 Sharpen Guided Normal: add use_gpu toggle (faithful vectorized torch port)
Adds a GPU path to the guided_normal backend behind a use_gpu toggle. The new
guided_normal_gpu module is a faithful torch port of Zhang et al. 2015: same
min-range-metric guidance (incl. the O(patch^2) max-pairwise-diff, chunked) and
the same bilateral normal filter + interleaved vertex update. Mesh topology
(1-ring face patches + their inner adjacency edges) is built once on CPU as
padded index tensors; every iteration then runs as batched scatter/gather on
CUDA (falls back to vectorized CPU torch).

Verified vs the CPU reference: vertex agreement ~1e-6 (float32 vs float64),
~17x faster on 82k faces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 20:06:38 +02:00
PozzettiAndreaandClaude Opus 4.8 324aa8685a Decimate vertex_clustering: lower cluster_threshold floor 0.1 -> 1e-6
The cell size (% of bbox diagonal) was floored at 0.1% with step 0.1, far too
coarse for fine clustering. Lower min to 1e-6 and step to 1e-6 (display_mode=number)
so small thresholds are actually enterable; clarify the tooltip. Backend passes the
value straight through (no re-clamp). Verified: 1e-6 is a near no-op, 5 reduces hard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 19:03:03 +02:00
PozzettiAndreaandClaude Opus 4.8 7a8f881e64 Remesh blender_sharp: expose remove-disconnected cull, fix ranges, clearer tooltips
blender_sharp = Blender's Remesh modifier in SHARP mode (octree dual-contouring,
watertight output, reconstructs sharp edges).

- Expose use_remove_disconnected + threshold as remove_disconnected (default true,
  matching Blender) + disconnected_threshold. Previously unset, so Blender's defaults
  silently culled small disconnected pieces; now it's controllable. Verified: true
  culls a floating cube (1 component), false keeps it (2 components).
- sharpness max 5.0 -> 2.0 (Blender's normal slider range; higher just over-sharpens).
- octree_depth max 10 -> 12 (Blender's real max), scale max 1.0 -> 0.99 (real max).
- Rewrite octree_depth/scale/sharpness tooltips with concrete meaning (power-of-2
  face growth, octree fit, sharpness behavior).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 18:42:22 +02:00
PozzettiAndreaandClaude Opus 4.8 fd4e322174 Remesh pymeshlab_isotropic: expose reproject toggle
Surfaces MeshLab's reprojectflag (Botsch back-projection onto the original surface
after each iteration) as a `reproject` combo, default true -- matching the PMP
backends' use_projection. true keeps output verts on the input surface; false is
pure tangential smoothing that lets them drift. Verified the toggle changes
surface fidelity ~14x on a sphere.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 18:36:51 +02:00
PozzettiAndreaandClaude Opus 4.8 d961aff457 Remesh: explain remesh_band, fix pymeshlab edge-length floor, add target points/faces
- remesh_band (GPU cumesh): rewrite tooltip with concrete guidance -- it's the voxel
  narrow-band shell width (robustness/gap-fill knob), not the detail knob; 1.0 default,
  0.5 hugs surface (sharper, risk holes), 2-3 fills gaps / fuses thin walls / smoother.
- pymeshlab_isotropic: target_edge_length floor was effectively stuck at 0.01 (min
  0.001 but step 0.01); lower to min 0.0001 / step 0.0001 so fine edge lengths work.
- pymeshlab_isotropic: add target_vertices / target_faces (0 = off) that back-solve the
  edge length from mesh area (faces > vertices > edge_length). Verified within ~5% of
  the requested count on a sphere.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 18:22:43 +02:00
PozzettiAndreaandClaude Opus 4.8 7918b734dc Add "Bad Winding Faces" analysis node
Writes a per-face field 'bad_winding' = number of shared manifold edges whose
neighbour disagrees on winding direction (0 = consistent). Marks every face on a
winding seam so they can be visualized / thresholded, mirroring the Open Edges and
Degenerate Faces nodes (face_attributes + metadata + UI summary). Batch-capable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:53:13 +02:00
PozzettiAndreaandClaude Opus 4.8 2fd6a40546 Fix Normals: selectable signed-dist oracle, batched embree raycast, GPU raystab backend
- igl_signed_dist: expose sd_sign_type (fast_winding_number default / winding_number /
  pseudonormal). Fix a pre-existing inverted sign bug -- this igl build returns
  distance<0 inside, but the flip rule was S>0, so it flipped every face on a
  correctly-oriented mesh. Now flips on S<0. fast_winding_number is the only oracle
  that both no-ops a correct mesh and re-flips a wholly-inverted one (verified).
- igl_raycast: replace the per-face Python ray loop + unscaled 1e-6 epsilon with a
  single batched igl.embree.reorient_facets_raycast (Takayama 2014), oriented per
  connected component. Expose rays_minimum / use_parity / facet_wise.
- New cumesh_raystab backend: GPU cuBVH.signed_distance(mode='raystab') as a
  winding-independent sign oracle (never 'watertight', which reads sign from the
  input winding). CUDA-only, >8 tris. Verified no-op on correct, full-fix on inverted.
- Dispatcher: register cumesh_raystab and mirror the new params into the unified node.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:44:29 +02:00
PozzettiAndreaandClaude Opus 4.8 abf100935a Sharpen L0 Minimize: add use_gpu toggle (vectorized torch path)
Folds the vectorized torch L0 implementation into the l0_minimize backend
behind a use_gpu toggle instead of a separate backend node. When enabled it
runs CuMesh-style index_add_ scatter ops on CUDA (falls back to vectorized CPU
torch) -- orders of magnitude faster on large meshes. Surfaced in the Sharpen
dispatcher; the standalone GPU node is no longer registered (its function is
reused by l0_minimize).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:32:38 +02:00
PozzettiAndreaandClaude Opus 4.8 3d054579b9 Sharpen L0: alpha angle table in tooltip, raise alpha cap to 4.0
alpha is scale-invariant (angle threshold). Document the alpha->degrees
mapping in the tooltip, note beta is a no-op at iterations=1, and raise the
unified-node alpha max from 0.1 (~18deg) to 4.0 (180deg).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:28:17 +02:00
PozzettiAndreaandClaude Opus 4.8 4a0d824778 Fix Normals: add GPU cumesh unify_face_orientations backend
New "cumesh" backend runs CuMesh.unify_face_orientations() alone -- the GPU
winding/orientation fix -- to make face windings (and thus normals) consistent.
CUDA-only; fast on large meshes. Slots in alongside the trimesh/igl backends.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:15:56 +02:00
PozzettiAndreaandClaude Opus 4.8 587c1927ce Add Preview Mesh Slicer node (interactive VTK.js clip)
3D clip view + orthographic pick view (XY/YZ/XZ toggle): click 2 points to
define a cut line swept along the view axis into a clip plane; flip clip
slices the other side. Python node exports the mesh .vtp; clipping is
interactive in viewer_slicer.html. prestartup copies the new slicer viewer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:12:45 +02:00
PozzettiAndreaandClaude Opus 4.8 47c98b796e Remesh PMP Uniform: drive density by target vertex count too
Add pmp_target_vertices (0 = off) on the backend + Remesh node pmp_uniform
option. When set, back-solves the target edge length from the input mesh
area for a triangle mesh: V ~= 2A/(sqrt(3) e^2) -> e = sqrt(2A/(sqrt(3) V)).
Overrides pmp_edge_length. Approximate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:54:29 +02:00
PozzettiAndreaandClaude Opus 4.8 07d6466724 Remesh QuadWild: clearer qw_alpha tooltip (regularity vs feature alignment)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:52:42 +02:00
PozzettiAndreaandClaude Opus 4.8 2376c6247b Remesh GPU (cumesh): expose post-remesh cleanup toggles
Add optional cleanup passes (run on the simplified mesh, before read):
remove_degenerate_faces, remove_duplicate_faces, repair_non_manifold_edges,
remove_non_manifold_faces, remove_small_components_min_area (0=off),
remove_unreferenced_vertices. Each guarded; applied per-face removals ->
small components -> orphan verts last. Exposed on backend + Remesh node
gpu_cumesh option (same names, no remap).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:46:34 +02:00
PozzettiAndreaandClaude Opus 4.8 1dc05beb5d Preview Mesh Batch Render: revert GPU process-pool (kept serial + shading)
The per-process-EGL GPU pool fell back to vtkXOpenGLRenderWindow with no
DISPLAY ("bad X server connection") and ran ~12s/mesh -- worse than
serial. Gate the process pool back to the software path only; GPU renders
per-mesh on the serial path (fresh plotter -> shading). Software CPU pool
and the shading fix are kept.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:39:13 +02:00
PozzettiAndreaandClaude Opus 4.8 c2d4ddd173 Remesh GPU (cumesh): expose grid_resolution + project_back
grid_resolution (DC voxel grid, was hardcoded 512) is the main detail/
speed knob; project_back re-projects DC verts onto the input surface for
fidelity (was hardcoded 0). Exposed on the backend node and the Remesh
node gpu_cumesh option (gpu_grid_resolution/gpu_project_back -> mapped).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:31:35 +02:00
PozzettiAndreaandClaude Opus 4.8 6ae69c14e4 Remesh QuadWild: drive output density by target vertices or edge length
QuadWild only exposes scale_factor (no count/edge input). Add
qw_target_vertices and qw_target_edge_length (both 0 = off) on the
QuadWild backend + the Remesh node UI. Back-solve scale_factor from the
input mesh area: vertices -> edge via e=sqrt(area/N), edge -> scale via
scale = e / mean_input_edge. Priority edge_length > vertices > scale_factor.
Approximate (QuadWild is edge-length-driven, not count-exact).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:23:51 +02:00
PozzettiAndreaandClaude Opus 4.8 2f6b607e4e Preview Mesh Batch Render: process-pool rendering on GPU too + shading fix
- Revert plotter reuse (p.clear() dropped lights -> flat renders; reuse
  barely helped anyway). Fresh plotter per mesh restores shading.
- Parallelise BOTH gpu and software paths across max CPU cores via a
  process pool: each worker renders in its own GL context (gpu children
  unset DISPLAY -> per-process EGL; software children share parent Xvfb)
  and returns the small image, not the mesh. This is the Lightning-style
  (processes, not threads) parallelism -- parallelises the CPU-bound prep
  while the shared GPU serialises the cheap rasterisation. Serial fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 16:08:07 +02:00
PozzettiAndreaandClaude Opus 4.8 26e8a432d5 Preview Mesh Boundaries: fix cell_data length (auto-vert cells)
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>
2026-06-16 16:08:06 +02:00
PozzettiAndreaandClaude Opus 4.8 ddb0a54126 Add Preview Mesh Boundaries node (VTK.js, edge threshold by adjacent-face metric)
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>
2026-06-16 16:05:40 +02:00
PozzettiAndreaandClaude Opus 4.8 77f51157a4 Preview Mesh Batch Render: reuse one plotter/GL context on the GPU path
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>
2026-06-16 15:57:05 +02:00
PozzettiAndreaandClaude Opus 4.8 a7e77db03e Preview Mesh Batch Render: fix revert_yz_flip (off-screen / vanishing)
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>
2026-06-16 15:48:56 +02:00
PozzettiAndreaandClaude Opus 4.8 29cb39cc05 Load Mesh Batch: ComfyUI progress bar during loading
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>
2026-06-16 15:47:27 +02:00
PozzettiAndreaandClaude Opus 4.8 333974880a Load Mesh Batch: fix numpy-truthiness crash + use processes for real speedup
- 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>
2026-06-16 15:43:43 +02:00
PozzettiAndreaandClaude Opus 4.8 1a9e6961ed Preview Mesh Batch Render: parallel software rendering (use_gpu off)
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>
2026-06-16 15:38:51 +02:00
PozzettiAndreaandClaude Opus 4.8 be0a715460 Load Mesh Batch: optional multithreaded loading (use all CPUs)
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>
2026-06-16 15:31:57 +02:00
PozzettiAndreaandClaude Opus 4.8 6593ed8cf7 Preview Mesh Batch Render: yz-flip, 3-plane grid, mesh/edge opacity, connected components
- 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>
2026-06-16 15:31:45 +02:00
PozzettiAndreaandClaude Opus 4.8 5ff6fc1342 Preview Mesh Batch Render: GPU(EGL)/software offscreen + tqdm + add_title
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>
2026-06-16 15:24:03 +02:00
PozzettiAndreaandClaude Opus 4.8 df72bc63b7 Load Mesh Batch: custom floating dropdown for folder autocomplete
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>
2026-06-16 15:02:21 +02:00
PozzettiAndreaandClaude Opus 4.8 b5fb441e3e Load Mesh Batch: folder-path autocomplete via own /gpack/getpath route
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>
2026-06-16 14:58:36 +02:00
PozzettiAndreaandClaude Opus 4.8 7ff9dbcf37 Load Mesh View 3D: use VTK viewer (robust OBJ) instead of Three.js
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>
2026-06-16 14:51:50 +02:00
PozzettiAndreaandClaude Opus 4.8 7651ee7f9f Load Mesh: validate_inputs to accept uploaded files
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>
2026-06-16 14:14:58 +02:00
PozzettiAndreaandClaude Opus 4.8 62ab5659f3 Load Mesh: XHR upload with progress bar + debug log
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>
2026-06-16 14:09:34 +02:00
PozzettiAndreaandClaude Opus 4.8 892626791a Load Mesh drag-n-drop upload + inline View 3D; add Render Mesh Batch node
- 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>
2026-06-16 14:01:02 +02:00
PozzettiAndrea 9ac0d8da23 ultimate inspector node 2026-06-16 13:26:54 +02:00
Andrea PozzettiandClaude Opus 4.8 5a426d195a Add Threshold Mesh by Field node (pyvista)
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>
2026-06-13 13:20:31 +02:00
PozzettiAndrea f878e7e5a0 process extrinsics/intrinsics input 2026-06-02 02:52:40 +02:00
PozzettiAndrea ffa0c24cf9 bump 2026-05-19 17:51:46 +02:00
PozzettiAndrea 85ebb3aff9 mmgpy new syntax 2026-05-18 22:57:09 +02:00
PozzettiAndrea 73b6f49b3a pin mmgpy on linux 2026-05-18 22:31:54 +02:00
PozzettiAndrea 2b41602297 upper bound on mmgpy 2026-05-18 22:04:04 +02:00
PozzettiAndrea ec356e6d4e docs: warn about experimental comfy-env install in README + pyproject 2026-05-16 21:38:45 +02:00
PozzettiAndrea aac15ea13a lazy import for bpy 2026-05-16 21:14:42 +02:00
PozzettiAndrea c7e9995b38 trigger ci (comfy-test v0.3.103) 2026-05-15 11:00:31 +02:00
PozzettiAndrea 9bed32edfd comfy-env 0.3.89 2026-05-15 08:54:22 +02:00
PozzettiAndrea 345492b4fc comfy-env 0.3.88 2026-05-15 07:16:44 +02:00
PozzettiAndrea 0426edb5d1 bump 2026-05-14 14:26:13 +02:00
PozzettiAndrea 7303ca1a08 bump 2026-05-13 12:57:52 +02:00