molstar
Version:
A comprehensive macromolecular library.
127 lines (126 loc) • 5.68 kB
JavaScript
/**
* 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);
}
}
}