TubePainter.js 4.6 KB

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