Skip to content

Fix inverted hex cell faces in 3D mesh visualization#62

Merged
lmoresi merged 3 commits intodevelopmentfrom
bugfix/fix-hex-viz
Mar 2, 2026
Merged

Fix inverted hex cell faces in 3D mesh visualization#62
lmoresi merged 3 commits intodevelopmentfrom
bugfix/fix-hex-viz

Conversation

@lmoresi
Copy link
Member

@lmoresi lmoresi commented Mar 2, 2026

Summary

  • Fix inverted face normals when visualizing 3D StructuredQuadBox (hexahedral) meshes
  • PETSc DMPlex returns hex vertices with bottom-face winding opposite to VTK/meshio convention — vertices 1 and 3 on the bottom face are swapped
  • Apply permutation [0, 3, 2, 1, 4, 5, 6, 7] in mesh_to_pv_mesh() before passing to meshio or direct VTK path
  • Only affects 3D hexahedra (not isSimplex() and dim == 3); 2D quads, triangles, and tetrahedra are unaffected

Closes #40

Test plan

  • Verified all 8 hex cells have positive Jacobian determinant after fix (2×2×2 mesh)
  • Verified 2D quads remain correctly oriented
  • Verified 2D simplices remain correctly oriented
  • 3D simplices unaffected (condition excludes them)

PETSc DMPlex returns hex vertices with bottom-face winding opposite to VTK
convention (CCW vs CW from above). Apply permutation [0,3,2,1,4,5,6,7] to
swap vertices 1 and 3 on the bottom face when converting to meshio/VTK format.

Closes #40

Underworld development team with AI support from Claude Code
Copilot AI review requested due to automatic review settings March 2, 2026 00:20
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes incorrect hexahedral cell vertex ordering when converting Underworld3 StructuredQuadBox (3D, non-simplex) meshes to PyVista, preventing inverted faces / normals during visualization (as reported in #40).

Changes:

  • Reorders PETSc DMPlex hexahedron vertex indices to match VTK/meshio convention using permutation [0, 3, 2, 1, 4, 5, 6, 7].
  • Applies the reorder in mesh_to_pv_mesh() for dim == 3 and not isSimplex(), affecting both the meshio and direct VTK construction paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +116 to +118
if not mesh.dm.isSimplex() and mesh.dim == 3:
hex_reorder = [0, 3, 2, 1, 4, 5, 6, 7]
cell_points_list = [pts[hex_reorder] for pts in cell_points_list]
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an automated regression test for this hexahedron reordering. The repository already has optional pyvista tests; consider extending them to build a small 3D StructuredQuadBox (e.g., 2×2×2), convert via mesh_to_pv_mesh(), and assert cell volumes/Jacobians are positive so inverted faces can’t regress.

Copilot uses AI. Check for mistakes.
lmoresi added 2 commits March 2, 2026 14:00
PETSc DMPlex uses left-handed orientation for tetrahedra; VTK expects
right-handed. Swap vertices 1 and 2 ([0,2,1,3]) to correct this.

Without correct orientation, face normals point inward which can cause
shading artifacts, incorrect surface clipping, and back-face culling issues.

Verified: all 3D cell types (hex + tet) now produce positive Jacobian
determinant; 2D meshes (quad + triangle) are unaffected.

Underworld development team with AI support from Claude Code
Tests that hex and tet cells have positive Jacobian determinant after
the PETSc→VTK vertex reordering, and that 2D meshes are unaffected.

Underworld development team with AI support from Claude Code
@lmoresi lmoresi merged commit 9971667 into development Mar 2, 2026
1 check passed
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.

2 participants