Browse Source

Merge pull request #17272 from AlbertoPa/dev

Implemented solid coloring for ASCII STL files with multiple solids
Mr.doob 6 years ago
parent
commit
cb0861b9e9
2 changed files with 158 additions and 50 deletions
  1. 79 25
      examples/js/loaders/STLLoader.js
  2. 79 25
      examples/jsm/loaders/STLLoader.js

+ 79 - 25
examples/js/loaders/STLLoader.js

@@ -28,6 +28,31 @@
  *    material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors });
  *  } else { .... }
  *  var mesh = new THREE.Mesh( geometry, material );
+ *
+ * For ASCII STLs containing multiple solids, each solid is assigned to a different group.
+ * Groups can be used to assign a different color by defining an array of materials with the same length of
+ * geometry.groups and passing it to the Mesh constructor:
+ *
+ * var mesh = new THREE.Mesh( geometry, material );
+ *
+ * For example:
+ *
+ *  var materials = [];
+ *  var nGeometryGroups = geometry.groups.length;
+ *
+ *  var colorMap = ...; // Some logic to index colors.
+ *
+ *  for (var i = 0; i < nGeometryGroups; i++) {
+ *
+ *		var material = new THREE.MeshStandardMaterial({
+ *			color: colorMap[i],
+ *			wireframe: false
+ *		});
+ *
+ *  }
+ *
+ *  materials.push(material);
+ *  var mesh = new THREE.Mesh(geometry, materials);
  */
 
 
@@ -107,7 +132,7 @@ THREE.STLLoader.prototype = {
 
 				// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
 
-				if ( matchDataViewAt ( solid, reader, off ) ) return false;
+				if ( matchDataViewAt( solid, reader, off ) ) return false;
 
 			}
 
@@ -201,7 +226,7 @@ THREE.STLLoader.prototype = {
 
 					var vertexstart = start + i * 12;
 					var componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 );
-					
+
 					vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
 					vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
 					vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
@@ -240,6 +265,7 @@ THREE.STLLoader.prototype = {
 		function parseASCII( data ) {
 
 			var geometry = new THREE.BufferGeometry();
+			var patternSolid = /solid([\s\S]*?)endsolid/g;
 			var patternFace = /facet([\s\S]*?)endfacet/g;
 			var faceCounter = 0;
 
@@ -254,53 +280,80 @@ THREE.STLLoader.prototype = {
 
 			var result;
 
-			while ( ( result = patternFace.exec( data ) ) !== null ) {
+			var groupVertexes = [];
+			var groupCount = 0;
+			var startVertex = 0;
+			var endVertex = 0;
 
-				var vertexCountPerFace = 0;
-				var normalCountPerFace = 0;
+			while ( ( result = patternSolid.exec( data ) ) !== null ) {
 
-				var text = result[ 0 ];
+				startVertex = endVertex;
 
-				while ( ( result = patternNormal.exec( text ) ) !== null ) {
+				var solid = result[ 0 ];
 
-					normal.x = parseFloat( result[ 1 ] );
-					normal.y = parseFloat( result[ 2 ] );
-					normal.z = parseFloat( result[ 3 ] );
-					normalCountPerFace ++;
+				while ( ( result = patternFace.exec( solid ) ) !== null ) {
 
-				}
+					var vertexCountPerFace = 0;
+					var normalCountPerFace = 0;
 
-				while ( ( result = patternVertex.exec( text ) ) !== null ) {
+					var text = result[ 0 ];
 
-					vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
-					normals.push( normal.x, normal.y, normal.z );
-					vertexCountPerFace ++;
+					while ( ( result = patternNormal.exec( text ) ) !== null ) {
 
-				}
+						normal.x = parseFloat( result[ 1 ] );
+						normal.y = parseFloat( result[ 2 ] );
+						normal.z = parseFloat( result[ 3 ] );
+						normalCountPerFace ++;
 
-				// every face have to own ONE valid normal
+					}
 
-				if ( normalCountPerFace !== 1 ) {
+					while ( ( result = patternVertex.exec( text ) ) !== null ) {
 
-					console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
+						vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
+						normals.push( normal.x, normal.y, normal.z );
+						vertexCountPerFace ++;
+						endVertex ++;
 
-				}
+					}
 
-				// each face have to own THREE valid vertices
+					// every face have to own ONE valid normal
 
-				if ( vertexCountPerFace !== 3 ) {
+					if ( normalCountPerFace !== 1 ) {
 
-					console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
+						console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
+
+					}
+
+					// each face have to own THREE valid vertices
+
+					if ( vertexCountPerFace !== 3 ) {
+
+						console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
+
+					}
+
+					faceCounter ++;
 
 				}
 
-				faceCounter ++;
+				groupVertexes.push( { startVertex: startVertex, endVertex: endVertex } );
+				groupCount ++;
 
 			}
 
 			geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
 			geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
 
+			if ( groupCount > 0 ) {
+
+				for ( var i = 0; i < groupVertexes.length; i ++ ) {
+
+					geometry.addGroup( groupVertexes[ i ].startVertex, groupVertexes[ i ].endVertex, i );
+
+				}
+
+			}
+
 			return geometry;
 
 		}
@@ -327,6 +380,7 @@ THREE.STLLoader.prototype = {
 					array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
 
 				}
+
 				return array_buffer.buffer || array_buffer;
 
 			} else {

+ 79 - 25
examples/jsm/loaders/STLLoader.js

@@ -28,6 +28,31 @@
  *    material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: THREE.VertexColors });
  *  } else { .... }
  *  var mesh = new THREE.Mesh( geometry, material );
+ *
+ * For ASCII STLs containing multiple solids, each solid is assigned to a different group.
+ * Groups can be used to assign a different color by defining an array of materials with the same length of
+ * geometry.groups and passing it to the Mesh constructor:
+ *
+ * var mesh = new THREE.Mesh( geometry, material );
+ *
+ * For example:
+ *
+ *  var materials = [];
+ *  var nGeometryGroups = geometry.groups.length;
+ *
+ *  var colorMap = ...; // Some logic to index colors.
+ *
+ *  for (var i = 0; i < nGeometryGroups; i++) {
+ *
+ *		var material = new THREE.MeshStandardMaterial({
+ *			color: colorMap[i],
+ *			wireframe: false
+ *		});
+ *
+ *  }
+ *
+ *  materials.push(material);
+ *  var mesh = new THREE.Mesh(geometry, materials);
  */
 
 import {
@@ -117,7 +142,7 @@ STLLoader.prototype = {
 
 				// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
 
-				if ( matchDataViewAt ( solid, reader, off ) ) return false;
+				if ( matchDataViewAt( solid, reader, off ) ) return false;
 
 			}
 
@@ -211,7 +236,7 @@ STLLoader.prototype = {
 
 					var vertexstart = start + i * 12;
 					var componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 );
-					
+
 					vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
 					vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
 					vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
@@ -250,6 +275,7 @@ STLLoader.prototype = {
 		function parseASCII( data ) {
 
 			var geometry = new BufferGeometry();
+			var patternSolid = /solid([\s\S]*?)endsolid/g;
 			var patternFace = /facet([\s\S]*?)endfacet/g;
 			var faceCounter = 0;
 
@@ -264,53 +290,80 @@ STLLoader.prototype = {
 
 			var result;
 
-			while ( ( result = patternFace.exec( data ) ) !== null ) {
+			var groupVertexes = [];
+			var groupCount = 0;
+			var startVertex = 0;
+			var endVertex = 0;
 
-				var vertexCountPerFace = 0;
-				var normalCountPerFace = 0;
+			while ( ( result = patternSolid.exec( data ) ) !== null ) {
 
-				var text = result[ 0 ];
+				startVertex = endVertex;
 
-				while ( ( result = patternNormal.exec( text ) ) !== null ) {
+				var solid = result[ 0 ];
 
-					normal.x = parseFloat( result[ 1 ] );
-					normal.y = parseFloat( result[ 2 ] );
-					normal.z = parseFloat( result[ 3 ] );
-					normalCountPerFace ++;
+				while ( ( result = patternFace.exec( solid ) ) !== null ) {
 
-				}
+					var vertexCountPerFace = 0;
+					var normalCountPerFace = 0;
 
-				while ( ( result = patternVertex.exec( text ) ) !== null ) {
+					var text = result[ 0 ];
 
-					vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
-					normals.push( normal.x, normal.y, normal.z );
-					vertexCountPerFace ++;
+					while ( ( result = patternNormal.exec( text ) ) !== null ) {
 
-				}
+						normal.x = parseFloat( result[ 1 ] );
+						normal.y = parseFloat( result[ 2 ] );
+						normal.z = parseFloat( result[ 3 ] );
+						normalCountPerFace ++;
 
-				// every face have to own ONE valid normal
+					}
 
-				if ( normalCountPerFace !== 1 ) {
+					while ( ( result = patternVertex.exec( text ) ) !== null ) {
 
-					console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
+						vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
+						normals.push( normal.x, normal.y, normal.z );
+						vertexCountPerFace ++;
+						endVertex ++;
 
-				}
+					}
 
-				// each face have to own THREE valid vertices
+					// every face have to own ONE valid normal
 
-				if ( vertexCountPerFace !== 3 ) {
+					if ( normalCountPerFace !== 1 ) {
 
-					console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
+						console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
+
+					}
+
+					// each face have to own THREE valid vertices
+
+					if ( vertexCountPerFace !== 3 ) {
+
+						console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
+
+					}
+
+					faceCounter ++;
 
 				}
 
-				faceCounter ++;
+				groupVertexes.push( { startVertex: startVertex, endVertex: endVertex } );
+				groupCount ++;
 
 			}
 
 			geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
 			geometry.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
 
+			if ( groupCount > 0 ) {
+
+				for ( var i = 0; i < groupVertexes.length; i ++ ) {
+
+					geometry.addGroup( groupVertexes[ i ].startVertex, groupVertexes[ i ].endVertex, i );
+
+				}
+
+			}
+
 			return geometry;
 
 		}
@@ -337,6 +390,7 @@ STLLoader.prototype = {
 					array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
 
 				}
+
 				return array_buffer.buffer || array_buffer;
 
 			} else {