UNPKG

@3dverse/livelink-camera-controls

Version:

A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features.

1 lines 71.5 kB
import*as THREE from"threejs-math";import{Vector3}from"threejs-math";const MOUSE_BUTTON={LEFT:1,RIGHT:2,MIDDLE:4};const ACTION=Object.freeze({NONE:0,ROTATE:1,TRUCK:2,SCREEN_PAN:4,OFFSET:8,DOLLY:16,ZOOM:32,TOUCH_ROTATE:64,TOUCH_TRUCK:128,TOUCH_SCREEN_PAN:256,TOUCH_OFFSET:512,TOUCH_DOLLY:1024,TOUCH_ZOOM:2048,TOUCH_DOLLY_TRUCK:4096,TOUCH_DOLLY_SCREEN_PAN:8192,TOUCH_DOLLY_OFFSET:16384,TOUCH_DOLLY_ROTATE:32768,TOUCH_ZOOM_TRUCK:65536,TOUCH_ZOOM_OFFSET:131072,TOUCH_ZOOM_SCREEN_PAN:262144,TOUCH_ZOOM_ROTATE:524288});const DOLLY_DIRECTION={NONE:0,IN:1,OUT:-1};const PI_2=Math.PI*2;const PI_HALF=Math.PI/2;const EPSILON=1e-5;const DEG2RAD=Math.PI/180;function clamp(value,min,max){return Math.max(min,Math.min(max,value))}function approxZero(number,error=EPSILON){return Math.abs(number)<error}function approxEquals(a,b,error=EPSILON){return approxZero(a-b,error)}function roundToStep(value,step){return Math.round(value/step)*step}function infinityToMaxNumber(value){if(isFinite(value))return value;if(value<0)return-Number.MAX_VALUE;return Number.MAX_VALUE}function maxNumberToInfinity(value){if(Math.abs(value)<Number.MAX_VALUE)return value;return value*Infinity}function unproject(vec,camera){return vec.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld)}function smoothDamp(current,target,currentVelocityRef,smoothTime,maxSpeed=Infinity,deltaTime){smoothTime=Math.max(1e-4,smoothTime);const omega=2/smoothTime;const x=omega*deltaTime;const exp=1/(1+x+.48*x*x+.235*x*x*x);let change=current-target;const originalTo=target;const maxChange=maxSpeed*smoothTime;change=clamp(change,-maxChange,maxChange);target=current-change;const temp=(currentVelocityRef.value+omega*change)*deltaTime;currentVelocityRef.value=(currentVelocityRef.value-omega*temp)*exp;let output=target+(change+temp)*exp;if(originalTo-current>0===output>originalTo){output=originalTo;currentVelocityRef.value=(output-originalTo)/deltaTime}return output}function smoothDampVec3(current,target,currentVelocityRef,smoothTime,maxSpeed=Infinity,deltaTime,out){smoothTime=Math.max(1e-4,smoothTime);const omega=2/smoothTime;const x=omega*deltaTime;const exp=1/(1+x+.48*x*x+.235*x*x*x);let targetX=target.x;let targetY=target.y;let targetZ=target.z;let changeX=current.x-targetX;let changeY=current.y-targetY;let changeZ=current.z-targetZ;const originalToX=targetX;const originalToY=targetY;const originalToZ=targetZ;const maxChange=maxSpeed*smoothTime;const maxChangeSq=maxChange*maxChange;const magnitudeSq=changeX*changeX+changeY*changeY+changeZ*changeZ;if(magnitudeSq>maxChangeSq){const magnitude=Math.sqrt(magnitudeSq);changeX=changeX/magnitude*maxChange;changeY=changeY/magnitude*maxChange;changeZ=changeZ/magnitude*maxChange}targetX=current.x-changeX;targetY=current.y-changeY;targetZ=current.z-changeZ;const tempX=(currentVelocityRef.x+omega*changeX)*deltaTime;const tempY=(currentVelocityRef.y+omega*changeY)*deltaTime;const tempZ=(currentVelocityRef.z+omega*changeZ)*deltaTime;currentVelocityRef.x=(currentVelocityRef.x-omega*tempX)*exp;currentVelocityRef.y=(currentVelocityRef.y-omega*tempY)*exp;currentVelocityRef.z=(currentVelocityRef.z-omega*tempZ)*exp;out.x=targetX+(changeX+tempX)*exp;out.y=targetY+(changeY+tempY)*exp;out.z=targetZ+(changeZ+tempZ)*exp;const origMinusCurrentX=originalToX-current.x;const origMinusCurrentY=originalToY-current.y;const origMinusCurrentZ=originalToZ-current.z;const outMinusOrigX=out.x-originalToX;const outMinusOrigY=out.y-originalToY;const outMinusOrigZ=out.z-originalToZ;if(origMinusCurrentX*outMinusOrigX+origMinusCurrentY*outMinusOrigY+origMinusCurrentZ*outMinusOrigZ>0){out.x=originalToX;out.y=originalToY;out.z=originalToZ;currentVelocityRef.x=(out.x-originalToX)/deltaTime;currentVelocityRef.y=(out.y-originalToY)/deltaTime;currentVelocityRef.z=(out.z-originalToZ)/deltaTime}return out}function extractClientCoordFromEvent(pointers,out){out.set(0,0);pointers.forEach((pointer=>{out.x+=pointer.clientX;out.y+=pointer.clientY}));out.x/=pointers.length;out.y/=pointers.length}let _m1=new THREE.Matrix4;let _position=new THREE.Vector3;class Camera{position;quaternion;up;scale=new THREE.Vector3(1,1,1);matrix=new THREE.Matrix4;matrixWorld=new THREE.Matrix4;matrixWorldInverse=new THREE.Matrix4;projectionMatrix=new THREE.Matrix4;projectionMatrixInverse=new THREE.Matrix4;zoom=1;matrixWorldNeedsUpdate=true;matrixAutoUpdate=true;matrixWorldAutoUpdate=true;constructor(localTransform){this.position=(new THREE.Vector3).fromArray(localTransform.position);this.quaternion=(new THREE.Quaternion).fromArray(localTransform.orientation);this.up=new THREE.Vector3(0,1,0)}updateMatrix(){this.matrix.compose(this.position,this.quaternion,this.scale);this.matrixWorldNeedsUpdate=true}updateMatrixWorld(force=false){if(this.matrixAutoUpdate)this.updateMatrix();if(this.matrixWorldNeedsUpdate||force){if(this.matrixWorldAutoUpdate===true){this.matrixWorld.copy(this.matrix)}this.matrixWorldNeedsUpdate=false}this.matrixWorldInverse.copy(this.matrixWorld).invert()}lookAt(target){this.updateMatrixWorld();_position.setFromMatrixPosition(this.matrixWorld);_m1.lookAt(_position,target,this.up);this.quaternion.setFromRotationMatrix(_m1)}}class PerspectiveCamera extends Camera{lens;constructor(localTransform,lens,aspectRatio){super(localTransform);this.lens=lens;this.updateProjectionMatrix(aspectRatio)}updateProjectionMatrix(aspectRatio){const near=this.lens.nearPlane;let top=near*Math.tan(DEG2RAD*.5*this.lens.fovy)/this.zoom;let height=2*top;let width=aspectRatio*height;let left=-.5*width;this.projectionMatrix.makePerspective(left,left+width,top,top-height,near,this.lens.farPlane);this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}}class OrthographicCamera extends Camera{lens;left=0;right=0;top=0;bottom=0;constructor(localTransform,lens,aspectRatio){super(localTransform);this.lens=lens;this.updateProjectionMatrix(aspectRatio)}updateProjectionMatrix(aspectRatio){this.left=-aspectRatio*this.lens.zoomFactor[0];this.right=aspectRatio*this.lens.zoomFactor[0];this.top=this.lens.zoomFactor[1];this.bottom=-this.lens.zoomFactor[1];const dx=(this.right-this.left)/(2*this.zoom);const dy=(this.top-this.bottom)/(2*this.zoom);const cx=(this.right+this.left)/2;const cy=(this.top+this.bottom)/2;let _left=cx-dx;let _right=cx+dx;let _top=cy+dy;let _bottom=cy-dy;this.projectionMatrix.makeOrthographic(_left,_right,_top,_bottom,this.lens.zNear,this.lens.zFar);this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}}function isPerspectiveCamera(camera){return camera instanceof PerspectiveCamera}function isOrthographicCamera(camera){return camera instanceof OrthographicCamera}function notSupportedInOrthographicCamera(camera,message){if(isOrthographicCamera(camera)){console.warn(`${message} is not supported in OrthographicCamera`);return true}return false}let EventDispatcher$1=class EventDispatcher{_listeners={};addEventListener(type,listener){const listeners=this._listeners;if(listeners[type]===undefined)listeners[type]=[];if(listeners[type].indexOf(listener)===-1)listeners[type].push(listener)}hasEventListener(type,listener){const listeners=this._listeners;return listeners[type]!==undefined&&listeners[type].indexOf(listener)!==-1}removeEventListener(type,listener){const listeners=this._listeners;const listenerArray=listeners[type];if(listenerArray!==undefined){const index=listenerArray.indexOf(listener);if(index!==-1)listenerArray.splice(index,1)}}removeAllEventListeners(type){if(!type){this._listeners={};return}if(Array.isArray(this._listeners[type]))this._listeners[type].length=0}dispatchEvent(event){const listeners=this._listeners;const listenerArray=listeners[event.type];if(listenerArray!==undefined){event.target=this;const array=listenerArray.slice(0);for(let i=0,l=array.length;i<l;i++){array[i].call(this,event)}}}};const VERSION="0.4.10";const TOUCH_DOLLY_FACTOR=1/8;const isMac=/Mac/.test(globalThis?.navigator?.platform);const _AXIS_Y=Object.freeze(new THREE.Vector3(0,1,0));const _AXIS_Z=Object.freeze(new THREE.Vector3(0,0,1));const _v2=new THREE.Vector2;const _v3A=new THREE.Vector3;const _v3B=new THREE.Vector3;const _v3C=new THREE.Vector3;const _cameraDirection=new THREE.Vector3;const _xColumn=new THREE.Vector3;const _yColumn=new THREE.Vector3;const _zColumn=new THREE.Vector3;const _deltaTarget=new THREE.Vector3;const _deltaOffset=new THREE.Vector3;const _sphericalA=new THREE.Spherical;const _sphericalB=new THREE.Spherical;const _box3B=new THREE.Box3;const _quaternionA=new THREE.Quaternion;const _quaternionB=new THREE.Quaternion;class CameraControls extends EventDispatcher$1{static get ACTION(){return ACTION}minPolarAngle=0;maxPolarAngle=Math.PI;minAzimuthAngle=-Infinity;maxAzimuthAngle=Infinity;minDistance=Number.EPSILON;maxDistance=Infinity;infinityDolly=false;minZoom=.01;maxZoom=Infinity;smoothTime=.25;draggingSmoothTime=.125;maxSpeed=Infinity;azimuthRotateSpeed=1;polarRotateSpeed=1;dollySpeed=1;dollyDragInverted=false;truckSpeed=2;scaleTruckSpeed=true;dollyToCursor=false;dragToOffset=false;boundaryFriction=0;restThreshold=.01;mouseButtons;touches;cancel=()=>{};lockPointer;unlockPointer;_enabled=true;_camera;_yAxisUpSpace;_yAxisUpSpaceInverse;_state=ACTION.NONE;_aspectRatio;_domElement;_viewport=null;_target;_targetEnd;_focalOffset;_focalOffsetEnd;_spherical;_sphericalEnd;_lastDistance;_zoom;_zoomEnd;_lastZoom;_cameraUp0;_target0;_position0;_zoom0;_focalOffset0;_dollyControlCoord;_changedDolly=0;_changedZoom=0;_nearPlaneCorners;_hasRested=true;_boundary;_boundaryEnclosesCamera=false;_needsUpdate=true;_updatedLastTime=false;_elementRect=new DOMRect;_isDragging=false;_dragNeedsUpdate=true;_activePointers=[];_lockedPointer=null;_interactiveArea=new DOMRect(0,0,1,1);_isUserControllingRotate=false;_isUserControllingDolly=false;_isUserControllingTruck=false;_isUserControllingOffset=false;_isUserControllingZoom=false;_lastDollyDirection=DOLLY_DIRECTION.NONE;_thetaVelocity={value:0};_phiVelocity={value:0};_radiusVelocity={value:0};_targetVelocity=new THREE.Vector3;_focalOffsetVelocity=new THREE.Vector3;_zoomVelocity={value:0};_livelink_viewport;constructor(localTransform,lens,viewport){super();const isPerspective="fovy"in lens;this._aspectRatio=viewport.aspect_ratio;this._livelink_viewport=viewport;this._camera=isPerspective?new PerspectiveCamera(localTransform,lens,this._aspectRatio):new OrthographicCamera(localTransform,lens,this._aspectRatio);this._yAxisUpSpace=(new THREE.Quaternion).setFromUnitVectors(this._camera.up,_AXIS_Y);this._yAxisUpSpaceInverse=this._yAxisUpSpace.clone().invert();this._state=ACTION.NONE;this._target=new THREE.Vector3;this._targetEnd=this._target.clone();this._focalOffset=new THREE.Vector3;this._focalOffsetEnd=this._focalOffset.clone();this._spherical=(new THREE.Spherical).setFromVector3(_v3A.copy(this._camera.position).applyQuaternion(this._yAxisUpSpace));this._sphericalEnd=this._spherical.clone();this._lastDistance=this._spherical.radius;this._zoom=this._camera.zoom;this._zoomEnd=this._zoom;this._lastZoom=this._zoom;this._nearPlaneCorners=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3];this._updateNearPlaneCorners();this._boundary=new THREE.Box3(new THREE.Vector3(-Infinity,-Infinity,-Infinity),new THREE.Vector3(Infinity,Infinity,Infinity));this._cameraUp0=this._camera.up.clone();this._target0=this._target.clone();this._position0=this._camera.position.clone();this._zoom0=this._zoom;this._focalOffset0=this._focalOffset.clone();this._dollyControlCoord=new THREE.Vector2;this.mouseButtons={left:ACTION.ROTATE,middle:ACTION.DOLLY,right:ACTION.TRUCK,wheel:isPerspectiveCamera(this._camera)?ACTION.DOLLY:isOrthographicCamera(this._camera)?ACTION.ZOOM:ACTION.NONE};this.touches={one:ACTION.TOUCH_ROTATE,two:isPerspectiveCamera(this._camera)?ACTION.TOUCH_DOLLY_TRUCK:isOrthographicCamera(this._camera)?ACTION.TOUCH_ZOOM_TRUCK:ACTION.NONE,three:ACTION.TOUCH_TRUCK};const dragStartPosition=new THREE.Vector2;const lastDragPosition=new THREE.Vector2;const dollyStart=new THREE.Vector2;const onPointerDown=event=>{if(!this._enabled||!this._domElement)return;if(event.target!==this._domElement&&this._livelink_viewport.overlay_dom_elements.every((el=>!el.contains(event.target))))return;if(this._interactiveArea.left!==0||this._interactiveArea.top!==0||this._interactiveArea.width!==1||this._interactiveArea.height!==1){const elRect=this._domElement.getBoundingClientRect();const left=event.clientX/elRect.width;const top=event.clientY/elRect.height;if(left<this._interactiveArea.left||left>this._interactiveArea.right||top<this._interactiveArea.top||top>this._interactiveArea.bottom)return}const mouseButton=event.pointerType!=="mouse"?null:(event.buttons&MOUSE_BUTTON.LEFT)===MOUSE_BUTTON.LEFT?MOUSE_BUTTON.LEFT:(event.buttons&MOUSE_BUTTON.MIDDLE)===MOUSE_BUTTON.MIDDLE?MOUSE_BUTTON.MIDDLE:(event.buttons&MOUSE_BUTTON.RIGHT)===MOUSE_BUTTON.RIGHT?MOUSE_BUTTON.RIGHT:null;if(mouseButton!==null){const zombiePointer=this._findPointerByMouseButton(mouseButton);zombiePointer&&this._disposePointer(zombiePointer)}if((event.buttons&MOUSE_BUTTON.LEFT)===MOUSE_BUTTON.LEFT&&this._lockedPointer)return;const pointer={pointerId:event.pointerId,clientX:event.clientX,clientY:event.clientY,deltaX:0,deltaY:0,mouseButton:mouseButton};this._activePointers.push(pointer);event.stopPropagation();this._domElement.ownerDocument.removeEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.removeEventListener("pointerup",onPointerUp);this._domElement.ownerDocument.addEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.addEventListener("pointerup",onPointerUp);this._isDragging=true;startDragging(event)};const onPointerMove=event=>{if(event.cancelable)event.preventDefault();const pointerId=event.pointerId;const pointer=this._lockedPointer||this._findPointerById(pointerId);if(!pointer)return;pointer.clientX=event.clientX;pointer.clientY=event.clientY;pointer.deltaX=event.movementX;pointer.deltaY=event.movementY;this._state=0;if(event.pointerType==="touch"){switch(this._activePointers.length){case 1:this._state=this.touches.one;break;case 2:this._state=this.touches.two;break;case 3:this._state=this.touches.three;break}}else{if(!this._isDragging&&this._lockedPointer||this._isDragging&&(event.buttons&MOUSE_BUTTON.LEFT)===MOUSE_BUTTON.LEFT){this._state=this._state|this.mouseButtons.left}if(this._isDragging&&(event.buttons&MOUSE_BUTTON.MIDDLE)===MOUSE_BUTTON.MIDDLE){this._state=this._state|this.mouseButtons.middle}if(this._isDragging&&(event.buttons&MOUSE_BUTTON.RIGHT)===MOUSE_BUTTON.RIGHT){this._state=this._state|this.mouseButtons.right}}dragging()};const onPointerUp=event=>{const pointer=this._findPointerById(event.pointerId);if(pointer&&pointer===this._lockedPointer)return;pointer&&this._disposePointer(pointer);if(event.pointerType==="touch"){switch(this._activePointers.length){case 0:this._state=ACTION.NONE;break;case 1:this._state=this.touches.one;break;case 2:this._state=this.touches.two;break;case 3:this._state=this.touches.three;break}}else{this._state=ACTION.NONE}endDragging()};let lastScrollTimeStamp=-1;const onMouseWheel=event=>{if(!this._domElement)return;if(!this._enabled||this.mouseButtons.wheel===ACTION.NONE)return;if(event.target!==this._domElement&&this._livelink_viewport.overlay_dom_elements.every((el=>!el.contains(event.target))))return;if(this._interactiveArea.left!==0||this._interactiveArea.top!==0||this._interactiveArea.width!==1||this._interactiveArea.height!==1){const elRect=this._domElement.getBoundingClientRect();const left=event.clientX/elRect.width;const top=event.clientY/elRect.height;if(left<this._interactiveArea.left||left>this._interactiveArea.right||top<this._interactiveArea.top||top>this._interactiveArea.bottom)return}event.preventDefault();event.stopPropagation();if(this.dollyToCursor||this.mouseButtons.wheel===ACTION.ROTATE||this.mouseButtons.wheel===ACTION.TRUCK){const now=performance.now();if(lastScrollTimeStamp-now<1e3)this._getClientRect(this._elementRect);lastScrollTimeStamp=now}const deltaYFactor=isMac?-1:-3;const delta=event.deltaMode===1?event.deltaY/deltaYFactor:event.deltaY/(deltaYFactor*10);const x=this.dollyToCursor?(event.clientX-this._elementRect.x)/this._elementRect.width*2-1:0;const y=this.dollyToCursor?(event.clientY-this._elementRect.y)/this._elementRect.height*-2+1:0;switch(this.mouseButtons.wheel){case ACTION.ROTATE:{this._rotateInternal(event.deltaX,event.deltaY);this._isUserControllingRotate=true;break}case ACTION.TRUCK:{this._truckInternal(event.deltaX,-event.deltaY,false,false);this._isUserControllingTruck=true;break}case ACTION.SCREEN_PAN:{this._truckInternal(event.deltaX,-event.deltaY,false,true);this._isUserControllingTruck=true;break}case ACTION.OFFSET:{this._truckInternal(event.deltaX,event.deltaY,true,false);this._isUserControllingOffset=true;break}case ACTION.DOLLY:{this._dollyInternal(-delta,x,y);this._isUserControllingDolly=true;break}case ACTION.ZOOM:{this._zoomInternal(-delta,x,y);this._isUserControllingZoom=true;break}}this.dispatchEvent({type:"control"})};const onContextMenu=event=>{if(!this._domElement||!this._enabled)return;if(this.mouseButtons.right===CameraControls.ACTION.NONE){const pointerId=event instanceof PointerEvent?event.pointerId:0;const pointer=this._findPointerById(pointerId);pointer&&this._disposePointer(pointer);this._domElement.ownerDocument.removeEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.removeEventListener("pointerup",onPointerUp);return}event.preventDefault();event.stopPropagation()};const startDragging=event=>{if(!this._enabled)return;extractClientCoordFromEvent(this._activePointers,_v2);this._getClientRect(this._elementRect);dragStartPosition.copy(_v2);lastDragPosition.copy(_v2);const isMultiTouch=this._activePointers.length>=2;if(isMultiTouch){const dx=_v2.x-this._activePointers[1].clientX;const dy=_v2.y-this._activePointers[1].clientY;const distance=Math.sqrt(dx*dx+dy*dy);dollyStart.set(0,distance);const x=(this._activePointers[0].clientX+this._activePointers[1].clientX)*.5;const y=(this._activePointers[0].clientY+this._activePointers[1].clientY)*.5;lastDragPosition.set(x,y)}this._state=0;if(!event){if(this._lockedPointer)this._state=this._state|this.mouseButtons.left}else if("pointerType"in event&&event.pointerType==="touch"){switch(this._activePointers.length){case 1:this._state=this.touches.one;break;case 2:this._state=this.touches.two;break;case 3:this._state=this.touches.three;break}}else{if(!this._lockedPointer&&(event.buttons&MOUSE_BUTTON.LEFT)===MOUSE_BUTTON.LEFT){this._state=this._state|this.mouseButtons.left}if((event.buttons&MOUSE_BUTTON.MIDDLE)===MOUSE_BUTTON.MIDDLE){this._state=this._state|this.mouseButtons.middle}if((event.buttons&MOUSE_BUTTON.RIGHT)===MOUSE_BUTTON.RIGHT){this._state=this._state|this.mouseButtons.right}}if((this._state&ACTION.ROTATE)===ACTION.ROTATE||(this._state&ACTION.TOUCH_ROTATE)===ACTION.TOUCH_ROTATE||(this._state&ACTION.TOUCH_DOLLY_ROTATE)===ACTION.TOUCH_DOLLY_ROTATE||(this._state&ACTION.TOUCH_ZOOM_ROTATE)===ACTION.TOUCH_ZOOM_ROTATE){this._sphericalEnd.theta=this._spherical.theta;this._sphericalEnd.phi=this._spherical.phi;this._thetaVelocity.value=0;this._phiVelocity.value=0}if((this._state&ACTION.TRUCK)===ACTION.TRUCK||(this._state&ACTION.SCREEN_PAN)===ACTION.SCREEN_PAN||(this._state&ACTION.TOUCH_TRUCK)===ACTION.TOUCH_TRUCK||(this._state&ACTION.TOUCH_SCREEN_PAN)===ACTION.TOUCH_SCREEN_PAN||(this._state&ACTION.TOUCH_DOLLY_TRUCK)===ACTION.TOUCH_DOLLY_TRUCK||(this._state&ACTION.TOUCH_DOLLY_SCREEN_PAN)===ACTION.TOUCH_DOLLY_SCREEN_PAN||(this._state&ACTION.TOUCH_ZOOM_TRUCK)===ACTION.TOUCH_ZOOM_TRUCK||(this._state&ACTION.TOUCH_ZOOM_SCREEN_PAN)===ACTION.TOUCH_DOLLY_SCREEN_PAN){this._targetEnd.copy(this._target);this._targetVelocity.set(0,0,0)}if((this._state&ACTION.DOLLY)===ACTION.DOLLY||(this._state&ACTION.TOUCH_DOLLY)===ACTION.TOUCH_DOLLY||(this._state&ACTION.TOUCH_DOLLY_TRUCK)===ACTION.TOUCH_DOLLY_TRUCK||(this._state&ACTION.TOUCH_DOLLY_SCREEN_PAN)===ACTION.TOUCH_DOLLY_SCREEN_PAN||(this._state&ACTION.TOUCH_DOLLY_OFFSET)===ACTION.TOUCH_DOLLY_OFFSET||(this._state&ACTION.TOUCH_DOLLY_ROTATE)===ACTION.TOUCH_DOLLY_ROTATE){this._sphericalEnd.radius=this._spherical.radius;this._radiusVelocity.value=0}if((this._state&ACTION.ZOOM)===ACTION.ZOOM||(this._state&ACTION.TOUCH_ZOOM)===ACTION.TOUCH_ZOOM||(this._state&ACTION.TOUCH_ZOOM_TRUCK)===ACTION.TOUCH_ZOOM_TRUCK||(this._state&ACTION.TOUCH_ZOOM_SCREEN_PAN)===ACTION.TOUCH_ZOOM_SCREEN_PAN||(this._state&ACTION.TOUCH_ZOOM_OFFSET)===ACTION.TOUCH_ZOOM_OFFSET||(this._state&ACTION.TOUCH_ZOOM_ROTATE)===ACTION.TOUCH_ZOOM_ROTATE){this._zoomEnd=this._zoom;this._zoomVelocity.value=0}if((this._state&ACTION.OFFSET)===ACTION.OFFSET||(this._state&ACTION.TOUCH_OFFSET)===ACTION.TOUCH_OFFSET||(this._state&ACTION.TOUCH_DOLLY_OFFSET)===ACTION.TOUCH_DOLLY_OFFSET||(this._state&ACTION.TOUCH_ZOOM_OFFSET)===ACTION.TOUCH_ZOOM_OFFSET){this._focalOffsetEnd.copy(this._focalOffset);this._focalOffsetVelocity.set(0,0,0)}this.dispatchEvent({type:"controlstart"})};const dragging=()=>{if(!this._enabled||!this._dragNeedsUpdate)return;this._dragNeedsUpdate=false;extractClientCoordFromEvent(this._activePointers,_v2);const isPointerLockActive=this._domElement&&this._domElement.ownerDocument.pointerLockElement===this._domElement;const lockedPointer=isPointerLockActive?this._lockedPointer||this._activePointers[0]:null;const deltaX=lockedPointer?-lockedPointer.deltaX:lastDragPosition.x-_v2.x;const deltaY=lockedPointer?-lockedPointer.deltaY:lastDragPosition.y-_v2.y;lastDragPosition.copy(_v2);if((this._state&ACTION.ROTATE)===ACTION.ROTATE||(this._state&ACTION.TOUCH_ROTATE)===ACTION.TOUCH_ROTATE||(this._state&ACTION.TOUCH_DOLLY_ROTATE)===ACTION.TOUCH_DOLLY_ROTATE||(this._state&ACTION.TOUCH_ZOOM_ROTATE)===ACTION.TOUCH_ZOOM_ROTATE){this._rotateInternal(deltaX,deltaY);this._isUserControllingRotate=true}if((this._state&ACTION.DOLLY)===ACTION.DOLLY||(this._state&ACTION.ZOOM)===ACTION.ZOOM){const dollyX=this.dollyToCursor?(dragStartPosition.x-this._elementRect.x)/this._elementRect.width*2-1:0;const dollyY=this.dollyToCursor?(dragStartPosition.y-this._elementRect.y)/this._elementRect.height*-2+1:0;const dollyDirection=this.dollyDragInverted?-1:1;if((this._state&ACTION.DOLLY)===ACTION.DOLLY){this._dollyInternal(dollyDirection*deltaY*TOUCH_DOLLY_FACTOR,dollyX,dollyY);this._isUserControllingDolly=true}else{this._zoomInternal(dollyDirection*deltaY*TOUCH_DOLLY_FACTOR,dollyX,dollyY);this._isUserControllingZoom=true}}if((this._state&ACTION.TOUCH_DOLLY)===ACTION.TOUCH_DOLLY||(this._state&ACTION.TOUCH_ZOOM)===ACTION.TOUCH_ZOOM||(this._state&ACTION.TOUCH_DOLLY_TRUCK)===ACTION.TOUCH_DOLLY_TRUCK||(this._state&ACTION.TOUCH_ZOOM_TRUCK)===ACTION.TOUCH_ZOOM_TRUCK||(this._state&ACTION.TOUCH_DOLLY_SCREEN_PAN)===ACTION.TOUCH_DOLLY_SCREEN_PAN||(this._state&ACTION.TOUCH_ZOOM_SCREEN_PAN)===ACTION.TOUCH_ZOOM_SCREEN_PAN||(this._state&ACTION.TOUCH_DOLLY_OFFSET)===ACTION.TOUCH_DOLLY_OFFSET||(this._state&ACTION.TOUCH_ZOOM_OFFSET)===ACTION.TOUCH_ZOOM_OFFSET||(this._state&ACTION.TOUCH_DOLLY_ROTATE)===ACTION.TOUCH_DOLLY_ROTATE||(this._state&ACTION.TOUCH_ZOOM_ROTATE)===ACTION.TOUCH_ZOOM_ROTATE){const dx=_v2.x-this._activePointers[1].clientX;const dy=_v2.y-this._activePointers[1].clientY;const distance=Math.sqrt(dx*dx+dy*dy);const dollyDelta=dollyStart.y-distance;dollyStart.set(0,distance);const dollyX=this.dollyToCursor?(lastDragPosition.x-this._elementRect.x)/this._elementRect.width*2-1:0;const dollyY=this.dollyToCursor?(lastDragPosition.y-this._elementRect.y)/this._elementRect.height*-2+1:0;if((this._state&ACTION.TOUCH_DOLLY)===ACTION.TOUCH_DOLLY||(this._state&ACTION.TOUCH_DOLLY_ROTATE)===ACTION.TOUCH_DOLLY_ROTATE||(this._state&ACTION.TOUCH_DOLLY_TRUCK)===ACTION.TOUCH_DOLLY_TRUCK||(this._state&ACTION.TOUCH_DOLLY_SCREEN_PAN)===ACTION.TOUCH_DOLLY_SCREEN_PAN||(this._state&ACTION.TOUCH_DOLLY_OFFSET)===ACTION.TOUCH_DOLLY_OFFSET){this._dollyInternal(dollyDelta*TOUCH_DOLLY_FACTOR,dollyX,dollyY);this._isUserControllingDolly=true}else{this._zoomInternal(dollyDelta*TOUCH_DOLLY_FACTOR,dollyX,dollyY);this._isUserControllingZoom=true}}if((this._state&ACTION.TRUCK)===ACTION.TRUCK||(this._state&ACTION.TOUCH_TRUCK)===ACTION.TOUCH_TRUCK||(this._state&ACTION.TOUCH_DOLLY_TRUCK)===ACTION.TOUCH_DOLLY_TRUCK||(this._state&ACTION.TOUCH_ZOOM_TRUCK)===ACTION.TOUCH_ZOOM_TRUCK){this._truckInternal(deltaX,deltaY,false,false);this._isUserControllingTruck=true}if((this._state&ACTION.SCREEN_PAN)===ACTION.SCREEN_PAN||(this._state&ACTION.TOUCH_SCREEN_PAN)===ACTION.TOUCH_SCREEN_PAN||(this._state&ACTION.TOUCH_DOLLY_SCREEN_PAN)===ACTION.TOUCH_DOLLY_SCREEN_PAN||(this._state&ACTION.TOUCH_ZOOM_SCREEN_PAN)===ACTION.TOUCH_ZOOM_SCREEN_PAN){this._truckInternal(deltaX,deltaY,false,true);this._isUserControllingTruck=true}if((this._state&ACTION.OFFSET)===ACTION.OFFSET||(this._state&ACTION.TOUCH_OFFSET)===ACTION.TOUCH_OFFSET||(this._state&ACTION.TOUCH_DOLLY_OFFSET)===ACTION.TOUCH_DOLLY_OFFSET||(this._state&ACTION.TOUCH_ZOOM_OFFSET)===ACTION.TOUCH_ZOOM_OFFSET){this._truckInternal(deltaX,deltaY,true,false);this._isUserControllingOffset=true}this.dispatchEvent({type:"control"})};const endDragging=()=>{extractClientCoordFromEvent(this._activePointers,_v2);lastDragPosition.copy(_v2);this._dragNeedsUpdate=false;if(this._activePointers.length===0||this._activePointers.length===1&&this._activePointers[0]===this._lockedPointer){this._isDragging=false}if(this._activePointers.length===0&&this._domElement){this._domElement.ownerDocument.removeEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.removeEventListener("pointerup",onPointerUp);this.dispatchEvent({type:"controlend"})}};this.lockPointer=()=>{if(!this._enabled||!this._domElement)return;this.cancel();this._lockedPointer={pointerId:-1,clientX:0,clientY:0,deltaX:0,deltaY:0,mouseButton:null};this._activePointers.push(this._lockedPointer);this._domElement.ownerDocument.removeEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.removeEventListener("pointerup",onPointerUp);this._domElement.requestPointerLock();this._domElement.ownerDocument.addEventListener("pointerlockchange",onPointerLockChange);this._domElement.ownerDocument.addEventListener("pointerlockerror",onPointerLockError);this._domElement.ownerDocument.addEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.addEventListener("pointerup",onPointerUp);startDragging()};this.unlockPointer=()=>{if(this._lockedPointer!==null){this._disposePointer(this._lockedPointer);this._lockedPointer=null}this._domElement?.ownerDocument.exitPointerLock();this._domElement?.ownerDocument.removeEventListener("pointerlockchange",onPointerLockChange);this._domElement?.ownerDocument.removeEventListener("pointerlockerror",onPointerLockError);this.cancel()};const onPointerLockChange=()=>{const isPointerLockActive=this._domElement&&this._domElement.ownerDocument.pointerLockElement===this._domElement;if(!isPointerLockActive)this.unlockPointer()};const onPointerLockError=()=>{this.unlockPointer()};this._addAllEventListeners=domElement=>{this._domElement=domElement;this._domElement.style.touchAction="none";this._domElement.style.userSelect="none";this._domElement.style.webkitUserSelect="none";this._domElement.addEventListener("pointerdown",onPointerDown);this._domElement.addEventListener("pointercancel",onPointerUp);this._domElement.addEventListener("wheel",onMouseWheel,{passive:false});this._domElement.addEventListener("contextmenu",onContextMenu)};this._removeAllEventListeners=()=>{if(!this._domElement)return;this._domElement.style.touchAction="";this._domElement.style.userSelect="";this._domElement.style.webkitUserSelect="";this._domElement.removeEventListener("pointerdown",onPointerDown);this._domElement.removeEventListener("pointercancel",onPointerUp);this._domElement.removeEventListener("wheel",onMouseWheel,{passive:false});this._domElement.removeEventListener("contextmenu",onContextMenu);this._domElement.ownerDocument.removeEventListener("pointermove",onPointerMove,{passive:false});this._domElement.ownerDocument.removeEventListener("pointerup",onPointerUp);this._domElement.ownerDocument.removeEventListener("pointerlockchange",onPointerLockChange);this._domElement.ownerDocument.removeEventListener("pointerlockerror",onPointerLockError)};this.cancel=()=>{if(this._state===ACTION.NONE)return;this._state=ACTION.NONE;this._activePointers.length=0;endDragging()};this.connect(viewport.dom_element);this.update(0)}get position(){return this._camera.position}get orientation(){return this._camera.quaternion}get direction(){return this._getCameraDirection(new THREE.Vector3).normalize()}updateTransform(position,orientation){this._camera.position.fromArray(position);this._camera.quaternion.fromArray(orientation);this.applyCameraUp();this._needsUpdate=true}set aspectRatio(aspectRatio){this._aspectRatio=aspectRatio;this._camera.updateProjectionMatrix(this._aspectRatio);this._needsUpdate=true}get enabled(){return this._enabled}set enabled(enabled){this._enabled=enabled;if(!this._domElement)return;if(enabled){this._domElement.style.touchAction="none";this._domElement.style.userSelect="none";this._domElement.style.webkitUserSelect="none"}else{this.cancel();this._domElement.style.touchAction="";this._domElement.style.userSelect="";this._domElement.style.webkitUserSelect=""}}get active(){return!this._hasRested}get currentAction(){return this._state}get distance(){return this._spherical.radius}set distance(distance){if(this._spherical.radius===distance&&this._sphericalEnd.radius===distance)return;this._spherical.radius=distance;this._sphericalEnd.radius=distance;this._needsUpdate=true}get azimuthAngle(){return this._spherical.theta}set azimuthAngle(azimuthAngle){if(this._spherical.theta===azimuthAngle&&this._sphericalEnd.theta===azimuthAngle)return;this._spherical.theta=azimuthAngle;this._sphericalEnd.theta=azimuthAngle;this._needsUpdate=true}get polarAngle(){return this._spherical.phi}set polarAngle(polarAngle){if(this._spherical.phi===polarAngle&&this._sphericalEnd.phi===polarAngle)return;this._spherical.phi=polarAngle;this._sphericalEnd.phi=polarAngle;this._needsUpdate=true}get boundaryEnclosesCamera(){return this._boundaryEnclosesCamera}set boundaryEnclosesCamera(boundaryEnclosesCamera){this._boundaryEnclosesCamera=boundaryEnclosesCamera;this._needsUpdate=true}set interactiveArea(interactiveArea){this._interactiveArea.width=clamp(interactiveArea.width,0,1);this._interactiveArea.height=clamp(interactiveArea.height,0,1);this._interactiveArea.x=clamp(interactiveArea.x,0,1-this._interactiveArea.width);this._interactiveArea.y=clamp(interactiveArea.y,0,1-this._interactiveArea.height)}addEventListener(type,listener){super.addEventListener(type,listener)}removeEventListener(type,listener){super.removeEventListener(type,listener)}rotate(azimuthAngle,polarAngle,enableTransition=false){return this.rotateTo(this._sphericalEnd.theta+azimuthAngle,this._sphericalEnd.phi+polarAngle,enableTransition)}rotateAzimuthTo(azimuthAngle,enableTransition=false){return this.rotateTo(azimuthAngle,this._sphericalEnd.phi,enableTransition)}rotatePolarTo(polarAngle,enableTransition=false){return this.rotateTo(this._sphericalEnd.theta,polarAngle,enableTransition)}rotateTo(azimuthAngle,polarAngle,enableTransition=false){this._isUserControllingRotate=false;const theta=clamp(azimuthAngle,this.minAzimuthAngle,this.maxAzimuthAngle);const phi=clamp(polarAngle,this.minPolarAngle,this.maxPolarAngle);this._sphericalEnd.theta=theta;this._sphericalEnd.phi=phi;this._sphericalEnd.makeSafe();this._needsUpdate=true;if(!enableTransition){this._spherical.theta=this._sphericalEnd.theta;this._spherical.phi=this._sphericalEnd.phi}const resolveImmediately=!enableTransition||approxEquals(this._spherical.theta,this._sphericalEnd.theta,this.restThreshold)&&approxEquals(this._spherical.phi,this._sphericalEnd.phi,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}dolly(distance,enableTransition=false){return this.dollyTo(this._sphericalEnd.radius-distance,enableTransition)}dollyTo(distance,enableTransition=false){this._isUserControllingDolly=false;this._lastDollyDirection=DOLLY_DIRECTION.NONE;this._changedDolly=0;return this._dollyToNoClamp(clamp(distance,this.minDistance,this.maxDistance),enableTransition)}_dollyToNoClamp(distance,enableTransition=false){this._sphericalEnd.radius=distance;this._needsUpdate=true;if(!enableTransition){this._spherical.radius=this._sphericalEnd.radius}const resolveImmediately=!enableTransition||approxEquals(this._spherical.radius,this._sphericalEnd.radius,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}dollyInFixed(distance,enableTransition=false){this._targetEnd.add(this._getCameraDirection(_cameraDirection).multiplyScalar(distance));if(!enableTransition){this._target.copy(this._targetEnd)}const resolveImmediately=!enableTransition||approxEquals(this._target.x,this._targetEnd.x,this.restThreshold)&&approxEquals(this._target.y,this._targetEnd.y,this.restThreshold)&&approxEquals(this._target.z,this._targetEnd.z,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}zoom(zoomStep,enableTransition=false){return this.zoomTo(this._zoomEnd+zoomStep,enableTransition)}zoomTo(zoom,enableTransition=false){this._isUserControllingZoom=false;this._zoomEnd=clamp(zoom,this.minZoom,this.maxZoom);this._needsUpdate=true;if(!enableTransition){this._zoom=this._zoomEnd}const resolveImmediately=!enableTransition||approxEquals(this._zoom,this._zoomEnd,this.restThreshold);this._changedZoom=0;return this._createOnRestPromise(resolveImmediately)}pan(x,y,enableTransition=false){console.warn("`pan` has been renamed to `truck`");return this.truck(x,y,enableTransition)}truck(x,y,enableTransition=false){this._camera.updateMatrix();_xColumn.setFromMatrixColumn(this._camera.matrix,0);_yColumn.setFromMatrixColumn(this._camera.matrix,1);_xColumn.multiplyScalar(x);_yColumn.multiplyScalar(-y);const offset=_v3A.copy(_xColumn).add(_yColumn);const to=_v3B.copy(this._targetEnd).add(offset);return this.moveTo(to.x,to.y,to.z,enableTransition)}forward(distance,enableTransition=false){_v3A.setFromMatrixColumn(this._camera.matrix,0);_v3A.crossVectors(this._camera.up,_v3A);_v3A.multiplyScalar(distance);const to=_v3B.copy(this._targetEnd).add(_v3A);return this.moveTo(to.x,to.y,to.z,enableTransition)}elevate(height,enableTransition=false){_v3A.copy(this._camera.up).multiplyScalar(height);return this.moveTo(this._targetEnd.x+_v3A.x,this._targetEnd.y+_v3A.y,this._targetEnd.z+_v3A.z,enableTransition)}moveTo(x,y,z,enableTransition=false){this._isUserControllingTruck=false;const offset=_v3A.set(x,y,z).sub(this._targetEnd);this._encloseToBoundary(this._targetEnd,offset,this.boundaryFriction);this._needsUpdate=true;if(!enableTransition){this._target.copy(this._targetEnd)}const resolveImmediately=!enableTransition||approxEquals(this._target.x,this._targetEnd.x,this.restThreshold)&&approxEquals(this._target.y,this._targetEnd.y,this.restThreshold)&&approxEquals(this._target.z,this._targetEnd.z,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}lookInDirectionOf(x,y,z,enableTransition=false){const point=_v3A.set(x,y,z);const direction=point.sub(this._targetEnd).normalize();const position=direction.multiplyScalar(-this._sphericalEnd.radius).add(this._targetEnd);return this.setPosition(position.x,position.y,position.z,enableTransition)}fitToBox(aabb,enableTransition,{cover:cover=false,paddingLeft:paddingLeft=0,paddingRight:paddingRight=0,paddingBottom:paddingBottom=0,paddingTop:paddingTop=0}={}){const promises=[];if(aabb.isEmpty()){console.warn("camera-controls: fitTo() cannot be used with an empty box. Aborting");Promise.resolve()}const theta=roundToStep(this._sphericalEnd.theta,PI_HALF);const phi=roundToStep(this._sphericalEnd.phi,PI_HALF);promises.push(this.rotateTo(theta,phi,enableTransition));const normal=_v3A.setFromSpherical(this._sphericalEnd).normalize();const rotation=_quaternionA.setFromUnitVectors(normal,_AXIS_Z);const viewFromPolar=approxEquals(Math.abs(normal.y),1);if(viewFromPolar){rotation.multiply(_quaternionB.setFromAxisAngle(_AXIS_Y,theta))}rotation.multiply(this._yAxisUpSpaceInverse);const bb=_box3B.makeEmpty();_v3B.copy(aabb.min).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.min).setX(aabb.max.x).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.min).setY(aabb.max.y).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.max).setZ(aabb.min.z).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.min).setZ(aabb.max.z).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.max).setY(aabb.min.y).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.max).setX(aabb.min.x).applyQuaternion(rotation);bb.expandByPoint(_v3B);_v3B.copy(aabb.max).applyQuaternion(rotation);bb.expandByPoint(_v3B);bb.min.x-=paddingLeft;bb.min.y-=paddingBottom;bb.max.x+=paddingRight;bb.max.y+=paddingTop;rotation.setFromUnitVectors(_AXIS_Z,normal);if(viewFromPolar){rotation.premultiply(_quaternionB.invert())}rotation.premultiply(this._yAxisUpSpace);const bbSize=bb.getSize(_v3A);const center=bb.getCenter(_v3B).applyQuaternion(rotation);if(isPerspectiveCamera(this._camera)){const distance=this.getDistanceToFitBox(bbSize.x,bbSize.y,bbSize.z,cover);promises.push(this.moveTo(center.x,center.y,center.z,enableTransition));promises.push(this.dollyTo(distance,enableTransition));promises.push(this.setFocalOffset(0,0,0,enableTransition))}else if(isOrthographicCamera(this._camera)){const camera=this._camera;const width=camera.right-camera.left;const height=camera.top-camera.bottom;const zoom=cover?Math.max(width/bbSize.x,height/bbSize.y):Math.min(width/bbSize.x,height/bbSize.y);promises.push(this.moveTo(center.x,center.y,center.z,enableTransition));promises.push(this.zoomTo(zoom,enableTransition));promises.push(this.setFocalOffset(0,0,0,enableTransition))}return Promise.all(promises)}fitToSphere(boundingSphere,enableTransition){const promises=[];promises.push(this.moveTo(boundingSphere.center.x,boundingSphere.center.y,boundingSphere.center.z,enableTransition));if(isPerspectiveCamera(this._camera)){const distanceToFit=this.getDistanceToFitSphere(boundingSphere.radius);promises.push(this.dollyTo(distanceToFit,enableTransition))}else if(isOrthographicCamera(this._camera)){const width=this._camera.right-this._camera.left;const height=this._camera.top-this._camera.bottom;const diameter=2*boundingSphere.radius;const zoom=Math.min(width/diameter,height/diameter);promises.push(this.zoomTo(zoom,enableTransition))}promises.push(this.setFocalOffset(0,0,0,enableTransition));return Promise.all(promises)}setLookAt(positionX,positionY,positionZ,targetX,targetY,targetZ,enableTransition=false){this._isUserControllingRotate=false;this._isUserControllingDolly=false;this._isUserControllingTruck=false;this._lastDollyDirection=DOLLY_DIRECTION.NONE;this._changedDolly=0;const target=_v3B.set(targetX,targetY,targetZ);const position=_v3A.set(positionX,positionY,positionZ);this._targetEnd.copy(target);this._sphericalEnd.setFromVector3(position.sub(target).applyQuaternion(this._yAxisUpSpace));this.normalizeRotations();this._needsUpdate=true;if(!enableTransition){this._target.copy(this._targetEnd);this._spherical.copy(this._sphericalEnd)}const resolveImmediately=!enableTransition||approxEquals(this._target.x,this._targetEnd.x,this.restThreshold)&&approxEquals(this._target.y,this._targetEnd.y,this.restThreshold)&&approxEquals(this._target.z,this._targetEnd.z,this.restThreshold)&&approxEquals(this._spherical.theta,this._sphericalEnd.theta,this.restThreshold)&&approxEquals(this._spherical.phi,this._sphericalEnd.phi,this.restThreshold)&&approxEquals(this._spherical.radius,this._sphericalEnd.radius,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}lerpLookAt(positionAX,positionAY,positionAZ,targetAX,targetAY,targetAZ,positionBX,positionBY,positionBZ,targetBX,targetBY,targetBZ,t,enableTransition=false){this._isUserControllingRotate=false;this._isUserControllingDolly=false;this._isUserControllingTruck=false;this._lastDollyDirection=DOLLY_DIRECTION.NONE;this._changedDolly=0;const targetA=_v3A.set(targetAX,targetAY,targetAZ);const positionA=_v3B.set(positionAX,positionAY,positionAZ);_sphericalA.setFromVector3(positionA.sub(targetA).applyQuaternion(this._yAxisUpSpace));const targetB=_v3C.set(targetBX,targetBY,targetBZ);const positionB=_v3B.set(positionBX,positionBY,positionBZ);_sphericalB.setFromVector3(positionB.sub(targetB).applyQuaternion(this._yAxisUpSpace));this._targetEnd.copy(targetA.lerp(targetB,t));const deltaTheta=_sphericalB.theta-_sphericalA.theta;const deltaPhi=_sphericalB.phi-_sphericalA.phi;const deltaRadius=_sphericalB.radius-_sphericalA.radius;this._sphericalEnd.set(_sphericalA.radius+deltaRadius*t,_sphericalA.phi+deltaPhi*t,_sphericalA.theta+deltaTheta*t);this.normalizeRotations();this._needsUpdate=true;if(!enableTransition){this._target.copy(this._targetEnd);this._spherical.copy(this._sphericalEnd)}const resolveImmediately=!enableTransition||approxEquals(this._target.x,this._targetEnd.x,this.restThreshold)&&approxEquals(this._target.y,this._targetEnd.y,this.restThreshold)&&approxEquals(this._target.z,this._targetEnd.z,this.restThreshold)&&approxEquals(this._spherical.theta,this._sphericalEnd.theta,this.restThreshold)&&approxEquals(this._spherical.phi,this._sphericalEnd.phi,this.restThreshold)&&approxEquals(this._spherical.radius,this._sphericalEnd.radius,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}setPosition(positionX,positionY,positionZ,enableTransition=false){return this.setLookAt(positionX,positionY,positionZ,this._targetEnd.x,this._targetEnd.y,this._targetEnd.z,enableTransition)}setTarget(targetX,targetY,targetZ,enableTransition=false){const pos=this.getPosition(_v3A);const promise=this.setLookAt(pos.x,pos.y,pos.z,targetX,targetY,targetZ,enableTransition);this._sphericalEnd.phi=clamp(this._sphericalEnd.phi,this.minPolarAngle,this.maxPolarAngle);return promise}setFocalOffset(x,y,z,enableTransition=false){this._isUserControllingOffset=false;this._focalOffsetEnd.set(x,y,z);this._needsUpdate=true;if(!enableTransition)this._focalOffset.copy(this._focalOffsetEnd);const resolveImmediately=!enableTransition||approxEquals(this._focalOffset.x,this._focalOffsetEnd.x,this.restThreshold)&&approxEquals(this._focalOffset.y,this._focalOffsetEnd.y,this.restThreshold)&&approxEquals(this._focalOffset.z,this._focalOffsetEnd.z,this.restThreshold);return this._createOnRestPromise(resolveImmediately)}setOrbitPoint(targetX,targetY,targetZ){this._camera.updateMatrixWorld();_xColumn.setFromMatrixColumn(this._camera.matrixWorldInverse,0);_yColumn.setFromMatrixColumn(this._camera.matrixWorldInverse,1);_zColumn.setFromMatrixColumn(this._camera.matrixWorldInverse,2);const position=_v3A.set(targetX,targetY,targetZ);const distance=position.distanceTo(this._camera.position);const cameraToPoint=position.sub(this._camera.position);_xColumn.multiplyScalar(cameraToPoint.x);_yColumn.multiplyScalar(cameraToPoint.y);_zColumn.multiplyScalar(cameraToPoint.z);_v3A.copy(_xColumn).add(_yColumn).add(_zColumn);_v3A.z=_v3A.z+distance;this.dollyTo(distance,false);this.setFocalOffset(-_v3A.x,_v3A.y,-_v3A.z,false);this.moveTo(targetX,targetY,targetZ,false)}setBoundary(box3){if(!box3){this._boundary.min.set(-Infinity,-Infinity,-Infinity);this._boundary.max.set(Infinity,Infinity,Infinity);this._needsUpdate=true;return}this._boundary.copy(box3);this._boundary.clampPoint(this._targetEnd,this._targetEnd);this._needsUpdate=true}setViewport(viewportOrX,y,width,height){if(viewportOrX===null){this._viewport=null;return}this._viewport=this._viewport||new THREE.Vector4;if(typeof viewportOrX==="number"){this._viewport.set(viewportOrX,y,width,height)}else{this._viewport.copy(viewportOrX)}}getDistanceToFitBox(width,height,depth,cover=false){if(notSupportedInOrthographicCamera(this._camera,"getDistanceToFitBox"))return this._spherical.radius;const boundingRectAspect=width/height;const fov=this._camera.lens.fovy*DEG2RAD;const aspect=this._aspectRatio;const heightToFit=(cover?boundingRectAspect>aspect:boundingRectAspect<aspect)?height:width/aspect;return heightToFit*.5/Math.tan(fov*.5)+depth*.5}getDistanceToFitSphere(radius){if(notSupportedInOrthographicCamera(this._camera,"getDistanceToFitSphere"))return this._spherical.radius;const vFOV=this._camera.lens.fovy*DEG2RAD;const hFOV=Math.atan(Math.tan(vFOV*.5)*this._aspectRatio)*2;const fov=1<this._aspectRatio?vFOV:hFOV;return radius/Math.sin(fov*.5)}getTarget(out,receiveEndValue=true){const _out=!!out&&out.isVector3?out:new THREE.Vector3;return _out.copy(receiveEndValue?this._targetEnd:this._target)}getPosition(out,receiveEndValue=true){const _out=!!out&&out.isVector3?out:new THREE.Vector3;return _out.setFromSpherical(receiveEndValue?this._sphericalEnd:this._spherical).applyQuaternion(this._yAxisUpSpaceInverse).add(receiveEndValue?this._targetEnd:this._target)}getSpherical(out,receiveEndValue=true){const _out=out||new THREE.Spherical;return _out.copy(receiveEndValue?this._sphericalEnd:this._spherical)}getFocalOffset(out,receiveEndValue=true){const _out=!!out&&out.isVector3?out:new THREE.Vector3;return _out.copy(receiveEndValue?this._focalOffsetEnd:this._focalOffset)}normalizeRotations(){this._sphericalEnd.theta=this._sphericalEnd.theta%PI_2;if(this._sphericalEnd.theta<0)this._sphericalEnd.theta+=PI_2;this._spherical.theta+=PI_2*Math.round((this._sphericalEnd.theta-this._spherical.theta)/PI_2)}stop(){this._focalOffset.copy(this._focalOffsetEnd);this._target.copy(this._targetEnd);this._spherical.copy(this._sphericalEnd);this._zoom=this._zoomEnd}reset(enableTransition=false){if(!approxEquals(this._camera.up.x,this._cameraUp0.x)||!approxEquals(this._camera.up.y,this._cameraUp0.y)||!approxEquals(this._camera.up.z,this._cameraUp0.z)){this._camera.up.copy(this._cameraUp0);const position=this.getPosition(_v3A);this.updateCameraUp();this.setPosition(position.x,position.y,position.z)}const promises=[this.setLookAt(this._position0.x,this._position0.y,this._position0.z,this._target0.x,this._target0.y,this._target0.z,enableTransition),this.setFocalOffset(this._focalOffset0.x,this._focalOffset0.y,this._focalOffset0.z,enableTransition),this.zoomTo(this._zoom0,enableTransition)];return Promise.all(promises)}saveState(){this._cameraUp0.copy(this._camera.up);this.getTarget(this._target0);this.getPosition(this._position0);this._zoom0=this._zoom;this._focalOffset0.copy(this._focalOffset)}updateCameraUp(){this._yAxisUpSpace.setFromUnitVectors(this._camera.up,_AXIS_Y);this._yAxisUpSpaceInverse.copy(this._yAxisUpSpace).invert()}applyCameraUp(){const cameraDirection=_v3A.subVectors(this._target,this._camera.position).normalize();const side=_v3B.crossVectors(cameraDirection,this._camera.up);this._camera.up.crossVectors(side,cameraDirection).normalize();this._camera.updateMatrixWorld();const position=this.getPosition(_v3A);this.updateCameraUp();this.setPosition(position.x,position.y,position.z)}update(delta){const deltaTheta=this._sphericalEnd.theta-this._spherical.theta;const deltaPhi=this._sphericalEnd.phi-this._spherical.phi;const deltaRadius=this._sphericalEnd.radius-this._spherical.radius;const deltaTarget=_deltaTarget.subVectors(this._targetEnd,this._target);const deltaOffset=_deltaOffset.subVectors(this._focalOffsetEnd,this._focalOffset);const deltaZoom=this._zoomEnd-this._zoom;if(approxZero(deltaTheta)){this._thetaVelocity.value=0;this._spherical.theta=this._sphericalEnd.theta}else{const smoothTime=this._isUserControllingRotate?this.draggingSmoothTime:this.smoothTime;this._spherical.theta=smoothDamp(this._spherical.theta,this._sphericalEnd.theta,this._thetaVelocity,smoothTime,Infinity,delta);this._needsUpdate=true}if(approxZero(deltaPhi)){this._phiVelocity.value=0;this._spherical.phi=this._sphericalEnd.phi}else{const smoothTime=this._isUserControllingRotate?this.draggingSmoothTime:this.smoothTime;this._spherical.phi=smoothDamp(this._spherical.phi,this._sphericalEnd.phi,this._phiVelocity,smoothTime,Infinity,delta);this._needsUpdate=true}if(approxZero(deltaRadius)){this._radiusVelocity.value=0;this._spherical.radius=this._sphericalEnd.radius}else{const smoothTime=this._isUserControllingDolly?this.draggingSmoothTime:this.smoothTime;this._spherical.radius=smoothDamp(this._spherical.radius,this._sphericalEnd.radius,this._radiusVelocity,smoothTime,this.maxSpeed,delta);this._needsUpdate=true}if(approxZero(deltaTarget.x)&&approxZero(deltaTarget.y)&&approxZero(deltaTarget.z)){this._targetVelocity.set(0,0,0);this._target.copy(this._targetEnd)}else{const smoothTime=this._isUserControllingTruck?this.draggingSmoothTime:this.smoothTime;smoothDampVec3(this._target,this._targetEnd,this._targetVelocity,smoothTime,this.maxSpeed,delta,this._target);this._needsUpdate=true}if(approxZero(deltaOffset.x)&&approxZero(deltaOffset.y)&&approxZero(deltaOffset.z)){this._focalOffsetVelocity.set(0,0,0);this._focalOffset.copy(this._focalOffsetEnd)}else{const smoothTime=this._isUserControllingOffset?this.draggingSmoothTime:this.smoothTime;smoothDampVec3(this._focalOffset,this._focalOffsetEnd,this._focalOffsetVelocity,smoothTime,this.maxSpeed,delta,this._focalOffset);this._needsUpdate=true}if(approxZero(deltaZoom)){this._zoomVelocity.value=0;this._zoom=this._zoomEnd}else{const smoothTime=this._isUserControllingZoom?this.draggingSmoothTime:this.smoothTime;this._zoom=smoothDamp(this._zoom,this._zoomEnd,this._zoomVelocity,smoothTime,Infinity,delta)}if(this.dollyToCursor){if(isPerspectiveCamera(this._camera)&&this._changedDolly!==0){const dollyControlAmount=this._spherical.radius-this._lastDistance;const camera=this._camera;const cameraDirection=this._getCameraDirection(_cameraDirection);const planeX=_v3A.copy(cameraDirection).cross(camera.up).normalize();if(planeX.lengthSq()===0)planeX.x=1;const planeY=_v3B.crossVectors(planeX,cameraDirection);const worldToScreen=this._sphericalEnd.radius*Math.tan