TubeBufferGeometry.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { BufferGeometry } from '../core/BufferGeometry';
  2. import { Float32Attribute, Uint16Attribute, Uint32Attribute } from '../core/BufferAttribute';
  3. import { Vector2 } from '../math/Vector2';
  4. import { Vector3 } from '../math/Vector3';
  5. /**
  6. * @author Mugen87 / https://github.com/Mugen87
  7. *
  8. * Creates a tube which extrudes along a 3d spline.
  9. *
  10. */
  11. function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
  12. BufferGeometry.call( this );
  13. this.type = 'TubeBufferGeometry';
  14. this.parameters = {
  15. path: path,
  16. tubularSegments: tubularSegments,
  17. radius: radius,
  18. radialSegments: radialSegments,
  19. closed: closed
  20. };
  21. tubularSegments = tubularSegments || 64;
  22. radius = radius || 1;
  23. radialSegments = radialSegments || 8;
  24. closed = closed || false;
  25. var frames = path.computeFrenetFrames( tubularSegments, closed );
  26. // expose internals
  27. this.tangents = frames.tangents;
  28. this.normals = frames.normals;
  29. this.binormals = frames.binormals;
  30. // helper variables
  31. var vertex = new Vector3();
  32. var normal = new Vector3();
  33. var uv = new Vector2();
  34. var i, j;
  35. // buffer
  36. var vertices = [];
  37. var normals = [];
  38. var uvs = [];
  39. var indices = [];
  40. // create buffer data
  41. generateBufferData();
  42. // build geometry
  43. this.setIndex( ( indices.length > 65535 ? Uint32Attribute : Uint16Attribute )( indices, 1 ) );
  44. this.addAttribute( 'position', Float32Attribute( vertices, 3 ) );
  45. this.addAttribute( 'normal', Float32Attribute( normals, 3 ) );
  46. this.addAttribute( 'uv', Float32Attribute( uvs, 2 ) );
  47. // functions
  48. function generateBufferData() {
  49. for ( i = 0; i < tubularSegments; i ++ ) {
  50. generateSegment( i );
  51. }
  52. // if the geometry is not closed, generate the last row of vertices and normals
  53. // at the regular position on the given path
  54. //
  55. // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
  56. generateSegment( ( closed === false ) ? tubularSegments : 0 );
  57. // uvs are generated in a separate function.
  58. // this makes it easy compute correct values for closed geometries
  59. generateUVs();
  60. // finally create faces
  61. generateIndices();
  62. }
  63. function generateSegment( i ) {
  64. // we use getPointAt to sample evenly distributed points from the given path
  65. var P = path.getPointAt( i / tubularSegments );
  66. // retrieve corresponding normal and binormal
  67. var N = frames.normals[ i ];
  68. var B = frames.binormals[ i ];
  69. // generate normals and vertices for the current segment
  70. for ( j = 0; j <= radialSegments; j ++ ) {
  71. var v = j / radialSegments * Math.PI * 2;
  72. var sin = Math.sin( v );
  73. var cos = - Math.cos( v );
  74. // normal
  75. normal.x = ( cos * N.x + sin * B.x );
  76. normal.y = ( cos * N.y + sin * B.y );
  77. normal.z = ( cos * N.z + sin * B.z );
  78. normal.normalize();
  79. normals.push( normal.x, normal.y, normal.z );
  80. // vertex
  81. vertex.x = P.x + radius * normal.x;
  82. vertex.y = P.y + radius * normal.y;
  83. vertex.z = P.z + radius * normal.z;
  84. vertices.push( vertex.x, vertex.y, vertex.z );
  85. }
  86. }
  87. function generateIndices() {
  88. for ( j = 1; j <= tubularSegments; j ++ ) {
  89. for ( i = 1; i <= radialSegments; i ++ ) {
  90. var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
  91. var b = ( radialSegments + 1 ) * j + ( i - 1 );
  92. var c = ( radialSegments + 1 ) * j + i;
  93. var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
  94. // faces
  95. indices.push( a, b, d );
  96. indices.push( b, c, d );
  97. }
  98. }
  99. }
  100. function generateUVs() {
  101. for ( i = 0; i <= tubularSegments; i ++ ) {
  102. for ( j = 0; j <= radialSegments; j ++ ) {
  103. uv.x = i / tubularSegments;
  104. uv.y = j / radialSegments;
  105. uvs.push( uv.x, uv.y );
  106. }
  107. }
  108. }
  109. }
  110. TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
  111. TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
  112. export { TubeBufferGeometry };
粤ICP备19079148号