@@ -47,27 +47,38 @@ impl Iterator for IndexIterator<'_> {
4747
4848impl ExactSizeIterator for IndexIterator < ' _ > { }
4949
50+ /// Source from which outline normals are derived.
51+ #[ derive( Copy , Clone , Default , PartialEq , Eq ) ]
52+ #[ non_exhaustive]
53+ pub enum GenerateOutlineNormalsFrom {
54+ /// Use vertex normals provided by the mesh. This falls back to
55+ /// `FaceNormal` if no vertex normals are available.
56+ #[ default]
57+ VertexNormal ,
58+ /// Use normals computed from face geometry.
59+ FaceNormal ,
60+ /// Use the external bisector at each vertex. This is suitable for
61+ /// non-manifold meshes.
62+ ExternalBisector ,
63+ }
64+
5065/// Settings for generating mesh outline normals.
5166#[ derive( Clone , Default ) ]
5267pub struct GenerateOutlineNormalsSettings {
53- ignore_vertex_normals : bool ,
54- stretch_edges : bool ,
68+ from : GenerateOutlineNormalsFrom ,
5569}
5670
5771/// Settings for generating mesh outline normals.
5872impl GenerateOutlineNormalsSettings {
59- /// If true, any pre-existing vertex normals are ignored and freshly
60- /// calculated face normals are used when generating outline normals.
61- pub fn with_ignore_vertex_normals ( mut self , value : bool ) -> Self {
62- self . ignore_vertex_normals = value;
73+ pub fn with_from ( mut self , value : GenerateOutlineNormalsFrom ) -> Self {
74+ self . from = value;
6375 self
6476 }
77+ }
6578
66- /// If true, an extra component is added to the generated outline normals
67- /// to angle them outwards at edges of non-manifold meshes.
68- pub fn with_stretch_edges ( mut self , value : bool ) -> Self {
69- self . stretch_edges = value;
70- self
79+ impl From < GenerateOutlineNormalsFrom > for GenerateOutlineNormalsSettings {
80+ fn from ( value : GenerateOutlineNormalsFrom ) -> Self {
81+ Self :: default ( ) . with_from ( value)
7182 }
7283}
7384
@@ -128,7 +139,11 @@ impl OutlineMeshExt for Mesh {
128139 ) ) ,
129140 } ?;
130141 let normals = match self . attribute ( Mesh :: ATTRIBUTE_NORMAL ) {
131- Some ( VertexAttributeValues :: Float32x3 ( p) ) if !settings. ignore_vertex_normals => Some ( p) ,
142+ Some ( VertexAttributeValues :: Float32x3 ( p) )
143+ if settings. from == GenerateOutlineNormalsFrom :: VertexNormal =>
144+ {
145+ Some ( p)
146+ }
132147 _ => None ,
133148 } ;
134149 let mut map = HashMap :: < [ FloatOrd ; 3 ] , Vec3 > :: with_capacity ( positions. len ( ) ) ;
@@ -142,21 +157,20 @@ impl OutlineMeshExt for Mesh {
142157 let n = map
143158 . entry ( [ FloatOrd ( p0. x ) , FloatOrd ( p0. y ) , FloatOrd ( p0. z ) ] )
144159 . or_default ( ) ;
145- * n += angle
146- * if let Some ( ns) = normals {
147- // Use vertex normal
148- Vec3 :: from ( ns[ j0] )
149- } else {
150- // Calculate face normal
151- ( p1 - p0) . cross ( p2 - p0) . normalize_or_zero ( )
152- } ;
153- if settings. stretch_edges {
160+ let vector = if settings. from == GenerateOutlineNormalsFrom :: ExternalBisector {
161+ // External bisector
154162 let face_normal = ( p1 - p0) . cross ( p2 - p0) ;
155163 let perp1 = Dir3 :: new ( face_normal. cross ( p0 - p1) ) . unwrap ( ) ;
156164 let perp2 = Dir3 :: new ( face_normal. cross ( p2 - p0) ) . unwrap ( ) ;
157- let stretch = perp1. slerp ( perp2, 0.5 ) . as_vec3 ( ) ;
158- * n += angle * stretch;
159- }
165+ perp1. slerp ( perp2, 0.5 ) . as_vec3 ( )
166+ } else if let Some ( ns) = normals {
167+ // Use vertex normal
168+ Vec3 :: from ( ns[ j0] )
169+ } else {
170+ // Calculate face normal
171+ ( p1 - p0) . cross ( p2 - p0) . normalize_or_zero ( )
172+ } ;
173+ * n += angle * vector;
160174 }
161175 }
162176 let mut outlines = Vec :: with_capacity ( positions. len ( ) ) ;
0 commit comments