import { vec3 } from 'gl-matrix' ; import { AABB } from './AABB' ; import { BoundingSphere } from './BoundingSphere' ; import { Plane } from './Plane' ; const tmpVecA = vec3 . create ( ) ; const tmpVecB = vec3 . create ( ) ; const tmpVecC = vec3 . create ( ) ; const tmpVecD = vec3 . create ( ) ; const tmpVecE = vec3 . create ( ) ; see https see https export class Ray { public origin : vec3 ; public direction : vec3 ; constructor ( origin , direction ) { this . origin = origin || vec3 . create ( ) ; this . direction = direction || vec3 . fromValues ( 0 , 0 , - 1 ) ; } public intersectsAABB ( aabb , intersection ? ) { return intersection ? this . intersectAABBWithIntersection ( aabb , intersection ) : this . intersectsAABBWithoutIntersection ( aabb ) ; } public intersectsSphere ( sphere , intersection ? ) { const m = vec3 . sub ( tmpVecA , this . origin , sphere . center ) ; vec3 . normalize ( tmpVecB , vec3 . copy ( tmpVecB , this . direction ) ) ; const b = vec3 . dot ( m , tmpVecB ) ; const c = vec3 . dot ( m , m ) - sphere . radius * sphere . radius ; if ( c > 0 && b > 0 ) { return null ; } const discr = b * b - c ; if ( discr < 0 ) { return false ; } const t = Math . abs ( - b - Math . sqrt ( discr ) ) ; if ( intersection ) { vec3 . copy ( intersection , this . direction ) ; vec3 . scaleAndAdd ( intersection , this . origin , intersection , t ) ; } return true ; } public intersectsPlane ( plane , intersection ? ) { const t = ( plane . distance - vec3 . dot ( plane . normal , this . origin ) ) / vec3 . dot ( plane . normal , this . direction ) ; const intersects = t >= 0 ; if ( intersects && intersection ) { vec3 . scaleAndAdd ( intersection , this . origin , this . direction , t ) ; } return intersects ; } see https private intersectsAABBWithoutIntersection ( aabb ) { const diff = tmpVecA ; const cross = tmpVecB ; const prod = tmpVecC ; const absDiff = tmpVecD ; const absDir = tmpVecE ; const rayDir = this . direction ; vec3 . sub ( diff , this . origin , aabb . center ) ; vec3 . set ( absDiff , Math . abs ( diff [ 0 ] ) , Math . abs ( diff [ 1 ] ) , Math . abs ( diff [ 2 ] ) ) ; vec3 . mul ( prod , diff , rayDir ) ; if ( ( absDiff [ 0 ] > aabb . halfExtents [ 0 ] && prod [ 0 ] >= 0 ) || ( absDiff [ 1 ] > aabb . halfExtents [ 1 ] && prod [ 1 ] >= 0 ) || ( absDiff [ 2 ] > aabb . halfExtents [ 2 ] && prod [ 2 ] >= 0 ) ) { return false ; } vec3 . set ( absDir , Math . abs ( rayDir [ 0 ] ) , Math . abs ( rayDir [ 1 ] ) , Math . abs ( rayDir [ 2 ] ) ) ; vec3 . cross ( cross , rayDir , diff ) ; vec3 . set ( cross , Math . abs ( cross [ 0 ] ) , Math . abs ( cross [ 1 ] ) , Math . abs ( cross [ 2 ] ) ) ; return ! ( cross [ 0 ] > aabb . halfExtents [ 1 ] * absDir [ 2 ] + aabb . halfExtents [ 2 ] * absDir [ 1 ] || cross [ 1 ] > aabb . halfExtents [ 0 ] * absDir [ 2 ] + aabb . halfExtents [ 2 ] * absDir [ 0 ] || cross [ 2 ] > aabb . halfExtents [ 0 ] * absDir [ 1 ] + aabb . halfExtents [ 1 ] * absDir [ 0 ] ) ; } private intersectAABBWithIntersection ( aabb , intersection ) { const tMin = vec3 . copy ( vec3 . create ( ) , aabb . getMin ( ) ) ; vec3 . sub ( tMin , tMin , this . origin ) ; const tMax = vec3 . copy ( vec3 . create ( ) , aabb . getMax ( ) ) ; vec3 . sub ( tMax , tMax , this . origin ) ; const dir = this . direction ; if ( dir [ 0 ] === 0 ) { tMin [ 0 ] = tMin [ 0 ] < 0 ? - Number . MAX_VALUE : Number . MAX_VALUE ; tMax [ 0 ] = tMax [ 0 ] < 0 ? - Number . MAX_VALUE : Number . MAX_VALUE ; } else { tMin [ 0 ] /= dir [ 0 ] ; tMax [ 0 ] /= dir [ 0 ] ; } if ( dir [ 1 ] === 0 ) { tMin [ 1 ] = tMin [ 1 ] < 0 ? - Number . MAX_VALUE : Number . MAX_VALUE ; tMax [ 1 ] = tMax [ 1 ] < 0 ? - Number . MAX_VALUE : Number . MAX_VALUE ; } else { tMin [ 1 ] /= dir [ 1 ] ; tMax [ 1 ] /= dir [ 1 ] ; } if ( dir [ 2 ] === 0 ) { tMin [ 2 ] = tMin [ 2 ] < 0 ? - Number . MAX_VALUE : Number . MAX_VALUE ; tMax [ 2 ] = tMax [ 2 ] < 0 ? - Number . MAX_VALUE : Number . MAX_VALUE ; } else { tMin [ 2 ] /= dir [ 2 ] ; tMax [ 2 ] /= dir [ 2 ] ; } const realMin = vec3 . set ( tmpVecC , Math . min ( tMin [ 0 ] , tMax [ 0 ] ) , Math . min ( tMin [ 1 ] , tMax [ 1 ] ) , Math . min ( tMin [ 2 ] , tMax [ 2 ] ) ) ; const realMax = vec3 . set ( tmpVecD , Math . max ( tMin [ 0 ] , tMax [ 0 ] ) , Math . max ( tMin [ 1 ] , tMax [ 1 ] ) , Math . max ( tMin [ 2 ] , tMax [ 2 ] ) ) ; const minMax = Math . min ( Math . min ( realMax [ 0 ] , realMax [ 1 ] ) , realMax [ 2 ] ) ; const maxMin = Math . max ( Math . max ( realMin [ 0 ] , realMin [ 1 ] ) , realMin [ 2 ] ) ; const intersects = minMax >= maxMin && maxMin >= 0 ; if ( intersects ) { vec3 . copy ( intersection , this . direction ) ; vec3 . scaleAndAdd ( intersection , this . origin , intersection , maxMin ) ; } return intersects ; } }