STLExporter.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. console.warn( "THREE.STLExporter: As part of the transition to ES6 Modules, the files in 'examples/js' were deprecated in May 2020 (r117) and will be deleted in December 2020 (r124). You can find more information about developing using ES6 Modules in https://threejs.org/docs/#manual/en/introduction/Installation." );
  2. /**
  3. * Usage:
  4. * var exporter = new THREE.STLExporter();
  5. *
  6. * // second argument is a list of options
  7. * var data = exporter.parse( mesh, { binary: true } );
  8. *
  9. */
  10. THREE.STLExporter = function () {};
  11. THREE.STLExporter.prototype = {
  12. constructor: THREE.STLExporter,
  13. parse: function ( scene, options ) {
  14. if ( options === undefined ) options = {};
  15. var binary = options.binary !== undefined ? options.binary : false;
  16. //
  17. var objects = [];
  18. var triangles = 0;
  19. scene.traverse( function ( object ) {
  20. if ( object.isMesh ) {
  21. var geometry = object.geometry;
  22. if ( geometry.isGeometry ) {
  23. geometry = new THREE.BufferGeometry().fromGeometry( geometry );
  24. }
  25. var index = geometry.index;
  26. var positionAttribute = geometry.getAttribute( 'position' );
  27. triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 );
  28. objects.push( {
  29. object3d: object,
  30. geometry: geometry
  31. } );
  32. }
  33. } );
  34. var output;
  35. var offset = 80; // skip header
  36. if ( binary === true ) {
  37. var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
  38. var arrayBuffer = new ArrayBuffer( bufferLength );
  39. output = new DataView( arrayBuffer );
  40. output.setUint32( offset, triangles, true ); offset += 4;
  41. } else {
  42. output = '';
  43. output += 'solid exported\n';
  44. }
  45. var vA = new THREE.Vector3();
  46. var vB = new THREE.Vector3();
  47. var vC = new THREE.Vector3();
  48. var cb = new THREE.Vector3();
  49. var ab = new THREE.Vector3();
  50. var normal = new THREE.Vector3();
  51. for ( var i = 0, il = objects.length; i < il; i ++ ) {
  52. var object = objects[ i ].object3d;
  53. var geometry = objects[ i ].geometry;
  54. var index = geometry.index;
  55. var positionAttribute = geometry.getAttribute( 'position' );
  56. if ( index !== null ) {
  57. // indexed geometry
  58. for ( var j = 0; j < index.count; j += 3 ) {
  59. var a = index.getX( j + 0 );
  60. var b = index.getX( j + 1 );
  61. var c = index.getX( j + 2 );
  62. writeFace( a, b, c, positionAttribute, object );
  63. }
  64. } else {
  65. // non-indexed geometry
  66. for ( var j = 0; j < positionAttribute.count; j += 3 ) {
  67. var a = j + 0;
  68. var b = j + 1;
  69. var c = j + 2;
  70. writeFace( a, b, c, positionAttribute, object );
  71. }
  72. }
  73. }
  74. if ( binary === false ) {
  75. output += 'endsolid exported\n';
  76. }
  77. return output;
  78. function writeFace( a, b, c, positionAttribute, object ) {
  79. vA.fromBufferAttribute( positionAttribute, a );
  80. vB.fromBufferAttribute( positionAttribute, b );
  81. vC.fromBufferAttribute( positionAttribute, c );
  82. if ( object.isSkinnedMesh === true ) {
  83. object.boneTransform( a, vA );
  84. object.boneTransform( b, vB );
  85. object.boneTransform( c, vC );
  86. }
  87. vA.applyMatrix4( object.matrixWorld );
  88. vB.applyMatrix4( object.matrixWorld );
  89. vC.applyMatrix4( object.matrixWorld );
  90. writeNormal( vA, vB, vC );
  91. writeVertex( vA );
  92. writeVertex( vB );
  93. writeVertex( vC );
  94. if ( binary === true ) {
  95. output.setUint16( offset, 0, true ); offset += 2;
  96. } else {
  97. output += '\t\tendloop\n';
  98. output += '\tendfacet\n';
  99. }
  100. }
  101. function writeNormal( vA, vB, vC ) {
  102. cb.subVectors( vC, vB );
  103. ab.subVectors( vA, vB );
  104. cb.cross( ab ).normalize();
  105. normal.copy( cb ).normalize();
  106. if ( binary === true ) {
  107. output.setFloat32( offset, normal.x, true ); offset += 4;
  108. output.setFloat32( offset, normal.y, true ); offset += 4;
  109. output.setFloat32( offset, normal.z, true ); offset += 4;
  110. } else {
  111. output += '\tfacet normal ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
  112. output += '\t\touter loop\n';
  113. }
  114. }
  115. function writeVertex( vertex ) {
  116. if ( binary === true ) {
  117. output.setFloat32( offset, vertex.x, true ); offset += 4;
  118. output.setFloat32( offset, vertex.y, true ); offset += 4;
  119. output.setFloat32( offset, vertex.z, true ); offset += 4;
  120. } else {
  121. output += '\t\t\tvertex ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
  122. }
  123. }
  124. }
  125. };