molstar
Version:
A comprehensive macromolecular library.
119 lines (118 loc) • 6.88 kB
JavaScript
/**
* Copyright (c) 2018-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.addFixedCountDashedCylinder = exports.addDoubleCylinder = exports.addCylinder = exports.addSimpleCylinder = void 0;
var linear_algebra_1 = require("../../../../mol-math/linear-algebra");
var mesh_builder_1 = require("../mesh-builder");
var primitive_1 = require("../../../primitive/primitive");
var cylinder_1 = require("../../../primitive/cylinder");
var prism_1 = require("../../../primitive/prism");
var polygon_1 = require("../../../primitive/polygon");
var util_1 = require("../../../../mol-data/util");
var cylinderMap = new Map();
var up = linear_algebra_1.Vec3.create(0, 1, 0);
var tmpCylinderDir = (0, linear_algebra_1.Vec3)();
var tmpCylinderMatDir = (0, linear_algebra_1.Vec3)();
var tmpCylinderCenter = (0, linear_algebra_1.Vec3)();
var tmpCylinderMat = (0, linear_algebra_1.Mat4)();
var tmpCylinderMatRot = (0, linear_algebra_1.Mat4)();
var tmpCylinderScale = (0, linear_algebra_1.Vec3)();
var tmpCylinderStart = (0, linear_algebra_1.Vec3)();
var tmpUp = (0, linear_algebra_1.Vec3)();
function setCylinderMat(m, start, dir, length, matchDir) {
linear_algebra_1.Vec3.setMagnitude(tmpCylinderMatDir, dir, length / 2);
linear_algebra_1.Vec3.add(tmpCylinderCenter, start, tmpCylinderMatDir);
// ensure the direction used to create the rotation is always pointing in the same
// direction so the triangles of adjacent cylinder will line up
if (matchDir)
linear_algebra_1.Vec3.matchDirection(tmpUp, up, tmpCylinderMatDir);
else
linear_algebra_1.Vec3.copy(tmpUp, up);
linear_algebra_1.Vec3.set(tmpCylinderScale, 1, length, 1);
linear_algebra_1.Vec3.makeRotation(tmpCylinderMatRot, tmpUp, tmpCylinderMatDir);
linear_algebra_1.Mat4.scale(m, tmpCylinderMatRot, tmpCylinderScale);
return linear_algebra_1.Mat4.setTranslation(m, tmpCylinderCenter);
}
var tmpPropValues = new Int32Array(9);
function getCylinderPropsKey(props) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
tmpPropValues[0] = Math.round(1000 * ((_a = props.radiusTop) !== null && _a !== void 0 ? _a : cylinder_1.DefaultCylinderProps.radiusTop));
tmpPropValues[1] = Math.round(1000 * ((_b = props.radiusBottom) !== null && _b !== void 0 ? _b : cylinder_1.DefaultCylinderProps.radiusBottom));
tmpPropValues[2] = Math.round(1000 * ((_c = props.height) !== null && _c !== void 0 ? _c : cylinder_1.DefaultCylinderProps.height));
tmpPropValues[3] = (_d = props.radialSegments) !== null && _d !== void 0 ? _d : cylinder_1.DefaultCylinderProps.radialSegments;
tmpPropValues[4] = (_e = props.heightSegments) !== null && _e !== void 0 ? _e : cylinder_1.DefaultCylinderProps.heightSegments;
tmpPropValues[5] = ((_f = props.topCap) !== null && _f !== void 0 ? _f : cylinder_1.DefaultCylinderProps.topCap) ? 1 : 0;
tmpPropValues[6] = ((_g = props.bottomCap) !== null && _g !== void 0 ? _g : cylinder_1.DefaultCylinderProps.bottomCap) ? 1 : 0;
tmpPropValues[7] = Math.round(1000 * ((_h = props.thetaStart) !== null && _h !== void 0 ? _h : cylinder_1.DefaultCylinderProps.thetaStart));
tmpPropValues[8] = Math.round(1000 * ((_j = props.thetaLength) !== null && _j !== void 0 ? _j : cylinder_1.DefaultCylinderProps.thetaLength));
return (0, util_1.hashFnv32a)(tmpPropValues);
}
function getCylinder(props) {
var key = getCylinderPropsKey(props);
var cylinder = cylinderMap.get(key);
if (cylinder === undefined) {
if (props.radialSegments && props.radialSegments <= 4) {
var sideCount = Math.max(3, props.radialSegments);
var prism = (0, prism_1.Prism)((0, polygon_1.polygon)(sideCount, true, props.radiusTop), props);
cylinder = (0, primitive_1.transformPrimitive)(prism, linear_algebra_1.Mat4.rotX90);
}
else {
cylinder = (0, cylinder_1.Cylinder)(props);
}
cylinderMap.set(key, cylinder);
}
return cylinder;
}
function addSimpleCylinder(state, start, end, props) {
var d = linear_algebra_1.Vec3.distance(start, end);
linear_algebra_1.Vec3.sub(tmpCylinderDir, end, start);
setCylinderMat(tmpCylinderMat, start, tmpCylinderDir, d, false);
mesh_builder_1.MeshBuilder.addPrimitive(state, tmpCylinderMat, getCylinder(props));
}
exports.addSimpleCylinder = addSimpleCylinder;
function addCylinder(state, start, end, lengthScale, props) {
var d = linear_algebra_1.Vec3.distance(start, end) * lengthScale;
linear_algebra_1.Vec3.sub(tmpCylinderDir, end, start);
setCylinderMat(tmpCylinderMat, start, tmpCylinderDir, d, true);
mesh_builder_1.MeshBuilder.addPrimitive(state, tmpCylinderMat, getCylinder(props));
}
exports.addCylinder = addCylinder;
function addDoubleCylinder(state, start, end, lengthScale, shift, props) {
var d = linear_algebra_1.Vec3.distance(start, end) * lengthScale;
var cylinder = getCylinder(props);
linear_algebra_1.Vec3.sub(tmpCylinderDir, end, start);
// positivly shifted cylinder
linear_algebra_1.Vec3.add(tmpCylinderStart, start, shift);
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d, true);
mesh_builder_1.MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder);
// negativly shifted cylinder
linear_algebra_1.Vec3.sub(tmpCylinderStart, start, shift);
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d, true);
mesh_builder_1.MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder);
}
exports.addDoubleCylinder = addDoubleCylinder;
function addFixedCountDashedCylinder(state, start, end, lengthScale, segmentCount, props) {
var s = Math.floor(segmentCount / 2);
var step = 1 / segmentCount;
// automatically adjust length so links/bonds that are rendered as two half cylinders
// have evenly spaced dashed cylinders
if (lengthScale < 1) {
var bias = lengthScale / 2 / segmentCount;
lengthScale += segmentCount % 2 === 1 ? bias : -bias;
}
var d = linear_algebra_1.Vec3.distance(start, end) * lengthScale;
var cylinder = getCylinder(props);
linear_algebra_1.Vec3.sub(tmpCylinderDir, end, start);
for (var j = 0; j < s; ++j) {
var f = step * (j * 2 + 1);
linear_algebra_1.Vec3.setMagnitude(tmpCylinderDir, tmpCylinderDir, d * f);
linear_algebra_1.Vec3.add(tmpCylinderStart, start, tmpCylinderDir);
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d * step, false);
mesh_builder_1.MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder);
}
}
exports.addFixedCountDashedCylinder = addFixedCountDashedCylinder;
;