UNPKG

@thewtex/vtk.js-esm

Version:

Visualization Toolkit for the Web

155 lines (120 loc) 6.41 kB
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 };