UNPKG

@metacell/geppetto-meta-ui

Version:

React components from geppetto-meta to create neuroscience applications and visualize data.

450 lines (424 loc) 16 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } import * as THREE from 'three'; var CameraManager = /*#__PURE__*/function () { function CameraManager(engine, cameraOptions) { _classCallCheck(this, CameraManager); this.engine = engine; this.sceneCenter = new THREE.Vector3(); this.camera = new THREE.PerspectiveCamera(cameraOptions.angle, cameraOptions.aspect, cameraOptions.near, cameraOptions.far); this.engine.scene.add(this.camera); this.camera.up = new THREE.Vector3(0, 1, 0); this.camera.direction = new THREE.Vector3(0, 0, 1); this.camera.lookAt(this.sceneCenter); this.baseZoom = cameraOptions.baseZoom; this.isFirstRender = true; var initialFlip = cameraOptions.initialFlip; if (initialFlip && initialFlip.length > 0) { this.flipCamera(initialFlip); } } return _createClass(CameraManager, [{ key: "update", value: function update(cameraOptions) { var initialPosition = cameraOptions.initialPosition, initialRotation = cameraOptions.initialRotation, autoRotate = cameraOptions.autoRotate, movieFilter = cameraOptions.movieFilter, initialZoomTo = cameraOptions.initialZoomTo, reset = cameraOptions.reset, trackballControls = cameraOptions.trackballControls; if (reset || this.isFirstRender && initialPosition === undefined && initialZoomTo === undefined) { this.resetCamera(initialPosition, initialRotation, initialZoomTo); if (this.isFirstRender) { this.isFirstRender = false; } } else { if (initialPosition && this.isFirstRender) { this.setCameraPosition(initialPosition.x, initialPosition.y, initialPosition.z); } if (initialRotation && this.isFirstRender) { this.setCameraRotation(initialRotation.rx, initialRotation.ry, initialRotation.rz, initialRotation.radius); } if (initialZoomTo && Array.isArray(initialZoomTo) && this.isFirstRender) { var instances = initialZoomTo.map(function (element) { return Instances.getInstance(element); }); if (instances.length > 0) { this.zoomTo(instances); } } if (autoRotate) { this.autoRotate(movieFilter); } if (trackballControls) { this.setTrackballControlsConfigs(trackballControls); } if (this.isFirstRender) { this.isFirstRender = false; } } } /** * * @param instances */ }, { key: "zoomTo", value: function zoomTo(instances) { this.engine.controls.reset(); this.zoomToParameters(this.zoomIterator(instances, {})); } /** * * @param initalFlip */ }, { key: "flipCamera", value: function flipCamera(initialFlip) { var _iterator = _createForOfIteratorHelper(initialFlip), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var axis = _step.value; if (axis.toLowerCase() === 'y') { this.flipCameraY(); } else if (axis.toLowerCase() === 'z') { this.flipCameraZ(); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } /** * Reinitializes the camera with the Y axis flipped */ }, { key: "flipCameraY", value: function flipCameraY() { this.camera.up = new THREE.Vector3(0, -1, 0); } /** * Reinitializes the camera with the Z axis flipped */ }, { key: "flipCameraZ", value: function flipCameraZ() { this.camera.direction = new THREE.Vector3(0, 0, -1); } /** * * @param instances * @param zoomParameters * @returns {*} */ }, { key: "zoomIterator", value: function zoomIterator(instances, zoomParameters) { var that = this; for (var i = 0; i < instances.length; i++) { var instancePath = instances[i].getInstancePath(); var mesh = this.engine.meshFactory.meshes[instancePath]; if (mesh) { mesh.traverse(function (object) { if (Object.prototype.hasOwnProperty.call(object, 'geometry')) { that.addMeshToZoomParameters(object, zoomParameters); } }); } else { zoomParameters = this.zoomIterator(instances[i].getChildren(), zoomParameters); } } return zoomParameters; } /** * * @param mesh * @param zoomParameters * @returns {*} */ }, { key: "addMeshToZoomParameters", value: function addMeshToZoomParameters(mesh, zoomParameters) { mesh.geometry.computeBoundingBox(); var bb = mesh.geometry.boundingBox; bb.translate(mesh.localToWorld(new THREE.Vector3())); // If min and max vectors are null, first values become default min and max if (zoomParameters.aabbMin == undefined && zoomParameters.aabbMax == undefined) { zoomParameters.aabbMin = bb.min; zoomParameters.aabbMax = bb.max; } else { // Compare other meshes, particles BB's to find min and max zoomParameters.aabbMin.x = Math.min(zoomParameters.aabbMin.x, bb.min.x); zoomParameters.aabbMin.y = Math.min(zoomParameters.aabbMin.y, bb.min.y); zoomParameters.aabbMin.z = Math.min(zoomParameters.aabbMin.z, bb.min.z); zoomParameters.aabbMax.x = Math.max(zoomParameters.aabbMax.x, bb.max.x); zoomParameters.aabbMax.y = Math.max(zoomParameters.aabbMax.y, bb.max.y); zoomParameters.aabbMax.z = Math.max(zoomParameters.aabbMax.z, bb.max.z); } return zoomParameters; } /** * * @param zoomParameters */ }, { key: "zoomToParameters", value: function zoomToParameters(zoomParameters) { // Compute world AABB center this.sceneCenter.x = (zoomParameters.aabbMax.x + zoomParameters.aabbMin.x) * 0.5; this.sceneCenter.y = (zoomParameters.aabbMax.y + zoomParameters.aabbMin.y) * 0.5; this.sceneCenter.z = (zoomParameters.aabbMax.z + zoomParameters.aabbMin.z) * 0.5; this.updateCamera(zoomParameters.aabbMax, zoomParameters.aabbMin); } }, { key: "resetCamera", value: function resetCamera(position, rotation, zoomTo) { var _this = this; var applyRotation = function applyRotation(rotation) { if (rotation) { _this.setCameraRotation(rotation.rx, rotation.ry, rotation.rz, rotation.radius); } }; if (zoomTo) { var instances = zoomTo.map(function (element) { return Instances.getInstance(element); }); if (instances.length > 0) { this.zoomTo(instances); } applyRotation(rotation); return; } if (position) { this.setCameraPosition(position.x, position.y, position.z); applyRotation(rotation); return; } this.engine.controls.reset(); var aabbMin = null; var aabbMax = null; var maxSize = null; this.engine.scene.traverse(function (child) { if (Object.prototype.hasOwnProperty.call(child, 'geometry') && child.visible === true) { child.geometry.computeBoundingBox(); var bb = child.geometry.boundingBox; var size = bb.getSize(new THREE.Vector3()).length(); bb.translate(child.localToWorld(new THREE.Vector3())); /* * If min and max vectors are null, first values become * default min and max */ if (aabbMin == null && aabbMax == null && maxSize == null) { aabbMin = bb.min; aabbMax = bb.max; maxSize = size; } else { // Compare other meshes, particles BB's to find min and max aabbMin.x = Math.min(aabbMin.x, bb.min.x); aabbMin.y = Math.min(aabbMin.y, bb.min.y); aabbMin.z = Math.min(aabbMin.z, bb.min.z); aabbMax.x = Math.max(aabbMax.x, bb.max.x); aabbMax.y = Math.max(aabbMax.y, bb.max.y); aabbMax.z = Math.max(aabbMax.z, bb.max.z); maxSize = Math.max(maxSize, size); } } }); if (aabbMin != null && aabbMax != null) { // Compute world AABB center this.sceneCenter.x = (aabbMax.x + aabbMin.x) * 0.5; this.sceneCenter.y = (aabbMax.y + aabbMin.y) * 0.5; this.sceneCenter.z = (aabbMax.z + aabbMin.z) * 0.5; this.camera.near = maxSize / 100; this.camera.far = maxSize * 100; this.updateCamera(aabbMax, aabbMin); } applyRotation(rotation); } /** * Update camera with new position and place to lookat * @param aabbMax * @param aabbMin */ }, { key: "updateCamera", value: function updateCamera(aabbMax, aabbMin) { // Compute world AABB "radius" var diag = new THREE.Vector3(); diag = diag.subVectors(aabbMax, aabbMin); var radius = diag.length() * 0.5; this.pointCameraTo(this.sceneCenter); // Compute offset needed to move the camera back that much needed to center AABB var offset = radius / Math.sin(Math.PI / 180.0 * this.camera.fov * 0.5) / this.baseZoom; var dir = this.camera.direction.clone(); dir.multiplyScalar(offset); // Store camera position this.camera.position.addVectors(dir, this.engine.controls.target); this.camera.updateProjectionMatrix(); } /** * Refocus camera to the center of the new object * @param node */ }, { key: "pointCameraTo", value: function pointCameraTo(node) { var COG; if (node instanceof THREE.Vector3) { COG = node; } else { COG = this.shapeCenterOfGravity(node); } var v = new THREE.Vector3(); v.subVectors(COG, this.engine.controls.target); this.camera.position.addVectors(this.camera.position, v); // retrieve camera orientation this.camera.lookAt(COG); this.engine.controls.target.set(COG.x, COG.y, COG.z); } /** * * @param obj * @returns {*} */ }, { key: "shapeCenterOfGravity", value: function shapeCenterOfGravity(obj) { return this.boundingBox(obj).center(); } /** * * @param obj * @returns {*} */ }, { key: "boundingBox", value: function boundingBox(obj) { if (obj instanceof THREE.Mesh) { var geometry = obj.geometry; geometry.computeBoundingBox(); return geometry.boundingBox; } if (obj instanceof THREE.Object3D) { var bb = new THREE.Box3(); for (var i = 0; i < obj.children.length; i++) { bb.union(this.boundingBox(obj.children[i])); } return bb; } } /** * Returns the camera * @returns camera */ }, { key: "getCamera", value: function getCamera() { return this.camera; } /** * @param x * @param y */ }, { key: "incrementCameraPan", value: function incrementCameraPan(x, y) { this.engine.controls.incrementPanEnd(x, y); } /** * @param x * @param y * @param z */ }, { key: "incrementCameraRotate", value: function incrementCameraRotate(x, y, z) { this.engine.controls.incrementRotationEnd(x, y, z); } /** * @param z */ }, { key: "incrementCameraZoom", value: function incrementCameraZoom(z) { this.engine.controls.incrementZoomEnd(z); } /** * @param x * @param y * @param z */ }, { key: "setCameraPosition", value: function setCameraPosition(x, y, z) { this.engine.controls.setPosition(x, y, z); } /** * @param rx * @param ry * @param rz * @param radius */ }, { key: "setCameraRotation", value: function setCameraRotation(rx, ry, rz, radius) { this.engine.controls.setRotation(rx, ry, rz, radius); } }, { key: "setTrackballControlsConfigs", value: function setTrackballControlsConfigs(config) { var rotationSpeed = config.rotationSpeed, zoomSpeed = config.zoomSpeed, panSpeed = config.panSpeed; this.engine.controls.setRotationalSpeed(rotationSpeed); this.engine.controls.setZoomSpeed(zoomSpeed); this.engine.controls.setPanSpeed(panSpeed); } /** * Rotate the camera around the selection * @movieFilter */ }, { key: "autoRotate", value: function autoRotate(movieFilter) { var that = this; if (this.rotate == null) { if (movieFilter === undefined || movieFilter === true) { this.movieMode(true); } this.engine.controls.setRotationalSpeed(0.075); this.rotate = setInterval(function () { that.incrementCameraRotate(0.5, 0); }, 25); } else { if (movieFilter === undefined || movieFilter === true) { this.movieMode(false); } this.engine.controls.resetRotationalSpeed(); clearInterval(this.rotate); this.rotate = null; } } /** * * @param shaders */ }, { key: "movieMode", value: function movieMode(shaders) { this.engine.configureRenderer(shaders); } }]); }(); export { CameraManager as default };