From 95654175fe3cd53483a010bf64ecb04c859de355 Mon Sep 17 00:00:00 2001 From: Alexander Rose Date: Fri, 26 Nov 2021 15:34:16 -0800 Subject: [PATCH] improve 'rounded' tube geometry - correct normals - circle offset --- src/mol-geo/geometry/mesh/builder/tube.ts | 26 +++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/mol-geo/geometry/mesh/builder/tube.ts b/src/mol-geo/geometry/mesh/builder/tube.ts index 68a318977..2edde6310 100644 --- a/src/mol-geo/geometry/mesh/builder/tube.ts +++ b/src/mol-geo/geometry/mesh/builder/tube.ts @@ -6,7 +6,7 @@ */ import { Vec3 } from '../../../../mol-math/linear-algebra'; -import { ChunkedArray } from '../../../../mol-data/util'; +import { cantorPairing, ChunkedArray } from '../../../../mol-data/util'; import { MeshBuilder } from '../mesh-builder'; const normalVector = Vec3(); @@ -37,18 +37,20 @@ const v3unitX = Vec3.unitX; const caAdd3 = ChunkedArray.add3; const CosSinCache = new Map(); -function getCosSin(radialSegments: number) { - if (!CosSinCache.has(radialSegments)) { +function getCosSin(radialSegments: number, shift: boolean) { + const offset = shift ? 1 : 0; + const hash = cantorPairing(radialSegments, offset); + if (!CosSinCache.has(hash)) { const cos: number[] = []; const sin: number[] = []; for (let j = 0; j < radialSegments; ++j) { - const t = 2 * Math.PI * j / radialSegments; + const t = (j * 2 + offset) / radialSegments * Math.PI; cos[j] = Math.cos(t); sin[j] = Math.sin(t); } - CosSinCache.set(radialSegments, { cos, sin }); + CosSinCache.set(hash, { cos, sin }); } - return CosSinCache.get(radialSegments)!; + return CosSinCache.get(hash)!; } export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike, normalVectors: ArrayLike, binormalVectors: ArrayLike, linearSegments: number, radialSegments: number, widthValues: ArrayLike, heightValues: ArrayLike, startCap: boolean, endCap: boolean, crossSection: 'elliptical' | 'rounded') { @@ -56,9 +58,9 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike= q3) ? height - width : -height + width : (j >= q1 && j < q3) ? -height + width : height - width; v3scaleAndAdd(surfacePoint, surfacePoint, u, h); - add2AndScale2(normalVector, u, v, cos[j], sin[j]); + if (j === q1 || j === q1 - 1) { + add2AndScale2(normalVector, u, v, 0, 1); + } else if (j === q3 || j === q3 - 1) { + add2AndScale2(normalVector, u, v, 0, -1); + } else { + add2AndScale2(normalVector, u, v, cos[j], sin[j]); + } } else { add3AndScale2(surfacePoint, u, v, controlPoint, height * cos[j], width * sin[j]); add2AndScale2(normalVector, u, v, width * cos[j], height * sin[j]);