From 948a2648ad563f758582da090d9c0bbbbf44f492 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:15:40 +0100 Subject: [PATCH 01/27] cleanup of reamde --- README.md | 28 +--------------------------- __init__.py | 29 ++--------------------------- requirements.txt | 2 +- 3 files changed, 4 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 562c343d..170ddb4e 100644 --- a/README.md +++ b/README.md @@ -20,33 +20,7 @@ https://github.com/user-attachments/assets/7718a5d7-cd5b-47d3-874c-29ada4320694 ## Installation -```bash -cd ComfyUI/custom_nodes/ -git clone https://github.com/PozzettiAndrea/ComfyUI-GeometryPack.git -cd ComfyUI-GeometryPack -pip install -r requirements.txt -``` - -**Automatic Blender Installation (Recommended):** -```bash -python install.py -``` - -This will automatically download and install a portable version of Blender for UV unwrapping and remeshing nodes. No admin rights required! - -Restart ComfyUI. Nodes appear in the `geompack/` category. - -**Optional Dependencies:** -- **Blender**: Auto-installed via `install.py`, or install manually from [blender.org](https://www.blender.org/download/) -- **CGAL**: Build tools for CGAL remeshing (see `cgal_tools/README.md`) - -## Quick Start - -**Basic workflow:** -``` -Create Primitive → Mesh Info → Preview Mesh (3D) -Load Mesh → PyMeshLab Remesh → Save Mesh -``` +Please always install from ComfyUI Manager. ## Community diff --git a/__init__.py b/__init__.py index 1b634ad0..2fee78b4 100644 --- a/__init__.py +++ b/__init__.py @@ -1,10 +1,4 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -"""ComfyUI GeometryPack - Geometry Processing Custom Nodes.""" - -import os import sys -from pathlib import Path - print("[geompack] loading...", file=sys.stderr, flush=True) from comfy_env import register_nodes print("[geompack] calling register_nodes", file=sys.stderr, flush=True) @@ -12,27 +6,8 @@ print("[geompack] calling register_nodes", file=sys.stderr, flush=True) NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS = register_nodes() -def _generate_widget_mappings(): - """Generate widget visibility mappings from node metadata.""" - try: - from comfy_dynamic_widgets import scan_specific_nodes, generate_mappings - import json - - configs = scan_specific_nodes(NODE_CLASS_MAPPINGS) - if not configs: - return - - mappings = generate_mappings(configs) - output_path = os.path.join(os.path.dirname(__file__), "web", "js", "mappings.json") - with open(output_path, "w") as f: - json.dump(mappings, f, indent=2) - except ImportError: - pass - except Exception: - pass - - -_generate_widget_mappings() +from comfy_dynamic_widgets import write_mappings +write_mappings(NODE_CLASS_MAPPINGS, __file__) WEB_DIRECTORY = "./web" __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] diff --git a/requirements.txt b/requirements.txt index 0d7d9028..bb6c6b24 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) comfy-env==0.1.79 comfy-dynamic-widgets==0.1.1 -comfy-3d-viewers==0.2.6 +comfy-3d-viewers==0.2.8 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 From 50859c2218b7f73cc2e6973bbd32ad6f97b8e5a6 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:16:40 +0100 Subject: [PATCH 02/27] run tests on manual dispatch --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 66dcc2bc..b1589611 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -1,5 +1,5 @@ name: Test Installation -on: [push, pull_request] +on: workflow_dispatch jobs: test: From 63d8942923c20e988f2db8a14cf5bcad15f274d9 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:17:40 +0100 Subject: [PATCH 03/27] run tests on push with manual approval gate --- .github/workflows/run-tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index b1589611..1842738b 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -1,8 +1,11 @@ name: Test Installation -on: workflow_dispatch +on: + push: + branches: [main, dev] jobs: test: + environment: test uses: PozzettiAndrea/comfy-test/.github/workflows/test-matrix.yml@main with: config-file: "comfy-test.toml" From 2f567210c9998d7baed79a311910a2e42ef4f363 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:18:40 +0100 Subject: [PATCH 04/27] dynamic widgets ver bump --- __init__.py | 4 ++-- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/__init__.py b/__init__.py index 2fee78b4..7a00459d 100644 --- a/__init__.py +++ b/__init__.py @@ -6,8 +6,8 @@ print("[geompack] calling register_nodes", file=sys.stderr, flush=True) NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS = register_nodes() -from comfy_dynamic_widgets import write_mappings -write_mappings(NODE_CLASS_MAPPINGS, __file__) +from comfy_dynamic_widgets import generate_mappings +generate_mappings(NODE_CLASS_MAPPINGS) WEB_DIRECTORY = "./web" __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] diff --git a/requirements.txt b/requirements.txt index bb6c6b24..385d11e1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Main process deps (prestartup + lightweight shared libs) comfy-env==0.1.79 -comfy-dynamic-widgets==0.1.1 +comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.8 numpy trimesh[easy]>=4.0.0 From 1b4d76d62b9e7fe71ec98cadfbb116b36798a74a Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:19:40 +0100 Subject: [PATCH 05/27] add promote dev results to main workflow --- .github/workflows/promote-results.yml | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/promote-results.yml diff --git a/.github/workflows/promote-results.yml b/.github/workflows/promote-results.yml new file mode 100644 index 00000000..546edc02 --- /dev/null +++ b/.github/workflows/promote-results.yml @@ -0,0 +1,37 @@ +name: Promote dev results to main +on: workflow_dispatch + +jobs: + promote: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - run: pip install comfy-test + + - name: Checkout gh-pages + uses: actions/checkout@v4 + with: + ref: gh-pages + path: gh-pages + fetch-depth: 1 + + - name: Copy dev results to main + run: | + rm -rf gh-pages/main + cp -r gh-pages/dev gh-pages/main + + - name: Regenerate indexes + run: | + comfy-test generate-index gh-pages/main --repo-name "${{ github.repository }}" + comfy-test generate-root-index gh-pages --repo-name "${{ github.repository }}" + + - name: Publish to gh-pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: gh-pages + keep_files: true From 6595fb7fd66d76af877963660c4a907857c38f01 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:20:40 +0100 Subject: [PATCH 06/27] fixed init --- __init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 7a00459d..2fee78b4 100644 --- a/__init__.py +++ b/__init__.py @@ -6,8 +6,8 @@ print("[geompack] calling register_nodes", file=sys.stderr, flush=True) NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS = register_nodes() -from comfy_dynamic_widgets import generate_mappings -generate_mappings(NODE_CLASS_MAPPINGS) +from comfy_dynamic_widgets import write_mappings +write_mappings(NODE_CLASS_MAPPINGS, __file__) WEB_DIRECTORY = "./web" __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] From 0adf7903bfdc2c62f19d8ddb69c8eafed7609bec Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:21:40 +0100 Subject: [PATCH 07/27] fix run-tests: add approval gate job --- .github/workflows/run-tests.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 1842738b..bae55412 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -4,8 +4,13 @@ on: branches: [main, dev] jobs: - test: + approve: + runs-on: ubuntu-latest environment: test + steps: + - run: echo "Approved" + test: + needs: approve uses: PozzettiAndrea/comfy-test/.github/workflows/test-matrix.yml@main with: config-file: "comfy-test.toml" From be850c2156e86037b0fb69accf25a9238f4c3e40 Mon Sep 17 00:00:00 2001 From: Andrea Pozzetti <57418757+PozzettiAndrea@users.noreply.github.com> Date: Fri, 13 Feb 2026 01:22:40 +0100 Subject: [PATCH 08/27] Add workflow_dispatch trigger --- .github/workflows/run-tests.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index bae55412..9533b172 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -1,16 +1,8 @@ name: Test Installation -on: - push: - branches: [main, dev] +on: [push, pull_request, workflow_dispatch] jobs: - approve: - runs-on: ubuntu-latest - environment: test - steps: - - run: echo "Approved" test: - needs: approve uses: PozzettiAndrea/comfy-test/.github/workflows/test-matrix.yml@main with: config-file: "comfy-test.toml" From 8bcac7077bf12e5474bf3ccbdc1df98c924ad372 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:23:40 +0100 Subject: [PATCH 09/27] fixed info text --- prestartup_script.py | 3 ++- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/prestartup_script.py b/prestartup_script.py index c0f1f654..22bd271e 100644 --- a/prestartup_script.py +++ b/prestartup_script.py @@ -18,7 +18,8 @@ viewers = [ "multi", "dual", "dual_slider", "dual_textured", "uv", "pbr", "gaussian", "fbx", "fbx_debug", "fbx_compare", - "bvh", "fbx_animation", "compare_smpl_bvh" + "bvh", "fbx_animation", "compare_smpl_bvh", + "text_report", ] for viewer in viewers: try: diff --git a/requirements.txt b/requirements.txt index 385d11e1..5569f481 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) comfy-env==0.1.79 comfy-dynamic-widgets==0.1.4 -comfy-3d-viewers==0.2.8 +comfy-3d-viewers==0.2.12 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 From 86c900ee58edb4e42d44d4539f9fec452b40f91c Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:24:40 +0100 Subject: [PATCH 10/27] blender more, reqs --- nodes/blender/remeshing/remesh.py | 283 +++++++++++++++++++++++++----- requirements.txt | 2 +- 2 files changed, 239 insertions(+), 46 deletions(-) diff --git a/nodes/blender/remeshing/remesh.py b/nodes/blender/remeshing/remesh.py index 9edde9c0..c4aebf05 100644 --- a/nodes/blender/remeshing/remesh.py +++ b/nodes/blender/remeshing/remesh.py @@ -2,7 +2,8 @@ # Copyright (C) 2025 ComfyUI-GeometryPack Contributors """ -Remesh Blender Node - Blender voxel and quadriflow remeshing +Remesh Blender Node - Blender remeshing backends using bpy. +Supports: voxel, quadriflow, smooth, sharp, blocks. Requires bpy (Blender Python module). """ @@ -10,63 +11,154 @@ import numpy as np import trimesh as trimesh_module +def _bpy_setup_object(vertices, faces): + """Create a Blender mesh object from vertices and faces. Returns (obj, mesh).""" + import bpy + + mesh = bpy.data.meshes.new("RemeshMesh") + obj = bpy.data.objects.new("RemeshObject", mesh) + bpy.context.collection.objects.link(obj) + + # Deselect everything first (default scene has a Cube selected) + bpy.ops.object.select_all(action='DESELECT') + + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + + mesh.from_pydata(vertices.tolist(), [], faces.tolist()) + mesh.update() + + return obj, mesh + + +def _bpy_extract_and_cleanup(obj): + """Extract vertices/faces from object, then delete it. Triangulates quads/n-gons.""" + import bpy + + mesh = obj.data + result_vertices = [list(v.co) for v in mesh.vertices] + + # Triangulate polygons with >3 verts (Quadriflow produces quads) + result_faces = [] + for p in mesh.polygons: + verts = list(p.vertices) + if len(verts) == 3: + result_faces.append(verts) + elif len(verts) == 4: + # Split quad into 2 triangles + result_faces.append([verts[0], verts[1], verts[2]]) + result_faces.append([verts[0], verts[2], verts[3]]) + else: + # Fan triangulation for n-gons + for i in range(1, len(verts) - 1): + result_faces.append([verts[0], verts[i], verts[i + 1]]) + + bpy.data.objects.remove(obj, do_unlink=True) + bpy.data.meshes.remove(mesh) + + return {'vertices': result_vertices, 'faces': result_faces} + + def _bpy_voxel_remesh(vertices, faces, voxel_size): """Blender voxel remesh using bpy.""" import bpy - mesh = bpy.data.meshes.new("RemeshMesh") - obj = bpy.data.objects.new("RemeshObject", mesh) - bpy.context.collection.objects.link(obj) - bpy.context.view_layer.objects.active = obj - obj.select_set(True) - - mesh.from_pydata(vertices.tolist(), [], faces.tolist()) - mesh.update() + obj, mesh = _bpy_setup_object(vertices, faces) obj.data.remesh_voxel_size = voxel_size bpy.ops.object.voxel_remesh() - mesh = obj.data - result_vertices = [list(v.co) for v in mesh.vertices] - result_faces = [list(p.vertices) for p in mesh.polygons] - - bpy.data.objects.remove(obj, do_unlink=True) - bpy.data.meshes.remove(mesh) - - return {'vertices': result_vertices, 'faces': result_faces} + return _bpy_extract_and_cleanup(obj) def _bpy_quadriflow_remesh(vertices, faces, target_face_count): - """Blender Quadriflow remesh using bpy.""" + """Blender Quadriflow remesh using bpy with context override for headless.""" + import bpy + import traceback + + obj, mesh = _bpy_setup_object(vertices, faces) + + # Quadriflow operator needs proper context — use temp_override for headless + window = bpy.context.window + screen = window.screen + area = next((a for a in screen.areas if a.type == 'VIEW_3D'), None) + + print(f"[Remesh Blender] Quadriflow debug: areas={[a.type for a in screen.areas]}") + + if area is None: + # Headless: no VIEW_3D area exists, override the first area + area = screen.areas[0] + original_type = area.type + area.type = 'VIEW_3D' + print(f"[Remesh Blender] Quadriflow debug: changed area from {original_type} to VIEW_3D") + else: + original_type = None + + region = next((r for r in area.regions if r.type == 'WINDOW'), area.regions[0]) + print(f"[Remesh Blender] Quadriflow debug: area.type={area.type}, region.type={region.type}") + + # Check poll before calling + try: + with bpy.context.temp_override(window=window, area=area, region=region): + poll_ok = bpy.ops.object.quadriflow_remesh.poll() + print(f"[Remesh Blender] Quadriflow debug: poll={poll_ok}") + print(f"[Remesh Blender] Quadriflow debug: active_object={bpy.context.active_object}") + print(f"[Remesh Blender] Quadriflow debug: selected_objects={bpy.context.selected_objects}") + except Exception as e: + print(f"[Remesh Blender] Quadriflow debug: poll check failed: {e}") + + # Clean mesh before quadriflow (fixes CANCELLED on non-manifold/degenerate meshes) + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete_loose() + bpy.ops.mesh.dissolve_degenerate() + bpy.ops.mesh.normals_make_consistent(inside=False) + bpy.ops.object.mode_set(mode='OBJECT') + print(f"[Remesh Blender] Quadriflow debug: mesh cleaned") + + result = {'CANCELLED'} + try: + with bpy.context.temp_override(window=window, area=area, region=region): + result = bpy.ops.object.quadriflow_remesh( + 'EXEC_DEFAULT', + use_mesh_symmetry=False, + use_preserve_sharp=False, + use_preserve_boundary=True, + smooth_normals=False, + mode='FACES', + target_faces=target_face_count, + seed=0 + ) + print(f"[Remesh Blender] Quadriflow result: {result}") + except Exception as e: + print(f"[Remesh Blender] Quadriflow EXCEPTION: {e}") + traceback.print_exc() + finally: + if original_type is not None: + area.type = original_type + + if result != {'FINISHED'}: + print(f"[Remesh Blender] Quadriflow FAILED with result={result}") + + return _bpy_extract_and_cleanup(obj) + + +def _bpy_remesh_modifier(vertices, faces, mode, octree_depth=6, scale=0.9, sharpness=1.0): + """Blender Remesh Modifier (Smooth/Sharp/Blocks) using bpy.""" import bpy - mesh = bpy.data.meshes.new("RemeshMesh") - obj = bpy.data.objects.new("RemeshObject", mesh) - bpy.context.collection.objects.link(obj) - bpy.context.view_layer.objects.active = obj - obj.select_set(True) + obj, mesh = _bpy_setup_object(vertices, faces) - mesh.from_pydata(vertices.tolist(), [], faces.tolist()) - mesh.update() + mod = obj.modifiers.new(name="Remesh", type='REMESH') + mod.mode = mode # 'SMOOTH', 'SHARP', or 'BLOCKS' + mod.octree_depth = octree_depth + mod.scale = scale + if mode == 'SHARP': + mod.sharpness = sharpness - bpy.ops.object.quadriflow_remesh( - use_mesh_symmetry=False, - use_preserve_sharp=False, - use_preserve_boundary=False, - smooth_normals=False, - mode='FACES', - target_faces=target_face_count, - seed=0 - ) + bpy.ops.object.modifier_apply(modifier="Remesh") - mesh = obj.data - result_vertices = [list(v.co) for v in mesh.vertices] - result_faces = [list(p.vertices) for p in mesh.polygons] - - bpy.data.objects.remove(obj, do_unlink=True) - bpy.data.meshes.remove(mesh) - - return {'vertices': result_vertices, 'faces': result_faces} + return _bpy_extract_and_cleanup(obj) class RemeshBlenderNode: @@ -76,6 +168,9 @@ class RemeshBlenderNode: Available backends: - blender_voxel: Voxel-based remeshing (watertight output) - blender_quadriflow: Quadriflow quad remeshing + - blender_smooth: Smooth remesh modifier + - blender_sharp: Sharp remesh modifier (preserves edges) + - blender_blocks: Blocky remesh modifier Requires bpy (Blender Python module) to be installed. """ @@ -88,9 +183,12 @@ class RemeshBlenderNode: "backend": ([ "blender_voxel", "blender_quadriflow", + "blender_smooth", + "blender_sharp", + "blender_blocks", ], { "default": "blender_voxel", - "tooltip": "Remeshing algorithm. blender_voxel=watertight output, blender_quadriflow=quad remesh" + "tooltip": "Remeshing algorithm. voxel=watertight, quadriflow=quad remesh, smooth/sharp/blocks=modifier-based" }), }, "optional": { @@ -113,6 +211,33 @@ class RemeshBlenderNode: "tooltip": "Target number of output faces for quadriflow backend.", "visible_when": {"backend": ["blender_quadriflow"]}, }), + # Modifier-based (Smooth/Sharp/Blocks) + "octree_depth": ("INT", { + "default": 6, + "min": 1, + "max": 10, + "step": 1, + "tooltip": "Resolution of the remesh. Higher = more detail, more faces.", + "visible_when": {"backend": ["blender_smooth", "blender_sharp", "blender_blocks"]}, + }), + "scale": ("FLOAT", { + "default": 0.9, + "min": 0.0, + "max": 1.0, + "step": 0.05, + "display": "number", + "tooltip": "Ratio of output size to input bounding box.", + "visible_when": {"backend": ["blender_smooth", "blender_sharp", "blender_blocks"]}, + }), + "sharpness": ("FLOAT", { + "default": 1.0, + "min": 0.0, + "max": 5.0, + "step": 0.1, + "display": "number", + "tooltip": "Edge sharpness for Sharp mode.", + "visible_when": {"backend": ["blender_sharp"]}, + }), } } @@ -122,8 +247,16 @@ class RemeshBlenderNode: CATEGORY = "geompack/remeshing" OUTPUT_NODE = True - def remesh(self, trimesh, backend, voxel_size=1.0, target_face_count=500000): + def remesh(self, trimesh, backend, voxel_size=1.0, target_face_count=500000, + octree_depth=6, scale=0.9, sharpness=1.0): """Apply Blender-based remeshing.""" + # Sanitize hidden widget values (ComfyUI sends '' for hidden visible_when widgets) + voxel_size = float(voxel_size) if voxel_size not in (None, '') else 1.0 + target_face_count = int(target_face_count) if target_face_count not in (None, '') else 500000 + octree_depth = int(octree_depth) if octree_depth not in (None, '') else 6 + scale = float(scale) if scale not in (None, '') else 0.9 + sharpness = float(sharpness) if sharpness not in (None, '') else 1.0 + initial_vertices = len(trimesh.vertices) initial_faces = len(trimesh.faces) @@ -137,6 +270,11 @@ class RemeshBlenderNode: elif backend == "blender_quadriflow": print(f"[Remesh Blender] Parameters: target_face_count={target_face_count:,}") remeshed_mesh, info = self._blender_quadriflow(trimesh, target_face_count) + elif backend in ("blender_smooth", "blender_sharp", "blender_blocks"): + mode = backend.replace("blender_", "").upper() + print(f"[Remesh Blender] Parameters: mode={mode}, octree_depth={octree_depth}, scale={scale}" + + (f", sharpness={sharpness}" if backend == "blender_sharp" else "")) + remeshed_mesh, info = self._blender_modifier(trimesh, mode, octree_depth, scale, sharpness) else: raise ValueError(f"Unknown backend: {backend}") @@ -211,6 +349,14 @@ After: 'original_faces': len(trimesh.faces) } + changed = (len(remeshed_mesh.vertices) != len(trimesh.vertices) or + len(remeshed_mesh.faces) != len(trimesh.faces)) + if changed: + status = "" + else: + status = ("\nWARNING: Mesh unchanged — Quadriflow operator likely failed (CANCELLED).\n" + "This is a known issue with bpy headless. Check server logs for debug info.\n") + info = f"""Remesh Results (Blender Quadriflow): Target Face Count: {target_face_count:,} @@ -223,11 +369,58 @@ Before: After: Vertices: {len(remeshed_mesh.vertices):,} Faces: {len(remeshed_mesh.faces):,} - +{status} Quadriflow creates quad-dominant meshes with good topology. """ return remeshed_mesh, info + def _blender_modifier(self, trimesh, mode, octree_depth, scale, sharpness): + """Blender Remesh Modifier (Smooth/Sharp/Blocks).""" + print(f"[Remesh Blender] Running Blender Remesh Modifier (mode={mode}, depth={octree_depth})...") + result = _bpy_remesh_modifier( + vertices=np.asarray(trimesh.vertices, dtype=np.float32), + faces=np.asarray(trimesh.faces, dtype=np.int32), + mode=mode, + octree_depth=octree_depth, + scale=scale, + sharpness=sharpness + ) + + remeshed_mesh = trimesh_module.Trimesh( + vertices=np.array(result['vertices'], dtype=np.float32), + faces=np.array(result['faces'], dtype=np.int32), + process=False + ) + + remeshed_mesh.metadata = trimesh.metadata.copy() + remeshed_mesh.metadata['remeshing'] = { + 'algorithm': f'blender_{mode.lower()}', + 'octree_depth': octree_depth, + 'scale': scale, + 'original_vertices': len(trimesh.vertices), + 'original_faces': len(trimesh.faces) + } + + mode_label = mode.capitalize() + params = f"Octree Depth: {octree_depth}\nScale: {scale}" + if mode == 'SHARP': + params += f"\nSharpness: {sharpness}" + + info = f"""Remesh Results (Blender {mode_label}): + +{params} +Method: bpy (Remesh Modifier) + +Before: + Vertices: {len(trimesh.vertices):,} + Faces: {len(trimesh.faces):,} + +After: + Vertices: {len(remeshed_mesh.vertices):,} + Faces: {len(remeshed_mesh.faces):,} +""" + return remeshed_mesh, info + NODE_CLASS_MAPPINGS = { "GeomPackRemeshBlender": RemeshBlenderNode, diff --git a/requirements.txt b/requirements.txt index 5569f481..2db280b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.79 +comfy-env==0.1.80 comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.12 numpy From 89af2f67456c903419a4f4d0c7c977e96c3a4969 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:25:40 +0100 Subject: [PATCH 11/27] 81 --- nodes/blender/remeshing/remesh.py | 143 +----------------------------- nodes/main/comfy-env.toml | 1 + nodes/main/remeshing/remesh.py | 102 ++++++++++++++++++++- requirements.txt | 2 +- 4 files changed, 104 insertions(+), 144 deletions(-) diff --git a/nodes/blender/remeshing/remesh.py b/nodes/blender/remeshing/remesh.py index c4aebf05..152208f5 100644 --- a/nodes/blender/remeshing/remesh.py +++ b/nodes/blender/remeshing/remesh.py @@ -3,7 +3,7 @@ """ Remesh Blender Node - Blender remeshing backends using bpy. -Supports: voxel, quadriflow, smooth, sharp, blocks. +Supports: voxel, smooth, sharp, blocks. Requires bpy (Blender Python module). """ @@ -38,7 +38,7 @@ def _bpy_extract_and_cleanup(obj): mesh = obj.data result_vertices = [list(v.co) for v in mesh.vertices] - # Triangulate polygons with >3 verts (Quadriflow produces quads) + # Triangulate polygons with >3 verts (safety for any backend producing quads) result_faces = [] for p in mesh.polygons: verts = list(p.vertices) @@ -71,78 +71,6 @@ def _bpy_voxel_remesh(vertices, faces, voxel_size): return _bpy_extract_and_cleanup(obj) -def _bpy_quadriflow_remesh(vertices, faces, target_face_count): - """Blender Quadriflow remesh using bpy with context override for headless.""" - import bpy - import traceback - - obj, mesh = _bpy_setup_object(vertices, faces) - - # Quadriflow operator needs proper context — use temp_override for headless - window = bpy.context.window - screen = window.screen - area = next((a for a in screen.areas if a.type == 'VIEW_3D'), None) - - print(f"[Remesh Blender] Quadriflow debug: areas={[a.type for a in screen.areas]}") - - if area is None: - # Headless: no VIEW_3D area exists, override the first area - area = screen.areas[0] - original_type = area.type - area.type = 'VIEW_3D' - print(f"[Remesh Blender] Quadriflow debug: changed area from {original_type} to VIEW_3D") - else: - original_type = None - - region = next((r for r in area.regions if r.type == 'WINDOW'), area.regions[0]) - print(f"[Remesh Blender] Quadriflow debug: area.type={area.type}, region.type={region.type}") - - # Check poll before calling - try: - with bpy.context.temp_override(window=window, area=area, region=region): - poll_ok = bpy.ops.object.quadriflow_remesh.poll() - print(f"[Remesh Blender] Quadriflow debug: poll={poll_ok}") - print(f"[Remesh Blender] Quadriflow debug: active_object={bpy.context.active_object}") - print(f"[Remesh Blender] Quadriflow debug: selected_objects={bpy.context.selected_objects}") - except Exception as e: - print(f"[Remesh Blender] Quadriflow debug: poll check failed: {e}") - - # Clean mesh before quadriflow (fixes CANCELLED on non-manifold/degenerate meshes) - bpy.ops.object.mode_set(mode='EDIT') - bpy.ops.mesh.select_all(action='SELECT') - bpy.ops.mesh.delete_loose() - bpy.ops.mesh.dissolve_degenerate() - bpy.ops.mesh.normals_make_consistent(inside=False) - bpy.ops.object.mode_set(mode='OBJECT') - print(f"[Remesh Blender] Quadriflow debug: mesh cleaned") - - result = {'CANCELLED'} - try: - with bpy.context.temp_override(window=window, area=area, region=region): - result = bpy.ops.object.quadriflow_remesh( - 'EXEC_DEFAULT', - use_mesh_symmetry=False, - use_preserve_sharp=False, - use_preserve_boundary=True, - smooth_normals=False, - mode='FACES', - target_faces=target_face_count, - seed=0 - ) - print(f"[Remesh Blender] Quadriflow result: {result}") - except Exception as e: - print(f"[Remesh Blender] Quadriflow EXCEPTION: {e}") - traceback.print_exc() - finally: - if original_type is not None: - area.type = original_type - - if result != {'FINISHED'}: - print(f"[Remesh Blender] Quadriflow FAILED with result={result}") - - return _bpy_extract_and_cleanup(obj) - - def _bpy_remesh_modifier(vertices, faces, mode, octree_depth=6, scale=0.9, sharpness=1.0): """Blender Remesh Modifier (Smooth/Sharp/Blocks) using bpy.""" import bpy @@ -167,7 +95,6 @@ class RemeshBlenderNode: Available backends: - blender_voxel: Voxel-based remeshing (watertight output) - - blender_quadriflow: Quadriflow quad remeshing - blender_smooth: Smooth remesh modifier - blender_sharp: Sharp remesh modifier (preserves edges) - blender_blocks: Blocky remesh modifier @@ -182,13 +109,12 @@ class RemeshBlenderNode: "trimesh": ("TRIMESH",), "backend": ([ "blender_voxel", - "blender_quadriflow", "blender_smooth", "blender_sharp", "blender_blocks", ], { "default": "blender_voxel", - "tooltip": "Remeshing algorithm. voxel=watertight, quadriflow=quad remesh, smooth/sharp/blocks=modifier-based" + "tooltip": "Remeshing algorithm. voxel=watertight, smooth/sharp/blocks=modifier-based" }), }, "optional": { @@ -202,15 +128,6 @@ class RemeshBlenderNode: "tooltip": "Voxel size for Blender voxel remesh. Smaller = more detail, more faces. Output is always watertight.", "visible_when": {"backend": ["blender_voxel"]}, }), - # Quadriflow - "target_face_count": ("INT", { - "default": 500000, - "min": 1000, - "max": 5000000, - "step": 1000, - "tooltip": "Target number of output faces for quadriflow backend.", - "visible_when": {"backend": ["blender_quadriflow"]}, - }), # Modifier-based (Smooth/Sharp/Blocks) "octree_depth": ("INT", { "default": 6, @@ -247,12 +164,11 @@ class RemeshBlenderNode: CATEGORY = "geompack/remeshing" OUTPUT_NODE = True - def remesh(self, trimesh, backend, voxel_size=1.0, target_face_count=500000, + def remesh(self, trimesh, backend, voxel_size=1.0, octree_depth=6, scale=0.9, sharpness=1.0): """Apply Blender-based remeshing.""" # Sanitize hidden widget values (ComfyUI sends '' for hidden visible_when widgets) voxel_size = float(voxel_size) if voxel_size not in (None, '') else 1.0 - target_face_count = int(target_face_count) if target_face_count not in (None, '') else 500000 octree_depth = int(octree_depth) if octree_depth not in (None, '') else 6 scale = float(scale) if scale not in (None, '') else 0.9 sharpness = float(sharpness) if sharpness not in (None, '') else 1.0 @@ -267,9 +183,6 @@ class RemeshBlenderNode: if backend == "blender_voxel": print(f"[Remesh Blender] Parameters: voxel_size={voxel_size}") remeshed_mesh, info = self._blender_voxel(trimesh, voxel_size) - elif backend == "blender_quadriflow": - print(f"[Remesh Blender] Parameters: target_face_count={target_face_count:,}") - remeshed_mesh, info = self._blender_quadriflow(trimesh, target_face_count) elif backend in ("blender_smooth", "blender_sharp", "blender_blocks"): mode = backend.replace("blender_", "").upper() print(f"[Remesh Blender] Parameters: mode={mode}, octree_depth={octree_depth}, scale={scale}" @@ -323,54 +236,6 @@ Before: After: Vertices: {len(remeshed_mesh.vertices):,} Faces: {len(remeshed_mesh.faces):,} -""" - return remeshed_mesh, info - - def _blender_quadriflow(self, trimesh, target_face_count): - """Blender Quadriflow remeshing using bpy.""" - print(f"[Remesh Blender] Running Blender Quadriflow (target_faces={target_face_count})...") - result = _bpy_quadriflow_remesh( - vertices=np.asarray(trimesh.vertices, dtype=np.float32), - faces=np.asarray(trimesh.faces, dtype=np.int32), - target_face_count=target_face_count - ) - - remeshed_mesh = trimesh_module.Trimesh( - vertices=np.array(result['vertices'], dtype=np.float32), - faces=np.array(result['faces'], dtype=np.int32), - process=False - ) - - remeshed_mesh.metadata = trimesh.metadata.copy() - remeshed_mesh.metadata['remeshing'] = { - 'algorithm': 'blender_quadriflow', - 'target_face_count': target_face_count, - 'original_vertices': len(trimesh.vertices), - 'original_faces': len(trimesh.faces) - } - - changed = (len(remeshed_mesh.vertices) != len(trimesh.vertices) or - len(remeshed_mesh.faces) != len(trimesh.faces)) - if changed: - status = "" - else: - status = ("\nWARNING: Mesh unchanged — Quadriflow operator likely failed (CANCELLED).\n" - "This is a known issue with bpy headless. Check server logs for debug info.\n") - - info = f"""Remesh Results (Blender Quadriflow): - -Target Face Count: {target_face_count:,} -Method: bpy - -Before: - Vertices: {len(trimesh.vertices):,} - Faces: {len(trimesh.faces):,} - -After: - Vertices: {len(remeshed_mesh.vertices):,} - Faces: {len(remeshed_mesh.faces):,} -{status} -Quadriflow creates quad-dominant meshes with good topology. """ return remeshed_mesh, info diff --git a/nodes/main/comfy-env.toml b/nodes/main/comfy-env.toml index 17eeb127..9f3fd907 100644 --- a/nodes/main/comfy-env.toml +++ b/nodes/main/comfy-env.toml @@ -20,6 +20,7 @@ pymeshfix = ">=0.17.0" xatlas = ">=0.0.11" skeletor = ">=1.2.0" pynanoinstantmeshes = "*" +pyquadriflow = "*" matplotlib = ">=3.5.0" pillow = ">=9.0.0" pyvista = ">=0.43.0" diff --git a/nodes/main/remeshing/remesh.py b/nodes/main/remeshing/remesh.py index 0f312963..76996fd5 100644 --- a/nodes/main/remeshing/remesh.py +++ b/nodes/main/remeshing/remesh.py @@ -2,7 +2,7 @@ # Copyright (C) 2025 ComfyUI-GeometryPack Contributors """ -Remesh Node - Main backends (pymeshlab, instant_meshes) +Remesh Node - Main backends (pymeshlab, instant_meshes, quadriflow) """ import numpy as np @@ -125,9 +125,10 @@ class RemeshNode: Available backends: - pymeshlab_isotropic: PyMeshLab isotropic remeshing (fast) - instant_meshes: Field-aligned quad remeshing + - quadriflow: QuadriFlow quad remeshing (good topology) For CGAL isotropic remeshing, use "Remesh CGAL" node. - For Blender voxel/quadriflow remeshing, use "Remesh Blender" node. + For Blender voxel/modifier remeshing, use "Remesh Blender" node. For GPU-accelerated remeshing, use "Remesh GPU" node. """ @@ -139,9 +140,10 @@ class RemeshNode: "backend": ([ "pymeshlab_isotropic", "instant_meshes", + "quadriflow", ], { "default": "pymeshlab_isotropic", - "tooltip": "Remeshing algorithm. pymeshlab=fast isotropic, instant_meshes=field-aligned quads" + "tooltip": "Remeshing algorithm. pymeshlab=fast isotropic, instant_meshes=field-aligned quads, quadriflow=quad remesh with good topology" }), }, "optional": { @@ -199,6 +201,25 @@ class RemeshNode: "tooltip": "Angle threshold (degrees) for preserving sharp/crease edges in Instant Meshes. 0 = no crease preservation.", "visible_when": {"backend": ["instant_meshes"]}, }), + # QuadriFlow specific + "target_face_count": ("INT", { + "default": 5000, + "min": 100, + "max": 5000000, + "step": 100, + "tooltip": "Target number of output faces for QuadriFlow. Creates quad-dominant mesh with good topology.", + "visible_when": {"backend": ["quadriflow"]}, + }), + "preserve_sharp": (["true", "false"], { + "default": "false", + "tooltip": "Preserve sharp edges during QuadriFlow remeshing.", + "visible_when": {"backend": ["quadriflow"]}, + }), + "preserve_boundary": (["true", "false"], { + "default": "true", + "tooltip": "Preserve mesh boundary edges during QuadriFlow remeshing.", + "visible_when": {"backend": ["quadriflow"]}, + }), } } @@ -210,8 +231,17 @@ class RemeshNode: def remesh(self, trimesh, backend, target_edge_length=1.0, iterations=3, feature_angle=30.0, adaptive="false", - target_vertex_count=5000, deterministic="true", crease_angle=0.0): + target_vertex_count=5000, deterministic="true", crease_angle=0.0, + target_face_count=5000, preserve_sharp="false", preserve_boundary="true"): """Apply remeshing based on selected backend.""" + # Sanitize hidden widget values (ComfyUI sends '' for hidden visible_when widgets) + target_edge_length = float(target_edge_length) if target_edge_length not in (None, '') else 1.0 + iterations = int(iterations) if iterations not in (None, '') else 3 + feature_angle = float(feature_angle) if feature_angle not in (None, '') else 30.0 + target_vertex_count = int(target_vertex_count) if target_vertex_count not in (None, '') else 5000 + crease_angle = float(crease_angle) if crease_angle not in (None, '') else 0.0 + target_face_count = int(target_face_count) if target_face_count not in (None, '') else 5000 + initial_vertices = len(trimesh.vertices) initial_faces = len(trimesh.faces) @@ -229,6 +259,11 @@ class RemeshNode: remeshed_mesh, info = self._instant_meshes( trimesh, target_vertex_count, deterministic, crease_angle ) + elif backend == "quadriflow": + print(f"[Remesh] Parameters: target_face_count={target_face_count:,}, preserve_sharp={preserve_sharp}, preserve_boundary={preserve_boundary}") + remeshed_mesh, info = self._quadriflow( + trimesh, target_face_count, preserve_sharp, preserve_boundary + ) else: raise ValueError(f"Unknown backend: {backend}") @@ -319,6 +354,65 @@ After: Faces: {len(remeshed_mesh.faces):,} Instant Meshes creates flow-aligned quad meshes. +""" + return remeshed_mesh, info + + def _quadriflow(self, trimesh, target_face_count, preserve_sharp, preserve_boundary): + """QuadriFlow quad remeshing using pyQuadriFlow.""" + try: + from pyquadriflow import pyquadriflow + except ImportError: + raise ImportError( + "pyQuadriFlow not installed. Install with: pip install pyQuadriFlow" + ) + + V = np.asarray(trimesh.vertices, dtype=np.float64).tolist() + F = np.asarray(trimesh.faces, dtype=np.int32).tolist() + + print(f"[Remesh] Running QuadriFlow (target_faces={target_face_count})...") + V_out, F_out = pyquadriflow( + target_face_count, + 0, # seed + V, + F, + preserve_sharp == "true", + preserve_boundary == "true", + False, # adaptive_scale + False, # aggressive_sat + False, # minimum_cost_flow + ) + + remeshed_mesh = trimesh_module.Trimesh( + vertices=np.array(V_out, dtype=np.float32), + faces=np.array(F_out, dtype=np.int32), + process=False + ) + + remeshed_mesh.metadata = trimesh.metadata.copy() + remeshed_mesh.metadata['remeshing'] = { + 'algorithm': 'quadriflow', + 'target_face_count': target_face_count, + 'preserve_sharp': preserve_sharp == "true", + 'preserve_boundary': preserve_boundary == "true", + 'original_vertices': len(trimesh.vertices), + 'original_faces': len(trimesh.faces) + } + + info = f"""Remesh Results (QuadriFlow): + +Target Face Count: {target_face_count:,} +Preserve Sharp: {preserve_sharp} +Preserve Boundary: {preserve_boundary} + +Before: + Vertices: {len(trimesh.vertices):,} + Faces: {len(trimesh.faces):,} + +After: + Vertices: {len(remeshed_mesh.vertices):,} + Faces: {len(remeshed_mesh.faces):,} + +QuadriFlow creates quad-dominant meshes with good topology. """ return remeshed_mesh, info diff --git a/requirements.txt b/requirements.txt index 2db280b8..32b0dc81 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.80 +comfy-env==0.1.81 comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.12 numpy From 1a739110d8362b9ef4154292f1a38d8849306c91 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:26:40 +0100 Subject: [PATCH 12/27] updated blender workflow --- workflows/remeshing_blender.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workflows/remeshing_blender.json b/workflows/remeshing_blender.json index aabe301f..1d1d299e 100644 --- a/workflows/remeshing_blender.json +++ b/workflows/remeshing_blender.json @@ -1 +1 @@ -{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":28,"last_link_id":37,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-288.0410052280236,276.0522205128005],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":35},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":37},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","cnr_id":"comfyui-geometrypack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-553.8798563116762,-69.44822756818182],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[35,36]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":28,"type":"GeomPackRemeshBlender","pos":[-54.034114326584614,-70.78213153854568],"size":[210,102],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":36},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"voxel_size","name":"voxel_size","shape":7,"type":"FLOAT","widget":{"name":"voxel_size"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[37]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"ecb6110ecd36476ca03b7ed8bdb80d47e60ac388","Node name for S&R":"GeomPackRemeshBlender"},"widgets_values":["blender_quadriflow",1,500000]}],"links":[[35,1,0,25,0,"TRIMESH"],[36,1,0,28,0,"TRIMESH"],[37,28,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7935011461883303,"offset":[982.6914055475675,277.94845957682213]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":30,"last_link_id":41,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-210.03447320411541,106.04784971545217],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":35},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":40},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-553.8798563116762,-69.44822756818182],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[35,39]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":29,"type":"GeomPackRemeshBlender","pos":[-69.03193521512232,-241.27108459419395],"size":[210,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":39},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"voxel_size","name":"voxel_size","shape":7,"type":"FLOAT","widget":{"name":"voxel_size"},"link":null},{"localized_name":"octree_depth","name":"octree_depth","shape":7,"type":"INT","widget":{"name":"octree_depth"},"link":null},{"localized_name":"scale","name":"scale","shape":7,"type":"FLOAT","widget":{"name":"scale"},"link":null},{"localized_name":"sharpness","name":"sharpness","shape":7,"type":"FLOAT","widget":{"name":"sharpness"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[40]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"734034ab931e48d57e780ecc399811eb8bf444f6","Node name for S&R":"GeomPackRemeshBlender","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["blender_sharp",1,6,1,0.9,""]}],"links":[[35,1,0,25,0,"TRIMESH"],[39,1,0,29,0,"TRIMESH"],[40,29,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6460623271410663,"offset":[1058.8935929640404,524.9096852323577]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file From 023a7f3b770c7d399697a6be4ed26fed0b4a4b85 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:27:40 +0100 Subject: [PATCH 13/27] right pyquadriflow --- nodes/main/remeshing/remesh.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nodes/main/remeshing/remesh.py b/nodes/main/remeshing/remesh.py index 76996fd5..516d44f3 100644 --- a/nodes/main/remeshing/remesh.py +++ b/nodes/main/remeshing/remesh.py @@ -360,7 +360,7 @@ Instant Meshes creates flow-aligned quad meshes. def _quadriflow(self, trimesh, target_face_count, preserve_sharp, preserve_boundary): """QuadriFlow quad remeshing using pyQuadriFlow.""" try: - from pyquadriflow import pyquadriflow + from pyQuadriFlow.pyQuadriFlow import pyquadriflow except ImportError: raise ImportError( "pyQuadriFlow not installed. Install with: pip install pyQuadriFlow" @@ -370,7 +370,7 @@ Instant Meshes creates flow-aligned quad meshes. F = np.asarray(trimesh.faces, dtype=np.int32).tolist() print(f"[Remesh] Running QuadriFlow (target_faces={target_face_count})...") - V_out, F_out = pyquadriflow( + result = pyquadriflow( target_face_count, 0, # seed V, @@ -381,6 +381,8 @@ Instant Meshes creates flow-aligned quad meshes. False, # aggressive_sat False, # minimum_cost_flow ) + V_out = result['vertices'] + F_out = result['faces'] remeshed_mesh = trimesh_module.Trimesh( vertices=np.array(V_out, dtype=np.float32), From eeb6ba31a64b11054f9981cfe0ef30b2aeedebea Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:28:40 +0100 Subject: [PATCH 14/27] updated remesh workflow --- workflows/remeshing.json | 2 +- workflows/remeshing_blender.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/workflows/remeshing.json b/workflows/remeshing.json index 0a56749e..0ecba2a8 100644 --- a/workflows/remeshing.json +++ b/workflows/remeshing.json @@ -1 +1 @@ -{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":25,"last_link_id":29,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-502.81561847832234,-58.160239777583065],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[24,29]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-344.64489975927364,265.1754548878005],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":29},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":28},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":23,"type":"GeomPackRemesh","pos":[-150.60754064166025,-111.70359969148042],"size":[214.77734375,400],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":24},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[28]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"01a1fb3f161fe989dc1486b6064a395302d93af3","Node name for S&R":"GeomPackRemesh"},"widgets_values":["instant_meshes",10,3,30,"false",5000,"true",0,""]}],"links":[[24,1,0,23,0,"TRIMESH"],[28,23,0,25,1,"TRIMESH"],[29,1,0,25,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.751314800901578,"offset":[1235.385454446773,318.5928263621994]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":26,"last_link_id":32,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-344.64489975927364,265.1754548878005],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":29},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":32},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-502.81561847832234,-58.160239777583065],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[29,31]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":26,"type":"GeomPackRemesh","pos":[-636.4250560092735,188.81972832530045],"size":[214.34375,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":31},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"preserve_sharp","name":"preserve_sharp","shape":7,"type":"COMBO","widget":{"name":"preserve_sharp"},"link":null},{"localized_name":"preserve_boundary","name":"preserve_boundary","shape":7,"type":"COMBO","widget":{"name":"preserve_boundary"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[32]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"a57da232130b20d93f36248ed810254035c6226c","Node name for S&R":"GeomPackRemesh"},"widgets_values":["quadriflow",1,3,30,"false",5000,"true",0,5000,"false","true",""]}],"links":[[29,1,0,25,0,"TRIMESH"],[31,1,0,26,0,"TRIMESH"],[32,26,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.751314800901578,"offset":[1235.739001321773,318.7695997996994]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/remeshing_blender.json b/workflows/remeshing_blender.json index 1d1d299e..bb7cc581 100644 --- a/workflows/remeshing_blender.json +++ b/workflows/remeshing_blender.json @@ -1 +1 @@ -{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":30,"last_link_id":41,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-210.03447320411541,106.04784971545217],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":35},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":40},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-553.8798563116762,-69.44822756818182],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[35,39]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":29,"type":"GeomPackRemeshBlender","pos":[-69.03193521512232,-241.27108459419395],"size":[210,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":39},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"voxel_size","name":"voxel_size","shape":7,"type":"FLOAT","widget":{"name":"voxel_size"},"link":null},{"localized_name":"octree_depth","name":"octree_depth","shape":7,"type":"INT","widget":{"name":"octree_depth"},"link":null},{"localized_name":"scale","name":"scale","shape":7,"type":"FLOAT","widget":{"name":"scale"},"link":null},{"localized_name":"sharpness","name":"sharpness","shape":7,"type":"FLOAT","widget":{"name":"sharpness"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[40]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"734034ab931e48d57e780ecc399811eb8bf444f6","Node name for S&R":"GeomPackRemeshBlender","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["blender_sharp",1,6,1,0.9,""]}],"links":[[35,1,0,25,0,"TRIMESH"],[39,1,0,29,0,"TRIMESH"],[40,29,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6460623271410663,"offset":[1058.8935929640404,524.9096852323577]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":31,"last_link_id":46,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-553.8798563116762,-69.44822756818182],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[43,46]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":31,"type":"GeomPackRemeshBlender","pos":[-98.55301081962853,-237.88071575885226],"size":[210,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":43},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"voxel_size","name":"voxel_size","shape":7,"type":"FLOAT","widget":{"name":"voxel_size"},"link":null},{"localized_name":"octree_depth","name":"octree_depth","shape":7,"type":"INT","widget":{"name":"octree_depth"},"link":null},{"localized_name":"scale","name":"scale","shape":7,"type":"FLOAT","widget":{"name":"scale"},"link":null},{"localized_name":"sharpness","name":"sharpness","shape":7,"type":"FLOAT","widget":{"name":"sharpness"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[45]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"a57da232130b20d93f36248ed810254035c6226c","Node name for S&R":"GeomPackRemeshBlender"},"widgets_values":["blender_sharp",1,8,0.9,1,""]},{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-210.03447320411541,106.04784971545217],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":46},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":45},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,""]}],"links":[[43,1,0,31,0,"TRIMESH"],[45,31,0,25,1,"TRIMESH"],[46,1,0,25,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.3715783642907196,"offset":[668.3399932521036,284.0568811975611]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file From 9df08df3064d15c792fe7bc50e230f532eeb426c Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:29:40 +0100 Subject: [PATCH 15/27] 85frfr --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 32b0dc81..20bfb017 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.81 +comfy-env==0.1.85 comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.12 numpy From 5625d025c73ac21833154f44e29ae3d9a1760767 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:30:40 +0100 Subject: [PATCH 16/27] better debug prinst --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 20bfb017..7e46baf6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.85 +comfy-env==0.1.86 comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.12 numpy From 2ba6d157200fe68228b7ed8a48b50a5645180471 Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:31:40 +0100 Subject: [PATCH 17/27] 87 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7e46baf6..c1f10843 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.86 +comfy-env==0.1.87 comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.12 numpy From 54a5da9c312f53852543adcb24fbb66b8d42727b Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:32:40 +0100 Subject: [PATCH 18/27] quadriflow for macos --- nodes/main/comfy-env.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/main/comfy-env.toml b/nodes/main/comfy-env.toml index 9f3fd907..d209c26b 100644 --- a/nodes/main/comfy-env.toml +++ b/nodes/main/comfy-env.toml @@ -20,7 +20,7 @@ pymeshfix = ">=0.17.0" xatlas = ">=0.0.11" skeletor = ">=1.2.0" pynanoinstantmeshes = "*" -pyquadriflow = "*" +pyquadriflow = { url = "https://github.com/PozzettiAndrea/pyQuadriFlow/releases/download/v0.0.3/pyquadriflow-0.0.4-py3-none-any.whl" } matplotlib = ">=3.5.0" pillow = ">=9.0.0" pyvista = ">=0.43.0" From 10cb7fd7cb6cb8e6185ac494489796d99c4f6e5b Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:33:40 +0100 Subject: [PATCH 19/27] paraview filters --- nodes/main/__init__.py | 5 + nodes/main/paraview/__init__.py | 16 ++ nodes/main/paraview/pv_filter.py | 262 ++++++++++++++++++ nodes/main/reconstruction_cgal/alpha_wrap.py | 3 +- nodes/main/visualization/preview_mesh_dual.py | 8 +- .../main/visualization/preview_mesh_multi.py | 7 +- nodes/main/visualization/preview_mesh_vtk.py | 7 +- .../visualization/preview_mesh_vtk_batch.py | 10 +- requirements.txt | 4 +- workflows/alpha_wrap.json | 2 +- workflows/batch_remesh.json | 2 +- workflows/mesh_mesh_distance.json | 2 +- workflows/remeshing.json | 2 +- 13 files changed, 319 insertions(+), 11 deletions(-) create mode 100644 nodes/main/paraview/__init__.py create mode 100644 nodes/main/paraview/pv_filter.py diff --git a/nodes/main/__init__.py b/nodes/main/__init__.py index 1477c1c8..3eadf839 100644 --- a/nodes/main/__init__.py +++ b/nodes/main/__init__.py @@ -21,6 +21,9 @@ from . import remeshing from . import reconstruction from . import texture_remeshing +# ParaView/VTK filter nodes +from . import paraview + # CGAL nodes (moved from nodes/cgal/) from . import boolean from . import reconstruction_cgal @@ -43,6 +46,7 @@ NODE_CLASS_MAPPINGS.update(repair.NODE_CLASS_MAPPINGS) NODE_CLASS_MAPPINGS.update(remeshing.NODE_CLASS_MAPPINGS) NODE_CLASS_MAPPINGS.update(reconstruction.NODE_CLASS_MAPPINGS) NODE_CLASS_MAPPINGS.update(texture_remeshing.NODE_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(paraview.NODE_CLASS_MAPPINGS) NODE_CLASS_MAPPINGS.update(boolean.NODE_CLASS_MAPPINGS) NODE_CLASS_MAPPINGS.update(reconstruction_cgal.NODE_CLASS_MAPPINGS) NODE_CLASS_MAPPINGS.update(remeshing_cgal.NODE_CLASS_MAPPINGS) @@ -64,6 +68,7 @@ NODE_DISPLAY_NAME_MAPPINGS.update(repair.NODE_DISPLAY_NAME_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(remeshing.NODE_DISPLAY_NAME_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(reconstruction.NODE_DISPLAY_NAME_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(texture_remeshing.NODE_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(paraview.NODE_DISPLAY_NAME_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(boolean.NODE_DISPLAY_NAME_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(reconstruction_cgal.NODE_DISPLAY_NAME_MAPPINGS) NODE_DISPLAY_NAME_MAPPINGS.update(remeshing_cgal.NODE_DISPLAY_NAME_MAPPINGS) diff --git a/nodes/main/paraview/__init__.py b/nodes/main/paraview/__init__.py new file mode 100644 index 00000000..11aa698b --- /dev/null +++ b/nodes/main/paraview/__init__.py @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2025 ComfyUI-GeometryPack Contributors + +""" +ParaView/VTK filter nodes using PyVista. +""" + +from .pv_filter import ParaViewFilterNode, NODE_CLASS_MAPPINGS as PV_FILTER_MAPS, NODE_DISPLAY_NAME_MAPPINGS as PV_FILTER_DISP + +NODE_CLASS_MAPPINGS = {} +NODE_DISPLAY_NAME_MAPPINGS = {} + +NODE_CLASS_MAPPINGS.update(PV_FILTER_MAPS) +NODE_DISPLAY_NAME_MAPPINGS.update(PV_FILTER_DISP) + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/nodes/main/paraview/pv_filter.py b/nodes/main/paraview/pv_filter.py new file mode 100644 index 00000000..1ef9968c --- /dev/null +++ b/nodes/main/paraview/pv_filter.py @@ -0,0 +1,262 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2025 ComfyUI-GeometryPack Contributors + +""" +ParaView/VTK filter node using PyVista. + +Applies VTK analysis filters to meshes, producing scalar fields +for visualization in the Preview Mesh (VTK) viewer. +""" + +import numpy as np +import trimesh + + +def _trimesh_to_pyvista(mesh): + """Convert trimesh.Trimesh to pyvista.PolyData.""" + import pyvista as pv + + vertices = np.array(mesh.vertices) + faces = np.array(mesh.faces) + faces_pv = np.column_stack([np.full(len(faces), 3), faces]) + pv_mesh = pv.PolyData(vertices, faces_pv) + + # Transfer vertex_attributes → point_data + if hasattr(mesh, 'vertex_attributes'): + for name, data in mesh.vertex_attributes.items(): + arr = np.array(data) + if arr.ndim == 1 and len(arr) == len(vertices): + pv_mesh.point_data[name] = arr.astype(np.float32) + + # Transfer face_attributes → cell_data + if hasattr(mesh, 'face_attributes'): + for name, data in mesh.face_attributes.items(): + arr = np.array(data) + if arr.ndim == 1 and len(arr) == len(faces): + pv_mesh.cell_data[name] = arr.astype(np.float32) + + return pv_mesh + + +def _pyvista_to_trimesh(pv_mesh): + """Convert pyvista.PolyData back to trimesh.Trimesh.""" + vertices = np.array(pv_mesh.points) + + # Parse pyvista face format: [n, v0, v1, ..., n, v0, v1, ...] + faces = [] + if pv_mesh.n_faces > 0: + faces_flat = np.array(pv_mesh.faces) + i = 0 + while i < len(faces_flat): + n = faces_flat[i] + if n == 3: + faces.append(faces_flat[i + 1:i + 4]) + elif n == 4: + # Triangulate quads + faces.append([faces_flat[i + 1], faces_flat[i + 2], faces_flat[i + 3]]) + faces.append([faces_flat[i + 1], faces_flat[i + 3], faces_flat[i + 4]]) + i += n + 1 + + if faces: + faces = np.array(faces, dtype=np.int32) + else: + faces = np.zeros((0, 3), dtype=np.int32) + + result = trimesh.Trimesh(vertices=vertices, faces=faces, process=False) + + # Transfer point_data → vertex_attributes + for name in pv_mesh.point_data.keys(): + data = np.array(pv_mesh.point_data[name]) + if data.ndim == 1 and len(data) == len(vertices): + result.vertex_attributes[name] = data.astype(np.float32) + + # Transfer cell_data → face_attributes + for name in pv_mesh.cell_data.keys(): + data = np.array(pv_mesh.cell_data[name]) + if data.ndim == 1 and len(data) == len(faces): + result.face_attributes[name] = data.astype(np.float32) + + return result + + +class ParaViewFilterNode: + """ + Apply VTK/ParaView analysis filters to meshes using PyVista. + + Produces scalar fields for visualization in Preview Mesh (fields mode). + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "trimesh": ("TRIMESH",), + "filter_type": ([ + "curvature_gaussian", + "curvature_mean", + "cell_sizes", + "elevation", + "feature_edges", + "warp_by_scalar", + ], {"default": "curvature_gaussian"}), + }, + "optional": { + "axis": (["X", "Y", "Z"], { + "default": "Z", + "tooltip": "Axis for elevation or warp direction" + }), + "factor": ("FLOAT", { + "default": 1.0, + "min": -100.0, + "max": 100.0, + "step": 0.1, + "tooltip": "Scale factor for warp_by_scalar" + }), + "scalar_field": ("STRING", { + "default": "", + "tooltip": "Vertex attribute name for warp_by_scalar" + }), + "angle": ("FLOAT", { + "default": 30.0, + "min": 0.0, + "max": 180.0, + "step": 1.0, + "tooltip": "Feature edge angle threshold (degrees)" + }), + }, + } + + RETURN_TYPES = ("TRIMESH",) + RETURN_NAMES = ("filtered_mesh",) + FUNCTION = "apply_filter" + CATEGORY = "geompack/paraview" + + def apply_filter(self, trimesh, filter_type, axis="Z", factor=1.0, scalar_field="", angle=30.0): + """ + Apply a VTK filter via PyVista. + + Args: + trimesh: Input trimesh.Trimesh object + filter_type: Which filter to apply + axis: Axis for elevation/warp + factor: Scale factor for warp + scalar_field: Vertex attribute name for warp_by_scalar + angle: Feature edge angle threshold + + Returns: + tuple: (filtered_mesh,) + """ + try: + import pyvista as pv + except (ImportError, OSError): + raise ImportError( + "ParaView Filter requires pyvista. Install with: pip install pyvista" + ) + + # Validate input + if not hasattr(trimesh, 'faces') or len(trimesh.faces) == 0: + raise ValueError("ParaView Filter requires a mesh with faces, not a point cloud") + + print(f"[ParaViewFilter] Applying '{filter_type}' to mesh: " + f"{len(trimesh.vertices)} vertices, {len(trimesh.faces)} faces") + + # Convert to pyvista + pv_mesh = _trimesh_to_pyvista(trimesh) + + # Apply filter + if filter_type == "curvature_gaussian": + pv_result = pv_mesh.curvature('gaussian') + # curvature() returns a new mesh with 'Gauss_Curvature' in point_data + result = _pyvista_to_trimesh(pv_result) + # Rename to friendlier name + if 'Gauss_Curvature' in result.vertex_attributes: + result.vertex_attributes['curvature'] = result.vertex_attributes.pop('Gauss_Curvature') + print(f"[ParaViewFilter] Computed Gaussian curvature") + + elif filter_type == "curvature_mean": + pv_result = pv_mesh.curvature('mean') + result = _pyvista_to_trimesh(pv_result) + if 'Mean_Curvature' in result.vertex_attributes: + result.vertex_attributes['curvature'] = result.vertex_attributes.pop('Mean_Curvature') + print(f"[ParaViewFilter] Computed mean curvature") + + elif filter_type == "cell_sizes": + pv_result = pv_mesh.compute_cell_sizes(length=False, volume=False, area=True) + result = _pyvista_to_trimesh(pv_result) + print(f"[ParaViewFilter] Computed cell sizes (face areas)") + + elif filter_type == "elevation": + axis_map = {"X": 0, "Y": 1, "Z": 2} + ax = axis_map.get(axis, 2) + bounds = pv_mesh.bounds + low_point = [0.0, 0.0, 0.0] + high_point = [0.0, 0.0, 0.0] + low_point[ax] = bounds[ax * 2] + high_point[ax] = bounds[ax * 2 + 1] + pv_result = pv_mesh.elevation( + low_point=low_point, + high_point=high_point, + set_active_scalars=True + ) + result = _pyvista_to_trimesh(pv_result) + print(f"[ParaViewFilter] Computed elevation along {axis} axis") + + elif filter_type == "feature_edges": + pv_result = pv_mesh.extract_feature_edges( + feature_angle=angle, + boundary_edges=True, + non_manifold_edges=True, + manifold_edges=False, + ) + if pv_result.n_points == 0: + print(f"[ParaViewFilter] Warning: No feature edges found at angle={angle}") + # Return original mesh with an empty marker attribute + result = trimesh.copy() + result.vertex_attributes['feature_edge'] = np.zeros(len(result.vertices), dtype=np.float32) + else: + result = _pyvista_to_trimesh(pv_result) + print(f"[ParaViewFilter] Extracted feature edges: {pv_result.n_points} points, {pv_result.n_lines} lines") + + elif filter_type == "warp_by_scalar": + if not scalar_field: + available = list(trimesh.vertex_attributes.keys()) if hasattr(trimesh, 'vertex_attributes') else [] + raise ValueError( + f"warp_by_scalar requires a scalar_field name. " + f"Available vertex attributes: {available}" + ) + if scalar_field not in pv_mesh.point_data: + available = list(pv_mesh.point_data.keys()) + raise ValueError( + f"scalar_field '{scalar_field}' not found. " + f"Available: {available}" + ) + pv_result = pv_mesh.warp_by_scalar( + scalars=scalar_field, + factor=factor, + ) + result = _pyvista_to_trimesh(pv_result) + print(f"[ParaViewFilter] Warped by '{scalar_field}' with factor={factor}") + + else: + raise ValueError(f"Unknown filter type: {filter_type}") + + print(f"[ParaViewFilter] Result: {len(result.vertices)} vertices, {len(result.faces)} faces") + + # List output fields + v_attrs = list(result.vertex_attributes.keys()) if hasattr(result, 'vertex_attributes') else [] + f_attrs = list(result.face_attributes.keys()) if hasattr(result, 'face_attributes') else [] + if v_attrs: + print(f"[ParaViewFilter] Vertex attributes: {v_attrs}") + if f_attrs: + print(f"[ParaViewFilter] Face attributes: {f_attrs}") + + return (result,) + + +NODE_CLASS_MAPPINGS = { + "GeomPackParaViewFilter": ParaViewFilterNode, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "GeomPackParaViewFilter": "ParaView Filter", +} diff --git a/nodes/main/reconstruction_cgal/alpha_wrap.py b/nodes/main/reconstruction_cgal/alpha_wrap.py index cab308cf..a3b67a8f 100644 --- a/nodes/main/reconstruction_cgal/alpha_wrap.py +++ b/nodes/main/reconstruction_cgal/alpha_wrap.py @@ -60,6 +60,7 @@ class AlphaWrapNode: RETURN_NAMES = ("wrapped_mesh", "report") FUNCTION = "alpha_wrap" CATEGORY = "geompack/reconstruction" + OUTPUT_NODE = True def alpha_wrap(self, input_mesh, alpha_percent=0.04, offset_percent=1.1): """ @@ -197,7 +198,7 @@ Tips: - Lower values = slower computation """ - return (result_mesh, report) + return {"ui": {"text": [report]}, "result": (result_mesh, report)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/visualization/preview_mesh_dual.py b/nodes/main/visualization/preview_mesh_dual.py index 51eb45dd..6dc5e2b0 100644 --- a/nodes/main/visualization/preview_mesh_dual.py +++ b/nodes/main/visualization/preview_mesh_dual.py @@ -82,6 +82,10 @@ class PreviewMeshDualNode: "mode": (["fields", "texture"], {"default": "fields"}), "opacity_1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.1}), "opacity_2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.1}), + "show_edges": ("BOOLEAN", { + "default": False, + "tooltip": "Show mesh edge overlay" + }), } } @@ -90,7 +94,7 @@ class PreviewMeshDualNode: FUNCTION = "preview_dual" CATEGORY = "geompack/visualization" - def preview_dual(self, mesh_1, mesh_2, layout="side_by_side", mode="fields", opacity_1=1.0, opacity_2=1.0): + def preview_dual(self, mesh_1, mesh_2, layout="side_by_side", mode="fields", opacity_1=1.0, opacity_2=1.0, show_edges=False): """ Preview two meshes with chosen layout and visualization mode. @@ -171,6 +175,7 @@ class PreviewMeshDualNode: "is_watertight_2": [bool(mesh_2.is_watertight) if not is_point_cloud(mesh_2) else False], "opacity_1": [float(opacity_1)], "opacity_2": [float(opacity_2)], + "show_edges": [bool(show_edges)], } # Add mode-specific metadata @@ -233,6 +238,7 @@ class PreviewMeshDualNode: "opacity_2": [float(opacity_2)], "is_watertight_1": [bool(mesh_1.is_watertight) if not is_point_cloud(mesh_1) else False], "is_watertight_2": [bool(mesh_2.is_watertight) if not is_point_cloud(mesh_2) else False], + "show_edges": [bool(show_edges)], } # Add mode-specific metadata diff --git a/nodes/main/visualization/preview_mesh_multi.py b/nodes/main/visualization/preview_mesh_multi.py index 93cca8f0..d493c1da 100644 --- a/nodes/main/visualization/preview_mesh_multi.py +++ b/nodes/main/visualization/preview_mesh_multi.py @@ -87,6 +87,10 @@ class PreviewMeshMultiNode: "mesh_3": ("TRIMESH",), "mesh_4": ("TRIMESH",), "mode": (["fields", "texture"], {"default": "fields"}), + "show_edges": ("BOOLEAN", { + "default": False, + "tooltip": "Show mesh edge overlay" + }), } } @@ -95,7 +99,7 @@ class PreviewMeshMultiNode: FUNCTION = "preview_multi" CATEGORY = "geompack/visualization" - def preview_multi(self, mesh_1, mesh_2=None, mesh_3=None, mesh_4=None, mode="fields"): + def preview_multi(self, mesh_1, mesh_2=None, mesh_3=None, mesh_4=None, mode="fields", show_edges=False): """ Preview multiple meshes in a grid layout. @@ -205,6 +209,7 @@ class PreviewMeshMultiNode: "bounds_list": [bounds_list], "extents_list": [extents_list], "is_watertight_list": [is_watertight_list], + "show_edges": [bool(show_edges)], } # Add mode-specific metadata diff --git a/nodes/main/visualization/preview_mesh_vtk.py b/nodes/main/visualization/preview_mesh_vtk.py index ceb92318..03254b73 100644 --- a/nodes/main/visualization/preview_mesh_vtk.py +++ b/nodes/main/visualization/preview_mesh_vtk.py @@ -43,6 +43,10 @@ class PreviewMeshVTKNode: "optional": { "trimesh": ("TRIMESH",), "voxelgrid": ("VOXELGRID",), + "show_edges": ("BOOLEAN", { + "default": False, + "tooltip": "Show mesh edge overlay" + }), }, } @@ -51,7 +55,7 @@ class PreviewMeshVTKNode: FUNCTION = "preview_mesh_vtk" CATEGORY = "geompack/visualization" - def preview_mesh_vtk(self, mode="fields", trimesh=None, voxelgrid=None): + def preview_mesh_vtk(self, mode="fields", trimesh=None, voxelgrid=None, show_edges=False): """ Export mesh and prepare for VTK.js preview. @@ -231,6 +235,7 @@ class PreviewMeshVTKNode: "extents": [extents.tolist()], "max_extent": [float(max_extent)], "is_watertight": [bool(is_watertight)], + "show_edges": [bool(show_edges)], } # Add mode-specific metadata diff --git a/nodes/main/visualization/preview_mesh_vtk_batch.py b/nodes/main/visualization/preview_mesh_vtk_batch.py index 50212b8b..c8bd3504 100644 --- a/nodes/main/visualization/preview_mesh_vtk_batch.py +++ b/nodes/main/visualization/preview_mesh_vtk_batch.py @@ -44,6 +44,12 @@ class PreviewMeshVTKBatchNode: "mode": (["fields", "texture"], {"default": "fields"}), "index": ("INT", {"default": 0, "min": 0, "max": 100}), }, + "optional": { + "show_edges": ("BOOLEAN", { + "default": False, + "tooltip": "Show mesh edge overlay" + }), + }, } RETURN_TYPES = () @@ -52,7 +58,7 @@ class PreviewMeshVTKBatchNode: CATEGORY = "geompack/visualization" INPUT_IS_LIST = True - def preview_mesh_vtk_batch(self, trimesh, mode, index): + def preview_mesh_vtk_batch(self, trimesh, mode, index, show_edges=None): """ Export mesh from batch and prepare for VTK.js preview. @@ -71,6 +77,7 @@ class PreviewMeshVTKBatchNode: # Extract values from lists (ComfyUI passes inputs as lists when INPUT_IS_LIST=True) mode_val = mode[0] if isinstance(mode, list) else mode index_val = index[0] if isinstance(index, list) else index + show_edges_val = (show_edges[0] if isinstance(show_edges, list) else show_edges) if show_edges is not None else False # Validate batch if not trimesh or len(trimesh) == 0: @@ -205,6 +212,7 @@ class PreviewMeshVTKBatchNode: # Batch-specific metadata "batch_size": [batch_size], "current_index": [actual_index], + "show_edges": [bool(show_edges_val)], } # Add mode-specific metadata diff --git a/requirements.txt b/requirements.txt index c1f10843..93bbe421 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.87 +comfy-env==0.1.88 comfy-dynamic-widgets==0.1.4 -comfy-3d-viewers==0.2.12 +comfy-3d-viewers==0.2.13 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 diff --git a/workflows/alpha_wrap.json b/workflows/alpha_wrap.json index 062c679f..01299373 100644 --- a/workflows/alpha_wrap.json +++ b/workflows/alpha_wrap.json @@ -1 +1 @@ -{"id":"11f9c0dd-d338-418a-8209-0993917893cb","revision":0,"last_node_id":10,"last_link_id":14,"nodes":[{"id":4,"type":"GeomPackLoadMesh","pos":[138.579513342687,105.38019450502425],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[3,4,10]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/ArmoredWarrior_00005_.glb"]},{"id":6,"type":"GeomPackPreviewMeshDual","pos":[1025.7466624163346,-188.32428251644288],"size":[768,834],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":4},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":5},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackPreviewMeshDual","cnr_id":"comfyui-geometrypack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":9,"type":"GeomPackPreviewMeshMulti","pos":[982.9677437943947,726.4156526443303],"size":[768,702],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":10},{"localized_name":"mesh_2","name":"mesh_2","shape":7,"type":"TRIMESH","link":11},{"localized_name":"mesh_3","name":"mesh_3","shape":7,"type":"TRIMESH","link":14},{"localized_name":"mesh_4","name":"mesh_4","shape":7,"type":"TRIMESH","link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackPreviewMeshMulti","cnr_id":"comfyui-geometrypack"},"widgets_values":["fields",""]},{"id":10,"type":"GeomPackRemesh","pos":[566.9199134902797,561.0072247359709],"size":[212.744140625,328],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":13},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[14]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"f9bba2bb5a0b42f6db8a70734e16acd25efcb485","Node name for S&R":"GeomPackRemesh"},"widgets_values":["pymeshlab_isotropic",1,3,30,"false",5000,"true",0,""]},{"id":5,"type":"GeomPackAlphaWrap","pos":[387.2845193072146,322.47657100070364],"size":[271.5845703125,102],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"input_mesh","name":"input_mesh","type":"TRIMESH","link":3},{"localized_name":"alpha_percent","name":"alpha_percent","shape":7,"type":"FLOAT","widget":{"name":"alpha_percent"},"link":null},{"localized_name":"offset_percent","name":"offset_percent","shape":7,"type":"FLOAT","widget":{"name":"offset_percent"},"link":null}],"outputs":[{"localized_name":"wrapped_mesh","name":"wrapped_mesh","type":"TRIMESH","links":[5,11,13]},{"localized_name":"report","name":"report","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackAlphaWrap","cnr_id":"comfyui-geometrypack"},"widgets_values":[1.1,0.02]}],"links":[[3,4,0,5,0,"TRIMESH"],[4,4,0,6,0,"TRIMESH"],[5,5,0,6,1,"TRIMESH"],[10,4,0,9,0,"TRIMESH"],[11,5,0,9,1,"TRIMESH"],[13,5,0,10,0,"TRIMESH"],[14,10,0,9,2,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7252961238884351,"offset":[306.0777454344964,210.06569283160206]},"workflowRendererVersion":"LG","frontendVersion":"1.35.9"},"version":0.4} \ No newline at end of file +{"id":"11f9c0dd-d338-418a-8209-0993917893cb","revision":0,"last_node_id":11,"last_link_id":16,"nodes":[{"id":4,"type":"GeomPackLoadMesh","pos":[138.579513342687,105.38019450502425],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[3,4,10]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/ArmoredWarrior_00005_.glb"]},{"id":6,"type":"GeomPackPreviewMeshDual","pos":[1025.7466624163346,-188.32428251644288],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":4},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":5},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,true,""]},{"id":9,"type":"GeomPackPreviewMeshMulti","pos":[982.9677437943947,726.4156526443303],"size":[768,702],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":10},{"localized_name":"mesh_2","name":"mesh_2","shape":7,"type":"TRIMESH","link":11},{"localized_name":"mesh_3","name":"mesh_3","shape":7,"type":"TRIMESH","link":16},{"localized_name":"mesh_4","name":"mesh_4","shape":7,"type":"TRIMESH","link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackPreviewMeshMulti","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["fields",true,""]},{"id":11,"type":"GeomPackRemesh","pos":[624.8620583384796,526.1960834441261],"size":[212.744140625,206],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":15},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"preserve_sharp","name":"preserve_sharp","shape":7,"type":"COMBO","widget":{"name":"preserve_sharp"},"link":null},{"localized_name":"preserve_boundary","name":"preserve_boundary","shape":7,"type":"COMBO","widget":{"name":"preserve_boundary"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[16]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"f4d5713f5feef867c82be5a2d67e532e7a95933b","Node name for S&R":"GeomPackRemesh"},"widgets_values":["pymeshlab_isotropic",1,3,30,"false",5000,"true",0,5000,"false","true",""]},{"id":5,"type":"GeomPackAlphaWrap","pos":[387.2845193072146,322.47657100070364],"size":[271.5845703125,102],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"input_mesh","name":"input_mesh","type":"TRIMESH","link":3},{"localized_name":"alpha_percent","name":"alpha_percent","shape":7,"type":"FLOAT","widget":{"name":"alpha_percent"},"link":null},{"localized_name":"offset_percent","name":"offset_percent","shape":7,"type":"FLOAT","widget":{"name":"offset_percent"},"link":null}],"outputs":[{"localized_name":"wrapped_mesh","name":"wrapped_mesh","type":"TRIMESH","links":[5,11,15]},{"localized_name":"report","name":"report","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"7380010c0f78151d54c66faf4cdd5cf51300156e","Node name for S&R":"GeomPackAlphaWrap","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[1.1,0.02]}],"links":[[3,4,0,5,0,"TRIMESH"],[4,4,0,6,0,"TRIMESH"],[5,5,0,6,1,"TRIMESH"],[10,4,0,9,0,"TRIMESH"],[11,5,0,9,1,"TRIMESH"],[15,5,0,11,0,"TRIMESH"],[16,11,0,9,2,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7252961238884351,"offset":[8.079849635392245,-76.08897994853922]},"workflowRendererVersion":"LG","frontendVersion":"1.35.9"},"version":0.4} \ No newline at end of file diff --git a/workflows/batch_remesh.json b/workflows/batch_remesh.json index 702ca1b4..b210f878 100644 --- a/workflows/batch_remesh.json +++ b/workflows/batch_remesh.json @@ -1 +1 @@ -{"id":"b2c3d4e5-6789-01ab-cdef-234567890bcd","revision":0,"last_node_id":10,"last_link_id":12,"nodes":[{"id":6,"type":"GeomPackPreviewMeshVTKBatch","pos":[270.4873325918748,58.03082610700009],"size":[648.2642445312499,772.8686878906249],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":12},{"localized_name":"mode","name":"mode","type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"index","name":"index","type":"INT","widget":{"name":"index"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"84b2d1816c08ec3cc7d3a4fffa90692669e17507","Node name for S&R":"GeomPackPreviewMeshVTKBatch","cnr_id":"comfyui-geometrypack"},"widgets_values":["fields",0,""]},{"id":4,"type":"GeomPackMeshInfo","pos":[85.91166423249982,-297.85304381487504],"size":[210,330],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":7}],"outputs":[{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"84b2d1816c08ec3cc7d3a4fffa90692669e17507","Node name for S&R":"GeomPackMeshInfo","cnr_id":"comfyui-geometrypack"},"widgets_values":[""]},{"id":1,"type":"GeomPackLoadMeshBatch","pos":[-635.45703125,14.94140625],"size":[320,150],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"folder_path","name":"folder_path","type":"STRING","widget":{"name":"folder_path"},"link":null},{"localized_name":"start_index","name":"start_index","type":"INT","widget":{"name":"start_index"},"link":null},{"localized_name":"max_meshes","name":"max_meshes","type":"INT","widget":{"name":"max_meshes"},"link":null}],"outputs":[{"localized_name":"meshes","name":"meshes","shape":6,"type":"TRIMESH","slot_index":0,"links":[7,11]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"0.1.1","Node name for S&R":"GeomPackLoadMeshBatch","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d",0,4]},{"id":10,"type":"GeomPackRemesh","pos":[-133.629473658125,61.91437181012475],"size":[212.744140625,328],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":11},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[12]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"f9bba2bb5a0b42f6db8a70734e16acd25efcb485","Node name for S&R":"GeomPackRemesh"},"widgets_values":["pymeshlab_isotropic",1,3,30,"false",5000,"true",0,""]}],"links":[[7,1,0,4,0,"TRIMESH"],[11,1,0,10,0,"TRIMESH"],[12,10,0,6,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1,"offset":[871.129473658125,345.08562818987525]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"b2c3d4e5-6789-01ab-cdef-234567890bcd","revision":0,"last_node_id":11,"last_link_id":15,"nodes":[{"id":4,"type":"GeomPackMeshInfo","pos":[85.91166423249982,-297.85304381487504],"size":[210,66],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":7}],"outputs":[{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"84b2d1816c08ec3cc7d3a4fffa90692669e17507","Node name for S&R":"GeomPackMeshInfo","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[""]},{"id":1,"type":"GeomPackLoadMeshBatch","pos":[-635.45703125,14.94140625],"size":[320,150],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"folder_path","name":"folder_path","type":"STRING","widget":{"name":"folder_path"},"link":null},{"localized_name":"start_index","name":"start_index","type":"INT","widget":{"name":"start_index"},"link":null},{"localized_name":"max_meshes","name":"max_meshes","type":"INT","widget":{"name":"max_meshes"},"link":null}],"outputs":[{"localized_name":"meshes","name":"meshes","shape":6,"type":"TRIMESH","slot_index":0,"links":[7,14]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"0.1.1","Node name for S&R":"GeomPackLoadMeshBatch","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d",0,4]},{"id":11,"type":"GeomPackRemesh","pos":[-144.22632486551126,161.44117614251124],"size":[212.744140625,206],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":14},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"preserve_sharp","name":"preserve_sharp","shape":7,"type":"COMBO","widget":{"name":"preserve_sharp"},"link":null},{"localized_name":"preserve_boundary","name":"preserve_boundary","shape":7,"type":"COMBO","widget":{"name":"preserve_boundary"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[15]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"f4d5713f5feef867c82be5a2d67e532e7a95933b","Node name for S&R":"GeomPackRemesh"},"widgets_values":["pymeshlab_isotropic",1,3,30,"false",5000,"true",0,5000,"false","true",""]},{"id":6,"type":"GeomPackPreviewMeshVTKBatch","pos":[198.34297321687484,-3.9126660804999145],"size":[648.2642445312499,772.8686878906249],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":15},{"localized_name":"mode","name":"mode","type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"index","name":"index","type":"INT","widget":{"name":"index"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"84b2d1816c08ec3cc7d3a4fffa90692669e17507","Node name for S&R":"GeomPackPreviewMeshVTKBatch","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["fields",0,""]}],"links":[[7,1,0,4,0,"TRIMESH"],[14,1,0,11,0,"TRIMESH"],[15,11,0,6,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7513148009015777,"offset":[515.1385904905114,382.1839371387389]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/mesh_mesh_distance.json b/workflows/mesh_mesh_distance.json index bc745ed0..4383276b 100644 --- a/workflows/mesh_mesh_distance.json +++ b/workflows/mesh_mesh_distance.json @@ -1 +1 @@ -{"id":"fb7bc5d6-aeb1-47ae-8e7c-69dec20b3cf2","revision":0,"last_node_id":14,"last_link_id":24,"nodes":[{"id":10,"type":"GeomPackMeshToMeshDistance","pos":[11.064371177688024,155.3109793550008],"size":[270,280],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"mesh_a","name":"mesh_a","type":"TRIMESH","link":12},{"localized_name":"mesh_b","name":"mesh_b","type":"TRIMESH","link":19},{"localized_name":"metric","name":"metric","type":"COMBO","widget":{"name":"metric"},"link":null},{"localized_name":"sample_count","name":"sample_count","shape":7,"type":"INT","widget":{"name":"sample_count"},"link":null},{"localized_name":"symmetric","name":"symmetric","shape":7,"type":"COMBO","widget":{"name":"symmetric"},"link":null}],"outputs":[{"localized_name":"distance","name":"distance","type":"FLOAT","links":[14]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"d616ab2f28493cf34f723ed59ea6747b61519c9d","Node name for S&R":"GeomPackMeshToMeshDistance","cnr_id":"comfyui-geometrypack"},"widgets_values":["hausdorff",10000,"true",""]},{"id":14,"type":"GeomPackRemeshCGAL","pos":[-344.26756151506873,228.9368912228689],"size":[274.009765625,126],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":18},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"protect_boundaries","name":"protect_boundaries","shape":7,"type":"COMBO","widget":{"name":"protect_boundaries"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[19]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"c5dfab62adf5e57a1800306b9c6d495f4dd52a43","Node name for S&R":"GeomPackRemeshCGAL"},"widgets_values":[1,3,"true"]},{"id":13,"type":"GeomPackRemesh","pos":[-276.181627952864,-290.84108938615606],"size":[212.744140625,328],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":21},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[23]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"c5dfab62adf5e57a1800306b9c6d495f4dd52a43","Node name for S&R":"GeomPackRemesh"},"widgets_values":["pymeshlab_isotropic",1,3,30,"false",5000,"true",0,""]},{"id":8,"type":"GeomPackLoadMesh","pos":[-704.5277550652091,-38.71235822893516],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[12,18,21,24]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"0d095605f8096b505a60407e6d471d9a963d92b8","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":3,"type":"GeomPackMeshToMeshDistance","pos":[73.75313558309,-211.58121546565187],"size":[270,280],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_a","name":"mesh_a","type":"TRIMESH","link":24},{"localized_name":"mesh_b","name":"mesh_b","type":"TRIMESH","link":23},{"localized_name":"metric","name":"metric","type":"COMBO","widget":{"name":"metric"},"link":null},{"localized_name":"sample_count","name":"sample_count","shape":7,"type":"INT","widget":{"name":"sample_count"},"link":null},{"localized_name":"symmetric","name":"symmetric","shape":7,"type":"COMBO","widget":{"name":"symmetric"},"link":null}],"outputs":[{"localized_name":"distance","name":"distance","type":"FLOAT","links":[5]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"d616ab2f28493cf34f723ed59ea6747b61519c9d","Node name for S&R":"GeomPackMeshToMeshDistance","cnr_id":"comfyui-geometrypack"},"widgets_values":["hausdorff",10000,"true",""]}],"links":[[12,8,0,10,0,"TRIMESH"],[18,8,0,14,0,"TRIMESH"],[19,14,0,10,1,"TRIMESH"],[21,8,0,13,0,"TRIMESH"],[23,13,0,3,1,"TRIMESH"],[24,8,0,3,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.9032702759933883,"offset":[1286.9532920551853,519.4548337860787]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fb7bc5d6-aeb1-47ae-8e7c-69dec20b3cf2","revision":0,"last_node_id":15,"last_link_id":27,"nodes":[{"id":10,"type":"GeomPackMeshToMeshDistance","pos":[11.064371177688024,155.3109793550008],"size":[270,158],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"mesh_a","name":"mesh_a","type":"TRIMESH","link":12},{"localized_name":"mesh_b","name":"mesh_b","type":"TRIMESH","link":19},{"localized_name":"metric","name":"metric","type":"COMBO","widget":{"name":"metric"},"link":null},{"localized_name":"sample_count","name":"sample_count","shape":7,"type":"INT","widget":{"name":"sample_count"},"link":null},{"localized_name":"symmetric","name":"symmetric","shape":7,"type":"COMBO","widget":{"name":"symmetric"},"link":null}],"outputs":[{"localized_name":"distance","name":"distance","type":"FLOAT","links":[14]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"d616ab2f28493cf34f723ed59ea6747b61519c9d","Node name for S&R":"GeomPackMeshToMeshDistance","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["hausdorff",10000,"true",""]},{"id":14,"type":"GeomPackRemeshCGAL","pos":[-344.26756151506873,228.9368912228689],"size":[274.009765625,158],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":18},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"protect_boundaries","name":"protect_boundaries","shape":7,"type":"COMBO","widget":{"name":"protect_boundaries"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[19]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"c5dfab62adf5e57a1800306b9c6d495f4dd52a43","Node name for S&R":"GeomPackRemeshCGAL","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[1,3,"true",""]},{"id":3,"type":"GeomPackMeshToMeshDistance","pos":[73.75313558309,-211.58121546565187],"size":[270,158],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_a","name":"mesh_a","type":"TRIMESH","link":24},{"localized_name":"mesh_b","name":"mesh_b","type":"TRIMESH","link":27},{"localized_name":"metric","name":"metric","type":"COMBO","widget":{"name":"metric"},"link":null},{"localized_name":"sample_count","name":"sample_count","shape":7,"type":"INT","widget":{"name":"sample_count"},"link":null},{"localized_name":"symmetric","name":"symmetric","shape":7,"type":"COMBO","widget":{"name":"symmetric"},"link":null}],"outputs":[{"localized_name":"distance","name":"distance","type":"FLOAT","links":[5]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"d616ab2f28493cf34f723ed59ea6747b61519c9d","Node name for S&R":"GeomPackMeshToMeshDistance","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["hausdorff",10000,"true",""]},{"id":8,"type":"GeomPackLoadMesh","pos":[-704.5277550652091,-38.71235822893516],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[12,18,24,26]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"0d095605f8096b505a60407e6d471d9a963d92b8","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":15,"type":"GeomPackRemesh","pos":[-240.24450219689868,-262.4330293270784],"size":[212.744140625,206],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":26},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"preserve_sharp","name":"preserve_sharp","shape":7,"type":"COMBO","widget":{"name":"preserve_sharp"},"link":null},{"localized_name":"preserve_boundary","name":"preserve_boundary","shape":7,"type":"COMBO","widget":{"name":"preserve_boundary"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[27]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"f4d5713f5feef867c82be5a2d67e532e7a95933b","Node name for S&R":"GeomPackRemesh"},"widgets_values":["pymeshlab_isotropic",1,3,30,"false",5000,"true",0,5000,"false","true",""]}],"links":[[12,8,0,10,0,"TRIMESH"],[18,8,0,14,0,"TRIMESH"],[19,14,0,10,1,"TRIMESH"],[24,8,0,3,0,"TRIMESH"],[26,8,0,15,0,"TRIMESH"],[27,15,0,3,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.9032702759933883,"offset":[1022.8132554669046,472.4079034492379]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/remeshing.json b/workflows/remeshing.json index 0ecba2a8..d3d752c5 100644 --- a/workflows/remeshing.json +++ b/workflows/remeshing.json @@ -1 +1 @@ -{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":26,"last_link_id":32,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-344.64489975927364,265.1754548878005],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":29},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":32},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-502.81561847832234,-58.160239777583065],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[29,31]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":26,"type":"GeomPackRemesh","pos":[-636.4250560092735,188.81972832530045],"size":[214.34375,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":31},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"preserve_sharp","name":"preserve_sharp","shape":7,"type":"COMBO","widget":{"name":"preserve_sharp"},"link":null},{"localized_name":"preserve_boundary","name":"preserve_boundary","shape":7,"type":"COMBO","widget":{"name":"preserve_boundary"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[32]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"a57da232130b20d93f36248ed810254035c6226c","Node name for S&R":"GeomPackRemesh"},"widgets_values":["quadriflow",1,3,30,"false",5000,"true",0,5000,"false","true",""]}],"links":[[29,1,0,25,0,"TRIMESH"],[31,1,0,26,0,"TRIMESH"],[32,26,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.751314800901578,"offset":[1235.739001321773,318.7695997996994]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":27,"last_link_id":35,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-344.64489975927364,265.1754548878005],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":29},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":35},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,true,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-502.81561847832234,-58.160239777583065],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[29,34]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":27,"type":"GeomPackRemesh","pos":[-674.8316849155233,165.8287830128005],"size":[214.34375,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":34},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"feature_angle","name":"feature_angle","shape":7,"type":"FLOAT","widget":{"name":"feature_angle"},"link":null},{"localized_name":"adaptive","name":"adaptive","shape":7,"type":"COMBO","widget":{"name":"adaptive"},"link":null},{"localized_name":"target_vertex_count","name":"target_vertex_count","shape":7,"type":"INT","widget":{"name":"target_vertex_count"},"link":null},{"localized_name":"deterministic","name":"deterministic","shape":7,"type":"COMBO","widget":{"name":"deterministic"},"link":null},{"localized_name":"crease_angle","name":"crease_angle","shape":7,"type":"FLOAT","widget":{"name":"crease_angle"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"preserve_sharp","name":"preserve_sharp","shape":7,"type":"COMBO","widget":{"name":"preserve_sharp"},"link":null},{"localized_name":"preserve_boundary","name":"preserve_boundary","shape":7,"type":"COMBO","widget":{"name":"preserve_boundary"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[35]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"f4d5713f5feef867c82be5a2d67e532e7a95933b","Node name for S&R":"GeomPackRemesh"},"widgets_values":["quadriflow",1,3,30,"false",5000,"true",0,5000,"false","true",""]}],"links":[[29,1,0,25,0,"TRIMESH"],[34,1,0,27,0,"TRIMESH"],[35,27,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.751314800901578,"offset":[1042.894778665523,-10.642501762800515]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file From 6534f3e2bed88046a01fa9ec59d8bc4f10c39c7d Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:34:40 +0100 Subject: [PATCH 20/27] correct ascii --- nodes/main/paraview/pv_filter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nodes/main/paraview/pv_filter.py b/nodes/main/paraview/pv_filter.py index 1ef9968c..417481bd 100644 --- a/nodes/main/paraview/pv_filter.py +++ b/nodes/main/paraview/pv_filter.py @@ -21,14 +21,14 @@ def _trimesh_to_pyvista(mesh): faces_pv = np.column_stack([np.full(len(faces), 3), faces]) pv_mesh = pv.PolyData(vertices, faces_pv) - # Transfer vertex_attributes → point_data + # Transfer vertex_attributes -> point_data if hasattr(mesh, 'vertex_attributes'): for name, data in mesh.vertex_attributes.items(): arr = np.array(data) if arr.ndim == 1 and len(arr) == len(vertices): pv_mesh.point_data[name] = arr.astype(np.float32) - # Transfer face_attributes → cell_data + # Transfer face_attributes -> cell_data if hasattr(mesh, 'face_attributes'): for name, data in mesh.face_attributes.items(): arr = np.array(data) @@ -64,13 +64,13 @@ def _pyvista_to_trimesh(pv_mesh): result = trimesh.Trimesh(vertices=vertices, faces=faces, process=False) - # Transfer point_data → vertex_attributes + # Transfer point_data -> vertex_attributes for name in pv_mesh.point_data.keys(): data = np.array(pv_mesh.point_data[name]) if data.ndim == 1 and len(data) == len(vertices): result.vertex_attributes[name] = data.astype(np.float32) - # Transfer cell_data → face_attributes + # Transfer cell_data -> face_attributes for name in pv_mesh.cell_data.keys(): data = np.array(pv_mesh.cell_data[name]) if data.ndim == 1 and len(data) == len(faces): From 93304b6a94b431ad5c9d7d3228486d229d22e1ac Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:35:40 +0100 Subject: [PATCH 21/27] use 89, info uniform javascript --- nodes/main/analysis/connected_components.py | 2 +- nodes/main/analysis/degenerate_faces.py | 2 +- nodes/main/analysis/mesh_quality.py | 2 +- nodes/main/analysis/open_edges.py | 2 +- nodes/main/combine/split_by_field.py | 2 +- nodes/main/reconstruction_cgal/alpha_wrap.py | 2 +- nodes/main/repair/check_normals.py | 2 +- nodes/main/repair/fix_intersections_removal.py | 2 +- nodes/main/repair/meshfix.py | 2 +- nodes/main/repair_cgal/detect_intersections.py | 2 +- nodes/main/repair_cgal/fix_intersections_perturbation.py | 2 +- nodes/main/repair_cgal/remesh_intersections.py | 2 +- nodes/main/visualization/preview_mesh_multi.py | 7 ++++++- nodes/main/visualization/preview_mesh_vtk.py | 7 ++++++- requirements.txt | 2 +- 15 files changed, 25 insertions(+), 15 deletions(-) diff --git a/nodes/main/analysis/connected_components.py b/nodes/main/analysis/connected_components.py index 468ef0e6..9023a17c 100644 --- a/nodes/main/analysis/connected_components.py +++ b/nodes/main/analysis/connected_components.py @@ -36,7 +36,7 @@ class ConnectedComponentsNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("trimesh", "component_summary") + RETURN_NAMES = ("trimesh", "info") OUTPUT_IS_LIST = (True, False) # TRIMESH is list, STRING is single summary OUTPUT_NODE = True # Enable UI output for dynamic display FUNCTION = "label_components" diff --git a/nodes/main/analysis/degenerate_faces.py b/nodes/main/analysis/degenerate_faces.py index 2cb30819..30a47d40 100644 --- a/nodes/main/analysis/degenerate_faces.py +++ b/nodes/main/analysis/degenerate_faces.py @@ -37,7 +37,7 @@ class DegenerateFacesNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("trimesh", "degenerate_summary") + RETURN_NAMES = ("trimesh", "info") OUTPUT_IS_LIST = (True, False) OUTPUT_NODE = True FUNCTION = "find_degenerate_faces" diff --git a/nodes/main/analysis/mesh_quality.py b/nodes/main/analysis/mesh_quality.py index fdbf9148..c0d690ac 100644 --- a/nodes/main/analysis/mesh_quality.py +++ b/nodes/main/analysis/mesh_quality.py @@ -35,7 +35,7 @@ class MeshQualityNode: } RETURN_TYPES = ("FLOAT", "FLOAT", "STRING") - RETURN_NAMES = ("min_quality", "mean_quality", "report") + RETURN_NAMES = ("min_quality", "mean_quality", "info") OUTPUT_NODE = True FUNCTION = "analyze_quality" CATEGORY = "geompack/analysis" diff --git a/nodes/main/analysis/open_edges.py b/nodes/main/analysis/open_edges.py index d3007868..c7c74ce1 100644 --- a/nodes/main/analysis/open_edges.py +++ b/nodes/main/analysis/open_edges.py @@ -35,7 +35,7 @@ class OpenEdgesNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("trimesh", "open_edges_summary") + RETURN_NAMES = ("trimesh", "info") OUTPUT_IS_LIST = (True, False) # TRIMESH is list, STRING is single summary OUTPUT_NODE = True # Enable UI output for dynamic display FUNCTION = "find_open_edges" diff --git a/nodes/main/combine/split_by_field.py b/nodes/main/combine/split_by_field.py index 1c822f75..5372c6c5 100644 --- a/nodes/main/combine/split_by_field.py +++ b/nodes/main/combine/split_by_field.py @@ -34,7 +34,7 @@ class SplitByFieldNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("geometries", "summary") + RETURN_NAMES = ("geometries", "info") OUTPUT_IS_LIST = (True, False) FUNCTION = "split" CATEGORY = "geompack/combine" diff --git a/nodes/main/reconstruction_cgal/alpha_wrap.py b/nodes/main/reconstruction_cgal/alpha_wrap.py index a3b67a8f..5747263d 100644 --- a/nodes/main/reconstruction_cgal/alpha_wrap.py +++ b/nodes/main/reconstruction_cgal/alpha_wrap.py @@ -57,7 +57,7 @@ class AlphaWrapNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("wrapped_mesh", "report") + RETURN_NAMES = ("wrapped_mesh", "info") FUNCTION = "alpha_wrap" CATEGORY = "geompack/reconstruction" OUTPUT_NODE = True diff --git a/nodes/main/repair/check_normals.py b/nodes/main/repair/check_normals.py index 5f6b7dc3..d6d7880d 100644 --- a/nodes/main/repair/check_normals.py +++ b/nodes/main/repair/check_normals.py @@ -26,7 +26,7 @@ class CheckNormalsNode: } RETURN_TYPES = ("STRING",) - RETURN_NAMES = ("report",) + RETURN_NAMES = ("info",) FUNCTION = "check_normals" CATEGORY = "geompack/repair" diff --git a/nodes/main/repair/fix_intersections_removal.py b/nodes/main/repair/fix_intersections_removal.py index 194e3d9f..f5f74d70 100644 --- a/nodes/main/repair/fix_intersections_removal.py +++ b/nodes/main/repair/fix_intersections_removal.py @@ -33,7 +33,7 @@ class FixSelfIntersectionsByRemovalNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("fixed_mesh", "report") + RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "fix_by_removal" CATEGORY = "geompack/repair" diff --git a/nodes/main/repair/meshfix.py b/nodes/main/repair/meshfix.py index 98953c97..e33c4a6e 100644 --- a/nodes/main/repair/meshfix.py +++ b/nodes/main/repair/meshfix.py @@ -77,7 +77,7 @@ class MeshFixNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("repaired_mesh", "report") + RETURN_NAMES = ("repaired_mesh", "info") FUNCTION = "repair_mesh" CATEGORY = "geompack/repair" OUTPUT_NODE = True diff --git a/nodes/main/repair_cgal/detect_intersections.py b/nodes/main/repair_cgal/detect_intersections.py index 2dda5a53..848d90be 100644 --- a/nodes/main/repair_cgal/detect_intersections.py +++ b/nodes/main/repair_cgal/detect_intersections.py @@ -29,7 +29,7 @@ class DetectSelfIntersectionsNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("mesh_with_field", "report") + RETURN_NAMES = ("mesh_with_field", "info") OUTPUT_NODE = True # Enable UI output for dynamic display FUNCTION = "detect_intersections" CATEGORY = "geompack/repair" diff --git a/nodes/main/repair_cgal/fix_intersections_perturbation.py b/nodes/main/repair_cgal/fix_intersections_perturbation.py index 719bf9df..544db31c 100644 --- a/nodes/main/repair_cgal/fix_intersections_perturbation.py +++ b/nodes/main/repair_cgal/fix_intersections_perturbation.py @@ -34,7 +34,7 @@ class FixSelfIntersectionsByPerturbationNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("fixed_mesh", "report") + RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "fix_by_perturbation" CATEGORY = "geompack/repair" diff --git a/nodes/main/repair_cgal/remesh_intersections.py b/nodes/main/repair_cgal/remesh_intersections.py index e5ffef1f..0641f109 100644 --- a/nodes/main/repair_cgal/remesh_intersections.py +++ b/nodes/main/repair_cgal/remesh_intersections.py @@ -32,7 +32,7 @@ class RemeshSelfIntersectionsNode: } RETURN_TYPES = ("TRIMESH", "STRING") - RETURN_NAMES = ("fixed_mesh", "report") + RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "remesh_intersections" CATEGORY = "geompack/repair" diff --git a/nodes/main/visualization/preview_mesh_multi.py b/nodes/main/visualization/preview_mesh_multi.py index d493c1da..3e32475b 100644 --- a/nodes/main/visualization/preview_mesh_multi.py +++ b/nodes/main/visualization/preview_mesh_multi.py @@ -91,6 +91,10 @@ class PreviewMeshMultiNode: "default": False, "tooltip": "Show mesh edge overlay" }), + "camera_state": ("STRING", { + "default": "", + "tooltip": "Camera position/orientation state (managed by viewer)" + }), } } @@ -99,7 +103,7 @@ class PreviewMeshMultiNode: FUNCTION = "preview_multi" CATEGORY = "geompack/visualization" - def preview_multi(self, mesh_1, mesh_2=None, mesh_3=None, mesh_4=None, mode="fields", show_edges=False): + def preview_multi(self, mesh_1, mesh_2=None, mesh_3=None, mesh_4=None, mode="fields", show_edges=False, camera_state=""): """ Preview multiple meshes in a grid layout. @@ -210,6 +214,7 @@ class PreviewMeshMultiNode: "extents_list": [extents_list], "is_watertight_list": [is_watertight_list], "show_edges": [bool(show_edges)], + "camera_state": [camera_state], } # Add mode-specific metadata diff --git a/nodes/main/visualization/preview_mesh_vtk.py b/nodes/main/visualization/preview_mesh_vtk.py index 03254b73..0fa60c54 100644 --- a/nodes/main/visualization/preview_mesh_vtk.py +++ b/nodes/main/visualization/preview_mesh_vtk.py @@ -47,6 +47,10 @@ class PreviewMeshVTKNode: "default": False, "tooltip": "Show mesh edge overlay" }), + "camera_state": ("STRING", { + "default": "", + "tooltip": "Camera position/orientation state (managed by viewer)" + }), }, } @@ -55,7 +59,7 @@ class PreviewMeshVTKNode: FUNCTION = "preview_mesh_vtk" CATEGORY = "geompack/visualization" - def preview_mesh_vtk(self, mode="fields", trimesh=None, voxelgrid=None, show_edges=False): + def preview_mesh_vtk(self, mode="fields", trimesh=None, voxelgrid=None, show_edges=False, camera_state=""): """ Export mesh and prepare for VTK.js preview. @@ -236,6 +240,7 @@ class PreviewMeshVTKNode: "max_extent": [float(max_extent)], "is_watertight": [bool(is_watertight)], "show_edges": [bool(show_edges)], + "camera_state": [camera_state], } # Add mode-specific metadata diff --git a/requirements.txt b/requirements.txt index 93bbe421..7d2a7e4d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.88 +comfy-env==0.1.89 comfy-dynamic-widgets==0.1.4 comfy-3d-viewers==0.2.13 numpy From ff6982f9e98c4a85f7d5702ede962ccf771cf3ab Mon Sep 17 00:00:00 2001 From: PozzettiAndrea Date: Fri, 13 Feb 2026 01:36:40 +0100 Subject: [PATCH 22/27] updated viewers reqs --- nodes/main/visualization/preview_mesh_dual.py | 14 +++++++++++++- nodes/main/visualization/preview_mesh_multi.py | 7 ++++++- nodes/main/visualization/preview_mesh_vtk.py | 7 ++++++- requirements.txt | 4 ++-- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/nodes/main/visualization/preview_mesh_dual.py b/nodes/main/visualization/preview_mesh_dual.py index 6dc5e2b0..f751722b 100644 --- a/nodes/main/visualization/preview_mesh_dual.py +++ b/nodes/main/visualization/preview_mesh_dual.py @@ -86,6 +86,14 @@ class PreviewMeshDualNode: "default": False, "tooltip": "Show mesh edge overlay" }), + "camera_state": ("STRING", { + "default": "", + "tooltip": "Camera position/orientation state (managed by viewer)" + }), + "selected_field": ("STRING", { + "default": "", + "tooltip": "Active scalar field for visualization (managed by viewer)" + }), } } @@ -94,7 +102,7 @@ class PreviewMeshDualNode: FUNCTION = "preview_dual" CATEGORY = "geompack/visualization" - def preview_dual(self, mesh_1, mesh_2, layout="side_by_side", mode="fields", opacity_1=1.0, opacity_2=1.0, show_edges=False): + def preview_dual(self, mesh_1, mesh_2, layout="side_by_side", mode="fields", opacity_1=1.0, opacity_2=1.0, show_edges=False, camera_state="", selected_field=""): """ Preview two meshes with chosen layout and visualization mode. @@ -176,6 +184,8 @@ class PreviewMeshDualNode: "opacity_1": [float(opacity_1)], "opacity_2": [float(opacity_2)], "show_edges": [bool(show_edges)], + "camera_state": [camera_state], + "selected_field": [selected_field], } # Add mode-specific metadata @@ -239,6 +249,8 @@ class PreviewMeshDualNode: "is_watertight_1": [bool(mesh_1.is_watertight) if not is_point_cloud(mesh_1) else False], "is_watertight_2": [bool(mesh_2.is_watertight) if not is_point_cloud(mesh_2) else False], "show_edges": [bool(show_edges)], + "camera_state": [camera_state], + "selected_field": [selected_field], } # Add mode-specific metadata diff --git a/nodes/main/visualization/preview_mesh_multi.py b/nodes/main/visualization/preview_mesh_multi.py index 3e32475b..fd93868d 100644 --- a/nodes/main/visualization/preview_mesh_multi.py +++ b/nodes/main/visualization/preview_mesh_multi.py @@ -95,6 +95,10 @@ class PreviewMeshMultiNode: "default": "", "tooltip": "Camera position/orientation state (managed by viewer)" }), + "selected_field": ("STRING", { + "default": "", + "tooltip": "Active scalar field for visualization (managed by viewer)" + }), } } @@ -103,7 +107,7 @@ class PreviewMeshMultiNode: FUNCTION = "preview_multi" CATEGORY = "geompack/visualization" - def preview_multi(self, mesh_1, mesh_2=None, mesh_3=None, mesh_4=None, mode="fields", show_edges=False, camera_state=""): + def preview_multi(self, mesh_1, mesh_2=None, mesh_3=None, mesh_4=None, mode="fields", show_edges=False, camera_state="", selected_field=""): """ Preview multiple meshes in a grid layout. @@ -215,6 +219,7 @@ class PreviewMeshMultiNode: "is_watertight_list": [is_watertight_list], "show_edges": [bool(show_edges)], "camera_state": [camera_state], + "selected_field": [selected_field], } # Add mode-specific metadata diff --git a/nodes/main/visualization/preview_mesh_vtk.py b/nodes/main/visualization/preview_mesh_vtk.py index 0fa60c54..86b33d6f 100644 --- a/nodes/main/visualization/preview_mesh_vtk.py +++ b/nodes/main/visualization/preview_mesh_vtk.py @@ -51,6 +51,10 @@ class PreviewMeshVTKNode: "default": "", "tooltip": "Camera position/orientation state (managed by viewer)" }), + "selected_field": ("STRING", { + "default": "", + "tooltip": "Active scalar field for visualization (managed by viewer)" + }), }, } @@ -59,7 +63,7 @@ class PreviewMeshVTKNode: FUNCTION = "preview_mesh_vtk" CATEGORY = "geompack/visualization" - def preview_mesh_vtk(self, mode="fields", trimesh=None, voxelgrid=None, show_edges=False, camera_state=""): + def preview_mesh_vtk(self, mode="fields", trimesh=None, voxelgrid=None, show_edges=False, camera_state="", selected_field=""): """ Export mesh and prepare for VTK.js preview. @@ -241,6 +245,7 @@ class PreviewMeshVTKNode: "is_watertight": [bool(is_watertight)], "show_edges": [bool(show_edges)], "camera_state": [camera_state], + "selected_field": [selected_field], } # Add mode-specific metadata diff --git a/requirements.txt b/requirements.txt index 7d2a7e4d..ee7f557a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) -comfy-env==0.1.89 +comfy-env==0.1.90 comfy-dynamic-widgets==0.1.4 -comfy-3d-viewers==0.2.13 +comfy-3d-viewers==0.2.14 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 From c6c709a23520f29ea66a194a7670be6820535bae Mon Sep 17 00:00:00 2001 From: Andrea Pozzetti Date: Fri, 13 Feb 2026 01:37:40 +0100 Subject: [PATCH 23/27] update some workflows --- requirements.txt | 2 +- workflows/fix_self_intersection.json | 387 +-------------------------- workflows/remeshing_CGAL.json | 2 +- workflows/remeshing_blender.json | 2 +- 4 files changed, 4 insertions(+), 389 deletions(-) diff --git a/requirements.txt b/requirements.txt index ee7f557a..509e57f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) comfy-env==0.1.90 comfy-dynamic-widgets==0.1.4 -comfy-3d-viewers==0.2.14 +comfy-3d-viewers==0.2.15 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 diff --git a/workflows/fix_self_intersection.json b/workflows/fix_self_intersection.json index e95f687e..c8b03b2d 100644 --- a/workflows/fix_self_intersection.json +++ b/workflows/fix_self_intersection.json @@ -1,386 +1 @@ -{ - "id": "94c1c61e-cf5c-42a8-b9ec-914bb4f038ea", - "revision": 0, - "last_node_id": 21, - "last_link_id": 33, - "nodes": [ - { - "id": 13, - "type": "GeomPackDetectSelfIntersections", - "pos": [ - -379.63813553555593, - 423.2928747712214 - ], - "size": [ - 210, - 178 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "localized_name": "trimesh", - "name": "trimesh", - "type": "TRIMESH", - "link": 25 - } - ], - "outputs": [ - { - "localized_name": "mesh_with_field", - "name": "mesh_with_field", - "type": "TRIMESH", - "links": [ - 33 - ] - }, - { - "localized_name": "report", - "name": "report", - "type": "STRING", - "links": [] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "c77434120c2984b0ad1dd308c733117a855a8a36", - "Node name for S&R": "GeomPackDetectSelfIntersections" - } - }, - { - "id": 21, - "type": "GeomPackPreviewMeshDual", - "pos": [ - 119.77009920706648, - -137.1509407158773 - ], - "size": [ - 768, - 834 - ], - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [ - { - "localized_name": "mesh_1", - "name": "mesh_1", - "type": "TRIMESH", - "link": 32 - }, - { - "localized_name": "mesh_2", - "name": "mesh_2", - "type": "TRIMESH", - "link": 33 - }, - { - "localized_name": "layout", - "name": "layout", - "shape": 7, - "type": "COMBO", - "widget": { - "name": "layout" - }, - "link": null - }, - { - "localized_name": "mode", - "name": "mode", - "shape": 7, - "type": "COMBO", - "widget": { - "name": "mode" - }, - "link": null - }, - { - "localized_name": "opacity_1", - "name": "opacity_1", - "shape": 7, - "type": "FLOAT", - "widget": { - "name": "opacity_1" - }, - "link": null - }, - { - "localized_name": "opacity_2", - "name": "opacity_2", - "shape": 7, - "type": "FLOAT", - "widget": { - "name": "opacity_2" - }, - "link": null - } - ], - "outputs": [], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "1fcec6e19dca5e04ec71d204dbe8ef1828885062", - "Node name for S&R": "GeomPackPreviewMeshDual" - }, - "widgets_values": [ - "side_by_side", - "fields", - 1, - 1, - "" - ] - }, - { - "id": 17, - "type": "GeomPackFixSelfIntersectionsByPerturbation", - "pos": [ - -248.37356706315592, - 30.294778781901346 - ], - "size": [ - 319.319921875, - 174 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "localized_name": "trimesh", - "name": "trimesh", - "type": "TRIMESH", - "link": 23 - }, - { - "localized_name": "epsilon", - "name": "epsilon", - "shape": 7, - "type": "FLOAT", - "widget": { - "name": "epsilon" - }, - "link": null - }, - { - "localized_name": "max_iterations", - "name": "max_iterations", - "shape": 7, - "type": "INT", - "widget": { - "name": "max_iterations" - }, - "link": null - }, - { - "localized_name": "direction", - "name": "direction", - "shape": 7, - "type": "COMBO", - "widget": { - "name": "direction" - }, - "link": null - }, - { - "localized_name": "scale_by_intersection_count", - "name": "scale_by_intersection_count", - "shape": 7, - "type": "BOOLEAN", - "widget": { - "name": "scale_by_intersection_count" - }, - "link": null - }, - { - "localized_name": "re_detect_after_fix", - "name": "re_detect_after_fix", - "shape": 7, - "type": "BOOLEAN", - "widget": { - "name": "re_detect_after_fix" - }, - "link": null - } - ], - "outputs": [ - { - "localized_name": "fixed_mesh", - "name": "fixed_mesh", - "type": "TRIMESH", - "links": [ - 25 - ] - }, - { - "localized_name": "report", - "name": "report", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", - "Node name for S&R": "GeomPackFixSelfIntersectionsByPerturbation" - }, - "widgets_values": [ - 0.0001, - 12, - "adaptive", - true, - true - ] - }, - { - "id": 1, - "type": "GeomPackLoadMesh", - "pos": [ - -857.4475596051225, - -67.3004633654837 - ], - "size": [ - 270, - 78 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [ - { - "localized_name": "file_path", - "name": "file_path", - "type": "COMBO", - "widget": { - "name": "file_path" - }, - "link": null - } - ], - "outputs": [ - { - "localized_name": "mesh", - "name": "mesh", - "type": "TRIMESH", - "links": [ - 19 - ] - }, - { - "localized_name": "texture", - "name": "texture", - "type": "IMAGE", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "253a956368261760da54dc96750c2ab0224e2b1f", - "Node name for S&R": "GeomPackLoadMesh" - }, - "widgets_values": [ - "3d/camelhead.off" - ] - }, - { - "id": 14, - "type": "GeomPackDetectSelfIntersections", - "pos": [ - -520.8806866148459, - -180.529783138655 - ], - "size": [ - 210, - 178 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [ - { - "localized_name": "trimesh", - "name": "trimesh", - "type": "TRIMESH", - "link": 19 - } - ], - "outputs": [ - { - "localized_name": "mesh_with_field", - "name": "mesh_with_field", - "type": "TRIMESH", - "links": [ - 23, - 32 - ] - }, - { - "localized_name": "report", - "name": "report", - "type": "STRING", - "links": [] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "c77434120c2984b0ad1dd308c733117a855a8a36", - "Node name for S&R": "GeomPackDetectSelfIntersections" - } - } - ], - "links": [ - [ - 19, - 1, - 0, - 14, - 0, - "TRIMESH" - ], - [ - 23, - 14, - 0, - 17, - 0, - "TRIMESH" - ], - [ - 25, - 17, - 0, - 13, - 0, - "TRIMESH" - ], - [ - 32, - 14, - 0, - 21, - 0, - "TRIMESH" - ], - [ - 33, - 13, - 0, - 21, - 1, - "TRIMESH" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.7741103156266208, - "offset": [ - 1152.5675348712587, - 411.93715587929773 - ] - }, - "frontendVersion": "1.30.6", - "workflowRendererVersion": "LG" - }, - "version": 0.4 -} \ No newline at end of file +{"id":"94c1c61e-cf5c-42a8-b9ec-914bb4f038ea","revision":0,"last_node_id":22,"last_link_id":36,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-857.4475596051225,-67.3004633654837],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[19]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/camelhead.off"]},{"id":17,"type":"GeomPackFixSelfIntersectionsByPerturbation","pos":[-628.2602741818372,99.13388533335451],"size":[319.319921875,174],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":23},{"localized_name":"epsilon","name":"epsilon","shape":7,"type":"FLOAT","widget":{"name":"epsilon"},"link":null},{"localized_name":"max_iterations","name":"max_iterations","shape":7,"type":"INT","widget":{"name":"max_iterations"},"link":null},{"localized_name":"direction","name":"direction","shape":7,"type":"COMBO","widget":{"name":"direction"},"link":null},{"localized_name":"scale_by_intersection_count","name":"scale_by_intersection_count","shape":7,"type":"BOOLEAN","widget":{"name":"scale_by_intersection_count"},"link":null},{"localized_name":"re_detect_after_fix","name":"re_detect_after_fix","shape":7,"type":"BOOLEAN","widget":{"name":"re_detect_after_fix"},"link":null}],"outputs":[{"localized_name":"fixed_mesh","name":"fixed_mesh","type":"TRIMESH","links":[35]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"8b8322e2f784d84097cd3427f097b55dc9a29d2a","Node name for S&R":"GeomPackFixSelfIntersectionsByPerturbation","cnr_id":"comfyui-geometrypack"},"widgets_values":[0.0001,12,"adaptive",true,true]},{"id":22,"type":"GeomPackDetectSelfIntersections","pos":[-246.54255743342944,131.98867129323492],"size":[177.6328125,46],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":35}],"outputs":[{"localized_name":"mesh_with_field","name":"mesh_with_field","type":"TRIMESH","links":[36]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"abe9ed9726622d0f29e3936feaf6c1aa446914a3","Node name for S&R":"GeomPackDetectSelfIntersections"}},{"id":14,"type":"GeomPackDetectSelfIntersections","pos":[-520.8806866148459,-180.529783138655],"size":[210,178],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":19}],"outputs":[{"localized_name":"mesh_with_field","name":"mesh_with_field","type":"TRIMESH","links":[23,32]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"c77434120c2984b0ad1dd308c733117a855a8a36","Node name for S&R":"GeomPackDetectSelfIntersections","cnr_id":"comfyui-geometrypack"},"widgets_values":[]},{"id":21,"type":"GeomPackPreviewMeshDual","pos":[11.636891884746433,-233.50651464931806],"size":[768,834],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":32},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":36},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"1fcec6e19dca5e04ec71d204dbe8ef1828885062","Node name for S&R":"GeomPackPreviewMeshDual","cnr_id":"comfyui-geometrypack"},"widgets_values":["side_by_side","fields",1,1,true,"{\"position\":[-0.09236526786018014,0.17034567262454137,0.11403091642671599],\"focalPoint\":[0.000001996755599975586,-0.0636419951915741,-0.03211300075054169],\"viewUp\":[-0.4041614428850428,0.36444564436893356,-0.8389474956072003]}","intersection_flag",""]}],"links":[[19,1,0,14,0,"TRIMESH"],[23,14,0,17,0,"TRIMESH"],[32,14,0,21,0,"TRIMESH"],[35,17,0,22,0,"TRIMESH"],[36,22,0,21,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7741103156266208,"offset":[1009.2124419215274,484.727370804141]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/remeshing_CGAL.json b/workflows/remeshing_CGAL.json index f73b3979..cca0a0c3 100644 --- a/workflows/remeshing_CGAL.json +++ b/workflows/remeshing_CGAL.json @@ -1 +1 @@ -{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":26,"last_link_id":32,"nodes":[{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-288.0410052280236,142.2919197315505],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":31},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":32},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-502.81561847832234,-58.160239777583065],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[30,32]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":26,"type":"GeomPackRemeshCGAL","pos":[-173.53963526716967,-268.5574315566234],"size":[274.009765625,126],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":30},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"protect_boundaries","name":"protect_boundaries","shape":7,"type":"COMBO","widget":{"name":"protect_boundaries"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[31]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"d0a698d6d5d375dc1e50b1146d4f5fbe9e819d16","Node name for S&R":"GeomPackRemeshCGAL","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[1,3,"true"]}],"links":[[30,1,0,26,0,"TRIMESH"],[31,26,0,25,0,"TRIMESH"],[32,1,0,25,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6830134553650705,"offset":[1287.828398939045,577.7913651503734]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":27,"last_link_id":34,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-502.81561847832234,-58.160239777583065],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[30,33]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":26,"type":"GeomPackRemeshCGAL","pos":[-469.8082770640447,136.13467820900172],"size":[274.009765625,158],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":30},{"localized_name":"target_edge_length","name":"target_edge_length","shape":7,"type":"FLOAT","widget":{"name":"target_edge_length"},"link":null},{"localized_name":"iterations","name":"iterations","shape":7,"type":"INT","widget":{"name":"iterations"},"link":null},{"localized_name":"protect_boundaries","name":"protect_boundaries","shape":7,"type":"COMBO","widget":{"name":"protect_boundaries"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[34]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"d0a698d6d5d375dc1e50b1146d4f5fbe9e819d16","Node name for S&R":"GeomPackRemeshCGAL","cnr_id":"comfyui-geometrypack"},"widgets_values":[1,3,"true",""]},{"id":27,"type":"GeomPackPreviewMeshDual","pos":[-115.79919151716959,-52.67131124412321],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":33},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":34},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"abe9ed9726622d0f29e3936feaf6c1aa446914a3","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,true,"{\"position\":[-131.66068270640417,-232.56748089092218,189.20482021602103],\"focalPoint\":[30.322647094726562,1.8909549713134766,59.22096252441406],\"viewUp\":[0.2535224962298691,0.329135569638136,0.9096131709162725]}","",""]}],"links":[[30,1,0,26,0,"TRIMESH"],[33,1,0,27,0,"TRIMESH"],[34,26,0,27,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.6830134553650705,"offset":[1094.6015137827944,690.2125124159984]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/remeshing_blender.json b/workflows/remeshing_blender.json index bb7cc581..cecf3dd3 100644 --- a/workflows/remeshing_blender.json +++ b/workflows/remeshing_blender.json @@ -1 +1 @@ -{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":31,"last_link_id":46,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-553.8798563116762,-69.44822756818182],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[43,46]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":31,"type":"GeomPackRemeshBlender","pos":[-98.55301081962853,-237.88071575885226],"size":[210,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":43},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"voxel_size","name":"voxel_size","shape":7,"type":"FLOAT","widget":{"name":"voxel_size"},"link":null},{"localized_name":"octree_depth","name":"octree_depth","shape":7,"type":"INT","widget":{"name":"octree_depth"},"link":null},{"localized_name":"scale","name":"scale","shape":7,"type":"FLOAT","widget":{"name":"scale"},"link":null},{"localized_name":"sharpness","name":"sharpness","shape":7,"type":"FLOAT","widget":{"name":"sharpness"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[45]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"a57da232130b20d93f36248ed810254035c6226c","Node name for S&R":"GeomPackRemeshBlender"},"widgets_values":["blender_sharp",1,8,0.9,1,""]},{"id":25,"type":"GeomPackPreviewMeshDual","pos":[-210.03447320411541,106.04784971545217],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":46},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":45},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,""]}],"links":[[43,1,0,31,0,"TRIMESH"],[45,31,0,25,1,"TRIMESH"],[46,1,0,25,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.3715783642907196,"offset":[668.3399932521036,284.0568811975611]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"fc31dc6e-fd82-4f42-9d3a-57283ccfadba","revision":0,"last_node_id":32,"last_link_id":48,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-553.8798563116762,-69.44822756818182],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[43,47]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":32,"type":"GeomPackPreviewMeshDual","pos":[-210.04648980414163,40.2496015193593],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":47},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":48},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"abe9ed9726622d0f29e3936feaf6c1aa446914a3","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,true,"{\"position\":[-104.03222092116789,-54.74525049655604,122.61947175655823],\"focalPoint\":[30.321775436401367,1.9068737030029297,59.235236167907715],\"viewUp\":[0.18685523349867636,0.5017895827965837,0.8445663599214603]}","",""]},{"id":31,"type":"GeomPackRemeshBlender","pos":[-486.88728378090264,115.45362409343684],"size":[210,182],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":43},{"localized_name":"backend","name":"backend","type":"COMBO","widget":{"name":"backend"},"link":null},{"localized_name":"voxel_size","name":"voxel_size","shape":7,"type":"FLOAT","widget":{"name":"voxel_size"},"link":null},{"localized_name":"octree_depth","name":"octree_depth","shape":7,"type":"INT","widget":{"name":"octree_depth"},"link":null},{"localized_name":"scale","name":"scale","shape":7,"type":"FLOAT","widget":{"name":"scale"},"link":null},{"localized_name":"sharpness","name":"sharpness","shape":7,"type":"FLOAT","widget":{"name":"sharpness"},"link":null}],"outputs":[{"localized_name":"remeshed_mesh","name":"remeshed_mesh","type":"TRIMESH","links":[48]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"a57da232130b20d93f36248ed810254035c6226c","Node name for S&R":"GeomPackRemeshBlender","cnr_id":"comfyui-geometrypack"},"widgets_values":["blender_sharp",1,7,0.9,1,""]}],"links":[[43,1,0,31,0,"TRIMESH"],[47,1,0,32,0,"TRIMESH"],[48,31,0,32,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7742202296679138,"offset":[905.6203370297437,319.52771290121194]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file From dea300415cac87235e63eca1e46745cc6d83b0f3 Mon Sep 17 00:00:00 2001 From: Andrea Pozzetti Date: Fri, 13 Feb 2026 01:38:40 +0100 Subject: [PATCH 24/27] added info dropdown to a bunch of nodes --- nodes/blender/blender_io/load_mesh_blend.py | 3 ++- nodes/blender/blender_io/load_mesh_fbx.py | 3 ++- nodes/blender/boolean/boolean.py | 3 ++- nodes/blender/texture_remeshing/remesh_uv.py | 3 ++- nodes/main/analysis/connected_components.py | 1 + nodes/main/analysis/degenerate_faces.py | 1 + nodes/main/analysis/open_edges.py | 1 + nodes/main/boolean/boolean.py | 3 ++- nodes/main/combine/combine_meshes.py | 3 ++- nodes/main/combine/combine_meshes_batch.py | 3 ++- nodes/main/combine/split_by_field.py | 3 ++- nodes/main/repair/add_normals_to_pointcloud.py | 3 ++- nodes/main/repair/check_normals.py | 3 ++- nodes/main/repair/fix_intersections_removal.py | 7 ++++--- nodes/main/repair/fix_normals.py | 3 ++- nodes/main/repair/merge_vertices.py | 3 ++- nodes/main/repair/remove_degenerate_faces.py | 3 ++- nodes/main/repair/visualize_normals.py | 3 ++- nodes/main/repair_cgal/detect_intersections.py | 5 +++-- .../repair_cgal/fix_intersections_perturbation.py | 7 ++++--- nodes/main/repair_cgal/remesh_intersections.py | 11 ++++++----- nodes/main/texture_remeshing/depth_normals_to_mesh.py | 3 ++- nodes/main/transforms/normalize_to_bbox.py | 3 ++- nodes/main/transforms/transform.py | 3 ++- nodes/main/uv/uv_unwrap.py | 3 ++- workflows/fill_holes.json | 2 +- 26 files changed, 57 insertions(+), 32 deletions(-) diff --git a/nodes/blender/blender_io/load_mesh_blend.py b/nodes/blender/blender_io/load_mesh_blend.py index ffb5cba3..265b0a87 100644 --- a/nodes/blender/blender_io/load_mesh_blend.py +++ b/nodes/blender/blender_io/load_mesh_blend.py @@ -94,6 +94,7 @@ class LoadMeshBlend: RETURN_NAMES = ("mesh", "info") FUNCTION = "load_blend" CATEGORY = "geompack/io" + OUTPUT_NODE = True @classmethod def get_blend_files(cls): @@ -212,7 +213,7 @@ class LoadMeshBlend: print(f"[LoadMeshBlend] Loaded: {len(loaded_mesh.vertices)} vertices, {len(loaded_mesh.faces)} faces") - return (loaded_mesh, info) + return {"ui": {"text": [info]}, "result": (loaded_mesh, info)} # Node mappings diff --git a/nodes/blender/blender_io/load_mesh_fbx.py b/nodes/blender/blender_io/load_mesh_fbx.py index 06d26395..15914809 100644 --- a/nodes/blender/blender_io/load_mesh_fbx.py +++ b/nodes/blender/blender_io/load_mesh_fbx.py @@ -94,6 +94,7 @@ class LoadMeshFBX: RETURN_NAMES = ("mesh", "info") FUNCTION = "load_fbx" CATEGORY = "geompack/io" + OUTPUT_NODE = True @classmethod def get_fbx_files(cls): @@ -212,7 +213,7 @@ class LoadMeshFBX: print(f"[LoadMeshFBX] Loaded: {len(loaded_mesh.vertices)} vertices, {len(loaded_mesh.faces)} faces") - return (loaded_mesh, info) + return {"ui": {"text": [info]}, "result": (loaded_mesh, info)} # Node mappings diff --git a/nodes/blender/boolean/boolean.py b/nodes/blender/boolean/boolean.py index f49f5265..d7ddd0d6 100644 --- a/nodes/blender/boolean/boolean.py +++ b/nodes/blender/boolean/boolean.py @@ -82,6 +82,7 @@ class BooleanBlenderNode: RETURN_NAMES = ("result_mesh", "info") FUNCTION = "boolean_op" CATEGORY = "geompack/boolean" + OUTPUT_NODE = True def boolean_op(self, mesh_a, mesh_b, operation): """ @@ -157,7 +158,7 @@ Watertight: {result.is_watertight} """ print(f"[Boolean Blender] Success: {len(result.vertices)} vertices, {len(result.faces)} faces") - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} except Exception as e: raise RuntimeError(f"Boolean Blender operation failed: {e}") diff --git a/nodes/blender/texture_remeshing/remesh_uv.py b/nodes/blender/texture_remeshing/remesh_uv.py index b5356dba..d1bdfecf 100644 --- a/nodes/blender/texture_remeshing/remesh_uv.py +++ b/nodes/blender/texture_remeshing/remesh_uv.py @@ -213,6 +213,7 @@ class RemeshWithTexture: RETURN_NAMES = ("remeshed_mesh", "baked_texture", "info") FUNCTION = "remesh_with_texture" CATEGORY = "geompack/texture_remeshing" + OUTPUT_NODE = True def remesh_with_texture(self, trimesh, method, remesh_method, voxel_size, target_face_count, bake_margin): @@ -541,7 +542,7 @@ Texture Transfer: Closest-Point Projection{placeholder_warning} """ print(f"[BlenderRemeshWithTexture] Complete") - return (remeshed_with_colors, comfy_image, info) + return {"ui": {"text": [info]}, "result": (remeshed_with_colors, comfy_image, info)} finally: # Cleanup diff --git a/nodes/main/analysis/connected_components.py b/nodes/main/analysis/connected_components.py index 9023a17c..4eaa20af 100644 --- a/nodes/main/analysis/connected_components.py +++ b/nodes/main/analysis/connected_components.py @@ -144,6 +144,7 @@ class ConnectedComponentsNode: return { "result": (result_meshes, summary), "ui": { + "text": [summary], "component_data": ui_components } } diff --git a/nodes/main/analysis/degenerate_faces.py b/nodes/main/analysis/degenerate_faces.py index 30a47d40..be45c846 100644 --- a/nodes/main/analysis/degenerate_faces.py +++ b/nodes/main/analysis/degenerate_faces.py @@ -186,6 +186,7 @@ class DegenerateFacesNode: return { "result": (result_meshes, summary), "ui": { + "text": [summary], "degenerate_data": ui_data } } diff --git a/nodes/main/analysis/open_edges.py b/nodes/main/analysis/open_edges.py index c7c74ce1..26723095 100644 --- a/nodes/main/analysis/open_edges.py +++ b/nodes/main/analysis/open_edges.py @@ -181,6 +181,7 @@ class OpenEdgesNode: return { "result": (result_meshes, summary), "ui": { + "text": [summary], "open_edges_data": ui_data } } diff --git a/nodes/main/boolean/boolean.py b/nodes/main/boolean/boolean.py index 6bac6d13..8686662e 100644 --- a/nodes/main/boolean/boolean.py +++ b/nodes/main/boolean/boolean.py @@ -37,6 +37,7 @@ class BooleanCGALNode: RETURN_NAMES = ("result_mesh", "info") FUNCTION = "boolean_op" CATEGORY = "geompack/boolean" + OUTPUT_NODE = True def boolean_op(self, mesh_a, mesh_b, operation): """ @@ -114,7 +115,7 @@ Watertight: {result.is_watertight} """ print(f"[Boolean CGAL] Success: {len(result.vertices)} vertices, {len(result.faces)} faces") - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} except Exception as e: raise RuntimeError(f"Boolean CGAL operation failed: {e}") diff --git a/nodes/main/combine/combine_meshes.py b/nodes/main/combine/combine_meshes.py index c9d4e7ff..60d0966b 100644 --- a/nodes/main/combine/combine_meshes.py +++ b/nodes/main/combine/combine_meshes.py @@ -35,6 +35,7 @@ class CombineMeshesNode: RETURN_NAMES = ("combined_mesh", "info") FUNCTION = "combine" CATEGORY = "geompack/combine" + OUTPUT_NODE = True def combine(self, mesh_a, mesh_b=None, mesh_c=None, mesh_d=None): """ @@ -109,7 +110,7 @@ Components remain separate within the combined mesh. """ print(f"[CombineMeshes] Result: {len(result.vertices)} vertices, {len(result.faces)} faces") - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} # Node mappings diff --git a/nodes/main/combine/combine_meshes_batch.py b/nodes/main/combine/combine_meshes_batch.py index 21aecf6b..d3b2a42d 100644 --- a/nodes/main/combine/combine_meshes_batch.py +++ b/nodes/main/combine/combine_meshes_batch.py @@ -33,6 +33,7 @@ class CombineMeshesBatchNode: RETURN_NAMES = ("combined_mesh", "info") FUNCTION = "combine" CATEGORY = "geompack/combine" + OUTPUT_NODE = True DESCRIPTION = "Combine a batch of meshes into a single mesh." def combine(self, meshes): @@ -121,7 +122,7 @@ Components remain separate within the combined mesh. """ print(f"[CombineMeshesBatch] Result: {len(result.vertices)} vertices, {len(result.faces)} faces") - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} # Node mappings diff --git a/nodes/main/combine/split_by_field.py b/nodes/main/combine/split_by_field.py index 5372c6c5..cdf9eae3 100644 --- a/nodes/main/combine/split_by_field.py +++ b/nodes/main/combine/split_by_field.py @@ -38,6 +38,7 @@ class SplitByFieldNode: OUTPUT_IS_LIST = (True, False) FUNCTION = "split" CATEGORY = "geompack/combine" + OUTPUT_NODE = True def split(self, geometry, field_name: str) -> Tuple: """Split geometry by a discrete field.""" @@ -131,7 +132,7 @@ class SplitByFieldNode: print(f" {field_name}={val}: {num_points} points") summary = "\n".join(summary_lines) - return (result, summary) + return {"ui": {"text": [summary]}, "result": (result, summary)} # Node mappings diff --git a/nodes/main/repair/add_normals_to_pointcloud.py b/nodes/main/repair/add_normals_to_pointcloud.py index 2aef6cd5..bf27b5dd 100644 --- a/nodes/main/repair/add_normals_to_pointcloud.py +++ b/nodes/main/repair/add_normals_to_pointcloud.py @@ -63,6 +63,7 @@ class AddNormalsToPointCloud: RETURN_NAMES = ("pointcloud_with_normals", "info") FUNCTION = "add_normals" CATEGORY = "geompack/repair" + OUTPUT_NODE = True DESCRIPTION = "Estimate and add normals to a point cloud using Open3D or PyMeshLab methods." def add_normals( @@ -160,7 +161,7 @@ class AddNormalsToPointCloud: print(f"[AddNormalsToPointCloud] [OK] {info}") - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} def _estimate_normals_open3d_knn(self, points, k_neighbors, orient_normals): """ diff --git a/nodes/main/repair/check_normals.py b/nodes/main/repair/check_normals.py index d6d7880d..81016875 100644 --- a/nodes/main/repair/check_normals.py +++ b/nodes/main/repair/check_normals.py @@ -29,6 +29,7 @@ class CheckNormalsNode: RETURN_NAMES = ("info",) FUNCTION = "check_normals" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def check_normals(self, trimesh): """ @@ -98,7 +99,7 @@ Recommendations: print(f"[CheckNormals] Winding: {is_winding_consistent}, Watertight: {is_watertight}, Degenerate: {degenerate_faces}") - return (report,) + return {"ui": {"text": [report]}, "result": (report,)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair/fix_intersections_removal.py b/nodes/main/repair/fix_intersections_removal.py index f5f74d70..ada45c49 100644 --- a/nodes/main/repair/fix_intersections_removal.py +++ b/nodes/main/repair/fix_intersections_removal.py @@ -36,6 +36,7 @@ class FixSelfIntersectionsByRemovalNode: RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "fix_by_removal" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def fix_by_removal(self, trimesh, fill_holes=True, fix_normals=True, max_hole_size=100, re_detect_after_fix=True): @@ -72,7 +73,7 @@ Returning mesh unchanged. Workflow suggestion: 1. Load Mesh -> Detect Self Intersections -> Fix Self Intersections By Removal """ - return (trimesh, warning_msg) + return {"ui": {"text": [warning_msg]}, "result": (trimesh, warning_msg)} # Get intersecting face indices face_field = trimesh.face_attributes['self_intersecting'] @@ -89,7 +90,7 @@ Either the mesh is already clean, or you need to run Returning mesh unchanged. """ - return (trimesh, report) + return {"ui": {"text": [report]}, "result": (trimesh, report)} print(f"[FixByRemoval] Found {num_intersecting} intersecting faces to remove") @@ -246,7 +247,7 @@ Status: """ print(f"[FixByRemoval] Complete: {final_vertices} vertices, {final_faces} faces") - return (result_mesh, report) + return {"ui": {"text": [report]}, "result": (result_mesh, report)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair/fix_normals.py b/nodes/main/repair/fix_normals.py index b61a9452..56a6a425 100644 --- a/nodes/main/repair/fix_normals.py +++ b/nodes/main/repair/fix_normals.py @@ -169,6 +169,7 @@ class FixNormalsNode: RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "fix_normals" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def fix_normals(self, trimesh, method="trimesh"): """ @@ -295,7 +296,7 @@ Faces: {len(fixed_mesh.faces):,} print(f"[FixNormals] {'[OK]' if is_consistent else '[WARN]'} Normal orientation: {was_consistent} -> {is_consistent}") - return (fixed_mesh, info) + return {"ui": {"text": [info]}, "result": (fixed_mesh, info)} # Node mappings diff --git a/nodes/main/repair/merge_vertices.py b/nodes/main/repair/merge_vertices.py index ad7baf33..4958adf2 100644 --- a/nodes/main/repair/merge_vertices.py +++ b/nodes/main/repair/merge_vertices.py @@ -45,6 +45,7 @@ class MergeVerticesNode: RETURN_NAMES = ("merged_mesh", "info") FUNCTION = "merge_vertices" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def merge_vertices(self, mesh, tolerance=1e-5): """ @@ -123,7 +124,7 @@ After: if components_change is not None: print(f"[MergeVertices] Components: {components_before} -> {components_after}") - return (merged_mesh, info) + return {"ui": {"text": [info]}, "result": (merged_mesh, info)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair/remove_degenerate_faces.py b/nodes/main/repair/remove_degenerate_faces.py index 746a9d8f..ae19c07f 100644 --- a/nodes/main/repair/remove_degenerate_faces.py +++ b/nodes/main/repair/remove_degenerate_faces.py @@ -46,6 +46,7 @@ class RemoveDegenerateFacesNode: RETURN_NAMES = ("cleaned_mesh", "info") FUNCTION = "remove_degenerate" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def remove_degenerate(self, mesh, min_area=1e-10): """ @@ -116,7 +117,7 @@ After: print(f"[RemoveDegenerateFaces] Removed {faces_removed} degenerate faces, {verts_removed} unreferenced vertices") - return (cleaned_mesh, info) + return {"ui": {"text": [info]}, "result": (cleaned_mesh, info)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair/visualize_normals.py b/nodes/main/repair/visualize_normals.py index 45a8694f..ea171e38 100644 --- a/nodes/main/repair/visualize_normals.py +++ b/nodes/main/repair/visualize_normals.py @@ -30,6 +30,7 @@ class VisualizNormalFieldNode: RETURN_NAMES = ("mesh_with_fields", "info") FUNCTION = "visualize_normals" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def visualize_normals(self, trimesh): """ @@ -76,7 +77,7 @@ Expected Values: print(f"[VisualizeNormals] Added 4 scalar fields to mesh") - return (result_mesh, info) + return {"ui": {"text": [info]}, "result": (result_mesh, info)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair_cgal/detect_intersections.py b/nodes/main/repair_cgal/detect_intersections.py index 848d90be..286b3905 100644 --- a/nodes/main/repair_cgal/detect_intersections.py +++ b/nodes/main/repair_cgal/detect_intersections.py @@ -195,6 +195,7 @@ Use 'Preview Mesh (VTK with Fields)' node to visualize the intersection fields! return { "result": (result_mesh, report), "ui": { + "text": [report], "intersection_data": [ui_data] } } @@ -211,7 +212,7 @@ Install with: pip install libigl cgal For now, returning mesh unchanged. """ print(f"[DetectSelfIntersections] libigl import error: {e}") - return (trimesh, error_msg) + return {"ui": {"text": [error_msg]}, "result": (trimesh, error_msg)} except Exception as e: import traceback @@ -223,7 +224,7 @@ For now, returning mesh unchanged. Returning mesh unchanged. Check console for details. """ print(f"[DetectSelfIntersections] Unexpected error: {e}") - return (trimesh, error_msg) + return {"ui": {"text": [error_msg]}, "result": (trimesh, error_msg)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair_cgal/fix_intersections_perturbation.py b/nodes/main/repair_cgal/fix_intersections_perturbation.py index 544db31c..e7c0024a 100644 --- a/nodes/main/repair_cgal/fix_intersections_perturbation.py +++ b/nodes/main/repair_cgal/fix_intersections_perturbation.py @@ -37,6 +37,7 @@ class FixSelfIntersectionsByPerturbationNode: RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "fix_by_perturbation" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def fix_by_perturbation(self, trimesh, epsilon=0.001, max_iterations=10, direction="outward", scale_by_intersection_count=True, @@ -72,7 +73,7 @@ Returning mesh unchanged. Workflow suggestion: 1. Load Mesh -> Detect Self Intersections -> Fix Self Intersections By Perturbation """ - return (trimesh, warning_msg) + return {"ui": {"text": [warning_msg]}, "result": (trimesh, warning_msg)} # Get vertices to perturb vertex_flags = trimesh.vertex_attributes['intersection_flag'] @@ -89,7 +90,7 @@ Either the mesh is already clean, or you need to run Returning mesh unchanged. """ - return (trimesh, report) + return {"ui": {"text": [report]}, "result": (trimesh, report)} print(f"[FixByPerturbation] Found {num_affected} vertices to perturb") @@ -279,7 +280,7 @@ Important Notes: """ print(f"[FixByPerturbation] Complete: perturbed {num_affected} vertices over {iterations_used} iterations") - return (result_mesh, report) + return {"ui": {"text": [report]}, "result": (result_mesh, report)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/repair_cgal/remesh_intersections.py b/nodes/main/repair_cgal/remesh_intersections.py index 0641f109..2074dceb 100644 --- a/nodes/main/repair_cgal/remesh_intersections.py +++ b/nodes/main/repair_cgal/remesh_intersections.py @@ -35,6 +35,7 @@ class RemeshSelfIntersectionsNode: RETURN_NAMES = ("fixed_mesh", "info") FUNCTION = "remesh_intersections" CATEGORY = "geompack/repair" + OUTPUT_NODE = True def remesh_intersections(self, mesh, detect_only=False, remove_unreferenced=True, extract_outer_hull=False, stitch_all=True): @@ -74,7 +75,7 @@ Install with: pip install cgal Returning mesh unchanged. """ print("[RemeshSelfIntersections] CGAL not available") - return (mesh, error_msg) + return {"ui": {"text": [error_msg]}, "result": (mesh, error_msg)} print("[RemeshSelfIntersections] Using libigl CGAL method") @@ -186,7 +187,7 @@ Status: {' Consider enabling extract_outer_hull for a clean manifold result.' if not extract_outer_hull else ''} """ - return (result_mesh, report) + return {"ui": {"text": [report]}, "result": (result_mesh, report)} except Exception as e: import traceback @@ -198,7 +199,7 @@ Status: Returning mesh unchanged. Check console for details. """ print(f"[RemeshSelfIntersections] Remeshing error: {e}") - return (mesh, error_msg) + return {"ui": {"text": [error_msg]}, "result": (mesh, error_msg)} except ImportError as e: error_msg = f"""Error: libigl not available @@ -211,7 +212,7 @@ Install with: pip install libigl cgal Returning mesh unchanged. """ print(f"[RemeshSelfIntersections] libigl import error: {e}") - return (mesh, error_msg) + return {"ui": {"text": [error_msg]}, "result": (mesh, error_msg)} except Exception as e: import traceback @@ -223,7 +224,7 @@ Returning mesh unchanged. Returning mesh unchanged. Check console for details. """ print(f"[RemeshSelfIntersections] Unexpected error: {e}") - return (mesh, error_msg) + return {"ui": {"text": [error_msg]}, "result": (mesh, error_msg)} NODE_CLASS_MAPPINGS = { diff --git a/nodes/main/texture_remeshing/depth_normals_to_mesh.py b/nodes/main/texture_remeshing/depth_normals_to_mesh.py index 7a9c349c..af5d1066 100644 --- a/nodes/main/texture_remeshing/depth_normals_to_mesh.py +++ b/nodes/main/texture_remeshing/depth_normals_to_mesh.py @@ -96,6 +96,7 @@ class DepthNormalsToMeshNode: RETURN_NAMES = ("mesh", "info") FUNCTION = "depth_normals_to_mesh" CATEGORY = "geompack/texture_remeshing" + OUTPUT_NODE = True def depth_normals_to_mesh(self, normal_map, resolution, depth_scale, depth=None, depth_image=None, @@ -265,7 +266,7 @@ Output Mesh: {method_info} """ - return (mesh, info) + return {"ui": {"text": [info]}, "result": (mesh, info)} def _poisson_reconstruct(self, points, normals, depth, scale): """Poisson surface reconstruction using Open3D or PyMeshLab.""" diff --git a/nodes/main/transforms/normalize_to_bbox.py b/nodes/main/transforms/normalize_to_bbox.py index 63e0acdb..3557b8d6 100644 --- a/nodes/main/transforms/normalize_to_bbox.py +++ b/nodes/main/transforms/normalize_to_bbox.py @@ -49,6 +49,7 @@ class NormalizeMeshToBBox: RETURN_NAMES = ("normalized_mesh", "info") FUNCTION = "normalize_to_bbox" CATEGORY = "geompack/transforms" + OUTPUT_NODE = True DESCRIPTION = "Center and scale mesh isotropically to fit target bounding box. Use before estimating normals for TripoSF." def normalize_to_bbox(self, trimesh, target_size=1.0): @@ -132,7 +133,7 @@ New Bounds: Note: Use this BEFORE AddNormalsToPointCloud for TripoSF workflows. """ - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} # Node registration diff --git a/nodes/main/transforms/transform.py b/nodes/main/transforms/transform.py index edad3031..44122120 100644 --- a/nodes/main/transforms/transform.py +++ b/nodes/main/transforms/transform.py @@ -152,6 +152,7 @@ class TransformMeshNode: RETURN_NAMES = ("transformed_mesh", "info") FUNCTION = "transform" CATEGORY = "geompack/transforms" + OUTPUT_NODE = True def transform(self, trimesh, operation, translate_x=0.0, translate_y=0.0, translate_z=0.0, @@ -203,7 +204,7 @@ class TransformMeshNode: } print(f"[Transform] Complete") - return (result, info) + return {"ui": {"text": [info]}, "result": (result, info)} def _translate(self, mesh, tx, ty, tz): """Translate mesh by offset.""" diff --git a/nodes/main/uv/uv_unwrap.py b/nodes/main/uv/uv_unwrap.py index b5eb1df4..3c3575b4 100644 --- a/nodes/main/uv/uv_unwrap.py +++ b/nodes/main/uv/uv_unwrap.py @@ -294,6 +294,7 @@ class UVUnwrapNode: RETURN_NAMES = ("unwrapped_mesh", "info") FUNCTION = "unwrap" CATEGORY = "geompack/uv" + OUTPUT_NODE = True def unwrap(self, trimesh, method, chart_cone_angle=90.0, chart_refine_iterations=0, @@ -352,7 +353,7 @@ class UVUnwrapNode: print(f"[UVUnwrap] Output: {len(unwrapped_mesh.vertices)} vertices, {len(unwrapped_mesh.faces)} faces") - return (unwrapped_mesh, info) + return {"ui": {"text": [info]}, "result": (unwrapped_mesh, info)} def _xatlas(self, trimesh): """XAtlas automatic UV unwrapping.""" diff --git a/workflows/fill_holes.json b/workflows/fill_holes.json index dce01ae7..e764056a 100644 --- a/workflows/fill_holes.json +++ b/workflows/fill_holes.json @@ -1 +1 @@ -{"id":"f1e2d3c4-5b6a-7890-abcd-ef1234567890","revision":0,"last_node_id":6,"last_link_id":10,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-502,-58],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[5,9]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"0.1.1","Node name for S&R":"GeomPackLoadMesh"},"widgets_values":["3d/camelhead.off"]},{"id":4,"type":"GeomPackPreviewMeshDual","pos":[153.61197916666663,-96.7200520833334],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":5},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":8},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":6,"type":"GeomPackFillHoles","pos":[-171.29036458333348,47.93098958333326],"size":[270,126],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","link":9},{"localized_name":"method","name":"method","type":"COMBO","widget":{"name":"method"},"link":null},{"localized_name":"perimeter","name":"perimeter","shape":7,"type":"FLOAT","widget":{"name":"perimeter"},"link":null},{"localized_name":"maxholesize","name":"maxholesize","shape":7,"type":"INT","widget":{"name":"maxholesize"},"link":null}],"outputs":[{"localized_name":"filled_mesh","name":"filled_mesh","type":"TRIMESH","links":[8]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackFillHoles"},"widgets_values":["igl_fan",0.03,1000]}],"links":[[5,1,0,4,0,"TRIMESH"],[8,6,0,4,1,"TRIMESH"],[9,1,0,6,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1,"offset":[668.4192708333335,261.92838541666674]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"f1e2d3c4-5b6a-7890-abcd-ef1234567890","revision":0,"last_node_id":6,"last_link_id":10,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-502,-58],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[5,9]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"0.1.1","Node name for S&R":"GeomPackLoadMesh"},"widgets_values":["3d/camelhead.off"]},{"id":4,"type":"GeomPackPreviewMeshDual","pos":[153.61197916666663,-96.7200520833334],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":5},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":8},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,true,"{\"position\":[-0.6681526257034239,-1.8611185662971887,0.48246462543800994],\"focalPoint\":[0.000001996755599975586,-0.0636419951915741,-0.03211300075054169],\"viewUp\":[-0.8176470407253343,0.4174384049100435,0.39648265397021126]}","",""]},{"id":6,"type":"GeomPackFillHoles","pos":[-171.29036458333348,47.93098958333326],"size":[210,134],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","link":9},{"localized_name":"method","name":"method","type":"COMBO","widget":{"name":"method"},"link":null},{"localized_name":"perimeter","name":"perimeter","shape":7,"type":"FLOAT","widget":{"name":"perimeter"},"link":null},{"localized_name":"maxholesize","name":"maxholesize","shape":7,"type":"INT","widget":{"name":"maxholesize"},"link":null}],"outputs":[{"localized_name":"filled_mesh","name":"filled_mesh","type":"TRIMESH","links":[8]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackFillHoles"},"widgets_values":["pymeshlab",0.03,1000,""]}],"links":[[5,1,0,4,0,"TRIMESH"],[8,6,0,4,1,"TRIMESH"],[9,1,0,6,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1,"offset":[636.1302083333335,280.33854166666674]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file From da6a40a1ba2ee7f07cef21429d0ac8a2e54fc764 Mon Sep 17 00:00:00 2001 From: Andrea Pozzetti Date: Fri, 13 Feb 2026 01:39:40 +0100 Subject: [PATCH 25/27] 2.16 bump for comfy 3d viewers --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 509e57f2..186a0457 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) comfy-env==0.1.90 comfy-dynamic-widgets==0.1.4 -comfy-3d-viewers==0.2.15 +comfy-3d-viewers==0.2.16 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 From 16fc58951760a84030865195f37af415b2564904 Mon Sep 17 00:00:00 2001 From: Andrea Pozzetti Date: Fri, 13 Feb 2026 01:40:40 +0100 Subject: [PATCH 26/27] touch ups to workflows --- requirements.txt | 2 +- workflows/boolean_ops.json | 2 +- workflows/fix_normals.json | 267 +------------------------- workflows/fix_self_intersection.json | 2 +- workflows/refine_mesh.json | 2 +- workflows/side_by_side_viewer.json | 150 +-------------- workflows/surface_reconstruction.json | 227 +--------------------- workflows/transform.json | 171 +---------------- 8 files changed, 8 insertions(+), 815 deletions(-) diff --git a/requirements.txt b/requirements.txt index 186a0457..23220aa4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ # Main process deps (prestartup + lightweight shared libs) comfy-env==0.1.90 comfy-dynamic-widgets==0.1.4 -comfy-3d-viewers==0.2.16 +comfy-3d-viewers==0.2.17 numpy trimesh[easy]>=4.0.0 scipy>=1.7.0 diff --git a/workflows/boolean_ops.json b/workflows/boolean_ops.json index ac71ba09..281e7a08 100644 --- a/workflows/boolean_ops.json +++ b/workflows/boolean_ops.json @@ -1 +1 @@ -{"id":"58a80d52-612a-405e-b687-4696702fb5a6","revision":1,"last_node_id":23,"last_link_id":32,"nodes":[{"id":21,"type":"GeomPackPreviewMeshDual","pos":[-435.8209574638419,90.32379879585822],"size":[768,834],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":27},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":28},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackPreviewMeshDual","cnr_id":"comfyui-geometrypack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":22,"type":"GeomPackPreviewMeshVTK","pos":[393.34808550490783,-249.69329104789136],"size":[512,722],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","shape":7,"type":"TRIMESH","link":32},{"localized_name":"voxelgrid","name":"voxelgrid","shape":7,"type":"VOXELGRID","link":null},{"localized_name":"mode","name":"mode","type":"COMBO","widget":{"name":"mode"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"2e13f224560ec09663784033fcbe8565327e9726","Node name for S&R":"GeomPackPreviewMeshVTK","cnr_id":"comfyui-geometrypack"},"widgets_values":["fields",""]},{"id":1,"type":"GeomPackCreatePrimitive","pos":[-800,-200],"size":[300,150],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"shape","name":"shape","type":"COMBO","widget":{"name":"shape"},"link":null},{"localized_name":"size","name":"size","type":"FLOAT","widget":{"name":"size"},"link":null},{"localized_name":"subdivisions","name":"subdivisions","shape":7,"type":"INT","widget":{"name":"subdivisions"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[27,30]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"8b8322e2f784d84097cd3427f097b55dc9a29d2a","Node name for S&R":"GeomPackCreatePrimitive","cnr_id":"comfyui-geometrypack"},"widgets_values":["cube",2,1]},{"id":2,"type":"GeomPackCreatePrimitive","pos":[-800,50],"size":[300,150],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"shape","name":"shape","type":"COMBO","widget":{"name":"shape"},"link":null},{"localized_name":"size","name":"size","type":"FLOAT","widget":{"name":"size"},"link":null},{"localized_name":"subdivisions","name":"subdivisions","shape":7,"type":"INT","widget":{"name":"subdivisions"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[28,31]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"8b8322e2f784d84097cd3427f097b55dc9a29d2a","Node name for S&R":"GeomPackCreatePrimitive","cnr_id":"comfyui-geometrypack"},"widgets_values":["sphere",2.5,2]},{"id":23,"type":"GeomPackBooleanCGAL","pos":[-384.9918134931428,-190.68513609068106],"size":[270,78],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"mesh_a","name":"mesh_a","type":"TRIMESH","link":30},{"localized_name":"mesh_b","name":"mesh_b","type":"TRIMESH","link":31},{"localized_name":"operation","name":"operation","type":"COMBO","widget":{"name":"operation"},"link":null}],"outputs":[{"localized_name":"result_mesh","name":"result_mesh","type":"TRIMESH","links":[32]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"c5dfab62adf5e57a1800306b9c6d495f4dd52a43","Node name for S&R":"GeomPackBooleanCGAL"},"widgets_values":["union"]}],"links":[[27,1,0,21,0,"TRIMESH"],[28,2,0,21,1,"TRIMESH"],[30,1,0,23,0,"TRIMESH"],[31,2,0,23,1,"TRIMESH"],[32,23,0,22,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.0648000000000015,"offset":[1069.616918677214,587.525350215399]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id": "58a80d52-612a-405e-b687-4696702fb5a6", "revision": 1, "last_node_id": 23, "last_link_id": 32, "nodes": [{"id": 21, "type": "GeomPackPreviewMeshDual", "pos": [-435.8209574638419, 90.32379879585822], "size": [768, 834], "flags": {}, "order": 2, "mode": 0, "inputs": [{"localized_name": "mesh_1", "name": "mesh_1", "type": "TRIMESH", "link": 27}, {"localized_name": "mesh_2", "name": "mesh_2", "type": "TRIMESH", "link": 28}, {"localized_name": "layout", "name": "layout", "shape": 7, "type": "COMBO", "widget": {"name": "layout"}, "link": null}, {"localized_name": "mode", "name": "mode", "shape": 7, "type": "COMBO", "widget": {"name": "mode"}, "link": null}, {"localized_name": "opacity_1", "name": "opacity_1", "shape": 7, "type": "FLOAT", "widget": {"name": "opacity_1"}, "link": null}, {"localized_name": "opacity_2", "name": "opacity_2", "shape": 7, "type": "FLOAT", "widget": {"name": "opacity_2"}, "link": null}], "outputs": [], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "991c7a75886f50d567e5ed6d36aed06d0729a938", "Node name for S&R": "GeomPackPreviewMeshDual", "cnr_id": "comfyui-geometrypack"}, "widgets_values": ["side_by_side", "fields", 1, 1, true, "", ""]}, {"id": 22, "type": "GeomPackPreviewMeshVTK", "pos": [393.34808550490783, -249.69329104789136], "size": [512, 722], "flags": {}, "order": 4, "mode": 0, "inputs": [{"localized_name": "trimesh", "name": "trimesh", "shape": 7, "type": "TRIMESH", "link": 32}, {"localized_name": "voxelgrid", "name": "voxelgrid", "shape": 7, "type": "VOXELGRID", "link": null}, {"localized_name": "mode", "name": "mode", "type": "COMBO", "widget": {"name": "mode"}, "link": null}], "outputs": [], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "2e13f224560ec09663784033fcbe8565327e9726", "Node name for S&R": "GeomPackPreviewMeshVTK", "cnr_id": "comfyui-geometrypack"}, "widgets_values": ["fields", ""]}, {"id": 1, "type": "GeomPackCreatePrimitive", "pos": [-800, -200], "size": [300, 150], "flags": {}, "order": 0, "mode": 0, "inputs": [{"localized_name": "shape", "name": "shape", "type": "COMBO", "widget": {"name": "shape"}, "link": null}, {"localized_name": "size", "name": "size", "type": "FLOAT", "widget": {"name": "size"}, "link": null}, {"localized_name": "subdivisions", "name": "subdivisions", "shape": 7, "type": "INT", "widget": {"name": "subdivisions"}, "link": null}], "outputs": [{"localized_name": "mesh", "name": "mesh", "type": "TRIMESH", "links": [27, 30]}], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", "Node name for S&R": "GeomPackCreatePrimitive", "cnr_id": "comfyui-geometrypack"}, "widgets_values": ["cube", 2, 1]}, {"id": 2, "type": "GeomPackCreatePrimitive", "pos": [-800, 50], "size": [300, 150], "flags": {}, "order": 1, "mode": 0, "inputs": [{"localized_name": "shape", "name": "shape", "type": "COMBO", "widget": {"name": "shape"}, "link": null}, {"localized_name": "size", "name": "size", "type": "FLOAT", "widget": {"name": "size"}, "link": null}, {"localized_name": "subdivisions", "name": "subdivisions", "shape": 7, "type": "INT", "widget": {"name": "subdivisions"}, "link": null}], "outputs": [{"localized_name": "mesh", "name": "mesh", "type": "TRIMESH", "links": [28, 31]}], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", "Node name for S&R": "GeomPackCreatePrimitive", "cnr_id": "comfyui-geometrypack"}, "widgets_values": ["sphere", 2.5, 2]}, {"id": 23, "type": "GeomPackBooleanCGAL", "pos": [-384.9918134931428, -190.68513609068106], "size": [270, 78], "flags": {}, "order": 3, "mode": 0, "inputs": [{"localized_name": "mesh_a", "name": "mesh_a", "type": "TRIMESH", "link": 30}, {"localized_name": "mesh_b", "name": "mesh_b", "type": "TRIMESH", "link": 31}, {"localized_name": "operation", "name": "operation", "type": "COMBO", "widget": {"name": "operation"}, "link": null}], "outputs": [{"localized_name": "result_mesh", "name": "result_mesh", "type": "TRIMESH", "links": [32]}, {"localized_name": "info", "name": "info", "type": "STRING", "links": null}], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "c5dfab62adf5e57a1800306b9c6d495f4dd52a43", "Node name for S&R": "GeomPackBooleanCGAL"}, "widgets_values": ["union"]}], "links": [[27, 1, 0, 21, 0, "TRIMESH"], [28, 2, 0, 21, 1, "TRIMESH"], [30, 1, 0, 23, 0, "TRIMESH"], [31, 2, 0, 23, 1, "TRIMESH"], [32, 23, 0, 22, 0, "TRIMESH"]], "groups": [], "config": {}, "extra": {"ds": {"scale": 1.0648000000000015, "offset": [1069.616918677214, 587.525350215399]}, "frontendVersion": "1.30.6", "workflowRendererVersion": "LG"}, "version": 0.4} \ No newline at end of file diff --git a/workflows/fix_normals.json b/workflows/fix_normals.json index b99e5db1..2c3eea27 100644 --- a/workflows/fix_normals.json +++ b/workflows/fix_normals.json @@ -1,266 +1 @@ -{ - "id": "f3e4d5c6-7b8a-9012-cdef-123456789012", - "revision": 0, - "last_node_id": 7, - "last_link_id": 12, - "nodes": [ - { - "id": 4, - "type": "GeomPackPreviewMeshDual", - "pos": [ - 114.71875000000023, - 226.32812500000006 - ], - "size": [ - 768, - 834 - ], - "flags": {}, - "order": 5, - "mode": 0, - "inputs": [ - { - "name": "mesh_1", - "type": "TRIMESH", - "link": 12 - }, - { - "name": "mesh_2", - "type": "TRIMESH", - "link": 11 - } - ], - "outputs": [], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "991c7a75886f50d567e5ed6d36aed06d0729a938", - "Node name for S&R": "GeomPackPreviewMeshDual" - }, - "widgets_values": [ - "side_by_side", - "fields", - 1, - 1, - "" - ] - }, - { - "id": 1, - "type": "GeomPackLoadMesh", - "pos": [ - -502, - -58 - ], - "size": [ - 270, - 78 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "mesh", - "type": "TRIMESH", - "links": [ - 1, - 9 - ] - }, - { - "name": "texture", - "type": "IMAGE", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "0.1.1", - "Node name for S&R": "GeomPackLoadMesh" - }, - "widgets_values": [ - "3d/truck.obj" - ] - }, - { - "id": 6, - "type": "GeomPackComputeNormals", - "pos": [ - -347.74999999999943, - 187.20312500000009 - ], - "size": [ - 292.056640625, - 58 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "trimesh", - "type": "TRIMESH", - "link": 9 - } - ], - "outputs": [ - { - "name": "mesh_with_normals", - "type": "TRIMESH", - "links": [ - 12 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "991c7a75886f50d567e5ed6d36aed06d0729a938", - "Node name for S&R": "GeomPackComputeNormals" - }, - "widgets_values": [ - "true" - ] - }, - { - "id": 7, - "type": "GeomPackComputeNormals", - "pos": [ - -360.8229166666663, - 291.45312499999994 - ], - "size": [ - 292.056640625, - 58 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "name": "trimesh", - "type": "TRIMESH", - "link": 10 - } - ], - "outputs": [ - { - "name": "mesh_with_normals", - "type": "TRIMESH", - "links": [ - 11 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "991c7a75886f50d567e5ed6d36aed06d0729a938", - "Node name for S&R": "GeomPackComputeNormals" - }, - "widgets_values": [ - "true" - ] - }, - { - "id": 2, - "type": "GeomPackFixNormals", - "pos": [ - -175, - -63 - ], - "size": [ - 270, - 78 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [ - { - "name": "trimesh", - "type": "TRIMESH", - "link": 1 - } - ], - "outputs": [ - { - "name": "fixed_mesh", - "type": "TRIMESH", - "links": [ - 10 - ] - }, - { - "name": "info", - "type": "STRING", - "links": [ - 8 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "0.1.1", - "Node name for S&R": "GeomPackFixNormals" - }, - "widgets_values": [ - "igl_bfs" - ] - } - ], - "links": [ - [ - 1, - 1, - 0, - 2, - 0, - "TRIMESH" - ], - [ - 9, - 1, - 0, - 6, - 0, - "TRIMESH" - ], - [ - 10, - 2, - 0, - 7, - 0, - "TRIMESH" - ], - [ - 11, - 7, - 0, - 4, - 1, - "TRIMESH" - ], - [ - 12, - 6, - 0, - 4, - 0, - "TRIMESH" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.75, - "offset": [ - 934.9999999999997, - 146.08333333333334 - ] - }, - "frontendVersion": "1.30.6" - }, - "version": 0.4 -} \ No newline at end of file +{"id":"f3e4d5c6-7b8a-9012-cdef-123456789012","revision":0,"last_node_id":8,"last_link_id":14,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-502,-58],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[1,9]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"0.1.1","Node name for S&R":"GeomPackLoadMesh"},"widgets_values":["3d/truck.obj"]},{"id":2,"type":"GeomPackFixNormals","pos":[-175,-63],"size":[270,110],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":1},{"localized_name":"method","name":"method","type":"COMBO","widget":{"name":"method"},"link":null}],"outputs":[{"localized_name":"fixed_mesh","name":"fixed_mesh","type":"TRIMESH","links":[10]},{"localized_name":"info","name":"info","type":"STRING","links":[8]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"0.1.1","Node name for S&R":"GeomPackFixNormals"},"widgets_values":["igl_bfs",""]},{"id":6,"type":"GeomPackComputeNormals","pos":[-347.74999999999943,187.20312500000009],"size":[292.056640625,58],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":9},{"localized_name":"smooth_vertex_normals","name":"smooth_vertex_normals","type":"COMBO","widget":{"name":"smooth_vertex_normals"},"link":null}],"outputs":[{"localized_name":"mesh_with_normals","name":"mesh_with_normals","type":"TRIMESH","links":[13]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackComputeNormals"},"widgets_values":["true"]},{"id":7,"type":"GeomPackComputeNormals","pos":[-360.8229166666663,291.45312499999994],"size":[292.056640625,58],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":10},{"localized_name":"smooth_vertex_normals","name":"smooth_vertex_normals","type":"COMBO","widget":{"name":"smooth_vertex_normals"},"link":null}],"outputs":[{"localized_name":"mesh_with_normals","name":"mesh_with_normals","type":"TRIMESH","links":[14]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"991c7a75886f50d567e5ed6d36aed06d0729a938","Node name for S&R":"GeomPackComputeNormals"},"widgets_values":["true"]},{"id":8,"type":"GeomPackPreviewMeshDual","pos":[64.0885416666671,143.14583333333331],"size":[768,826],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":13},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":14},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"2bc968b6282e2754cef4b5507346e0a9ebdbf32a","Node name for S&R":"GeomPackPreviewMeshDual"},"widgets_values":["side_by_side","fields",1,1,false,"{\"position\":[2.1230389037522457,2.254177889080077,-2.3107558874613097],\"focalPoint\":[0,0,0],\"viewUp\":[-0.37864046226114645,0.8119761508244989,0.4442140596952062]}","normal_x",""]}],"links":[[1,1,0,2,0,"TRIMESH"],[9,1,0,6,0,"TRIMESH"],[10,2,0,7,0,"TRIMESH"],[13,6,0,8,0,"TRIMESH"],[14,7,0,8,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.75,"offset":[935.9947916666663,198.18750000000003]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/fix_self_intersection.json b/workflows/fix_self_intersection.json index c8b03b2d..e45c9083 100644 --- a/workflows/fix_self_intersection.json +++ b/workflows/fix_self_intersection.json @@ -1 +1 @@ -{"id":"94c1c61e-cf5c-42a8-b9ec-914bb4f038ea","revision":0,"last_node_id":22,"last_link_id":36,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-857.4475596051225,-67.3004633654837],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[19]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/camelhead.off"]},{"id":17,"type":"GeomPackFixSelfIntersectionsByPerturbation","pos":[-628.2602741818372,99.13388533335451],"size":[319.319921875,174],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":23},{"localized_name":"epsilon","name":"epsilon","shape":7,"type":"FLOAT","widget":{"name":"epsilon"},"link":null},{"localized_name":"max_iterations","name":"max_iterations","shape":7,"type":"INT","widget":{"name":"max_iterations"},"link":null},{"localized_name":"direction","name":"direction","shape":7,"type":"COMBO","widget":{"name":"direction"},"link":null},{"localized_name":"scale_by_intersection_count","name":"scale_by_intersection_count","shape":7,"type":"BOOLEAN","widget":{"name":"scale_by_intersection_count"},"link":null},{"localized_name":"re_detect_after_fix","name":"re_detect_after_fix","shape":7,"type":"BOOLEAN","widget":{"name":"re_detect_after_fix"},"link":null}],"outputs":[{"localized_name":"fixed_mesh","name":"fixed_mesh","type":"TRIMESH","links":[35]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"8b8322e2f784d84097cd3427f097b55dc9a29d2a","Node name for S&R":"GeomPackFixSelfIntersectionsByPerturbation","cnr_id":"comfyui-geometrypack"},"widgets_values":[0.0001,12,"adaptive",true,true]},{"id":22,"type":"GeomPackDetectSelfIntersections","pos":[-246.54255743342944,131.98867129323492],"size":[177.6328125,46],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":35}],"outputs":[{"localized_name":"mesh_with_field","name":"mesh_with_field","type":"TRIMESH","links":[36]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"abe9ed9726622d0f29e3936feaf6c1aa446914a3","Node name for S&R":"GeomPackDetectSelfIntersections"}},{"id":14,"type":"GeomPackDetectSelfIntersections","pos":[-520.8806866148459,-180.529783138655],"size":[210,178],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":19}],"outputs":[{"localized_name":"mesh_with_field","name":"mesh_with_field","type":"TRIMESH","links":[23,32]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"c77434120c2984b0ad1dd308c733117a855a8a36","Node name for S&R":"GeomPackDetectSelfIntersections","cnr_id":"comfyui-geometrypack"},"widgets_values":[]},{"id":21,"type":"GeomPackPreviewMeshDual","pos":[11.636891884746433,-233.50651464931806],"size":[768,834],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":32},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":36},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"1fcec6e19dca5e04ec71d204dbe8ef1828885062","Node name for S&R":"GeomPackPreviewMeshDual","cnr_id":"comfyui-geometrypack"},"widgets_values":["side_by_side","fields",1,1,true,"{\"position\":[-0.09236526786018014,0.17034567262454137,0.11403091642671599],\"focalPoint\":[0.000001996755599975586,-0.0636419951915741,-0.03211300075054169],\"viewUp\":[-0.4041614428850428,0.36444564436893356,-0.8389474956072003]}","intersection_flag",""]}],"links":[[19,1,0,14,0,"TRIMESH"],[23,14,0,17,0,"TRIMESH"],[32,14,0,21,0,"TRIMESH"],[35,17,0,22,0,"TRIMESH"],[36,22,0,21,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.7741103156266208,"offset":[1009.2124419215274,484.727370804141]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id":"94c1c61e-cf5c-42a8-b9ec-914bb4f038ea","revision":0,"last_node_id":23,"last_link_id":36,"nodes":[{"id":1,"type":"GeomPackLoadMesh","pos":[-857.4475596051225,-67.3004633654837],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[19]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"253a956368261760da54dc96750c2ab0224e2b1f","Node name for S&R":"GeomPackLoadMesh","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["3d/camelhead.off"]},{"id":17,"type":"GeomPackFixSelfIntersectionsByPerturbation","pos":[-628.2602741818372,99.13388533335451],"size":[319.319921875,206],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":23},{"localized_name":"epsilon","name":"epsilon","shape":7,"type":"FLOAT","widget":{"name":"epsilon"},"link":null},{"localized_name":"max_iterations","name":"max_iterations","shape":7,"type":"INT","widget":{"name":"max_iterations"},"link":null},{"localized_name":"direction","name":"direction","shape":7,"type":"COMBO","widget":{"name":"direction"},"link":null},{"localized_name":"scale_by_intersection_count","name":"scale_by_intersection_count","shape":7,"type":"BOOLEAN","widget":{"name":"scale_by_intersection_count"},"link":null},{"localized_name":"re_detect_after_fix","name":"re_detect_after_fix","shape":7,"type":"BOOLEAN","widget":{"name":"re_detect_after_fix"},"link":null}],"outputs":[{"localized_name":"fixed_mesh","name":"fixed_mesh","type":"TRIMESH","links":[35]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"8b8322e2f784d84097cd3427f097b55dc9a29d2a","Node name for S&R":"GeomPackFixSelfIntersectionsByPerturbation","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[0.0001,12,"adaptive",true,true,""]},{"id":22,"type":"GeomPackDetectSelfIntersections","pos":[-246.54255743342944,131.98867129323492],"size":[210,86],"flags":{},"order":3,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":35}],"outputs":[{"localized_name":"mesh_with_field","name":"mesh_with_field","type":"TRIMESH","links":[36]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"abe9ed9726622d0f29e3936feaf6c1aa446914a3","Node name for S&R":"GeomPackDetectSelfIntersections","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[""]},{"id":21,"type":"GeomPackPreviewMeshDual","pos":[11.636891884746433,-233.50651464931806],"size":[768,834],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":32},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":36},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null},{"localized_name":"show_edges","name":"show_edges","shape":7,"type":"BOOLEAN","widget":{"name":"show_edges"},"link":null},{"localized_name":"camera_state","name":"camera_state","shape":7,"type":"STRING","widget":{"name":"camera_state"},"link":null},{"localized_name":"selected_field","name":"selected_field","shape":7,"type":"STRING","widget":{"name":"selected_field"},"link":null}],"outputs":[],"properties":{"cnr_id":"comfyui-geometrypack","ver":"1fcec6e19dca5e04ec71d204dbe8ef1828885062","Node name for S&R":"GeomPackPreviewMeshDual","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":["side_by_side","fields",1,1,true,"{\"position\":[-0.09236526786018014,0.17034567262454137,0.11403091642671599],\"focalPoint\":[0.000001996755599975586,-0.0636419951915741,-0.03211300075054169],\"viewUp\":[-0.4041614428850428,0.36444564436893356,-0.8389474956072003]}","intersection_flag",""]},{"id":14,"type":"GeomPackDetectSelfIntersections","pos":[-520.8806866148459,-180.529783138655],"size":[253.19681905131227,86],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":19}],"outputs":[{"localized_name":"mesh_with_field","name":"mesh_with_field","type":"TRIMESH","links":[23,32]},{"localized_name":"info","name":"info","type":"STRING","links":[]}],"properties":{"cnr_id":"comfyui-geometrypack","ver":"c77434120c2984b0ad1dd308c733117a855a8a36","Node name for S&R":"GeomPackDetectSelfIntersections","aux_id":"PozzettiAndrea/ComfyUI-GeometryPack"},"widgets_values":[""]}],"links":[[19,1,0,14,0,"TRIMESH"],[23,14,0,17,0,"TRIMESH"],[32,14,0,21,0,"TRIMESH"],[35,17,0,22,0,"TRIMESH"],[36,22,0,21,1,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":1.5085220093479947,"offset":[703.8743037171953,308.4955814894071]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file diff --git a/workflows/refine_mesh.json b/workflows/refine_mesh.json index 39c37e94..43214791 100644 --- a/workflows/refine_mesh.json +++ b/workflows/refine_mesh.json @@ -1 +1 @@ -{"id":"r6e7d8c9-0b1a-2345-f678-456789012345","revision":0,"last_node_id":4,"last_link_id":6,"nodes":[{"id":3,"type":"GeomPackPreviewMeshDual","pos":[120.60416666666666,144.38541666666669],"size":[802,848],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"mesh_1","name":"mesh_1","type":"TRIMESH","link":6},{"localized_name":"mesh_2","name":"mesh_2","type":"TRIMESH","link":5},{"localized_name":"layout","name":"layout","shape":7,"type":"COMBO","widget":{"name":"layout"},"link":null},{"localized_name":"mode","name":"mode","shape":7,"type":"COMBO","widget":{"name":"mode"},"link":null},{"localized_name":"opacity_1","name":"opacity_1","shape":7,"type":"FLOAT","widget":{"name":"opacity_1"},"link":null},{"localized_name":"opacity_2","name":"opacity_2","shape":7,"type":"FLOAT","widget":{"name":"opacity_2"},"link":null}],"outputs":[],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"0.1.1","Node name for S&R":"GeomPackPreviewMeshDual","cnr_id":"comfyui-geometrypack"},"widgets_values":["side_by_side","fields",1,1,""]},{"id":1,"type":"GeomPackLoadMesh","pos":[-502,-58],"size":[270,78],"flags":{},"order":0,"mode":0,"inputs":[{"localized_name":"file_path","name":"file_path","type":"COMBO","widget":{"name":"file_path"},"link":null}],"outputs":[{"localized_name":"mesh","name":"mesh","type":"TRIMESH","links":[4,6]},{"localized_name":"texture","name":"texture","type":"IMAGE","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"0.1.1","Node name for S&R":"GeomPackLoadMesh","cnr_id":"comfyui-geometrypack"},"widgets_values":["3d/Stanford_Bunny.stl"]},{"id":4,"type":"RefineMesh","pos":[-315.1250000000004,148.578125],"size":[286.501953125,198],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"trimesh","name":"trimesh","type":"TRIMESH","link":4},{"localized_name":"operation","name":"operation","type":"COMBO","widget":{"name":"operation"},"link":null},{"localized_name":"target_face_count","name":"target_face_count","shape":7,"type":"INT","widget":{"name":"target_face_count"},"link":null},{"localized_name":"decimation_method","name":"decimation_method","shape":7,"type":"COMBO","widget":{"name":"decimation_method"},"link":null},{"localized_name":"subdivision_iterations","name":"subdivision_iterations","shape":7,"type":"INT","widget":{"name":"subdivision_iterations"},"link":null},{"localized_name":"smoothing_iterations","name":"smoothing_iterations","shape":7,"type":"INT","widget":{"name":"smoothing_iterations"},"link":null},{"localized_name":"lambda_factor","name":"lambda_factor","shape":7,"type":"FLOAT","widget":{"name":"lambda_factor"},"link":null}],"outputs":[{"localized_name":"refined_mesh","name":"refined_mesh","type":"TRIMESH","links":[5]},{"localized_name":"info","name":"info","type":"STRING","links":null}],"properties":{"aux_id":"PozzettiAndrea/ComfyUI-GeometryPack","ver":"c5dfab62adf5e57a1800306b9c6d495f4dd52a43","Node name for S&R":"RefineMesh"},"widgets_values":["decimation",5000,"trimesh",1,5,0.5]}],"links":[[4,1,0,4,0,"TRIMESH"],[5,4,0,3,1,"TRIMESH"],[6,1,0,3,0,"TRIMESH"]],"groups":[],"config":{},"extra":{"ds":{"scale":0.75,"offset":[865.7916666666675,261.421875]},"frontendVersion":"1.30.6","workflowRendererVersion":"LG"},"version":0.4} \ No newline at end of file +{"id": "r6e7d8c9-0b1a-2345-f678-456789012345", "revision": 0, "last_node_id": 4, "last_link_id": 6, "nodes": [{"id": 3, "type": "GeomPackPreviewMeshDual", "pos": [120.60416666666666, 144.38541666666669], "size": [802, 848], "flags": {}, "order": 2, "mode": 0, "inputs": [{"localized_name": "mesh_1", "name": "mesh_1", "type": "TRIMESH", "link": 6}, {"localized_name": "mesh_2", "name": "mesh_2", "type": "TRIMESH", "link": 5}, {"localized_name": "layout", "name": "layout", "shape": 7, "type": "COMBO", "widget": {"name": "layout"}, "link": null}, {"localized_name": "mode", "name": "mode", "shape": 7, "type": "COMBO", "widget": {"name": "mode"}, "link": null}, {"localized_name": "opacity_1", "name": "opacity_1", "shape": 7, "type": "FLOAT", "widget": {"name": "opacity_1"}, "link": null}, {"localized_name": "opacity_2", "name": "opacity_2", "shape": 7, "type": "FLOAT", "widget": {"name": "opacity_2"}, "link": null}], "outputs": [], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "0.1.1", "Node name for S&R": "GeomPackPreviewMeshDual", "cnr_id": "comfyui-geometrypack"}, "widgets_values": ["side_by_side", "fields", 1, 1, true, "", ""]}, {"id": 1, "type": "GeomPackLoadMesh", "pos": [-502, -58], "size": [270, 78], "flags": {}, "order": 0, "mode": 0, "inputs": [{"localized_name": "file_path", "name": "file_path", "type": "COMBO", "widget": {"name": "file_path"}, "link": null}], "outputs": [{"localized_name": "mesh", "name": "mesh", "type": "TRIMESH", "links": [4, 6]}, {"localized_name": "texture", "name": "texture", "type": "IMAGE", "links": null}], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "0.1.1", "Node name for S&R": "GeomPackLoadMesh", "cnr_id": "comfyui-geometrypack"}, "widgets_values": ["3d/Stanford_Bunny.stl"]}, {"id": 4, "type": "RefineMesh", "pos": [-315.1250000000004, 148.578125], "size": [286.501953125, 198], "flags": {}, "order": 1, "mode": 0, "inputs": [{"localized_name": "trimesh", "name": "trimesh", "type": "TRIMESH", "link": 4}, {"localized_name": "operation", "name": "operation", "type": "COMBO", "widget": {"name": "operation"}, "link": null}, {"localized_name": "target_face_count", "name": "target_face_count", "shape": 7, "type": "INT", "widget": {"name": "target_face_count"}, "link": null}, {"localized_name": "decimation_method", "name": "decimation_method", "shape": 7, "type": "COMBO", "widget": {"name": "decimation_method"}, "link": null}, {"localized_name": "subdivision_iterations", "name": "subdivision_iterations", "shape": 7, "type": "INT", "widget": {"name": "subdivision_iterations"}, "link": null}, {"localized_name": "smoothing_iterations", "name": "smoothing_iterations", "shape": 7, "type": "INT", "widget": {"name": "smoothing_iterations"}, "link": null}, {"localized_name": "lambda_factor", "name": "lambda_factor", "shape": 7, "type": "FLOAT", "widget": {"name": "lambda_factor"}, "link": null}], "outputs": [{"localized_name": "refined_mesh", "name": "refined_mesh", "type": "TRIMESH", "links": [5]}, {"localized_name": "info", "name": "info", "type": "STRING", "links": null}], "properties": {"aux_id": "PozzettiAndrea/ComfyUI-GeometryPack", "ver": "c5dfab62adf5e57a1800306b9c6d495f4dd52a43", "Node name for S&R": "RefineMesh"}, "widgets_values": ["decimation", 5000, "trimesh", 1, 5, 0.5]}], "links": [[4, 1, 0, 4, 0, "TRIMESH"], [5, 4, 0, 3, 1, "TRIMESH"], [6, 1, 0, 3, 0, "TRIMESH"]], "groups": [], "config": {}, "extra": {"ds": {"scale": 0.75, "offset": [865.7916666666675, 261.421875]}, "frontendVersion": "1.30.6", "workflowRendererVersion": "LG"}, "version": 0.4} \ No newline at end of file diff --git a/workflows/side_by_side_viewer.json b/workflows/side_by_side_viewer.json index 77bd9613..3b02e24d 100644 --- a/workflows/side_by_side_viewer.json +++ b/workflows/side_by_side_viewer.json @@ -1,149 +1 @@ -{ - "id": "99d7a206-3afe-4ab6-ad84-842258739192", - "revision": 0, - "last_node_id": 7, - "last_link_id": 11, - "nodes": [ - { - "id": 2, - "type": "GeomPackCreatePrimitive", - "pos": [ - -385.07737412512756, - 169.36276444668482 - ], - "size": [ - 300, - 150 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "mesh", - "type": "TRIMESH", - "links": [ - 11 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", - "Node name for S&R": "GeomPackCreatePrimitive" - }, - "widgets_values": [ - "sphere", - 2.5, - 2 - ] - }, - { - "id": 1, - "type": "GeomPackCreatePrimitive", - "pos": [ - -406.7715890011608, - -54.81078927232348 - ], - "size": [ - 300, - 150 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "mesh", - "type": "TRIMESH", - "links": [ - 10 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", - "Node name for S&R": "GeomPackCreatePrimitive" - }, - "widgets_values": [ - "cube", - 2, - 1 - ] - }, - { - "id": 7, - "type": "GeomPackPreviewMeshDual", - "pos": [ - 290.82090195958176, - -94.5593042516624 - ], - "size": [ - 768, - 834 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "mesh_1", - "type": "TRIMESH", - "link": 10 - }, - { - "name": "mesh_2", - "type": "TRIMESH", - "link": 11 - } - ], - "outputs": [], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "a22feb725fe9afaf6cdcfa75002a514292fcec9a", - "Node name for S&R": "GeomPackPreviewMeshDual" - }, - "widgets_values": [ - "side_by_side", - "fields", - 1, - 1, - "" - ] - } - ], - "links": [ - [ - 10, - 1, - 0, - 7, - 0, - "TRIMESH" - ], - [ - 11, - 2, - 0, - 7, - 1, - "TRIMESH" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.9680000000000015, - "offset": [ - 616.5832173585986, - 348.8529509458769 - ] - }, - "frontendVersion": "1.30.6" - }, - "version": 0.4 -} \ No newline at end of file +{"id": "99d7a206-3afe-4ab6-ad84-842258739192", "revision": 0, "last_node_id": 7, "last_link_id": 11, "nodes": [{"id": 2, "type": "GeomPackCreatePrimitive", "pos": [-385.07737412512756, 169.36276444668482], "size": [300, 150], "flags": {}, "order": 0, "mode": 0, "inputs": [], "outputs": [{"name": "mesh", "type": "TRIMESH", "links": [11]}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", "Node name for S&R": "GeomPackCreatePrimitive"}, "widgets_values": ["sphere", 2.5, 2]}, {"id": 1, "type": "GeomPackCreatePrimitive", "pos": [-406.7715890011608, -54.81078927232348], "size": [300, 150], "flags": {}, "order": 1, "mode": 0, "inputs": [], "outputs": [{"name": "mesh", "type": "TRIMESH", "links": [10]}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "8b8322e2f784d84097cd3427f097b55dc9a29d2a", "Node name for S&R": "GeomPackCreatePrimitive"}, "widgets_values": ["cube", 2, 1]}, {"id": 7, "type": "GeomPackPreviewMeshDual", "pos": [290.82090195958176, -94.5593042516624], "size": [768, 834], "flags": {}, "order": 2, "mode": 0, "inputs": [{"name": "mesh_1", "type": "TRIMESH", "link": 10}, {"name": "mesh_2", "type": "TRIMESH", "link": 11}], "outputs": [], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "a22feb725fe9afaf6cdcfa75002a514292fcec9a", "Node name for S&R": "GeomPackPreviewMeshDual"}, "widgets_values": ["side_by_side", "fields", 1, 1, true, "", ""]}], "links": [[10, 1, 0, 7, 0, "TRIMESH"], [11, 2, 0, 7, 1, "TRIMESH"]], "groups": [], "config": {}, "extra": {"ds": {"scale": 0.9680000000000015, "offset": [616.5832173585986, 348.8529509458769]}, "frontendVersion": "1.30.6"}, "version": 0.4} \ No newline at end of file diff --git a/workflows/surface_reconstruction.json b/workflows/surface_reconstruction.json index 4a298f5a..8b33e7f8 100644 --- a/workflows/surface_reconstruction.json +++ b/workflows/surface_reconstruction.json @@ -1,226 +1 @@ -{ - "id": "58a80d52-612a-405e-b687-4696702fb5a6", - "revision": 1, - "last_node_id": 28, - "last_link_id": 39, - "nodes": [ - { - "id": 21, - "type": "GeomPackMeshToPointCloud", - "pos": [ - -250.96144566438386, - -55.75910409670366 - ], - "size": [ - 270, - 106 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [ - { - "name": "trimesh", - "type": "TRIMESH", - "link": 26 - } - ], - "outputs": [ - { - "name": "point_cloud", - "type": "TRIMESH", - "links": [ - 27 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "d616ab2f28493cf34f723ed59ea6747b61519c9d", - "Node name for S&R": "GeomPackMeshToPointCloud" - }, - "widgets_values": [ - "surface_sampling", - 10000, - "uniform", - "true" - ] - }, - { - "id": 22, - "type": "GeomPackReconstructSurface", - "pos": [ - 83.7654396661942, - -50.29923193761277 - ], - "size": [ - 270, - 222 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "points", - "type": "TRIMESH", - "link": 27 - } - ], - "outputs": [ - { - "name": "reconstructed_mesh", - "type": "TRIMESH", - "links": [ - 39 - ] - }, - { - "name": "info", - "type": "STRING", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "d616ab2f28493cf34f723ed59ea6747b61519c9d", - "Node name for S&R": "GeomPackReconstructSurface" - }, - "widgets_values": [ - "poisson", - 4, - 1.0, - 0, - 0, - "true", - 0.2 - ] - }, - { - "id": 20, - "type": "GeomPackLoadMesh", - "pos": [ - -582.83935113959, - -50.27501964422433 - ], - "size": [ - 270, - 78 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "mesh", - "type": "TRIMESH", - "links": [ - 26, - 38 - ] - }, - { - "name": "texture", - "type": "IMAGE", - "links": null - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "d616ab2f28493cf34f723ed59ea6747b61519c9d", - "Node name for S&R": "GeomPackLoadMesh" - }, - "widgets_values": [ - "3d/Stanford_Bunny.stl" - ] - }, - { - "id": 28, - "type": "GeomPackPreviewMeshDual", - "pos": [ - -196.6668574739802, - 247.0682656414106 - ], - "size": [ - 768, - 826 - ], - "flags": {}, - "order": 3, - "mode": 0, - "inputs": [ - { - "name": "mesh_1", - "type": "TRIMESH", - "link": 38 - }, - { - "name": "mesh_2", - "type": "TRIMESH", - "link": 39 - } - ], - "outputs": [], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "991c7a75886f50d567e5ed6d36aed06d0729a938", - "Node name for S&R": "GeomPackPreviewMeshDual" - }, - "widgets_values": [ - "side_by_side", - "fields", - 1, - 1, - "" - ] - } - ], - "links": [ - [ - 26, - 20, - 0, - 21, - 0, - "TRIMESH" - ], - [ - 27, - 21, - 0, - 22, - 0, - "TRIMESH" - ], - [ - 38, - 20, - 0, - 28, - 0, - "TRIMESH" - ], - [ - 39, - 22, - 0, - 28, - 1, - "TRIMESH" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.8000000000000014, - "offset": [ - 1161.036974661478, - 152.78036717108867 - ] - }, - "frontendVersion": "1.30.6" - }, - "version": 0.4 -} \ No newline at end of file +{"id": "58a80d52-612a-405e-b687-4696702fb5a6", "revision": 1, "last_node_id": 28, "last_link_id": 39, "nodes": [{"id": 21, "type": "GeomPackMeshToPointCloud", "pos": [-250.96144566438386, -55.75910409670366], "size": [270, 106], "flags": {}, "order": 1, "mode": 0, "inputs": [{"name": "trimesh", "type": "TRIMESH", "link": 26}], "outputs": [{"name": "point_cloud", "type": "TRIMESH", "links": [27]}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "d616ab2f28493cf34f723ed59ea6747b61519c9d", "Node name for S&R": "GeomPackMeshToPointCloud"}, "widgets_values": ["surface_sampling", 10000, "uniform", "true"]}, {"id": 22, "type": "GeomPackReconstructSurface", "pos": [83.7654396661942, -50.29923193761277], "size": [270, 222], "flags": {}, "order": 2, "mode": 0, "inputs": [{"name": "points", "type": "TRIMESH", "link": 27}], "outputs": [{"name": "reconstructed_mesh", "type": "TRIMESH", "links": [39]}, {"name": "info", "type": "STRING", "links": null}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "d616ab2f28493cf34f723ed59ea6747b61519c9d", "Node name for S&R": "GeomPackReconstructSurface"}, "widgets_values": ["poisson", 4, 1.0, 0, 0, "true", 0.2]}, {"id": 20, "type": "GeomPackLoadMesh", "pos": [-582.83935113959, -50.27501964422433], "size": [270, 78], "flags": {}, "order": 0, "mode": 0, "inputs": [], "outputs": [{"name": "mesh", "type": "TRIMESH", "links": [26, 38]}, {"name": "texture", "type": "IMAGE", "links": null}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "d616ab2f28493cf34f723ed59ea6747b61519c9d", "Node name for S&R": "GeomPackLoadMesh"}, "widgets_values": ["3d/Stanford_Bunny.stl"]}, {"id": 28, "type": "GeomPackPreviewMeshDual", "pos": [-196.6668574739802, 247.0682656414106], "size": [768, 826], "flags": {}, "order": 3, "mode": 0, "inputs": [{"name": "mesh_1", "type": "TRIMESH", "link": 38}, {"name": "mesh_2", "type": "TRIMESH", "link": 39}], "outputs": [], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "991c7a75886f50d567e5ed6d36aed06d0729a938", "Node name for S&R": "GeomPackPreviewMeshDual"}, "widgets_values": ["side_by_side", "fields", 1, 1, true, "", ""]}], "links": [[26, 20, 0, 21, 0, "TRIMESH"], [27, 21, 0, 22, 0, "TRIMESH"], [38, 20, 0, 28, 0, "TRIMESH"], [39, 22, 0, 28, 1, "TRIMESH"]], "groups": [], "config": {}, "extra": {"ds": {"scale": 0.8000000000000014, "offset": [1161.036974661478, 152.78036717108867]}, "frontendVersion": "1.30.6"}, "version": 0.4} \ No newline at end of file diff --git a/workflows/transform.json b/workflows/transform.json index ccd0151d..4bda61f5 100644 --- a/workflows/transform.json +++ b/workflows/transform.json @@ -1,170 +1 @@ -{ - "id": "c3d4e5f6-7890-12ab-cdef-345678901cde", - "revision": 0, - "last_node_id": 6, - "last_link_id": 10, - "nodes": [ - { - "id": 5, - "type": "GeomPackCreatePrimitive", - "pos": [ - -802.9354063816817, - 5.4249805979248436 - ], - "size": [ - 270, - 106 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "mesh", - "type": "TRIMESH", - "links": [ - 5, - 9 - ] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "84b2d1816c08ec3cc7d3a4fffa90692669e17507", - "Node name for S&R": "GeomPackCreatePrimitive" - }, - "widgets_values": [ - "cube", - 1, - 2 - ] - }, - { - "id": 6, - "type": "GeomPackPreviewMeshDual", - "pos": [ - 94.65433943293444, - -69.57587262019403 - ], - "size": [ - 768, - 834 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "mesh_1", - "type": "TRIMESH", - "link": 9 - }, - { - "name": "mesh_2", - "type": "TRIMESH", - "link": 10 - } - ], - "outputs": [], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "84b2d1816c08ec3cc7d3a4fffa90692669e17507", - "Node name for S&R": "GeomPackPreviewMeshDual" - }, - "widgets_values": [ - "overlay", - "fields", - 1, - 1, - "" - ] - }, - { - "id": 2, - "type": "GeomPackTransformMesh", - "pos": [ - -400, - 0 - ], - "size": [ - 320, - 150 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [ - { - "name": "trimesh", - "type": "TRIMESH", - "link": 5 - } - ], - "outputs": [ - { - "name": "transformed_mesh", - "type": "TRIMESH", - "links": [ - 10 - ] - }, - { - "name": "info", - "type": "STRING", - "links": [] - } - ], - "properties": { - "cnr_id": "comfyui-geometrypack", - "ver": "0.1.1", - "Node name for S&R": "GeomPackTransformMesh" - }, - "widgets_values": [ - "translate", - 0.5, - 0.5, - 2 - ] - } - ], - "links": [ - [ - 5, - 5, - 0, - 2, - 0, - "TRIMESH" - ], - [ - 9, - 5, - 0, - 6, - 0, - "TRIMESH" - ], - [ - 10, - 2, - 0, - 6, - 1, - "TRIMESH" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.8230486452640794, - "offset": [ - 952.132815408061, - 279.4146957873131 - ] - }, - "frontendVersion": "1.30.6" - }, - "version": 0.4 -} \ No newline at end of file +{"id": "c3d4e5f6-7890-12ab-cdef-345678901cde", "revision": 0, "last_node_id": 6, "last_link_id": 10, "nodes": [{"id": 5, "type": "GeomPackCreatePrimitive", "pos": [-802.9354063816817, 5.4249805979248436], "size": [270, 106], "flags": {}, "order": 0, "mode": 0, "inputs": [], "outputs": [{"name": "mesh", "type": "TRIMESH", "links": [5, 9]}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "84b2d1816c08ec3cc7d3a4fffa90692669e17507", "Node name for S&R": "GeomPackCreatePrimitive"}, "widgets_values": ["cube", 1, 2]}, {"id": 6, "type": "GeomPackPreviewMeshDual", "pos": [94.65433943293444, -69.57587262019403], "size": [768, 834], "flags": {}, "order": 2, "mode": 0, "inputs": [{"name": "mesh_1", "type": "TRIMESH", "link": 9}, {"name": "mesh_2", "type": "TRIMESH", "link": 10}], "outputs": [], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "84b2d1816c08ec3cc7d3a4fffa90692669e17507", "Node name for S&R": "GeomPackPreviewMeshDual"}, "widgets_values": ["overlay", "fields", 1, 1, true, "", ""]}, {"id": 2, "type": "GeomPackTransformMesh", "pos": [-400, 0], "size": [320, 150], "flags": {}, "order": 1, "mode": 0, "inputs": [{"name": "trimesh", "type": "TRIMESH", "link": 5}], "outputs": [{"name": "transformed_mesh", "type": "TRIMESH", "links": [10]}, {"name": "info", "type": "STRING", "links": []}], "properties": {"cnr_id": "comfyui-geometrypack", "ver": "0.1.1", "Node name for S&R": "GeomPackTransformMesh"}, "widgets_values": ["translate", 0.5, 0.5, 2]}], "links": [[5, 5, 0, 2, 0, "TRIMESH"], [9, 5, 0, 6, 0, "TRIMESH"], [10, 2, 0, 6, 1, "TRIMESH"]], "groups": [], "config": {}, "extra": {"ds": {"scale": 0.8230486452640794, "offset": [952.132815408061, 279.4146957873131]}, "frontendVersion": "1.30.6"}, "version": 0.4} \ No newline at end of file From 96a68b8dba85132c66f2f6543ebfdba60ad07bfb Mon Sep 17 00:00:00 2001 From: Andrea Pozzetti Date: Fri, 13 Feb 2026 01:41:40 +0100 Subject: [PATCH 27/27] ver bump --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5f8fcb4a..61f4bacc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] -name = "ComfyUI-GeometryPack" +name = "comfyui-geometrypack" description = "CGAL - Blender - IGL - Paraview - VTK. Geometry processing nodes for ComfyUI - mesh manipulation, remeshing, hole filling, UV unwrapping, Alpha Wrapping, and 3D visualization" -version = "0.1.16" +version = "0.2.0" license = {file = "LICENSE"} [project.urls]