Sprite.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import { Vector2 } from '../math/Vector2.js';
  2. import { Vector3 } from '../math/Vector3.js';
  3. import { Matrix4 } from '../math/Matrix4.js';
  4. import { Triangle } from '../math/Triangle.js';
  5. import { Object3D } from '../core/Object3D.js';
  6. import { BufferGeometry } from '../core/BufferGeometry.js';
  7. import { InterleavedBuffer } from '../core/InterleavedBuffer.js';
  8. import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js';
  9. import { SpriteMaterial } from '../materials/SpriteMaterial.js';
  10. let _geometry;
  11. const _intersectPoint = /*@__PURE__*/ new Vector3();
  12. const _worldScale = /*@__PURE__*/ new Vector3();
  13. const _mvPosition = /*@__PURE__*/ new Vector3();
  14. const _alignedPosition = /*@__PURE__*/ new Vector2();
  15. const _rotatedPosition = /*@__PURE__*/ new Vector2();
  16. const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
  17. const _vA = /*@__PURE__*/ new Vector3();
  18. const _vB = /*@__PURE__*/ new Vector3();
  19. const _vC = /*@__PURE__*/ new Vector3();
  20. const _uvA = /*@__PURE__*/ new Vector2();
  21. const _uvB = /*@__PURE__*/ new Vector2();
  22. const _uvC = /*@__PURE__*/ new Vector2();
  23. class Sprite extends Object3D {
  24. constructor( material ) {
  25. super();
  26. this.isSprite = true;
  27. this.type = 'Sprite';
  28. if ( _geometry === undefined ) {
  29. _geometry = new BufferGeometry();
  30. const float32Array = new Float32Array( [
  31. - 0.5, - 0.5, 0, 0, 0,
  32. 0.5, - 0.5, 0, 1, 0,
  33. 0.5, 0.5, 0, 1, 1,
  34. - 0.5, 0.5, 0, 0, 1
  35. ] );
  36. const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
  37. _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
  38. _geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
  39. _geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
  40. }
  41. this.geometry = _geometry;
  42. this.material = ( material !== undefined ) ? material : new SpriteMaterial();
  43. this.center = new Vector2( 0.5, 0.5 );
  44. }
  45. raycast( raycaster, intersects ) {
  46. if ( raycaster.camera === null ) {
  47. console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
  48. }
  49. _worldScale.setFromMatrixScale( this.matrixWorld );
  50. _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
  51. this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
  52. _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
  53. if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
  54. _worldScale.multiplyScalar( - _mvPosition.z );
  55. }
  56. const rotation = this.material.rotation;
  57. let sin, cos;
  58. if ( rotation !== 0 ) {
  59. cos = Math.cos( rotation );
  60. sin = Math.sin( rotation );
  61. }
  62. const center = this.center;
  63. transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  64. transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  65. transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  66. _uvA.set( 0, 0 );
  67. _uvB.set( 1, 0 );
  68. _uvC.set( 1, 1 );
  69. // check first triangle
  70. let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
  71. if ( intersect === null ) {
  72. // check second triangle
  73. transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
  74. _uvB.set( 0, 1 );
  75. intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
  76. if ( intersect === null ) {
  77. return;
  78. }
  79. }
  80. const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
  81. if ( distance < raycaster.near || distance > raycaster.far ) return;
  82. intersects.push( {
  83. distance: distance,
  84. point: _intersectPoint.clone(),
  85. uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
  86. face: null,
  87. object: this
  88. } );
  89. }
  90. copy( source ) {
  91. super.copy( source );
  92. if ( source.center !== undefined ) this.center.copy( source.center );
  93. this.material = source.material;
  94. return this;
  95. }
  96. }
  97. function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
  98. // compute position in camera space
  99. _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
  100. // to check if rotation is not zero
  101. if ( sin !== undefined ) {
  102. _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
  103. _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
  104. } else {
  105. _rotatedPosition.copy( _alignedPosition );
  106. }
  107. vertexPosition.copy( mvPosition );
  108. vertexPosition.x += _rotatedPosition.x;
  109. vertexPosition.y += _rotatedPosition.y;
  110. // transform to world space
  111. vertexPosition.applyMatrix4( _viewWorldMatrix );
  112. }
  113. export { Sprite };