diff --git a/src/mol-geo/geometry/mesh/builder/sheet.ts b/src/mol-geo/geometry/mesh/builder/sheet.ts index c0d7a473318356bcf891dcb8088d45411065e91a..001e45a233a2866e2d4a2a6184b92ee7118019b6 100644 --- a/src/mol-geo/geometry/mesh/builder/sheet.ts +++ b/src/mol-geo/geometry/mesh/builder/sheet.ts @@ -15,6 +15,8 @@ const tV = Vec3.zero() const horizontalVector = Vec3.zero() const verticalVector = Vec3.zero() +const verticalRightVector = Vec3.zero() +const verticalLeftVector = Vec3.zero() const normalOffset = Vec3.zero() const positionVector = Vec3.zero() const normalVector = Vec3.zero() @@ -25,6 +27,41 @@ const p2 = Vec3.zero() const p3 = Vec3.zero() const p4 = Vec3.zero() +function addCap(offset: number, builder: MeshBuilder, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, width: number, leftHeight: number, rightHeight: number) { + const { vertices, normals, indices } = builder.state + const vertexCount = vertices.elementCount + + Vec3.fromArray(verticalLeftVector, normalVectors, offset) + Vec3.scale(verticalLeftVector, verticalLeftVector, leftHeight) + + Vec3.fromArray(verticalRightVector, normalVectors, offset) + Vec3.scale(verticalRightVector, verticalRightVector, rightHeight) + + Vec3.fromArray(horizontalVector, binormalVectors, offset) + Vec3.scale(horizontalVector, horizontalVector, width) + + Vec3.fromArray(positionVector, controlPoints, offset) + + Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalRightVector) + Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalLeftVector) + Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalLeftVector) + Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalRightVector) + + ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]) + ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]) + ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]) + ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]) + + Vec3.cross(normalVector, horizontalVector, verticalLeftVector) + + for (let i = 0; i < 4; ++i) { + ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]) + } + ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount) + ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2) +} + +/** set arrowHeight = 0 for no arrow */ export function addSheet(builder: MeshBuilder, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean) { const { currentGroup, vertices, normals, indices, groups } = builder.state @@ -112,67 +149,19 @@ export function addSheet(builder: MeshBuilder, controlPoints: ArrayLike<number>, } if (startCap) { - const offset = 0 - vertexCount = vertices.elementCount - - Vec3.fromArray(verticalVector, normalVectors, offset) - Vec3.scale(verticalVector, verticalVector, arrowHeight === 0 ? height : arrowHeight); - - Vec3.fromArray(horizontalVector, binormalVectors, offset) - Vec3.scale(horizontalVector, horizontalVector, width); - - Vec3.fromArray(positionVector, controlPoints, offset) - - Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalVector) - Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalVector) - Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalVector) - Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalVector) - - ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]) - ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]) - ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]) - ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]) - - Vec3.cross(normalVector, horizontalVector, verticalVector) - - for (let i = 0; i < 4; ++i) { - ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]) - } - ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount); - ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2); + const h = arrowHeight === 0 ? height : arrowHeight + addCap(0, builder, controlPoints, normalVectors, binormalVectors, width, h, h) + } else if (arrowHeight > 0) { + addCap(0, builder, controlPoints, normalVectors, binormalVectors, width, -arrowHeight, height) + addCap(0, builder, controlPoints, normalVectors, binormalVectors, width, arrowHeight, -height) } if (endCap && arrowHeight === 0) { - const offset = linearSegments * 3 - vertexCount = vertices.elementCount - - Vec3.fromArray(verticalVector, normalVectors, offset) - Vec3.scale(verticalVector, verticalVector, height); - - Vec3.fromArray(horizontalVector, binormalVectors, offset) - Vec3.scale(horizontalVector, horizontalVector, width); - - Vec3.fromArray(positionVector, controlPoints, offset) - - Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalVector) - Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalVector) - Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalVector) - Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalVector) - - ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]) - ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]) - ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]) - ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]) - - Vec3.cross(normalVector, horizontalVector, verticalVector) - - for (let i = 0; i < 4; ++i) { - ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]) - } - ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount); - ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2); + addCap(linearSegments * 3, builder, controlPoints, normalVectors, binormalVectors, width, height, height) } - const addedVertexCount = (linearSegments + 1) * 8 + (startCap ? 4 : 0) + (endCap && arrowHeight === 0 ? 4 : 0) + const addedVertexCount = (linearSegments + 1) * 8 + + (startCap ? 4 : (arrowHeight > 0 ? 8 : 0)) + + (endCap && arrowHeight === 0 ? 4 : 0) for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup) } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/polymer-direction-wedge.ts b/src/mol-repr/structure/visual/polymer-direction-wedge.ts index 786ba2992b77deaf50e6ac687e74c8b93096a9c8..3c9dc41c38ed8bc2cbdd94b286962cf4a3e32b5e 100644 --- a/src/mol-repr/structure/visual/polymer-direction-wedge.ts +++ b/src/mol-repr/structure/visual/polymer-direction-wedge.ts @@ -62,7 +62,7 @@ async function createPolymerDirectionWedgeMesh(ctx: VisualContext, unit: Unit, s interpolateCurveSegment(state, v, tension, shift) - if ((isSheet && !v.secStrucChange) || !isSheet) { + if ((isSheet && !v.secStrucLast) || !isSheet) { const size = theme.size.size(v.center) * sizeFactor const depth = depthFactor * size const width = widthFactor * size diff --git a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts index 22438a0b1d2fec459a695d46d3ccf35303e75cd5..4b3e38c4558eb15a02e4a5adea2d173619e913db 100644 --- a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts +++ b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts @@ -119,8 +119,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> } private setControlPoint(out: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, residueIndex: ResidueIndex) { - const ss = this.unit.model.properties.secondaryStructure.type[residueIndex] - if (SecondaryStructureType.is(ss, SecondaryStructureType.Flag.Beta)) { + if (SecondaryStructureType.is(this.currSecStrucType, SecondaryStructureType.Flag.Beta)) { Vec3.scale(out, Vec3.add(out, p1, Vec3.add(out, p3, Vec3.add(out, p2, p2))), 1/4) } else { Vec3.copy(out, p2) @@ -137,6 +136,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> this.updateResidueSegmentRange(this.polymerSegment) if (residueIt.hasNext) { this.state = AtomicPolymerTraceIteratorState.nextResidue + this.currSecStrucType = SecStrucTypeNA + this.nextSecStrucType = this.secondaryStructureType[this.residueSegmentMin] break } } @@ -144,7 +145,17 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> if (this.state === AtomicPolymerTraceIteratorState.nextResidue) { const { index: residueIndex } = residueIt.move(); + this.prevSecStrucType = this.currSecStrucType + this.currSecStrucType = this.nextSecStrucType + this.nextSecStrucType = residueIt.hasNext ? this.secondaryStructureType[residueIndex + 1] : SecStrucTypeNA + + value.secStrucType = this.currSecStrucType value.center.element = this.getElementIndex(residueIndex, 'trace') + value.first = residueIndex === this.residueSegmentMin + value.last = residueIndex === this.residueSegmentMax + value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType + value.secStrucLast = this.currSecStrucType !== this.nextSecStrucType + value.moleculeType = getAtomicMoleculeType(this.unit.model, residueIndex) this.pos(this.p0, this.getElementIndex(residueIndex - 3 as ResidueIndex, 'trace')) this.pos(this.p1, this.getElementIndex(residueIndex - 2 as ResidueIndex, 'trace')) @@ -159,12 +170,6 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> this.pos(this.v23, this.getElementIndex(residueIndex, 'direction')) // this.pos(this.v34, this.getAtomIndex(residueIndex + 1 as ResidueIndex, 'direction')) - this.prevSecStrucType = this.currSecStrucType - this.currSecStrucType = this.nextSecStrucType - this.nextSecStrucType = residueIt.hasNext ? this.secondaryStructureType[residueIndex + 1] : SecStrucTypeNA - - this.value.secStrucType = this.currSecStrucType - this.setControlPoint(value.p0, this.p0, this.p1, this.p2, residueIndex - 2 as ResidueIndex) this.setControlPoint(value.p1, this.p1, this.p2, this.p3, residueIndex - 1 as ResidueIndex) this.setControlPoint(value.p2, this.p2, this.p3, this.p4, residueIndex) @@ -174,12 +179,6 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> Vec3.copy(value.d12, this.v12) Vec3.copy(value.d23, this.v23) - value.first = residueIndex === this.residueSegmentMin - value.last = residueIndex === this.residueSegmentMax - value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType - value.secStrucLast = this.currSecStrucType !== this.nextSecStrucType - value.moleculeType = getAtomicMoleculeType(this.unit.model, residueIndex) - if (!residueIt.hasNext) { this.state = AtomicPolymerTraceIteratorState.nextPolymer }