TubePainter.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /**
  2. * @author mr.doob / http://mrdoob.com/
  3. */
  4. import {
  5. BufferAttribute,
  6. BufferGeometry,
  7. Color,
  8. DynamicDrawUsage,
  9. Matrix4,
  10. Mesh,
  11. MeshStandardMaterial,
  12. Vector3,
  13. VertexColors
  14. } from '../../../build/three.module.js';
  15. function TubePainter() {
  16. const BUFFER_SIZE = 1000000 * 3;
  17. let positions = new BufferAttribute( new Float32Array( BUFFER_SIZE ), 3 );
  18. positions.usage = DynamicDrawUsage;
  19. let normals = new BufferAttribute( new Float32Array( BUFFER_SIZE ), 3 );
  20. normals.usage = DynamicDrawUsage;
  21. let colors = new BufferAttribute( new Float32Array( BUFFER_SIZE ), 3 );
  22. colors.usage = DynamicDrawUsage;
  23. let geometry = new BufferGeometry();
  24. geometry.setAttribute( 'position', positions );
  25. geometry.setAttribute( 'normal', normals );
  26. geometry.setAttribute( 'color', colors );
  27. geometry.drawRange.count = 0;
  28. let material = new MeshStandardMaterial( {
  29. vertexColors: VertexColors
  30. } );
  31. let mesh = new Mesh( geometry, material );
  32. mesh.frustumCulled = false;
  33. //
  34. function getPoints( size ) {
  35. let PI2 = Math.PI * 2;
  36. let sides = 10;
  37. let array = [];
  38. let radius = 0.01 * size;
  39. for ( let i = 0; i < sides; i ++ ) {
  40. let angle = ( i / sides ) * PI2;
  41. array.push( new Vector3( Math.sin( angle ) * radius, Math.cos( angle ) * radius, 0 ) );
  42. }
  43. return array;
  44. }
  45. //
  46. let vector1 = new Vector3();
  47. let vector2 = new Vector3();
  48. let vector3 = new Vector3();
  49. let vector4 = new Vector3();
  50. let color = new Color( 0xffffff );
  51. let size = 1;
  52. function stroke( position1, position2, matrix1, matrix2 ) {
  53. if ( position1.distanceToSquared( position2 ) === 0 ) return;
  54. let count = geometry.drawRange.count;
  55. let points = getPoints( size );
  56. for ( let i = 0, il = points.length; i < il; i ++ ) {
  57. let vertex1 = points[ i ];
  58. let vertex2 = points[ ( i + 1 ) % il ];
  59. // positions
  60. vector1.copy( vertex1 ).applyMatrix4( matrix2 ).add( position2 );
  61. vector2.copy( vertex2 ).applyMatrix4( matrix2 ).add( position2 );
  62. vector3.copy( vertex2 ).applyMatrix4( matrix1 ).add( position1 );
  63. vector4.copy( vertex1 ).applyMatrix4( matrix1 ).add( position1 );
  64. vector1.toArray( positions.array, ( count + 0 ) * 3 );
  65. vector2.toArray( positions.array, ( count + 1 ) * 3 );
  66. vector4.toArray( positions.array, ( count + 2 ) * 3 );
  67. vector2.toArray( positions.array, ( count + 3 ) * 3 );
  68. vector3.toArray( positions.array, ( count + 4 ) * 3 );
  69. vector4.toArray( positions.array, ( count + 5 ) * 3 );
  70. // normals
  71. vector1.copy( vertex1 ).applyMatrix4( matrix2 ).normalize();
  72. vector2.copy( vertex2 ).applyMatrix4( matrix2 ).normalize();
  73. vector3.copy( vertex2 ).applyMatrix4( matrix1 ).normalize();
  74. vector4.copy( vertex1 ).applyMatrix4( matrix1 ).normalize();
  75. vector1.toArray( normals.array, ( count + 0 ) * 3 );
  76. vector2.toArray( normals.array, ( count + 1 ) * 3 );
  77. vector4.toArray( normals.array, ( count + 2 ) * 3 );
  78. vector2.toArray( normals.array, ( count + 3 ) * 3 );
  79. vector3.toArray( normals.array, ( count + 4 ) * 3 );
  80. vector4.toArray( normals.array, ( count + 5 ) * 3 );
  81. // colors
  82. color.toArray( colors.array, ( count + 0 ) * 3 );
  83. color.toArray( colors.array, ( count + 1 ) * 3 );
  84. color.toArray( colors.array, ( count + 2 ) * 3 );
  85. color.toArray( colors.array, ( count + 3 ) * 3 );
  86. color.toArray( colors.array, ( count + 4 ) * 3 );
  87. color.toArray( colors.array, ( count + 5 ) * 3 );
  88. count += 6;
  89. }
  90. geometry.drawRange.count = count;
  91. }
  92. //
  93. let up = new Vector3( 0, 1, 0 );
  94. let point1 = new Vector3();
  95. let point2 = new Vector3();
  96. let matrix1 = new Matrix4();
  97. let matrix2 = new Matrix4();
  98. function moveTo( position ) {
  99. point1.copy( position );
  100. matrix1.lookAt( point2, point1, up );
  101. point2.copy( position );
  102. matrix2.copy( matrix1 );
  103. }
  104. function lineTo( position ) {
  105. point1.copy( position );
  106. matrix1.lookAt( point2, point1, up );
  107. stroke( point1, point2, matrix1, matrix2 );
  108. point2.copy( point1 );
  109. matrix2.copy( matrix1 );
  110. }
  111. function setSize( value ) {
  112. size = value;
  113. }
  114. //
  115. let count = 0;
  116. function update() {
  117. let start = count;
  118. let end = geometry.drawRange.count;
  119. if ( start === end ) return;
  120. positions.updateRange.offset = start * 3;
  121. positions.updateRange.count = ( end - start ) * 3;
  122. positions.needsUpdate = true;
  123. normals.updateRange.offset = start * 3;
  124. normals.updateRange.count = ( end - start ) * 3;
  125. normals.needsUpdate = true;
  126. colors.updateRange.offset = start * 3;
  127. colors.updateRange.count = ( end - start ) * 3;
  128. colors.needsUpdate = true;
  129. count = geometry.drawRange.count;
  130. }
  131. return {
  132. mesh: mesh,
  133. moveTo: moveTo,
  134. lineTo: lineTo,
  135. setSize: setSize,
  136. update: update
  137. };
  138. }
  139. export { TubePainter };