Procházet zdrojové kódy

SVGLoader: Make stroke generation more robust. (#33438)

Michael Herzog před 2 měsíci
rodič
revize
91961847e3

+ 42 - 0
examples/jsm/loaders/SVGLoader.js

@@ -2663,6 +2663,22 @@ class SVGLoader extends Loader {
 					outerPoint.copy( tempV2_5 ).add( currentPoint );
 					innerPoint.add( currentPoint );
 
+					// in-loop fold detection to mitigate #25326
+					if ( innerSideModified ) {
+
+						//  when the second triangle's signed area would flip, snap innerPoint to the previous inner-side vertex
+
+						const refPt = joinIsOnLeftSide ? lastPointR : lastPointL;
+						const foldCross = ( outerPoint.x - refPt.x ) * ( innerPoint.y - refPt.y )
+							- ( outerPoint.y - refPt.y ) * ( innerPoint.x - refPt.x );
+						if ( ( joinIsOnLeftSide && foldCross < 0 ) || ( ! joinIsOnLeftSide && foldCross > 0 ) ) {
+
+							innerPoint.copy( refPt );
+
+						}
+
+					}
+
 					isMiter = false;
 
 					if ( innerSideModified ) {
@@ -2941,6 +2957,32 @@ class SVGLoader extends Loader {
 
 		}
 
+		// Second fix for #25326: Scan for reamining flipped (CW) triangles and collapse them to
+		// degenerated ones. This is safe and leaves no "holes" in the stroke because the flipped
+		// triangle's area is covered by neighbouring (CCW) triangles.
+
+		if ( vertices ) {
+
+			const tri = [ new Vector2(), new Vector2(), new Vector2() ];
+			const startFloat = vertexOffset * 3;
+
+			for ( let t = startFloat; t < currentCoordinate; t += 9 ) {
+
+				tri[ 0 ].set( vertices[ t ], vertices[ t + 1 ] );
+				tri[ 1 ].set( vertices[ t + 3 ], vertices[ t + 4 ] );
+				tri[ 2 ].set( vertices[ t + 6 ], vertices[ t + 7 ] );
+
+				if ( ShapeUtils.area( tri ) < 0 ) {
+
+					vertices[ t + 3 ] = tri[ 0 ].x;
+					vertices[ t + 4 ] = tri[ 0 ].y;
+
+				}
+
+			}
+
+		}
+
 		return numVertices;
 
 		// -- End of algorithm

+ 4 - 0
examples/models/svg/tests/wideStroke.svg

@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<svg viewBox="0 0 600 792" width="600" height="792">
+  <path stroke="#64C36E" fill="none" id="link_2_21_ok" d="M30,463.61904761904765C150,463.61904761904765,150,571.0476190476189,270,571.0476190476189" stroke-width="290" stroke-opacity="0.6"/>
+</svg>

+ 2 - 0
examples/webgl_loader_svg.html

@@ -122,6 +122,7 @@
 					'emptyPath': 'models/svg/emptyPath.svg',
 					'emoji': 'models/svg/emoji.svg',
 					'blueprint': 'models/svg/blueprint.svg',
+					'wideStroke': 'models/svg/tests/wideStroke.svg',
 
 				} ).name( 'SVG File' ).onChange( update );
 
@@ -205,6 +206,7 @@
 							if ( material ) {
 
 								material.wireframe = guiData.strokesWireframe;
+								material.side = 0;
 
 								for ( const subPath of path.subPaths ) {
 

粤ICP备19079148号