Skip to content

feat: Add sharp edge preservation to dual contouring#19

Open
BizaNator wants to merge 1 commit intoJeffreyXiang:mainfrom
BizaNator:feat/sharp-edge-preservation
Open

feat: Add sharp edge preservation to dual contouring#19
BizaNator wants to merge 1 commit intoJeffreyXiang:mainfrom
BizaNator:feat/sharp-edge-preservation

Conversation

@BizaNator
Copy link

Summary

This PR adds optional sharp edge preservation to the remesh_narrow_band_dc() function. Sharp edges and corners are often lost during dual contouring remeshing because the standard algorithm averages all edge intersection points within a voxel. This change detects sharp features by clustering intersection points based on gradient similarity and uses iterative plane projection to find optimal vertex positions that preserve these features.

Changes

  • New CUDA kernel: simple_dual_contour_sharp in src/remesh/simple_dual_contour.cu

    • Computes surface gradients at intersection points using edge direction
    • Clusters intersections by gradient similarity (normal direction)
    • Uses iterative plane projection to find optimal vertex position for sharp features
  • Python API: Two new parameters added to remesh_narrow_band_dc():

    • preserve_sharp_edges: bool = False - Enable sharp edge detection
    • sharp_angle_threshold: float = 30.0 - Angle in degrees above which edges are considered sharp
  • Binding: New function registered in src/ext.cpp

  • Header: Declaration added to src/remesh/api.h

Backward Compatibility

Fully backward compatible. Default behavior unchanged (preserve_sharp_edges=False).

Usage

import cumesh

# Standard remeshing (original behavior)
vertices, faces = cumesh.remesh_narrow_band_dc(
    vertices, faces, center, scale, resolution
)

# With sharp edge preservation
vertices, faces = cumesh.remesh_narrow_band_dc(
    vertices, faces, center, scale, resolution,
    preserve_sharp_edges=True,
    sharp_angle_threshold=30.0  # degrees
)

Test Results

Tested on meshes with sharp features (boxes, mechanical parts):

Metric Without Sharp Edges With Sharp Edges
Edges > 60° 12 1224
Max edge angle 70° 89°

Technical Details

The algorithm:

  1. For each voxel, compute gradient direction at each edge-surface intersection
  2. Cluster intersections by gradient similarity using cosine threshold
  3. If single cluster: use simple averaging (original behavior)
  4. If multiple clusters: solve simplified QEF using iterative plane projection
  5. Clamp result to voxel bounds

The gradient is computed from the edge direction and UDF sign change, which is more robust in sparse grids than querying neighboring vertices.

Add new simple_dual_contour_sharp() function that preserves sharp edges
during mesh remeshing by:

- Computing surface gradients at intersection points using edge direction
- Clustering intersection points by gradient similarity (normal direction)
- Using iterative plane projection to find optimal vertex position for
  sharp features instead of simple averaging

New parameters added to remesh_narrow_band_dc():
- preserve_sharp_edges: bool = False
- sharp_angle_threshold: float = 30.0 (degrees)

Test results show significant improvement:
- Edges > 60°: 12 (smooth) → 1224 (sharp)
- Max edge angle: 70° (smooth) → 89° (sharp)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant