Sfoglia il codice sorgente

Merge pull request #13636 from jonobr1/13478-svg-loader

SVGLoader Additions
Mr.doob 7 anni fa
parent
commit
79042f78aa
1 ha cambiato i file con 259 aggiunte e 0 eliminazioni
  1. 259 0
      examples/js/loaders/SVGLoader.js

+ 259 - 0
examples/js/loaders/SVGLoader.js

@@ -58,6 +58,26 @@ THREE.SVGLoader.prototype = {
 					paths.push( parseRectNode( node ) );
 					break;
 
+				case 'polygon':
+					paths.push( parsePolygonNode( node ) );
+					break;
+
+				case 'polyline':
+					paths.push( parsePolylineNode( node ) );
+					break;
+
+				case 'circle':
+					paths.push( parseCircleNode( node ) );
+					break;
+
+				case 'ellipse':
+					paths.push( parseEllipseNode( node ) );
+					break;
+
+				case 'line':
+					paths.push( parseLineNode( node ) );
+					break;
+
 				default:
 					console.log( node );
 
@@ -71,6 +91,7 @@ THREE.SVGLoader.prototype = {
 
 			var path = new THREE.ShapePath();
 			var point = new THREE.Vector2();
+			var control = new THREE.Vector2();
 
 			var d = node.getAttribute( 'd' );
 
@@ -90,18 +111,24 @@ THREE.SVGLoader.prototype = {
 					case 'M':
 						var numbers = parseFloats( data );
 						point.fromArray( numbers );
+						control.x = point.x;
+						control.y = point.y;
 						path.moveTo( point.x, point.y );
 						break;
 
 					case 'H':
 						var numbers = parseFloats( data );
 						point.x = numbers[ 0 ];
+						control.x = point.x;
+						control.y = point.y;
 						path.lineTo( point.x, point.y );
 						break;
 
 					case 'V':
 						var numbers = parseFloats( data );
 						point.y = numbers[ 0 ];
+						control.x = point.x;
+						control.y = point.y;
 						path.lineTo( point.x, point.y );
 						break;
 
@@ -109,6 +136,8 @@ THREE.SVGLoader.prototype = {
 						var numbers = parseFloats( data );
 						point.x = numbers[ 0 ];
 						point.y = numbers[ 1 ];
+						control.x = point.x;
+						control.y = point.y;
 						path.lineTo( point.x, point.y );
 						break;
 
@@ -122,19 +151,84 @@ THREE.SVGLoader.prototype = {
 							numbers[ 4 ],
 							numbers[ 5 ],
 						);
+						control.x = numbers[ 2 ];
+						control.y = numbers[ 3 ];
 						point.x = numbers[ 4 ];
 						point.y = numbers[ 5 ];
 						break;
 
+					case 'S':
+						var numbers = parseFloats( data );
+						path.bezierCurveTo(
+							getReflection( point.x, control.x ),
+							getReflection( point.y, control.y ),
+							numbers[ 0 ],
+							numbers[ 1 ],
+							numbers[ 2 ],
+							numbers[ 3 ]
+						);
+						control.x = numbers[ 0 ];
+						control.y = numbers[ 1 ];
+						point.x = numbers[ 2 ];
+						point.y = numbers[ 3 ];
+						break;
+
+					case 'Q':
+						var numbers = parseFloats( data );
+						path.quadraticCurveTo(
+							numbers[ 0 ],
+							numbers[ 1 ],
+							numbers[ 2 ],
+							numbers[ 3 ]
+						);
+						control.x = numbers[ 0 ];
+						control.y = numbers[ 1 ];
+						point.x = numbers[ 2 ];
+						point.y = numbers[ 3 ];
+						break;
+
+					case 'T':
+						var numbers = parseFloats( data );
+						var rx = getReflection( point.x, control.x );
+						var ry = getReflection( point.y, control.y );
+						path.quadraticCurveTo(
+							rx,
+							ry,
+							numbers[ 0 ],
+							numbers[ 1 ]
+						);
+						control.x = rx;
+						control.y = ry;
+						point.x = numbers[ 0 ];
+						point.y = numbers[ 1 ];
+						break;
+
+					case 'A':
+						// TODO:
+						break;
+
+					case 'm':
+						var numbers = parseFloats( data );
+						point.x += numbers[ 0 ];
+						point.y += numbers[ 1 ];
+						control.x = point.x;
+						control.y = point.y;
+						path.moveTo( point.x, point.y );
+						break;
+
 					case 'h':
 						var numbers = parseFloats( data );
 						point.x += numbers[ 0 ];
+						control.x = point.x;
+						control.y = point.y;
 						path.lineTo( point.x, point.y );
 						break;
 
 					case 'v':
 						var numbers = parseFloats( data );
 						point.y += numbers[ 0 ];
+						control.x = point.x;
+						control.y = point.y;
 						path.lineTo( point.x, point.y );
 						break;
 
@@ -142,6 +236,8 @@ THREE.SVGLoader.prototype = {
 						var numbers = parseFloats( data );
 						point.x += numbers[ 0 ];
 						point.y += numbers[ 1 ];
+						control.x = point.x;
+						control.y = point.y;
 						path.lineTo( point.x, point.y );
 						break;
 
@@ -159,6 +255,58 @@ THREE.SVGLoader.prototype = {
 						point.y += numbers[ 5 ];
 						break;
 
+					case 's':
+						var numbers = parseFloats( data );
+						path.bezierCurveTo(
+							// TODO: Not sure if point needs
+							// to be added to reflection...
+							getReflection( point.x, control.x ),
+							getReflection( point.y, control.y ),
+							point.x + numbers[ 0 ],
+							point.y + numbers[ 1 ],
+							point.x + numbers[ 2 ],
+							point.y + numbers[ 3 ]
+						);
+						control.x = point.x + numbers[ 0 ];
+						control.y = point.y + numbers[ 1 ];
+						point.x += numbers[ 2 ];
+						point.y += numbers[ 3 ];
+						break;
+
+					case 'q':
+						var numbers = parseFloats( data );
+						path.quadraticCurveTo(
+							point.x + numbers[ 0 ],
+							point.y + numbers[ 1 ],
+							point.x + numbers[ 2 ],
+							point.y + numbers[ 3 ]
+						);
+						control.x = point.x + numbers[ 0 ];
+						control.y = point.y + numbers[ 1 ];
+						point.x += numbers[ 2 ];
+						point.y += numbers[ 3 ];
+						break;
+
+					case 't':
+						var numbers = parseFloats( data );
+						var rx = getReflection( point.x, control.x );
+						var ry = getReflection( point.y, control.y );
+						path.quadraticCurveTo(
+							rx,
+							ry,
+							point.x + numbers[ 0 ],
+							point.y + numbers[ 1 ]
+						);
+						control.x = rx;
+						control.y = ry;
+						point.x = point.x + numbers[ 0 ];
+						point.y = point.y + numbers[ 1 ];
+						break;
+
+					case 'a':
+						// TODO:
+						break;
+
 					case 'Z':
 					case 'z':
 						path.currentPath.autoClose = true;
@@ -191,6 +339,117 @@ THREE.SVGLoader.prototype = {
 
 		}
 
+		function parsePolygonNode( node ) {
+
+			function iterator( match, a, b ) {
+
+				var x = parseFloat( a );
+				var y = parseFloat( b );
+
+				if ( index === 0 ) {
+					path.moveTo( x, y );
+				} else {
+					path.lineTo( x, y );
+				}
+
+				index++;
+
+			}
+
+			var regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
+			var path = new THREE.ShapePath();
+			var index = 0;
+
+			node.getAttribute( 'points' ).replace(regex, iterator);
+
+			path.currentPath.autoClose = true;
+
+			return path;
+
+		}
+
+		function parsePolylineNode( node ) {
+
+			function iterator( match, a, b ) {
+
+				var x = parseFloat( a );
+				var y = parseFloat( b );
+
+				if ( index === 0 ) {
+					path.moveTo( x, y );
+				} else {
+					path.lineTo( x, y );
+				}
+
+				index++;
+
+			}
+
+			var regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
+			var path = new THREE.ShapePath();
+			var index = 0;
+
+			node.getAttribute( 'points' ).replace(regex, iterator);
+
+			path.currentPath.autoClose = false;
+
+			return path;
+
+		}
+
+		function parseCircleNode( node ) {
+
+			var x = parseFloat( node.getAttribute( 'cx' ) );
+			var y = parseFloat( node.getAttribute( 'cy' ) );
+			var r = parseFloat( node.getAttribute( 'r' ) );
+
+			var path = new THREE.ShapePath();
+
+			path.currentPath.absarc( x, y, r, 0, Math.PI * 2 );
+
+			return path;
+
+		}
+
+		function parseEllipseNode( node ) {
+
+			var x = parseFloat( node.getAttribute( 'cx' ) );
+			var y = parseFloat( node.getAttribute( 'cy' ) );
+			var rx parseFloat( node.getAttribute( 'rx' ) );
+			var ry = parseFloat( node.getAttribute( 'ry' ) );
+
+			var path = new THREE.ShapePath();
+
+			path.currentPath.absellipse( x, y, rx, ry, 0, Math.PI * 2 );
+
+			return path;
+
+		}
+
+		function parseLineNode( node ) {
+
+			var x1 = parseFloat( node.getAttribute( 'x1' ) );
+			var y1 = parseFloat( node.getAttribute( 'y1' ) );
+			var x2 = parseFloat( node.getAttribute( 'x2' ) );
+			var y2 = parseFloat( node.getAttribute( 'y2' ) );
+
+			var path = new THREE.ShapePath();
+			path.moveTo( x1, y1 );
+			path.lineTo( x2, y2 );
+			path.currentPath.autoClose = false;
+
+			return path;
+
+		}
+
+		// http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
+
+		function getReflection( a, b ) {
+
+			return 2 * a - ( b - a );
+
+		}
+
 		function parseFloats( string ) {
 
 			var array = string.split( /[\s,]+|(?=\s?[+\-])/ );