diff --git a/src/objects/Sprite.js b/src/objects/Sprite.js index c7b2438bef58d1..a7c389b358cf80 100644 --- a/src/objects/Sprite.js +++ b/src/objects/Sprite.js @@ -1,5 +1,6 @@ import { Vector2 } from '../math/Vector2.js'; import { Vector3 } from '../math/Vector3.js'; +import { Matrix4 } from '../math/Matrix4.js'; import { Object3D } from '../core/Object3D.js'; import { SpriteMaterial } from '../materials/SpriteMaterial.js'; @@ -29,18 +30,80 @@ Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { raycast: ( function () { var intersectPoint = new Vector3(); - var worldPosition = new Vector3(); var worldScale = new Vector3(); + var mvPosition = new Vector3(); - return function raycast( raycaster, intersects ) { + var alignedPosition = new Vector2(); + var rotatedPosition = new Vector2(); + var viewWorldMatrix = new Matrix4(); + + var vA = new Vector3(); + var vB = new Vector3(); + var vC = new Vector3(); + + 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 ); - worldPosition.setFromMatrixPosition( this.matrixWorld ); - raycaster.ray.closestPointToPoint( worldPosition, intersectPoint ); + } + + return function raycast( raycaster, intersects ) { worldScale.setFromMatrixScale( this.matrixWorld ); - var guessSizeSq = worldScale.x * worldScale.y / 4; + 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 ); + + // 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 ); + intersect = raycaster.ray.intersectTriangle( vA, vC, vB, false, intersectPoint ); + if ( intersect === null ) { + + return; + + } - if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return; + } var distance = raycaster.ray.origin.distanceTo( intersectPoint );