import macro from 'vtk.js/Sources/macros'; import vtkCompositeCameraManipulator from 'vtk.js/Sources/Interaction/Manipulators/CompositeCameraManipulator'; import vtkCompositeMouseManipulator from 'vtk.js/Sources/Interaction/Manipulators/CompositeMouseManipulator';
const ANIMATION_REQUESTER = 'vtkMouseCameraTrackballFirstPersonManipulator';
function vtkMouseCameraTrackballFirstPersonManipulator(publicAPI, model) { model.classHierarchy.push('vtkMouseCameraTrackballFirstPersonManipulator');
const internal = { interactor: null, renderer: null, previousPosition: null, };
publicAPI.onButtonDown = (interactor, renderer, position) => { internal.previousPosition = position;
if (model.usePointerLock && !interactor.isPointerLocked()) { Object.assign(internal, { interactor, renderer }); interactor.requestPointerLock(); publicAPI.startPointerLockInteraction(); } };
publicAPI.startPointerLockInteraction = () => { const { interactor } = internal;
document.addEventListener('mousemove', publicAPI.onPointerLockMove);
let subscription = null; const endInteraction = () => { document.removeEventListener('mousemove', publicAPI.onPointerLockMove); subscription.unsubscribe(); }; subscription = interactor.onEndPointerLock(endInteraction); };
publicAPI.onPointerLockMove = (e) => { const sensitivity = model.sensitivity; const yaw = -1 * e.movementX * sensitivity; const pitch = -1 * e.movementY * sensitivity;
publicAPI.moveCamera(yaw, pitch); };
publicAPI.onMouseMove = (interactor, renderer, position) => { if (!position) { return; }
const { previousPosition } = internal;
const sensitivity = model.sensitivity; const yaw = (previousPosition.x - position.x) * sensitivity; const pitch = (position.y - previousPosition.y) * sensitivity;
Object.assign(internal, { interactor, renderer }); publicAPI.moveCamera(yaw, pitch);
internal.previousPosition = position; };
publicAPI.moveCamera = (yaw, pitch) => { const { renderer, interactor } = internal;
const camera = renderer.getActiveCamera();
const numSteps = model.numAnimationSteps; const yawStep = yaw / numSteps; const pitchStep = pitch / numSteps;
const now = performance.now().toString(); const animationRequester = `${ANIMATION_REQUESTER}.${now}`;
let curStep = 0; let animationSub = null; const performStep = () => { camera.yaw(yawStep); camera.pitch(pitchStep); camera.orthogonalizeViewUp(); curStep += 1; if (curStep === numSteps) { animationSub.unsubscribe(); renderer.resetCameraClippingRange();
if (interactor.getLightFollowCamera()) { renderer.updateLightsGeometryToFollowCamera(); }
const cancelRequest = () => { internal.interactor.cancelAnimation(animationRequester); }; setTimeout(cancelRequest, 0); } };
interactor.requestAnimation(animationRequester); animationSub = interactor.onAnimation(() => performStep()); }; }
const DEFAULT_VALUES = { numAnimationSteps: 5, sensitivity: 0.05, usePointerLock: true, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model); vtkCompositeCameraManipulator.extend(publicAPI, model, initialValues); vtkCompositeMouseManipulator.extend(publicAPI, model, initialValues);
macro.setGet(publicAPI, model, [ 'numAnimationSteps', 'sensitivity', 'usePointerLock', ]);
vtkMouseCameraTrackballFirstPersonManipulator(publicAPI, model); }
export const newInstance = macro.newInstance( extend, 'vtkMouseCameraTrackballFirstPersonManipulator' );
export default { newInstance, extend };
|