123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /**
- * Copyright (c) 2018-2020 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 { NumberArray } from '../../../../../mol-util/type-helpers';
- import { lerp } from '../../../../../mol-math/interpolate';
- // avoiding namespace lookup improved performance in Chrome (Aug 2020)
- const v3fromArray = Vec3.fromArray;
- const v3toArray = Vec3.toArray;
- const v3normalize = Vec3.normalize;
- const v3sub = Vec3.sub;
- const v3spline = Vec3.spline;
- const v3slerp = Vec3.slerp;
- const v3copy = Vec3.copy;
- const v3cross = Vec3.cross;
- const v3orthogonalize = Vec3.orthogonalize;
- const v3matchDirection = Vec3.matchDirection;
- export interface CurveSegmentState {
- curvePoints: NumberArray,
- tangentVectors: NumberArray,
- normalVectors: NumberArray,
- binormalVectors: NumberArray,
- widthValues: NumberArray,
- heightValues: NumberArray,
- linearSegments: number
- }
- export interface CurveSegmentControls {
- secStrucFirst: boolean, secStrucLast: boolean
- p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3,
- d12: Vec3, d23: Vec3
- }
- export function createCurveSegmentState(linearSegments: number): CurveSegmentState {
- const n = linearSegments + 1;
- const 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
- };
- }
- export function interpolateCurveSegment(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) {
- interpolatePointsAndTangents(state, controls, tension, shift);
- interpolateNormals(state, controls);
- }
- const tanA = Vec3();
- const tanB = Vec3();
- const curvePoint = Vec3();
- export function interpolatePointsAndTangents(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) {
- const { curvePoints, tangentVectors, linearSegments } = state;
- const { p0, p1, p2, p3, p4, secStrucFirst, secStrucLast } = controls;
- const shift1 = 1 - shift;
- const tensionBeg = secStrucFirst ? 0.5 : tension;
- const tensionEnd = secStrucLast ? 0.5 : tension;
- for (let j = 0; j <= linearSegments; ++j) {
- const t = j * 1.0 / linearSegments;
- if (t < shift1) {
- const 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 {
- const 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);
- }
- }
- const tmpNormal = Vec3();
- const tangentVec = Vec3();
- const normalVec = Vec3();
- const binormalVec = Vec3();
- const prevNormal = Vec3();
- const firstTangentVec = Vec3();
- const lastTangentVec = Vec3();
- const firstNormalVec = Vec3();
- const lastNormalVec = Vec3();
- /**
- * Populate normalVectors by interpolating from firstDirection to lastDirection with
- * resulting vector perpendicular to tangentVectors and binormalVectors
- */
- export function interpolateNormals(state: CurveSegmentState, controls: CurveSegmentControls) {
- const { curvePoints, tangentVectors, normalVectors, binormalVectors } = state;
- const { d12: firstDirection, d23: lastDirection } = controls;
- const 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);
- for (let i = 0; i < n; ++i) {
- const t = i === 0 ? 0 : 1 / (n - i);
- 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);
- }
- }
- export function interpolateSizes(state: CurveSegmentState, w0: number, w1: number, w2: number, h0: number, h1: number, h2: number, shift: number) {
- const { widthValues, heightValues, linearSegments } = state;
- const shift1 = 1 - shift;
- for (let i = 0; i <= linearSegments; ++i) {
- const 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);
- }
- }
- }
|