import { PerspectiveCamera , MathUtils , Vector4 } from 'three' ; import { PlaneMesh } from './background' ; param { number } absoluteZ param { PerspectiveCamera } camera returns function getVisibleHeightAtDepth ( absoluteZ , camera ) { return 2 * Math . tan ( MathUtils . degToRad ( camera . fov ) / 2 ) * absoluteZ ; } param { number } absoluteZ param { PerspectiveCamera } camera returns function getVisibleWidthAtDepth ( absoluteZ , camera ) { return getVisibleHeightAtDepth ( absoluteZ , camera ) * camera . aspect ; } param { number } width param { number } height param { number } angleInRadians returns function getInnerBoundedBoxForRect ( width , height , angleInRadians = 0 ) { const widthIsLonger = width >= height ; const longSide = widthIsLonger ? width : height ; const shortSide = widthIsLonger ? height : width ; const sinAngle = Math . abs ( Math . sin ( angleInRadians ) ) ; const cosAngle = Math . abs ( Math . cos ( angleInRadians ) ) ; if ( ( shortSide <= 2 * sinAngle * cosAngle * longSide ) || ( Math . abs ( sinAngle - cosAngle ) < 1e-10 ) ) { const x = 0.5 * shortSide ; return { width : widthIsLonger ? x / sinAngle : x / cosAngle , height : widthIsLonger ? x / cosAngle : x / sinAngle , } ; } const cosDoubleAngle = cosAngle * cosAngle - sinAngle * sinAngle ; return { width : ( width * cosAngle - height * sinAngle ) / cosDoubleAngle , height : ( height * cosAngle - width * sinAngle ) / cosDoubleAngle , } ; } param { PlaneMesh } plane param { PerspectiveCamera } camera param { number } rotateZ returns function getMaxFullScreenDepthForPlane ( plane , camera , rotateZ ) { const { width : rectWidth , height : rectHeight } = plane . geometry . parameters ; const { width , height } = getInnerBoundedBoxForRect ( rectWidth , rectHeight , rotateZ ) ; const verticalFovConstant = 2 * Math . tan ( MathUtils . degToRad ( camera . fov ) / 2 ) ; const maxDepthForWidth = width / ( verticalFovConstant * camera . aspect ) ; const maxDepthForHeight = height / verticalFovConstant ; return Math . min ( maxDepthForWidth , maxDepthForHeight ) + plane . position . z ; } param { PlaneMesh } plane param { PerspectiveCamera } camera param { number } relativeZ param { number } rotateZ returns function getViewBox ( plane , camera , relativeZ , rotateZ ) { const maxDepth = getMaxFullScreenDepthForPlane ( plane , camera , rotateZ ) ; const absoluteDepth = relativeZ * maxDepth ; return { width : getVisibleWidthAtDepth ( absoluteDepth , camera ) , height : getVisibleHeightAtDepth ( absoluteDepth , camera ) , } ; } param { PlaneMesh } plane param { PerspectiveCamera } camera param { number } relativeZ param { number } rotateZ returns function getAvailablePanDistance ( plane , camera , relativeZ , rotateZ ) { const { width : rectWidth , height : rectHeight } = plane . geometry . parameters ; const { width , height } = getInnerBoundedBoxForRect ( rectWidth , rectHeight , rotateZ ) ; const viewBox = getViewBox ( plane , camera , relativeZ , rotateZ ) ; return { width : width - viewBox . width , height : height - viewBox . height , } ; } param { PlaneMesh } plane param { PerspectiveCamera } camera param { Vector4 } relativePosition returns function toAbsolutePosition ( plane , camera , relativePosition ) { const { x , y , z , w : zr } = relativePosition ; const panDistance = getAvailablePanDistance ( plane , camera , z , zr ) ; const absoluteX = - ( panDistance . width / 2 ) + ( x * panDistance . width ) ; const absoluteY = ( panDistance . height / 2 ) - ( y * panDistance . height ) ; const absoluteDepth = getMaxFullScreenDepthForPlane ( plane , camera , zr ) * z ; return new Vector4 ( absoluteX * Math . cos ( zr ) - absoluteY * Math . sin ( zr ) , absoluteX * Math . sin ( zr ) + absoluteY * Math . cos ( zr ) , absoluteDepth , zr ) ; } export { getMaxFullScreenDepthForPlane , toAbsolutePosition , } ;