UNPKG

molstar

Version:

A comprehensive macromolecular library.

218 lines 10.9 kB
"use strict"; /** * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PickHelper = exports.PickPass = void 0; var linear_algebra_1 = require("../../mol-math/linear-algebra"); var misc_1 = require("../../mol-math/misc"); var float_packing_1 = require("../../mol-util/float-packing"); var stereo_1 = require("../camera/stereo"); var util_1 = require("../camera/util"); var util_2 = require("../camera/util"); var NullId = Math.pow(2, 24) - 2; var PickPass = /** @class */ (function () { function PickPass(webgl, drawPass, pickBaseScale) { this.webgl = webgl; this.drawPass = drawPass; this.pickBaseScale = pickBaseScale; var pickScale = pickBaseScale / webgl.pixelRatio; this.pickWidth = Math.ceil(drawPass.colorTarget.getWidth() * pickScale); this.pickHeight = Math.ceil(drawPass.colorTarget.getHeight() * pickScale); this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); this.depthPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); } Object.defineProperty(PickPass.prototype, "drawingBufferHeight", { get: function () { return this.drawPass.colorTarget.getHeight(); }, enumerable: false, configurable: true }); PickPass.prototype.syncSize = function () { var pickScale = this.pickBaseScale / this.webgl.pixelRatio; var pickWidth = Math.ceil(this.drawPass.colorTarget.getWidth() * pickScale); var pickHeight = Math.ceil(this.drawPass.colorTarget.getHeight() * pickScale); if (pickWidth !== this.pickWidth || pickHeight !== this.pickHeight) { this.pickWidth = pickWidth; this.pickHeight = pickHeight; this.objectPickTarget.setSize(this.pickWidth, this.pickHeight); this.instancePickTarget.setSize(this.pickWidth, this.pickHeight); this.groupPickTarget.setSize(this.pickWidth, this.pickHeight); this.depthPickTarget.setSize(this.pickWidth, this.pickHeight); } }; PickPass.prototype.renderVariant = function (renderer, camera, scene, helper, variant) { var depth = this.drawPass.depthTexturePrimitives; renderer.clear(false); renderer.update(camera); renderer.renderPick(scene.primitives, camera, variant, null); renderer.renderPick(scene.volumes, camera, variant, depth); renderer.renderPick(helper.handle.scene, camera, variant, null); if (helper.camera.isEnabled) { helper.camera.update(camera); renderer.update(helper.camera.camera); renderer.renderPick(helper.camera.scene, helper.camera.camera, variant, null); } }; PickPass.prototype.render = function (renderer, camera, scene, helper) { this.objectPickTarget.bind(); this.renderVariant(renderer, camera, scene, helper, 'pickObject'); this.instancePickTarget.bind(); this.renderVariant(renderer, camera, scene, helper, 'pickInstance'); this.groupPickTarget.bind(); this.renderVariant(renderer, camera, scene, helper, 'pickGroup'); // printTexture(this.webgl, this.groupPickTarget.texture, { id: 'group' }) this.depthPickTarget.bind(); this.renderVariant(renderer, camera, scene, helper, 'depth'); }; return PickPass; }()); exports.PickPass = PickPass; var PickHelper = /** @class */ (function () { function PickHelper(webgl, renderer, scene, helper, pickPass, viewport, pickPadding) { if (pickPadding === void 0) { pickPadding = 1; } this.webgl = webgl; this.renderer = renderer; this.scene = scene; this.helper = helper; this.pickPass = pickPass; this.pickPadding = pickPadding; this.dirty = true; this.viewport = (0, util_2.Viewport)(); this.setViewport(viewport.x, viewport.y, viewport.width, viewport.height); } PickHelper.prototype.setupBuffers = function () { var bufferSize = this.pickWidth * this.pickHeight * 4; if (!this.objectBuffer || this.objectBuffer.length !== bufferSize) { this.objectBuffer = new Uint8Array(bufferSize); this.instanceBuffer = new Uint8Array(bufferSize); this.groupBuffer = new Uint8Array(bufferSize); this.depthBuffer = new Uint8Array(bufferSize); } }; PickHelper.prototype.setViewport = function (x, y, width, height) { util_2.Viewport.set(this.viewport, x, y, width, height); this.pickScale = this.pickPass.pickBaseScale / this.webgl.pixelRatio; this.pickX = Math.ceil(x * this.pickScale); this.pickY = Math.ceil(y * this.pickScale); var pickWidth = Math.floor(width * this.pickScale); var pickHeight = Math.floor(height * this.pickScale); if (pickWidth !== this.pickWidth || pickHeight !== this.pickHeight) { this.pickWidth = pickWidth; this.pickHeight = pickHeight; this.halfPickWidth = Math.floor(this.pickWidth / 2); this.setupBuffers(); } this.spiral = (0, misc_1.spiral2d)(Math.round(this.pickScale * this.pickPadding)); }; PickHelper.prototype.syncBuffers = function () { var _a = this, pickX = _a.pickX, pickY = _a.pickY, pickWidth = _a.pickWidth, pickHeight = _a.pickHeight; this.pickPass.objectPickTarget.bind(); this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.objectBuffer); this.pickPass.instancePickTarget.bind(); this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.instanceBuffer); this.pickPass.groupPickTarget.bind(); this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.groupBuffer); this.pickPass.depthPickTarget.bind(); this.webgl.readPixels(pickX, pickY, pickWidth, pickHeight, this.depthBuffer); }; PickHelper.prototype.getBufferIdx = function (x, y) { return (y * this.pickWidth + x) * 4; }; PickHelper.prototype.getDepth = function (x, y) { var idx = this.getBufferIdx(x, y); var b = this.depthBuffer; return (0, float_packing_1.unpackRGBAToDepth)(b[idx], b[idx + 1], b[idx + 2], b[idx + 3]); }; PickHelper.prototype.getId = function (x, y, buffer) { var idx = this.getBufferIdx(x, y); return (0, float_packing_1.decodeFloatRGB)(buffer[idx], buffer[idx + 1], buffer[idx + 2]); }; PickHelper.prototype.render = function (camera) { var _a = this, pickX = _a.pickX, pickY = _a.pickY, pickWidth = _a.pickWidth, pickHeight = _a.pickHeight, halfPickWidth = _a.halfPickWidth; var _b = this, renderer = _b.renderer, scene = _b.scene, helper = _b.helper; renderer.setTransparentBackground(false); renderer.setDrawingBufferSize(this.pickPass.objectPickTarget.getWidth(), this.pickPass.objectPickTarget.getHeight()); renderer.setPixelRatio(this.pickScale); if (stereo_1.StereoCamera.is(camera)) { renderer.setViewport(pickX, pickY, halfPickWidth, pickHeight); this.pickPass.render(renderer, camera.left, scene, helper); renderer.setViewport(pickX + halfPickWidth, pickY, pickWidth - halfPickWidth, pickHeight); this.pickPass.render(renderer, camera.right, scene, helper); } else { renderer.setViewport(pickX, pickY, pickWidth, pickHeight); this.pickPass.render(renderer, camera, scene, helper); } this.dirty = false; }; PickHelper.prototype.identifyInternal = function (x, y, camera) { var _a = this, webgl = _a.webgl, pickScale = _a.pickScale; if (webgl.isContextLost) return; x *= webgl.pixelRatio; y *= webgl.pixelRatio; y = this.pickPass.drawingBufferHeight - y; // flip y var viewport = this.viewport; // check if within viewport if (x < viewport.x || y < viewport.y || x > viewport.x + viewport.width || y > viewport.y + viewport.height) return; if (this.dirty) { this.render(camera); this.syncBuffers(); } var xv = x - viewport.x; var yv = y - viewport.y; var xp = Math.floor(xv * pickScale); var yp = Math.floor(yv * pickScale); var objectId = this.getId(xp, yp, this.objectBuffer); // console.log('objectId', objectId); if (objectId === -1 || objectId === NullId) return; var instanceId = this.getId(xp, yp, this.instanceBuffer); // console.log('instanceId', instanceId); if (instanceId === -1 || instanceId === NullId) return; var groupId = this.getId(xp, yp, this.groupBuffer); // console.log('groupId', groupId); if (groupId === -1 || groupId === NullId) return; var z = this.getDepth(xp, yp); var position = linear_algebra_1.Vec3.create(x, viewport.height - y, z); if (stereo_1.StereoCamera.is(camera)) { var halfWidth = Math.floor(viewport.width / 2); if (x > viewport.x + halfWidth) { position[0] = viewport.x + (xv - halfWidth) * 2; (0, util_1.cameraUnproject)(position, position, viewport, camera.right.inverseProjectionView); } else { position[0] = viewport.x + xv * 2; (0, util_1.cameraUnproject)(position, position, viewport, camera.left.inverseProjectionView); } } else { (0, util_1.cameraUnproject)(position, position, viewport, camera.inverseProjectionView); } // console.log({ { objectId, instanceId, groupId }, position} ); return { id: { objectId: objectId, instanceId: instanceId, groupId: groupId }, position: position }; }; PickHelper.prototype.identify = function (x, y, camera) { for (var _i = 0, _a = this.spiral; _i < _a.length; _i++) { var d = _a[_i]; var pickData = this.identifyInternal(x + d[0], y + d[1], camera); if (pickData) return pickData; } }; return PickHelper; }()); exports.PickHelper = PickHelper; //# sourceMappingURL=pick.js.map