/** * @author mikael emtinger / http://gomo.se/ * @author alteredq / http://alteredqualia.com/ */ import { Vector2 } from '../math/Vector2.js'; import { Vector3 } from '../math/Vector3.js'; import { Matrix4 } from '../math/Matrix4.js'; import { Triangle } from '../math/Triangle.js'; import { Object3D } from '../core/Object3D.js'; import { BufferGeometry } from '../core/BufferGeometry.js'; import { InterleavedBuffer } from '../core/InterleavedBuffer.js'; import { InterleavedBufferAttribute } from '../core/InterleavedBufferAttribute.js'; import { SpriteMaterial } from '../materials/SpriteMaterial.js'; var geometry; function Sprite( material ) { Object3D.call( this ); this.type = 'Sprite'; if ( geometry === undefined ) { geometry = new BufferGeometry(); var float32Array = new Float32Array( [ - 0.5, - 0.5, 0, 0, 0, 0.5, - 0.5, 0, 1, 0, 0.5, 0.5, 0, 1, 1, - 0.5, 0.5, 0, 0, 1 ] ); var interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); geometry.addAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); geometry.addAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); } this.geometry = geometry; this.material = ( material !== undefined ) ? material : new SpriteMaterial(); this.center = new Vector2( 0.5, 0.5 ); } Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { constructor: Sprite, isSprite: true, raycast: ( function () { var intersectPoint = new Vector3(); var worldScale = new Vector3(); var mvPosition = new Vector3(); var alignedPosition = new Vector2(); var rotatedPosition = new Vector2(); var viewWorldMatrix = new Matrix4(); var vA = new Vector3(); var vB = new Vector3(); var vC = new Vector3(); var uvA = new Vector2(); var uvB = new Vector2(); var uvC = new Vector2(); function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { // compute position in camera space alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); // to check if rotation is not zero if ( sin !== undefined ) { rotatedPosition.x = ( cos * alignedPosition.x ) - ( sin * alignedPosition.y ); rotatedPosition.y = ( sin * alignedPosition.x ) + ( cos * alignedPosition.y ); } else { rotatedPosition.copy( alignedPosition ); } vertexPosition.copy( mvPosition ); vertexPosition.x += rotatedPosition.x; vertexPosition.y += rotatedPosition.y; // transform to world space vertexPosition.applyMatrix4( viewWorldMatrix ); } return function raycast( raycaster, intersects ) { worldScale.setFromMatrixScale( this.matrixWorld ); viewWorldMatrix.getInverse( this.modelViewMatrix ).premultiply( this.matrixWorld ); mvPosition.setFromMatrixPosition( this.modelViewMatrix ); var rotation = this.material.rotation; var sin, cos; if ( rotation !== 0 ) { cos = Math.cos( rotation ); sin = Math.sin( rotation ); } var center = this.center; transformVertex( vA.set( - 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos ); transformVertex( vB.set( 0.5, - 0.5, 0 ), mvPosition, center, worldScale, sin, cos ); transformVertex( vC.set( 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos ); uvA.set( 0, 0 ); uvB.set( 1, 0 ); uvC.set( 1, 1 ); // check first triangle var intersect = raycaster.ray.intersectTriangle( vA, vB, vC, false, intersectPoint ); if ( intersect === null ) { // check second triangle transformVertex( vB.set( - 0.5, 0.5, 0 ), mvPosition, center, worldScale, sin, cos ); uvB.set( 0, 1 ); intersect = raycaster.ray.intersectTriangle( vA, vC, vB, false, intersectPoint ); if ( intersect === null ) { return; } } var distance = raycaster.ray.origin.distanceTo( intersectPoint ); if ( distance < raycaster.near || distance > raycaster.far ) return; intersects.push( { distance: distance, point: intersectPoint.clone(), uv: Triangle.getUV( intersectPoint, vA, vB, vC, uvA, uvB, uvC, new Vector2() ), face: null, object: this } ); }; }() ), clone: function () { return new this.constructor( this.material ).copy( this ); }, copy: function ( source ) { Object3D.prototype.copy.call( this, source ); if ( source.center !== undefined ) this.center.copy( source.center ); return this; } } ); export { Sprite };