LineSegmentsGeometry.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. import {
  2. Box3,
  3. Float32BufferAttribute,
  4. InstancedBufferGeometry,
  5. InstancedInterleavedBuffer,
  6. InterleavedBufferAttribute,
  7. Sphere,
  8. Vector3,
  9. WireframeGeometry
  10. } from 'three';
  11. const _box = new Box3();
  12. const _vector = new Vector3();
  13. /**
  14. * A series of vertex pairs, forming line segments.
  15. *
  16. * This is used in {@link LineSegments2} to describe the shape.
  17. *
  18. * @augments InstancedBufferGeometry
  19. */
  20. class LineSegmentsGeometry extends InstancedBufferGeometry {
  21. /**
  22. * Constructs a new line segments geometry.
  23. */
  24. constructor() {
  25. super();
  26. /**
  27. * This flag can be used for type testing.
  28. *
  29. * @type {boolean}
  30. * @readonly
  31. * @default true
  32. */
  33. this.isLineSegmentsGeometry = true;
  34. this.type = 'LineSegmentsGeometry';
  35. const positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ];
  36. const uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ];
  37. const index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ];
  38. this.setIndex( index );
  39. this.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
  40. this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
  41. }
  42. /**
  43. * Applies the given 4x4 transformation matrix to the geometry.
  44. *
  45. * @param {Matrix4} matrix - The matrix to apply.
  46. * @return {LineSegmentsGeometry} A reference to this instance.
  47. */
  48. applyMatrix4( matrix ) {
  49. const start = this.attributes.instanceStart;
  50. const end = this.attributes.instanceEnd;
  51. if ( start !== undefined ) {
  52. start.applyMatrix4( matrix );
  53. end.applyMatrix4( matrix );
  54. start.needsUpdate = true;
  55. }
  56. if ( this.boundingBox !== null ) {
  57. this.computeBoundingBox();
  58. }
  59. if ( this.boundingSphere !== null ) {
  60. this.computeBoundingSphere();
  61. }
  62. return this;
  63. }
  64. /**
  65. * Sets the given line positions for this geometry. The length must be a multiple of six since
  66. * each line segment is defined by a start end vertex in the pattern `(xyz xyz)`.
  67. *
  68. * @param {Float32|Array} array - The position data to set.
  69. * @return {LineSegmentsGeometry} A reference to this geometry.
  70. */
  71. setPositions( array ) {
  72. let lineSegments;
  73. if ( array instanceof Float32Array ) {
  74. lineSegments = array;
  75. } else if ( Array.isArray( array ) ) {
  76. lineSegments = new Float32Array( array );
  77. }
  78. const instanceBuffer = new InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz
  79. this.setAttribute( 'instanceStart', new InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz
  80. this.setAttribute( 'instanceEnd', new InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz
  81. this.instanceCount = this.attributes.instanceStart.count;
  82. //
  83. this.computeBoundingBox();
  84. this.computeBoundingSphere();
  85. return this;
  86. }
  87. /**
  88. * Sets the given line colors for this geometry. The length must be a multiple of six since
  89. * each line segment is defined by a start end color in the pattern `(rgb rgb)`.
  90. *
  91. * @param {Float32|Array} array - The position data to set.
  92. * @return {LineSegmentsGeometry} A reference to this geometry.
  93. */
  94. setColors( array ) {
  95. let colors;
  96. if ( array instanceof Float32Array ) {
  97. colors = array;
  98. } else if ( Array.isArray( array ) ) {
  99. colors = new Float32Array( array );
  100. }
  101. const instanceColorBuffer = new InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb
  102. this.setAttribute( 'instanceColorStart', new InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb
  103. this.setAttribute( 'instanceColorEnd', new InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb
  104. return this;
  105. }
  106. /**
  107. * Setups this line segments geometry from the given wireframe geometry.
  108. *
  109. * @param {WireframeGeometry} geometry - The geometry that should be used as a data source for this geometry.
  110. * @return {LineSegmentsGeometry} A reference to this geometry.
  111. */
  112. fromWireframeGeometry( geometry ) {
  113. this.setPositions( geometry.attributes.position.array );
  114. return this;
  115. }
  116. /**
  117. * Setups this line segments geometry from the given edges geometry.
  118. *
  119. * @param {EdgesGeometry} geometry - The geometry that should be used as a data source for this geometry.
  120. * @return {LineSegmentsGeometry} A reference to this geometry.
  121. */
  122. fromEdgesGeometry( geometry ) {
  123. this.setPositions( geometry.attributes.position.array );
  124. return this;
  125. }
  126. /**
  127. * Setups this line segments geometry from the given mesh.
  128. *
  129. * @param {Mesh} mesh - The mesh geometry that should be used as a data source for this geometry.
  130. * @return {LineSegmentsGeometry} A reference to this geometry.
  131. */
  132. fromMesh( mesh ) {
  133. this.fromWireframeGeometry( new WireframeGeometry( mesh.geometry ) );
  134. // set colors, maybe
  135. return this;
  136. }
  137. /**
  138. * Setups this line segments geometry from the given line segments.
  139. *
  140. * @param {LineSegments} lineSegments - The line segments that should be used as a data source for this geometry.
  141. * Assumes the source geometry is not using indices.
  142. * @return {LineSegmentsGeometry} A reference to this geometry.
  143. */
  144. fromLineSegments( lineSegments ) {
  145. const geometry = lineSegments.geometry;
  146. this.setPositions( geometry.attributes.position.array ); // assumes non-indexed
  147. // set colors, maybe
  148. return this;
  149. }
  150. computeBoundingBox() {
  151. if ( this.boundingBox === null ) {
  152. this.boundingBox = new Box3();
  153. }
  154. const start = this.attributes.instanceStart;
  155. const end = this.attributes.instanceEnd;
  156. if ( start !== undefined && end !== undefined ) {
  157. this.boundingBox.setFromBufferAttribute( start );
  158. _box.setFromBufferAttribute( end );
  159. this.boundingBox.union( _box );
  160. }
  161. }
  162. computeBoundingSphere() {
  163. if ( this.boundingSphere === null ) {
  164. this.boundingSphere = new Sphere();
  165. }
  166. if ( this.boundingBox === null ) {
  167. this.computeBoundingBox();
  168. }
  169. const start = this.attributes.instanceStart;
  170. const end = this.attributes.instanceEnd;
  171. if ( start !== undefined && end !== undefined ) {
  172. const center = this.boundingSphere.center;
  173. this.boundingBox.getCenter( center );
  174. let maxRadiusSq = 0;
  175. for ( let i = 0, il = start.count; i < il; i ++ ) {
  176. _vector.fromBufferAttribute( start, i );
  177. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );
  178. _vector.fromBufferAttribute( end, i );
  179. maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );
  180. }
  181. this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
  182. if ( isNaN( this.boundingSphere.radius ) ) {
  183. console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this );
  184. }
  185. }
  186. }
  187. toJSON() {
  188. // todo
  189. }
  190. }
  191. export { LineSegmentsGeometry };
粤ICP备19079148号