TiltLoader.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import {
  2. BufferAttribute,
  3. BufferGeometry,
  4. Color,
  5. DoubleSide,
  6. FileLoader,
  7. Group,
  8. Loader,
  9. Mesh,
  10. MeshBasicMaterial,
  11. Quaternion,
  12. Vector3
  13. } from '../../../build/three.module.js';
  14. import { JSZip } from '../libs/jszip.module.min.js';
  15. class TiltLoader extends Loader {
  16. load( url, onLoad, onProgress, onError ) {
  17. const scope = this;
  18. const loader = new FileLoader( this.manager );
  19. loader.setPath( this.path );
  20. loader.setResponseType( 'arraybuffer' );
  21. loader.setWithCredentials( this.withCredentials );
  22. loader.load( url, function ( buffer ) {
  23. try {
  24. onLoad( scope.parse( buffer ) );
  25. } catch ( e ) {
  26. if ( onError ) {
  27. onError( e );
  28. } else {
  29. console.error( e );
  30. }
  31. scope.manager.itemError( url );
  32. }
  33. }, onProgress, onError );
  34. }
  35. parse( buffer ) {
  36. const group = new Group();
  37. // https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/edit#
  38. const zip = new JSZip( buffer.slice( 16 ) ); // eslint-disable-line no-undef
  39. /*
  40. const thumbnail = zip.files[ 'thumbnail.png' ].asArrayBuffer();
  41. const img = document.createElement( 'img' );
  42. img.src = URL.createObjectURL( new Blob( [ thumbnail ] ) );
  43. document.body.appendChild( img );
  44. const metadata = JSON.parse( zip.files[ 'metadata.json' ].asText() );
  45. */
  46. /*
  47. const blob = new Blob( [ zip.files[ 'data.sketch' ].asArrayBuffer() ], { type: 'application/octet-stream' } );
  48. window.open( URL.createObjectURL( blob ) );
  49. */
  50. const data = new DataView( zip.files[ 'data.sketch' ].asArrayBuffer() );
  51. const num_strokes = data.getInt32( 16, true );
  52. let offset = 20;
  53. for ( let i = 0; i < num_strokes; i ++ ) {
  54. // const brush_index = data.getInt32( offset, true );
  55. const brush_color = [
  56. data.getFloat32( offset + 4, true ),
  57. data.getFloat32( offset + 8, true ),
  58. data.getFloat32( offset + 12, true ),
  59. data.getFloat32( offset + 16, true )
  60. ];
  61. const brush_size = data.getFloat32( offset + 20, true );
  62. const stroke_mask = data.getUint32( offset + 24, true );
  63. const controlpoint_mask = data.getUint32( offset + 28, true );
  64. let offset_stroke_mask = 0;
  65. let offset_controlpoint_mask = 0;
  66. for ( let j = 0; j < 4; j ++ ) {
  67. // TOFIX: I don't understand these masks yet
  68. const byte = 1 << j;
  69. if ( ( stroke_mask & byte ) > 0 ) offset_stroke_mask += 4;
  70. if ( ( controlpoint_mask & byte ) > 0 ) offset_controlpoint_mask += 4;
  71. }
  72. // console.log( { brush_index, brush_color, brush_size, stroke_mask, controlpoint_mask } );
  73. // console.log( offset_stroke_mask, offset_controlpoint_mask );
  74. offset = offset + 28 + offset_stroke_mask + 4; // TOFIX: This is wrong
  75. const num_control_points = data.getInt32( offset, true );
  76. // console.log( { num_control_points } );
  77. const positions = new Float32Array( num_control_points * 3 );
  78. const quaternions = new Float32Array( num_control_points * 4 );
  79. offset = offset + 4;
  80. for ( let j = 0, k = 0; j < positions.length; j += 3, k += 4 ) {
  81. positions[ j + 0 ] = data.getFloat32( offset + 0, true );
  82. positions[ j + 1 ] = data.getFloat32( offset + 4, true );
  83. positions[ j + 2 ] = data.getFloat32( offset + 8, true );
  84. quaternions[ k + 0 ] = data.getFloat32( offset + 12, true );
  85. quaternions[ k + 1 ] = data.getFloat32( offset + 16, true );
  86. quaternions[ k + 2 ] = data.getFloat32( offset + 20, true );
  87. quaternions[ k + 3 ] = data.getFloat32( offset + 24, true );
  88. offset = offset + 28 + offset_controlpoint_mask; // TOFIX: This is wrong
  89. }
  90. // console.log( positions, quaternions );
  91. const color = new Color().fromArray( brush_color );
  92. const opacity = brush_color[ 3 ];
  93. const geometry = new StrokeGeometry( positions, quaternions, brush_size );
  94. const material = new MeshBasicMaterial( {
  95. color: color, opacity: opacity, transparent: opacity < 1, side: DoubleSide
  96. } );
  97. group.add( new Mesh( geometry, material ) );
  98. }
  99. return group;
  100. }
  101. }
  102. class StrokeGeometry extends BufferGeometry {
  103. constructor( positions, quaternions, size ) {
  104. super();
  105. const vertices = [];
  106. const position = new Vector3();
  107. const prevPosition = new Vector3().fromArray( positions, 0 );
  108. const quaternion = new Quaternion();
  109. const prevQuaternion = new Quaternion().fromArray( quaternions, 0 );
  110. const vector1 = new Vector3();
  111. const vector2 = new Vector3();
  112. const vector3 = new Vector3();
  113. const vector4 = new Vector3();
  114. size = size / 2;
  115. for ( let i = 0, j = 0; i < positions.length; i += 3, j += 4 ) {
  116. position.fromArray( positions, i );
  117. quaternion.fromArray( quaternions, j );
  118. vector1.set( - size, 0, 0 );
  119. vector1.applyQuaternion( quaternion );
  120. vector1.add( position );
  121. vector2.set( size, 0, 0 );
  122. vector2.applyQuaternion( quaternion );
  123. vector2.add( position );
  124. vector3.set( size, 0, 0 );
  125. vector3.applyQuaternion( prevQuaternion );
  126. vector3.add( prevPosition );
  127. vector4.set( - size, 0, 0 );
  128. vector4.applyQuaternion( prevQuaternion );
  129. vector4.add( prevPosition );
  130. vertices.push( vector1.x, vector1.y, - vector1.z );
  131. vertices.push( vector2.x, vector2.y, - vector2.z );
  132. vertices.push( vector4.x, vector4.y, - vector4.z );
  133. vertices.push( vector2.x, vector2.y, - vector2.z );
  134. vertices.push( vector3.x, vector3.y, - vector3.z );
  135. vertices.push( vector4.x, vector4.y, - vector4.z );
  136. prevPosition.copy( position );
  137. prevQuaternion.copy( quaternion );
  138. }
  139. this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) );
  140. }
  141. }
  142. export { TiltLoader };