@thewtex/vtk.js-esm
Version:
Visualization Toolkit for the Web
155 lines (120 loc) • 6.41 kB
JavaScript
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import macro from '../../macro.js';
import vtkCompositeCameraManipulator from './CompositeCameraManipulator.js';
import vtkCompositeMouseManipulator from './CompositeMouseManipulator.js';
import { r as radiansFromDegrees, j as cross } from '../../Common/Core/Math/index.js';
import vtkMatrixBuilder from '../../Common/Core/MatrixBuilder.js';
import { i as identity, t as translate, r as rotate } from '../../vendor/gl-matrix/esm/mat4.js';
import { t as transformMat4, a as subtract, n as normalize, d as dot, h as distance, e as scaleAndAdd, c as cross$1, l as length } from '../../vendor/gl-matrix/esm/vec3.js';
// vtkMouseCameraAxisRotateManipulator methods
// ----------------------------------------------------------------------------
function vtkMouseCameraAxisRotateManipulator(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkMouseCameraAxisRotateManipulator');
var newCamPos = new Float64Array(3);
var newFp = new Float64Array(3); // const newViewUp = new Float64Array(3);
var trans = new Float64Array(16);
var v2 = new Float64Array(3);
var centerNeg = new Float64Array(3);
var direction = new Float64Array(3);
var fpDirection = new Float64Array(3);
publicAPI.onButtonDown = function (interactor, renderer, position) {
model.previousPosition = position;
};
publicAPI.onMouseMove = function (interactor, renderer, position) {
if (!position) {
return;
}
var camera = renderer.getActiveCamera();
var cameraPos = camera.getPosition();
var cameraFp = camera.getFocalPoint();
var cameraViewUp = camera.getViewUp();
var cameraDirection = camera.getDirectionOfProjection();
identity(trans);
var center = model.center,
rotationFactor = model.rotationFactor,
rotationAxis = model.rotationAxis; // Translate to center
translate(trans, trans, center);
var dx = model.previousPosition.x - position.x;
var dy = model.previousPosition.y - position.y;
var size = interactor.getView().getSize(); // Azimuth
rotate(trans, trans, radiansFromDegrees(360.0 * dx / size[0] * rotationFactor), rotationAxis); // Elevation
cross(cameraDirection, cameraViewUp, v2);
rotate(trans, trans, radiansFromDegrees(-360.0 * dy / size[1] * rotationFactor), v2); // Translate back
centerNeg[0] = -center[0];
centerNeg[1] = -center[1];
centerNeg[2] = -center[2];
translate(trans, trans, centerNeg); // Apply transformation to camera position, focal point, and view up
transformMat4(newCamPos, cameraPos, trans);
transformMat4(newFp, cameraFp, trans); // what is the current direction from the fp
// to the camera
subtract(fpDirection, newCamPos, newFp);
normalize(fpDirection, fpDirection); // make the top sticky to avoid accidental flips
if (Math.abs(dot(fpDirection, rotationAxis)) > 0.95) {
// this can be smarter where it still allows Azimuth here
// but prevents the elevation part
model.previousPosition = position;
return;
}
if (model.useHalfAxis) {
// what is the current distance from pos to center of rotation
var distance$1 = distance(newCamPos, center); // what is the current direction from the center of rotation
// to the camera
subtract(direction, newCamPos, center);
normalize(direction, direction); // project the rotation axis onto the direction
// so we know how much below the half plane we are
var dotP = dot(rotationAxis, direction);
if (dotP < 0) {
// adjust the new camera position to bring it up to the half plane
scaleAndAdd(newCamPos, newCamPos, rotationAxis, -dotP * distance$1); // the above step will change the distance which might feel odd
// so the next couple lines restore the distance to the center
// what is the new direction from the center of rotation
// to the camera
subtract(direction, newCamPos, center);
normalize(direction, direction);
scaleAndAdd(newCamPos, center, direction, distance$1); // compute original cam direction to center
subtract(v2, cameraPos, center);
normalize(v2, v2); // const rAngle = 0.0;
var acosR = Math.min(1.0, Math.max(-1.0, dot(direction, v2)));
var rAngle = Math.acos(acosR); // 0 to pi
cross$1(v2, v2, direction);
normalize(v2, v2);
subtract(newFp, cameraFp, center);
var fpDist = length(newFp); // Note it normalizes the vector to be rotated
var result = _toConsumableArray(newFp);
vtkMatrixBuilder.buildFromRadian().rotate(rAngle, v2).apply(result);
scaleAndAdd(newFp, center, result, fpDist);
}
}
camera.setPosition(newCamPos[0], newCamPos[1], newCamPos[2]);
camera.setFocalPoint(newFp[0], newFp[1], newFp[2]);
camera.setViewUp(rotationAxis);
renderer.resetCameraClippingRange();
if (interactor.getLightFollowCamera()) {
renderer.updateLightsGeometryToFollowCamera();
}
model.previousPosition = position;
};
} // ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
var DEFAULT_VALUES = {
rotationAxis: [0, 0, 1],
useHalfAxis: true
}; // ----------------------------------------------------------------------------
function extend(publicAPI, model) {
var initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance
macro.obj(publicAPI, model);
macro.setGet(publicAPI, model, ['rotationAxis', 'useHalfAxis']);
vtkCompositeMouseManipulator.extend(publicAPI, model, initialValues);
vtkCompositeCameraManipulator.extend(publicAPI, model, initialValues); // Object specific methods
vtkMouseCameraAxisRotateManipulator(publicAPI, model);
} // ----------------------------------------------------------------------------
var newInstance = macro.newInstance(extend, 'vtkMouseCameraAxisRotateManipulator'); // ----------------------------------------------------------------------------
var vtkMouseCameraAxisRotateManipulator$1 = {
newInstance: newInstance,
extend: extend
};
export default vtkMouseCameraAxisRotateManipulator$1;
export { extend, newInstance };