Sprite.js 4.9 KB

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