浏览代码

STLExporter: Merged exporters for ASCII and Binary

Mugen87 7 年之前
父节点
当前提交
3433be1b52

+ 1 - 0
examples/files.js

@@ -342,6 +342,7 @@ var files = {
 		"misc_controls_transform",
 		"misc_controls_transform",
 		"misc_exporter_gltf",
 		"misc_exporter_gltf",
 		"misc_exporter_obj",
 		"misc_exporter_obj",
+		"misc_exporter_stl",
 		"misc_fps",
 		"misc_fps",
 		"misc_lights_test",
 		"misc_lights_test",
 		"misc_lookat",
 		"misc_lookat",

+ 1 - 1
examples/js/exporters/PLYExporter.js

@@ -6,7 +6,7 @@
  *  var exporter = new THREE.PLYExporter();
  *  var exporter = new THREE.PLYExporter();
  *
  *
  *  // second argument is a list of options
  *  // second argument is a list of options
- *  var data = exporter.parse(mesh, { binar: true, excludeAttributes: [ 'color' ] });
+ *  var data = exporter.parse( mesh, { binary: true, excludeAttributes: [ 'color' ] } );
  *
  *
  * Format Definition:
  * Format Definition:
  *  http://paulbourke.net/dataformats/ply/
  *  http://paulbourke.net/dataformats/ply/

+ 0 - 94
examples/js/exporters/STLBinaryExporter.js

@@ -1,94 +0,0 @@
-/**
- * @author kovacsv / http://kovacsv.hu/
- * @author mrdoob / http://mrdoob.com/
- * @author mudcube / http://mudcu.be/
- */
-
-THREE.STLBinaryExporter = function () {};
-
-THREE.STLBinaryExporter.prototype = {
-
-	constructor: THREE.STLBinaryExporter,
-
-	parse: ( function () {
-
-		var vector = new THREE.Vector3();
-		var normalMatrixWorld = new THREE.Matrix3();
-
-		return function parse( scene ) {
-
-			// We collect objects first, as we may need to convert from BufferGeometry to Geometry
-			var objects = [];
-			var triangles = 0;
-			scene.traverse( function ( object ) {
-
-				if ( ! ( object instanceof THREE.Mesh ) ) return;
-
-				var geometry = object.geometry;
-				if ( geometry instanceof THREE.BufferGeometry ) {
-
-					geometry = new THREE.Geometry().fromBufferGeometry( geometry );
-
-				}
-
-				if ( ! ( geometry instanceof THREE.Geometry ) ) return;
-				triangles += geometry.faces.length;
-
-				objects.push( {
-
-					geometry: geometry,
-					matrix: object.matrixWorld
-
-				} );
-
-			} );
-
-			var offset = 80; // skip header
-			var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
-			var arrayBuffer = new ArrayBuffer( bufferLength );
-			var output = new DataView( arrayBuffer );
-			output.setUint32( offset, triangles, true ); offset += 4;
-
-			// Traversing our collected objects
-			objects.forEach( function ( object ) {
-
-				var vertices = object.geometry.vertices;
-				var faces = object.geometry.faces;
-
-				normalMatrixWorld.getNormalMatrix( object.matrix );
-
-				for ( var i = 0, l = faces.length; i < l; i ++ ) {
-
-					var face = faces[ i ];
-
-					vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
-
-					output.setFloat32( offset, vector.x, true ); offset += 4; // normal
-					output.setFloat32( offset, vector.y, true ); offset += 4;
-					output.setFloat32( offset, vector.z, true ); offset += 4;
-
-					var indices = [ face.a, face.b, face.c ];
-
-					for ( var j = 0; j < 3; j ++ ) {
-
-						vector.copy( vertices[ indices[ j ] ] ).applyMatrix4( object.matrix );
-
-						output.setFloat32( offset, vector.x, true ); offset += 4; // vertices
-						output.setFloat32( offset, vector.y, true ); offset += 4;
-						output.setFloat32( offset, vector.z, true ); offset += 4;
-
-					}
-
-					output.setUint16( offset, 0, true ); offset += 2; // attribute byte count
-
-				}
-
-			} );
-
-			return output;
-
-		};
-
-	}() )
-
-};

+ 108 - 25
examples/js/exporters/STLExporter.js

@@ -1,6 +1,13 @@
 /**
 /**
  * @author kovacsv / http://kovacsv.hu/
  * @author kovacsv / http://kovacsv.hu/
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
+ *
+ * Usage:
+ *  var exporter = new THREE.STLExporter();
+ *
+ *  // second argument is a list of options
+ *  var data = exporter.parse( mesh, { binary: true } );
+ *
  */
  */
 
 
 THREE.STLExporter = function () {};
 THREE.STLExporter = function () {};
@@ -14,65 +21,141 @@ THREE.STLExporter.prototype = {
 		var vector = new THREE.Vector3();
 		var vector = new THREE.Vector3();
 		var normalMatrixWorld = new THREE.Matrix3();
 		var normalMatrixWorld = new THREE.Matrix3();
 
 
-		return function parse( scene ) {
+		return function parse( scene, options ) {
 
 
-			var output = '';
+			if ( options === undefined ) options = {};
 
 
-			output += 'solid exported\n';
+			var binary = options.binary !== undefined ? options.binary : false;
+
+			//
+
+			var objects = [];
+			var triangles = 0;
 
 
 			scene.traverse( function ( object ) {
 			scene.traverse( function ( object ) {
 
 
-				if ( object instanceof THREE.Mesh ) {
+				if ( object.isMesh ) {
 
 
 					var geometry = object.geometry;
 					var geometry = object.geometry;
-					var matrixWorld = object.matrixWorld;
 
 
-					if ( geometry instanceof THREE.BufferGeometry ) {
+					if ( geometry.isBufferGeometry ) {
 
 
 						geometry = new THREE.Geometry().fromBufferGeometry( geometry );
 						geometry = new THREE.Geometry().fromBufferGeometry( geometry );
 
 
 					}
 					}
 
 
-					if ( geometry instanceof THREE.Geometry ) {
+					if ( geometry.isGeometry ) {
 
 
-						var vertices = geometry.vertices;
-						var faces = geometry.faces;
+						triangles += geometry.faces.length;
 
 
-						normalMatrixWorld.getNormalMatrix( matrixWorld );
+						objects.push( {
 
 
-						for ( var i = 0, l = faces.length; i < l; i ++ ) {
+							geometry: geometry,
+							matrixWorld: object.matrixWorld
 
 
-							var face = faces[ i ];
+						} );
 
 
-							vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
+					}
 
 
-							output += '\tfacet normal ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
-							output += '\t\touter loop\n';
+				}
 
 
-							var indices = [ face.a, face.b, face.c ];
+			} );
 
 
-							for ( var j = 0; j < 3; j ++ ) {
+			if ( binary ) {
+
+				var offset = 80; // skip header
+				var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
+				var arrayBuffer = new ArrayBuffer( bufferLength );
+				var output = new DataView( arrayBuffer );
+				output.setUint32( offset, triangles, true ); offset += 4;
+
+				for ( var i = 0, il = objects.length; i < il; i ++ ) {
+
+					var object = objects[ i ];
+
+					var vertices = object.geometry.vertices;
+					var faces = object.geometry.faces;
+					var matrixWorld = object.matrixWorld;
 
 
-								vector.copy( vertices[ indices[ j ] ] ).applyMatrix4( matrixWorld );
+					normalMatrixWorld.getNormalMatrix( matrixWorld );
 
 
-								output += '\t\t\tvertex ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
+					for ( var j = 0, jl = faces.length; j < jl; j ++ ) {
 
 
-							}
+						var face = faces[ j ];
 
 
-							output += '\t\tendloop\n';
-							output += '\tendfacet\n';
+						vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
+
+						output.setFloat32( offset, vector.x, true ); offset += 4; // normal
+						output.setFloat32( offset, vector.y, true ); offset += 4;
+						output.setFloat32( offset, vector.z, true ); offset += 4;
+
+						var indices = [ face.a, face.b, face.c ];
+
+						for ( var k = 0; k < 3; k ++ ) {
+
+							vector.copy( vertices[ indices[ k ] ] ).applyMatrix4( matrixWorld );
+
+							output.setFloat32( offset, vector.x, true ); offset += 4; // vertices
+							output.setFloat32( offset, vector.y, true ); offset += 4;
+							output.setFloat32( offset, vector.z, true ); offset += 4;
 
 
 						}
 						}
 
 
+						output.setUint16( offset, 0, true ); offset += 2; // attribute byte count
+
 					}
 					}
 
 
 				}
 				}
 
 
-			} );
+				return output;
+
+			} else {
+
+				var output = '';
+
+				output += 'solid exported\n';
+
+				for ( var i = 0, il = objects.length; i < il; i ++ ) {
+
+					var object = objects[ i ];
+
+					var vertices = object.geometry.vertices;
+					var faces = object.geometry.faces;
+					var matrixWorld = object.matrixWorld;
+
+					normalMatrixWorld.getNormalMatrix( matrixWorld );
+
+					for ( var j = 0, jl = faces.length; j < jl; j ++ ) {
+
+						var face = faces[ j ];
+
+						vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
+
+						output += '\tfacet normal ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
+						output += '\t\touter loop\n';
+
+						var indices = [ face.a, face.b, face.c ];
+
+						for ( var k = 0; k < 3; k ++ ) {
+
+							vector.copy( vertices[ indices[ k ] ] ).applyMatrix4( matrixWorld );
+
+							output += '\t\t\tvertex ' + vector.x + ' ' + vector.y + ' ' + vector.z + '\n';
+
+						}
+
+						output += '\t\tendloop\n';
+						output += '\tendfacet\n';
+
+					}
+
+				}
+
+				output += 'endsolid exported\n';
 
 
-			output += 'endsolid exported\n';
+				return output;
 
 
-			return output;
+			}
 
 
 		};
 		};
 
 

+ 193 - 0
examples/misc_exporter_stl.html

@@ -0,0 +1,193 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - exporter - stl</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				display:block;
+			}
+			#info a {
+				color: #046;
+				font-weight: bold;
+			}
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - exporter - stl
+		</div>
+
+		<script src="../build/three.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+		<script src="js/exporters/STLExporter.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var scene, camera, renderer, exporter;
+
+			init();
+			animate();
+
+			function init() {
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.set( 200, 100, 200 );
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xa0a0a0 );
+				scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
+
+				exporter = new THREE.STLExporter();
+
+				//
+
+				var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
+				hemiLight.position.set( 0, 200, 0 );
+				scene.add( hemiLight );
+
+				var directionalLight = new THREE.DirectionalLight( 0xffffff );
+				directionalLight.position.set( 0, 200, 100 );
+				directionalLight.castShadow = true;
+				directionalLight.shadow.camera.top = 180;
+				directionalLight.shadow.camera.bottom = - 100;
+				directionalLight.shadow.camera.left = - 120;
+				directionalLight.shadow.camera.right = 120;
+				scene.add( directionalLight );
+
+				// ground
+
+				var ground = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
+				ground.rotation.x = - Math.PI / 2;
+				ground.receiveShadow = true;
+				scene.add( ground );
+
+				var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
+				grid.material.opacity = 0.2;
+				grid.material.transparent = true;
+				scene.add( grid );
+
+				// export mesh
+
+				var geometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
+				var material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
+
+				mesh = new THREE.Mesh( geometry, material );
+				mesh.castShadow = true;
+				mesh.position.y = 25;
+				scene.add( mesh );
+
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.shadowMap.enabled = true;
+				document.body.appendChild( renderer.domElement );
+
+				//
+
+				var controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls.target.set( 0, 25, 0 );
+				controls.update();
+
+				//
+
+				var params = {
+					ASCII: function() {
+						exportASCII();
+					},
+					Binary: function() {
+						exportBinary();
+					}
+				}
+
+				var gui = new dat.GUI();
+				var folder = gui.addFolder( 'Export' );
+
+				folder.add( params, 'ASCII' );
+				folder.add( params, 'Binary' );
+				folder.open();
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				renderer.render( scene, camera );
+
+			}
+
+			function exportASCII() {
+
+				var result = exporter.parse( mesh );
+				saveString( result, 'box.stl' );
+
+			}
+
+			function exportBinary() {
+
+				var result = exporter.parse( mesh, { binary: true } );
+				saveArrayBuffer( result, 'box.stl' );
+
+			}
+
+			var link = document.createElement( 'a' );
+			link.style.display = 'none';
+			document.body.appendChild( link );
+
+			function save( blob, filename ) {
+
+				link.href = URL.createObjectURL( blob );
+				link.download = filename;
+				link.click();
+
+			}
+
+			function saveString( text, filename ) {
+
+				save( new Blob( [ text ], { type: 'text/plain' } ), filename );
+
+			}
+
+			function saveArrayBuffer( buffer, filename ) {
+
+				save( new Blob( [ buffer ], { type: 'application/octet-stream' } ), filename );
+
+			}
+
+		</script>
+
+	</body>
+</html>