UNPKG

molstar

Version:

A comprehensive macromolecular library.

127 lines (126 loc) 5.68 kB
/** * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { Vec3 } from '../../../../../mol-math/linear-algebra'; import { lerp, smoothstep } from '../../../../../mol-math/interpolate'; // avoiding namespace lookup improved performance in Chrome (Aug 2020) var v3fromArray = Vec3.fromArray; var v3toArray = Vec3.toArray; var v3normalize = Vec3.normalize; var v3sub = Vec3.sub; var v3spline = Vec3.spline; var v3slerp = Vec3.slerp; var v3copy = Vec3.copy; var v3cross = Vec3.cross; var v3orthogonalize = Vec3.orthogonalize; var v3matchDirection = Vec3.matchDirection; var v3scale = Vec3.scale; var v3add = Vec3.add; export function createCurveSegmentState(linearSegments) { var n = linearSegments + 1; var pn = n * 3; return { curvePoints: new Float32Array(pn), tangentVectors: new Float32Array(pn), normalVectors: new Float32Array(pn), binormalVectors: new Float32Array(pn), widthValues: new Float32Array(n), heightValues: new Float32Array(n), linearSegments: linearSegments }; } export function interpolateCurveSegment(state, controls, tension, shift) { interpolatePointsAndTangents(state, controls, tension, shift); interpolateNormals(state, controls); } var tanA = Vec3(); var tanB = Vec3(); var curvePoint = Vec3(); export function interpolatePointsAndTangents(state, controls, tension, shift) { var curvePoints = state.curvePoints, tangentVectors = state.tangentVectors, linearSegments = state.linearSegments; var p0 = controls.p0, p1 = controls.p1, p2 = controls.p2, p3 = controls.p3, p4 = controls.p4, secStrucFirst = controls.secStrucFirst, secStrucLast = controls.secStrucLast; var shift1 = 1 - shift; var tensionBeg = secStrucFirst ? 0.5 : tension; var tensionEnd = secStrucLast ? 0.5 : tension; for (var j = 0; j <= linearSegments; ++j) { var t = j * 1.0 / linearSegments; if (t < shift1) { var te = lerp(tensionBeg, tension, t); v3spline(curvePoint, p0, p1, p2, p3, t + shift, te); v3spline(tanA, p0, p1, p2, p3, t + shift + 0.01, tensionBeg); v3spline(tanB, p0, p1, p2, p3, t + shift - 0.01, tensionBeg); } else { var te = lerp(tension, tensionEnd, t); v3spline(curvePoint, p1, p2, p3, p4, t - shift1, te); v3spline(tanA, p1, p2, p3, p4, t - shift1 + 0.01, te); v3spline(tanB, p1, p2, p3, p4, t - shift1 - 0.01, te); } v3toArray(curvePoint, curvePoints, j * 3); v3normalize(tangentVec, v3sub(tangentVec, tanA, tanB)); v3toArray(tangentVec, tangentVectors, j * 3); } } var tmpNormal = Vec3(); var tangentVec = Vec3(); var normalVec = Vec3(); var binormalVec = Vec3(); var prevNormal = Vec3(); var nextNormal = Vec3(); var firstTangentVec = Vec3(); var lastTangentVec = Vec3(); var firstNormalVec = Vec3(); var lastNormalVec = Vec3(); /** * Populate normalVectors by interpolating from firstDirection to lastDirection with * resulting vector perpendicular to tangentVectors and binormalVectors */ export function interpolateNormals(state, controls) { var curvePoints = state.curvePoints, tangentVectors = state.tangentVectors, normalVectors = state.normalVectors, binormalVectors = state.binormalVectors; var firstDirection = controls.d12, lastDirection = controls.d23; var n = curvePoints.length / 3; v3fromArray(firstTangentVec, tangentVectors, 0); v3fromArray(lastTangentVec, tangentVectors, (n - 1) * 3); v3orthogonalize(firstNormalVec, firstTangentVec, firstDirection); v3orthogonalize(lastNormalVec, lastTangentVec, lastDirection); v3matchDirection(lastNormalVec, lastNormalVec, firstNormalVec); v3copy(prevNormal, firstNormalVec); var n1 = n - 1; for (var i = 0; i < n; ++i) { var j = smoothstep(0, n1, i) * n1; var t = i === 0 ? 0 : 1 / (n - j); v3fromArray(tangentVec, tangentVectors, i * 3); v3orthogonalize(normalVec, tangentVec, v3slerp(tmpNormal, prevNormal, lastNormalVec, t)); v3toArray(normalVec, normalVectors, i * 3); v3copy(prevNormal, normalVec); v3normalize(binormalVec, v3cross(binormalVec, tangentVec, normalVec)); v3toArray(binormalVec, binormalVectors, i * 3); } for (var i = 1; i < n1; ++i) { v3fromArray(prevNormal, normalVectors, (i - 1) * 3); v3fromArray(normalVec, normalVectors, i * 3); v3fromArray(nextNormal, normalVectors, (i + 1) * 3); v3scale(normalVec, v3add(normalVec, prevNormal, v3add(normalVec, nextNormal, normalVec)), 1 / 3); v3toArray(normalVec, normalVectors, i * 3); v3fromArray(tangentVec, tangentVectors, i * 3); v3normalize(binormalVec, v3cross(binormalVec, tangentVec, normalVec)); v3toArray(binormalVec, binormalVectors, i * 3); } } export function interpolateSizes(state, w0, w1, w2, h0, h1, h2, shift) { var widthValues = state.widthValues, heightValues = state.heightValues, linearSegments = state.linearSegments; var shift1 = 1 - shift; for (var i = 0; i <= linearSegments; ++i) { var t = i * 1.0 / linearSegments; if (t < shift1) { widthValues[i] = lerp(w0, w1, t + shift); heightValues[i] = lerp(h0, h1, t + shift); } else { widthValues[i] = lerp(w1, w2, t - shift1); heightValues[i] = lerp(h1, h2, t - shift1); } } }