DracoExporter.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. 'use strict';
  2. /**
  3. * Export draco compressed files from threejs geometry objects.
  4. *
  5. * Draco files are compressed and usually are smaller than conventional 3D file formats.
  6. *
  7. * @class DracoExporter
  8. * @author syed-usman
  9. * @author tentone
  10. */
  11. THREE.DracoExporter = function () {};
  12. THREE.DracoExporter.prototype = {
  13. constructor: THREE.DracoExporter,
  14. parse: function ( geometry, options ) {
  15. if ( DracoEncoderModule === undefined ) {
  16. throw new Error( 'THREE.DracoExporter: required the draco_decoder to work.' );
  17. }
  18. if ( options === undefined ) {
  19. options = {
  20. decodeSpeed: 5,
  21. encodeSpeed: 5,
  22. encoderMethod: THREE.DracoExporter.MESH_EDGEBREAKER_ENCODING,
  23. quantization: [ 16, 8, 8, 8, 16 ]
  24. };
  25. }
  26. if ( geometry.isBufferGeometry === true ) {
  27. var convert = new THREE.Geometry();
  28. convert.fromBufferGeometry( geometry );
  29. geometry = convert;
  30. }
  31. var dracoEncoder = DracoEncoderModule();
  32. var encoder = new dracoEncoder.Encoder();
  33. var builder = new dracoEncoder.MeshBuilder();
  34. var mesh = new dracoEncoder.Mesh();
  35. var numFaces = geometry.faces.length;
  36. var numPoints = geometry.vertices.length;
  37. var numIndices = numFaces * 3;
  38. var indices = new Uint32Array( numIndices );
  39. var vertices = new Float32Array( geometry.vertices.length * 3 );
  40. var normals = new Float32Array( geometry.vertices.length * 3 );
  41. // Faces
  42. for ( var i = 0; i < numFaces; i ++ ) {
  43. var index = i * 3;
  44. indices[ index ] = geometry.faces[ i ].a;
  45. indices[ index + 1 ] = geometry.faces[ i ].b;
  46. indices[ index + 2 ] = geometry.faces[ i ].c;
  47. }
  48. builder.AddFacesToMesh( mesh, numFaces, indices );
  49. // Vertex
  50. for ( var i = 0; i < geometry.vertices.length; i ++ ) {
  51. var index = i * 3;
  52. vertices[ index ] = geometry.vertices[ i ].x;
  53. vertices[ index + 1 ] = geometry.vertices[ i ].y;
  54. vertices[ index + 2 ] = geometry.vertices[ i ].z;
  55. }
  56. builder.AddFloatAttributeToMesh( mesh, dracoEncoder.POSITION, numPoints, 3, vertices );
  57. // Normals
  58. for ( var face of geometry.faces ) {
  59. normals[ face[ 'a' ] * 3 ] = face.vertexNormals[ 0 ].x;
  60. normals[ ( face[ 'a' ] * 3 ) + 1 ] = face.vertexNormals[ 0 ].y;
  61. normals[ ( face[ 'a' ] * 3 ) + 2 ] = face.vertexNormals[ 0 ].z;
  62. normals[ face[ 'b' ] * 3 ] = face.vertexNormals[ 1 ].x;
  63. normals[ ( face[ 'b' ] * 3 ) + 1 ] = face.vertexNormals[ 1 ].y;
  64. normals[ ( face[ 'b' ] * 3 ) + 2 ] = face.vertexNormals[ 1 ].z;
  65. normals[ face[ 'c' ] * 3 ] = face.vertexNormals[ 2 ].x;
  66. normals[ ( face[ 'c' ] * 3 ) + 1 ] = face.vertexNormals[ 2 ].y;
  67. normals[ ( face[ 'c' ] * 3 ) + 2 ] = face.vertexNormals[ 2 ].z;
  68. }
  69. builder.AddFloatAttributeToMesh( mesh, dracoEncoder.NORMAL, numPoints, 3, normals );
  70. //Compress using draco encoder
  71. var encodedData = new dracoEncoder.DracoInt8Array();
  72. //Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression).
  73. encoder.SetSpeedOptions( options.encodeSpeed || 5, options.decodeSpeed || 5 );
  74. // Sets the desired encoding method for a given geometry.
  75. if ( options.encoderMethod !== undefined ) {
  76. encoder.SetEncodingMethod( options.encoderMethod );
  77. }
  78. // Sets the quantization (number of bits used to represent) compression options for a named attribute.
  79. // The attribute values will be quantized in a box defined by the maximum extent of the attribute values.
  80. for ( var i = 0; i < 5; i ++ ) {
  81. if ( options.quantization[ i ] !== undefined ) {
  82. encoder.SetAttributeQuantization( i, options.quantization[ i ] );
  83. }
  84. }
  85. var length = encoder.EncodeMeshToDracoBuffer( mesh, encodedData );
  86. dracoEncoder.destroy( mesh );
  87. if ( length === 0 ) {
  88. throw new Error( 'THREE.DracoExporter: Draco encoding failed' );
  89. }
  90. //Copy encoded data to buffer.
  91. var outputData = new Int8Array( new ArrayBuffer( length ) );
  92. for ( var i = 0; i < length; i ++ ) {
  93. outputData[ i ] = encodedData.GetValue( i );
  94. }
  95. dracoEncoder.destroy( encodedData );
  96. dracoEncoder.destroy( encoder );
  97. dracoEncoder.destroy( builder );
  98. return outputData;
  99. }
  100. };
  101. // Encoder methods
  102. THREE.DracoExporter.MESH_EDGEBREAKER_ENCODING = 1;
  103. THREE.DracoExporter.MESH_SEQUENTIAL_ENCODING = 0;
  104. // Geometry type
  105. THREE.DracoExporter.POINT_CLOUD = 0;
  106. THREE.DracoExporter.TRIANGULAR_MESH = 1;
  107. // Attribute type
  108. THREE.DracoExporter.INVALID = - 1;
  109. THREE.DracoExporter.POSITION = 0;
  110. THREE.DracoExporter.NORMAL = 1;
  111. THREE.DracoExporter.COLOR = 2;
  112. THREE.DracoExporter.TEX_COORD = 3;
  113. THREE.DracoExporter.GENERIC = 4;