How the Smooth Normal Degrees Parameter Affects Feature Detection in AutoRemesher
TLDR: In huxingyi/autoremesher, the smooth normal degrees parameter controls PN-Triangle subdivision to create smoother projection surfaces, but it does not directly influence which edges are classified as features—feature detection remains exclusively governed by the sharp-edge angle threshold.
The smooth normal degrees parameter in AutoRemesher configures an optional preprocessing stage that smooths the input mesh before remeshing iterations begin. While this setting affects the geometric surface used for vertex projection in isotropicremesher.cpp, it operates independently of the feature detection logic that identifies sharp creases and boundaries. Understanding this distinction is crucial for achieving predictable results when remeshing CAD or scanned models with hard edges.
What the Smooth Normal Degrees Parameter Controls
When you invoke setSmoothNormalDegrees() with a positive value (declared in thirdparty/isotropicremesher/isotropicremesher.h), the remesher executes a three-stage smoothing pipeline inside IsotropicRemesher::remesh() before the main remeshing iterations commence.
Computing Per-Vertex Smooth Normals
The method computeSmoothVertexNormals() calculates an angle-area weighted average of adjoining face normals for each vertex. It filters these contributions using an angular threshold converted from degrees to radians (thresholdRadians = degrees·π/180), storing the results in the member variable m_smoothVertexNormals. These values are subsequently copied to the half-edge mesh vertices via vertex->_smoothNormal for use during subdivision.
PN-Triangle Subdivision and AABB Tree Construction
Next, subdivideMeshWithPNTriangles() generates refined geometry by computing edge mid-points using the smooth normals (pnTriangleEdgeMidpoint). This process creates m_smoothVertices and m_smoothTriangles representing a higher-resolution curved surface. The system then builds a new AABB tree from this subdivided mesh, which the projection step uses instead of the original piecewise-linear geometry to guide vertex placement.
How Feature Detection Actually Works
Feature detection occurs independently in IsotropicHalfedgeMesh::featureEdges(), defined in thirdparty/isotropicremesher/isotropichalfedgemesh.cpp. This routine marks an edge as "featured" when the dihedral angle between two incident faces exceeds the sharp-edge threshold set via setSharpEdgeIncludedAngle().
Crucially, the algorithm examines raw face normals (leftFace->_normal) and completely ignores the smooth normals computed earlier. The detection logic checks m_sharpEdgeThresholdRadians and operates on the original mesh topology, not the PN-Triangle subdivided version. Consequently, adjusting the smooth normal degrees does not alter the set of edges identified as sharp features.
The Indirect Relationship Between Smooth Normals and Features
Although the smooth normal degrees parameter does not directly affect feature classification, it indirectly influences final mesh quality. By projecting vertices onto the smoother PN-Triangle surface rather than the original faceted geometry, the remesher can reduce the appearance of spurious artifacts in regions where the input mesh was noisy or poorly tessellated. However, genuine hard edges exceeding the sharp-edge angle threshold will remain preserved regardless of the smoothing setting, because feature detection relies solely on the angle between raw face normals.
Practical Configuration Example
To enable normal smoothing while maintaining explicit control over feature detection, configure both parameters as shown in this implementation pattern:
#include "isotropicremesher.h"
// Initialize remesher with your mesh data
IsotropicRemesher remesher(vertices, triangles);
// Enable 30-degree normal smoothing for PN-Triangle subdivision
remesher.setSmoothNormalDegrees(30.0);
// Preserve edges where face normals differ by more than 30 degrees
remesher.setSharpEdgeIncludedAngle(30.0);
// Execute 5 remeshing iterations
remesher.remesh(5);
Inside IsotropicRemesher::remesh() (located in thirdparty/isotropicremesher/isotropicremesher.cpp), the implementation conditionalizes the smoothing pipeline separately from feature detection:
if (m_smoothNormalDegrees > 0.0) {
computeSmoothVertexNormals(); // Step 1: Normal smoothing
subdivideMeshWithPNTriangles(); // Step 2: PN-Triangle subdivision
// Build AABB tree from the smooth (subdivided) mesh
// Projection later uses this smoother representation
}
...
// Feature detection (independent of smooth normals)
if (m_sharpEdgeThresholdRadians > 0) {
splitLongEdges(maxTargetLengthSquared);
m_halfedgeMesh->updateTriangleNormals();
m_halfedgeMesh->featureEdges(m_sharpEdgeThresholdRadians);
}
Summary
- The smooth normal degrees parameter activates PN-Triangle subdivision by triggering
computeSmoothVertexNormals()andsubdivideMeshWithPNTriangles()inisotropicremesher.cpp. - Feature detection relies solely on the sharp-edge angle threshold in
IsotropicHalfedgeMesh::featureEdges(), examining raw face normals (leftFace->_normal) without considering smooth normals. - Smooth normals create a curved projection surface that improves vertex placement quality, but they do not alter which edges the algorithm classifies as sharp features.
- Configure both
setSmoothNormalDegrees()andsetSharpEdgeIncludedAngle()independently to control surface smoothness versus feature preservation.
Frequently Asked Questions
Does increasing smooth normal degrees reduce sharp features in the output?
No. The smooth normal degrees parameter only affects the projection surface used during vertex placement via PN-Triangle subdivision. It does not modify the feature detection logic that relies on the sharp-edge angle threshold in featureEdges(). To reduce the number of preserved sharp features, you must increase the angle threshold passed to setSharpEdgeIncludedAngle(), not the smooth normal degrees.
What value should I set for smooth normal degrees?
A typical value ranges between 15 and 45 degrees, depending on how much smoothing your input mesh requires. This value defines the angular threshold in computeSmoothVertexNormals() for including adjacent face normals in the weighted average. Set it to 0.0 to disable PN-Triangle subdivision entirely, causing vertices to project directly onto the original piecewise-linear geometry.
Why does feature detection use face normals instead of smooth normals?
The featureEdges() method in isotropichalfedgemesh.cpp uses raw face normals (leftFace->_normal) because it must detect geometric creases based on the actual dihedral angles between adjacent faces. Smooth normals represent averaged, artificial directions used for interpolating subdivision surfaces, not the true geometric discontinuities that define sharp edges in the original model.
Where is the smooth normal logic implemented in the source code?
The smooth normal logic resides in thirdparty/isotropicremesher/isotropicremesher.cpp, specifically within computeSmoothVertexNormals(), subdivideMeshWithPNTriangles(), and the conditional block inside remesh(). The public API declarations are located in thirdparty/isotropicremesher/isotropicremesher.h, while the isolated feature detection routine remains in thirdparty/isotropicremesher/isotropichalfedgemesh.cpp.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →