@kitware/vtk.js
Version:
Visualization Toolkit for the Web
369 lines (321 loc) • 13.7 kB
JavaScript
import { m as macro } from '../../macros2.js';
import vtkInteractorStyle from '../../Rendering/Core/InteractorStyle.js';
import vtkInteractorStyleConstants from '../../Rendering/Core/InteractorStyle/Constants.js';
import { B as degreesFromRadians } from '../../Common/Core/Math/index.js';
import { Device, Input } from '../../Rendering/Core/RenderWindowInteractor/Constants.js';
const {
States
} = vtkInteractorStyleConstants;
/* eslint-disable no-lonely-if */
// ----------------------------------------------------------------------------
// vtkInteractorStyleTrackballCamera methods
// ----------------------------------------------------------------------------
function vtkInteractorStyleTrackballCamera(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkInteractorStyleTrackballCamera');
// Public API methods
publicAPI.handleMouseMove = callData => {
const pos = callData.position;
const renderer = model.getRenderer(callData);
switch (model.state) {
case States.IS_ROTATE:
publicAPI.handleMouseRotate(renderer, pos);
publicAPI.invokeInteractionEvent({
type: 'InteractionEvent'
});
break;
case States.IS_PAN:
publicAPI.handleMousePan(renderer, pos);
publicAPI.invokeInteractionEvent({
type: 'InteractionEvent'
});
break;
case States.IS_DOLLY:
publicAPI.handleMouseDolly(renderer, pos);
publicAPI.invokeInteractionEvent({
type: 'InteractionEvent'
});
break;
case States.IS_SPIN:
publicAPI.handleMouseSpin(renderer, pos);
publicAPI.invokeInteractionEvent({
type: 'InteractionEvent'
});
break;
}
model.previousPosition = pos;
};
//----------------------------------------------------------------------------
publicAPI.handleButton3D = ed => {
if (ed && ed.pressed && ed.device === Device.RightController && (ed.input === Input.Trigger || ed.input === Input.TrackPad)) {
publicAPI.startCameraPose();
return;
}
if (ed && !ed.pressed && ed.device === Device.RightController && (ed.input === Input.Trigger || ed.input === Input.TrackPad) && model.state === States.IS_CAMERA_POSE) {
publicAPI.endCameraPose();
// return;
}
};
publicAPI.handleMove3D = ed => {
switch (model.state) {
case States.IS_CAMERA_POSE:
publicAPI.updateCameraPose(ed);
break;
}
};
publicAPI.updateCameraPose = ed => {
// move the world in the direction of the
// controller
const camera = model.getRenderer(ed).getActiveCamera();
const oldTrans = camera.getPhysicalTranslation();
// look at the y axis to determine how fast / what direction to move
const speed = 0.5; // ed.gamepad.axes[1];
// 0.05 meters / frame movement
const pscale = speed * 0.05 * camera.getPhysicalScale();
// convert orientation to world coordinate direction
const dir = camera.physicalOrientationToWorldDirection([ed.orientation.x, ed.orientation.y, ed.orientation.z, ed.orientation.w]);
camera.setPhysicalTranslation(oldTrans[0] + dir[0] * pscale, oldTrans[1] + dir[1] * pscale, oldTrans[2] + dir[2] * pscale);
};
//----------------------------------------------------------------------------
publicAPI.handleLeftButtonPress = callData => {
const pos = callData.position;
model.previousPosition = pos;
if (callData.shiftKey) {
if (callData.controlKey || callData.altKey) {
publicAPI.startDolly();
} else {
publicAPI.startPan();
}
} else {
if (callData.controlKey || callData.altKey) {
publicAPI.startSpin();
} else {
publicAPI.startRotate();
}
}
};
//--------------------------------------------------------------------------
publicAPI.handleLeftButtonRelease = () => {
switch (model.state) {
case States.IS_DOLLY:
publicAPI.endDolly();
break;
case States.IS_PAN:
publicAPI.endPan();
break;
case States.IS_SPIN:
publicAPI.endSpin();
break;
case States.IS_ROTATE:
publicAPI.endRotate();
break;
}
};
//----------------------------------------------------------------------------
publicAPI.handleStartMouseWheel = () => {
publicAPI.startDolly();
};
//--------------------------------------------------------------------------
publicAPI.handleEndMouseWheel = () => {
publicAPI.endDolly();
};
//----------------------------------------------------------------------------
publicAPI.handleStartPinch = callData => {
model.previousScale = callData.scale;
publicAPI.startDolly();
};
//--------------------------------------------------------------------------
publicAPI.handleEndPinch = () => {
publicAPI.endDolly();
};
//----------------------------------------------------------------------------
publicAPI.handleStartRotate = callData => {
model.previousRotation = callData.rotation;
publicAPI.startRotate();
};
//--------------------------------------------------------------------------
publicAPI.handleEndRotate = () => {
publicAPI.endRotate();
};
//----------------------------------------------------------------------------
publicAPI.handleStartPan = callData => {
model.previousTranslation = callData.translation;
publicAPI.startPan();
};
//--------------------------------------------------------------------------
publicAPI.handleEndPan = () => {
publicAPI.endPan();
};
//----------------------------------------------------------------------------
publicAPI.handlePinch = callData => {
publicAPI.dollyByFactor(model.getRenderer(callData), callData.scale / model.previousScale);
model.previousScale = callData.scale;
};
//----------------------------------------------------------------------------
publicAPI.handlePan = callData => {
const camera = model.getRenderer(callData).getActiveCamera();
// Calculate the focal depth since we'll be using it a lot
let viewFocus = camera.getFocalPoint();
viewFocus = publicAPI.computeWorldToDisplay(model.getRenderer(callData), viewFocus[0], viewFocus[1], viewFocus[2]);
const focalDepth = viewFocus[2];
const trans = callData.translation;
const lastTrans = model.previousTranslation;
const newPickPoint = publicAPI.computeDisplayToWorld(model.getRenderer(callData), viewFocus[0] + trans[0] - lastTrans[0], viewFocus[1] + trans[1] - lastTrans[1], focalDepth);
// Has to recalc old mouse point since the viewport has moved,
// so can't move it outside the loop
const oldPickPoint = publicAPI.computeDisplayToWorld(model.getRenderer(callData), viewFocus[0], viewFocus[1], focalDepth);
// Camera motion is reversed
const motionVector = [];
motionVector[0] = oldPickPoint[0] - newPickPoint[0];
motionVector[1] = oldPickPoint[1] - newPickPoint[1];
motionVector[2] = oldPickPoint[2] - newPickPoint[2];
viewFocus = camera.getFocalPoint();
const viewPoint = camera.getPosition();
camera.setFocalPoint(motionVector[0] + viewFocus[0], motionVector[1] + viewFocus[1], motionVector[2] + viewFocus[2]);
camera.setPosition(motionVector[0] + viewPoint[0], motionVector[1] + viewPoint[1], motionVector[2] + viewPoint[2]);
if (model._interactor.getLightFollowCamera()) {
model.getRenderer(callData).updateLightsGeometryToFollowCamera();
}
camera.orthogonalizeViewUp();
model.previousTranslation = callData.translation;
};
//----------------------------------------------------------------------------
publicAPI.handleRotate = callData => {
const camera = model.getRenderer(callData).getActiveCamera();
camera.roll(callData.rotation - model.previousRotation);
camera.orthogonalizeViewUp();
model.previousRotation = callData.rotation;
};
//--------------------------------------------------------------------------
publicAPI.handleMouseRotate = (renderer, position) => {
if (!model.previousPosition) {
return;
}
const rwi = model._interactor;
const dx = position.x - model.previousPosition.x;
const dy = position.y - model.previousPosition.y;
const size = rwi.getView().getViewportSize(renderer);
let deltaElevation = -0.1;
let deltaAzimuth = -0.1;
if (size[0] && size[1]) {
deltaElevation = -20.0 / size[1];
deltaAzimuth = -20.0 / size[0];
}
const rxf = dx * deltaAzimuth * model.motionFactor;
const ryf = dy * deltaElevation * model.motionFactor;
const camera = renderer.getActiveCamera();
if (!Number.isNaN(rxf) && !Number.isNaN(ryf)) {
camera.azimuth(rxf);
camera.elevation(ryf);
camera.orthogonalizeViewUp();
}
if (model.autoAdjustCameraClippingRange) {
renderer.resetCameraClippingRange();
}
if (rwi.getLightFollowCamera()) {
renderer.updateLightsGeometryToFollowCamera();
}
};
//--------------------------------------------------------------------------
publicAPI.handleMouseSpin = (renderer, position) => {
if (!model.previousPosition) {
return;
}
const rwi = model._interactor;
const camera = renderer.getActiveCamera();
const center = rwi.getView().getViewportCenter(renderer);
const oldAngle = degreesFromRadians(Math.atan2(model.previousPosition.y - center[1], model.previousPosition.x - center[0]));
const newAngle = degreesFromRadians(Math.atan2(position.y - center[1], position.x - center[0])) - oldAngle;
if (!Number.isNaN(newAngle)) {
camera.roll(newAngle);
camera.orthogonalizeViewUp();
}
};
//--------------------------------------------------------------------------
publicAPI.handleMousePan = (renderer, position) => {
if (!model.previousPosition) {
return;
}
const camera = renderer.getActiveCamera();
// Calculate the focal depth since we'll be using it a lot
let viewFocus = camera.getFocalPoint();
viewFocus = publicAPI.computeWorldToDisplay(renderer, viewFocus[0], viewFocus[1], viewFocus[2]);
const focalDepth = viewFocus[2];
const newPickPoint = publicAPI.computeDisplayToWorld(renderer, position.x, position.y, focalDepth);
// Has to recalc old mouse point since the viewport has moved,
// so can't move it outside the loop
const oldPickPoint = publicAPI.computeDisplayToWorld(renderer, model.previousPosition.x, model.previousPosition.y, focalDepth);
// Camera motion is reversed
const motionVector = [];
motionVector[0] = oldPickPoint[0] - newPickPoint[0];
motionVector[1] = oldPickPoint[1] - newPickPoint[1];
motionVector[2] = oldPickPoint[2] - newPickPoint[2];
viewFocus = camera.getFocalPoint();
const viewPoint = camera.getPosition();
camera.setFocalPoint(motionVector[0] + viewFocus[0], motionVector[1] + viewFocus[1], motionVector[2] + viewFocus[2]);
camera.setPosition(motionVector[0] + viewPoint[0], motionVector[1] + viewPoint[1], motionVector[2] + viewPoint[2]);
if (model._interactor.getLightFollowCamera()) {
renderer.updateLightsGeometryToFollowCamera();
}
};
//----------------------------------------------------------------------------
publicAPI.handleMouseDolly = (renderer, position) => {
if (!model.previousPosition) {
return;
}
const dy = position.y - model.previousPosition.y;
const rwi = model._interactor;
const center = rwi.getView().getViewportCenter(renderer);
const dyf = model.motionFactor * dy / center[1];
publicAPI.dollyByFactor(renderer, 1.1 ** dyf);
};
//----------------------------------------------------------------------------
publicAPI.handleMouseWheel = callData => {
const dyf = 1 - callData.spinY / model.zoomFactor;
publicAPI.dollyByFactor(model.getRenderer(callData), dyf);
};
//----------------------------------------------------------------------------
publicAPI.dollyByFactor = (renderer, factor) => {
if (Number.isNaN(factor)) {
return;
}
const camera = renderer.getActiveCamera();
if (camera.getParallelProjection()) {
camera.setParallelScale(camera.getParallelScale() / factor);
} else {
camera.dolly(factor);
if (model.autoAdjustCameraClippingRange) {
renderer.resetCameraClippingRange();
}
}
if (model._interactor.getLightFollowCamera()) {
renderer.updateLightsGeometryToFollowCamera();
}
};
}
// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
const DEFAULT_VALUES = {
motionFactor: 10.0,
zoomFactor: 10.0
};
// ----------------------------------------------------------------------------
function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
// Inheritance
vtkInteractorStyle.extend(publicAPI, model, initialValues);
// Create get-set macros
macro.setGet(publicAPI, model, ['motionFactor', 'zoomFactor']);
// For more macro methods, see "Sources/macros.js"
// Object specific methods
vtkInteractorStyleTrackballCamera(publicAPI, model);
}
// ----------------------------------------------------------------------------
const newInstance = macro.newInstance(extend, 'vtkInteractorStyleTrackballCamera');
// ----------------------------------------------------------------------------
var vtkInteractorStyleTrackballCamera$1 = {
newInstance,
extend
};
export { vtkInteractorStyleTrackballCamera$1 as default, extend, newInstance };