molstar
Version:
A comprehensive macromolecular library.
218 lines • 10.9 kB
JavaScript
"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