STLExporter.js 4.0 KB

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