LatheGeometry.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /**
  2. * @author zz85 / https://github.com/zz85
  3. * @author bhouston / http://clara.io
  4. * @author Mugen87 / https://github.com/Mugen87
  5. */
  6. import { Geometry } from '../core/Geometry.js';
  7. import { Float32BufferAttribute } from '../core/BufferAttribute.js';
  8. import { BufferGeometry } from '../core/BufferGeometry.js';
  9. import { Vector3 } from '../math/Vector3.js';
  10. import { Vector2 } from '../math/Vector2.js';
  11. import { MathUtils } from '../math/MathUtils.js';
  12. // LatheGeometry
  13. function LatheGeometry( points, segments, phiStart, phiLength ) {
  14. Geometry.call( this );
  15. this.type = 'LatheGeometry';
  16. this.parameters = {
  17. points: points,
  18. segments: segments,
  19. phiStart: phiStart,
  20. phiLength: phiLength
  21. };
  22. this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
  23. this.mergeVertices();
  24. }
  25. LatheGeometry.prototype = Object.create( Geometry.prototype );
  26. LatheGeometry.prototype.constructor = LatheGeometry;
  27. // LatheBufferGeometry
  28. function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
  29. BufferGeometry.call( this );
  30. this.type = 'LatheBufferGeometry';
  31. this.parameters = {
  32. points: points,
  33. segments: segments,
  34. phiStart: phiStart,
  35. phiLength: phiLength
  36. };
  37. segments = Math.floor( segments ) || 12;
  38. phiStart = phiStart || 0;
  39. phiLength = phiLength || Math.PI * 2;
  40. // clamp phiLength so it's in range of [ 0, 2PI ]
  41. phiLength = MathUtils.clamp( phiLength, 0, Math.PI * 2 );
  42. // buffers
  43. const indices = [];
  44. const vertices = [];
  45. const uvs = [];
  46. // helper variables
  47. const inverseSegments = 1.0 / segments;
  48. const vertex = new Vector3();
  49. const uv = new Vector2();
  50. // generate vertices and uvs
  51. for ( let i = 0; i <= segments; i ++ ) {
  52. const phi = phiStart + i * inverseSegments * phiLength;
  53. const sin = Math.sin( phi );
  54. const cos = Math.cos( phi );
  55. for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
  56. // vertex
  57. vertex.x = points[ j ].x * sin;
  58. vertex.y = points[ j ].y;
  59. vertex.z = points[ j ].x * cos;
  60. vertices.push( vertex.x, vertex.y, vertex.z );
  61. // uv
  62. uv.x = i / segments;
  63. uv.y = j / ( points.length - 1 );
  64. uvs.push( uv.x, uv.y );
  65. }
  66. }
  67. // indices
  68. for ( let i = 0; i < segments; i ++ ) {
  69. for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
  70. const base = j + i * points.length;
  71. const a = base;
  72. const b = base + points.length;
  73. const c = base + points.length + 1;
  74. const d = base + 1;
  75. // faces
  76. indices.push( a, b, d );
  77. indices.push( b, c, d );
  78. }
  79. }
  80. // build geometry
  81. this.setIndex( indices );
  82. this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
  83. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  84. // generate normals
  85. this.computeVertexNormals();
  86. // if the geometry is closed, we need to average the normals along the seam.
  87. // because the corresponding vertices are identical (but still have different UVs).
  88. if ( phiLength === Math.PI * 2 ) {
  89. const normals = this.attributes.normal.array;
  90. const n1 = new Vector3();
  91. const n2 = new Vector3();
  92. const n = new Vector3();
  93. // this is the buffer offset for the last line of vertices
  94. const base = segments * points.length * 3;
  95. for ( let i = 0, j = 0; i < points.length; i ++, j += 3 ) {
  96. // select the normal of the vertex in the first line
  97. n1.x = normals[ j + 0 ];
  98. n1.y = normals[ j + 1 ];
  99. n1.z = normals[ j + 2 ];
  100. // select the normal of the vertex in the last line
  101. n2.x = normals[ base + j + 0 ];
  102. n2.y = normals[ base + j + 1 ];
  103. n2.z = normals[ base + j + 2 ];
  104. // average normals
  105. n.addVectors( n1, n2 ).normalize();
  106. // assign the new values to both normals
  107. normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
  108. normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
  109. normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
  110. }
  111. }
  112. }
  113. LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
  114. LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
  115. export { LatheGeometry, LatheBufferGeometry };