Ver Fonte

added wedge and plane primitives, added directiong wdges to cartoon

Alexander Rose há 6 anos atrás
pai
commit
d0cd635261

+ 1 - 1
src/mol-geo/primitive/box.ts

@@ -17,7 +17,7 @@ export type BoxProps = Partial<typeof DefaultBoxProps>
 
 const tmpVector = Vec3.zero();
 
-export default function Box(props?: BoxProps) {
+export function Box(props?: BoxProps) {
     const { width, height, depth } = { ...DefaultBoxProps, ...props }
 
     // buffers

+ 1 - 1
src/mol-geo/primitive/cylinder.ts

@@ -21,7 +21,7 @@ export const DefaultCylinderProps = {
 }
 export type CylinderProps = Partial<typeof DefaultCylinderProps>
 
-export default function Cylinder(props?: CylinderProps) {
+export function Cylinder(props?: CylinderProps) {
     const { radiusTop, radiusBottom, height, radialSegments, heightSegments, topCap, bottomCap, thetaStart, thetaLength } = { ...DefaultCylinderProps, ...props };
 
     // buffers

+ 2 - 2
src/mol-geo/primitive/icosahedron.ts

@@ -6,7 +6,7 @@
 
 // adapted from three.js, MIT License Copyright 2010-2018 three.js authors
 
-import Polyhedron from './polyhedron'
+import { Polyhedron } from './polyhedron'
 
 const t = ( 1 + Math.sqrt( 5 ) ) / 2;
 
@@ -33,6 +33,6 @@ export const DefaultIcosahedronProps = {
 }
 export type IcosahedronProps = Partial<typeof DefaultIcosahedronProps>
 
-export default function Icosahedron(props?: IcosahedronProps) {
+export function Icosahedron(props?: IcosahedronProps) {
     return Polyhedron(vertices, indices, { ...DefaultIcosahedronProps, ...props })
 }

+ 34 - 0
src/mol-geo/primitive/plane.ts

@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+export const DefaultPlaneProps = {
+    width: 1,
+    height: 1
+}
+export type PlaneProps = Partial<typeof DefaultPlaneProps>
+
+export function Plane(props?: PlaneProps) {
+    const { width, height } = { ...DefaultPlaneProps, ...props }
+
+    return {
+        vertices: new Float32Array([
+            -width / 2, height / 2, 0,
+            width / 2, height / 2, 0,
+            -width / 2, -height / 2, 0,
+            width / 2, -height / 2, 0
+        ]),
+        normals: new Float32Array([
+            0, 0, 1,
+            0, 0, 1,
+            0, 0, 1,
+            0, 0, 1
+        ]),
+        indices: new Uint32Array([
+            0, 2, 1,
+            1, 2, 3
+        ])
+    }
+}

+ 1 - 1
src/mol-geo/primitive/polyhedron.ts

@@ -15,7 +15,7 @@ export const DefaultPolyhedronProps = {
 }
 export type PolyhedronProps = Partial<typeof DefaultPolyhedronProps>
 
-export default function Polyhedron(_vertices: Helpers.NumberArray, _indices: Helpers.NumberArray, props?: PolyhedronProps) {
+export function Polyhedron(_vertices: Helpers.NumberArray, _indices: Helpers.NumberArray, props?: PolyhedronProps) {
     const { radius, detail } = { ...DefaultPolyhedronProps, ...props }
     const builder = createBuilder()
     const { vertices, indices } = builder

+ 121 - 0
src/mol-geo/primitive/wedge.ts

@@ -0,0 +1,121 @@
+/**
+ * Copyright (c) 2018 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'
+
+export const DefaultWedgeProps = {
+    width: 1,
+    height: 1,
+    depth: 1
+}
+export type WedgeProps = Partial<typeof DefaultWedgeProps>
+
+const _a = Vec3.create(0, 0.5, 0.5)
+const _b = Vec3.create(0.5, -0.5, 0.5)
+const _c = Vec3.create(-0.5, -0.5, 0.5)
+const _d = Vec3.create(0, 0.5, -0.5)
+const _e = Vec3.create(0.5, -0.5, -0.5)
+const _f = Vec3.create(-0.5, -0.5, -0.5)
+
+const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero()
+const d = Vec3.zero(), e = Vec3.zero(), f = Vec3.zero()
+
+const nabc = Vec3.create(0, 0, 1)
+const ndef = Vec3.create(0, 0, -1)
+const nabde = Vec3.zero()
+const nbcef = Vec3.create(0, -1, 0)
+const nacdf = Vec3.zero()
+
+const s = Vec3.zero()
+
+export function Wedge(props?: WedgeProps) {
+    const { width, height, depth } = { ...DefaultWedgeProps, ...props }
+
+    const vertices = new Float32Array(54)
+    const normals = new Float32Array(54)
+    const indices = new Uint32Array(24)
+
+    Vec3.set(s, width, height, depth)
+    Vec3.mul(a, _a, s); Vec3.mul(b, _b, s); Vec3.mul(c, _c, s)
+    Vec3.mul(d, _d, s); Vec3.mul(e, _e, s); Vec3.mul(f, _f, s)
+
+    Vec3.sub(nabde, b, a)
+    Vec3.normalize(nabde, Vec3.set(nabde, -nabde[1], nabde[0], 0))
+    Vec3.sub(nacdf, c, a)
+    Vec3.normalize(nacdf, Vec3.set(nacdf, nacdf[1], -nacdf[0], 0))
+
+    let vc = 0
+    let ic = 0
+
+    // abc
+    Vec3.toArray(a, vertices, vc + 0)
+    Vec3.toArray(c, vertices, vc + 3)
+    Vec3.toArray(b, vertices, vc + 6)
+    for (let i = 0; i < 3; ++i) Vec3.toArray(nabc, normals, vc + i * 3)
+    indices[ic + 0] = vc / 3 + 0
+    indices[ic + 1] = vc / 3 + 1
+    indices[ic + 2] = vc / 3 + 2
+    vc += 9
+    ic += 3
+
+    // def
+    Vec3.toArray(d, vertices, vc + 0)
+    Vec3.toArray(e, vertices, vc + 3)
+    Vec3.toArray(f, vertices, vc + 6)
+    for (let i = 0; i < 3; ++i) Vec3.toArray(ndef, normals, vc + i * 3)
+    indices[ic + 0] = vc / 3 + 0
+    indices[ic + 1] = vc / 3 + 1
+    indices[ic + 2] = vc / 3 + 2
+    vc += 9
+    ic += 3
+
+    // abde
+    Vec3.toArray(a, vertices, vc + 0)
+    Vec3.toArray(d, vertices, vc + 3)
+    Vec3.toArray(e, vertices, vc + 6)
+    Vec3.toArray(b, vertices, vc + 9)
+    for (let i = 0; i < 4; ++i) Vec3.toArray(nabde, normals, vc + i * 3)
+    indices[ic + 0] = vc / 3 + 2
+    indices[ic + 1] = vc / 3 + 1
+    indices[ic + 2] = vc / 3 + 0
+    indices[ic + 3] = vc / 3 + 0
+    indices[ic + 4] = vc / 3 + 3
+    indices[ic + 5] = vc / 3 + 2
+    vc += 12
+    ic += 6
+
+    // acdf
+    Vec3.toArray(d, vertices, vc + 0)
+    Vec3.toArray(a, vertices, vc + 3)
+    Vec3.toArray(c, vertices, vc + 6)
+    Vec3.toArray(f, vertices, vc + 9)
+    for (let i = 0; i < 4; ++i) Vec3.toArray(nacdf, normals, vc + i * 3)
+    indices[ic + 0] = vc / 3 + 2
+    indices[ic + 1] = vc / 3 + 1
+    indices[ic + 2] = vc / 3 + 0
+    indices[ic + 3] = vc / 3 + 0
+    indices[ic + 4] = vc / 3 + 3
+    indices[ic + 5] = vc / 3 + 2
+    vc += 12
+    ic += 6
+
+    // bcef
+    Vec3.toArray(e, vertices, vc + 0)
+    Vec3.toArray(f, vertices, vc + 3)
+    Vec3.toArray(c, vertices, vc + 6)
+    Vec3.toArray(b, vertices, vc + 9)
+    for (let i = 0; i < 4; ++i) Vec3.toArray(nbcef, normals, vc + i * 3)
+    indices[ic + 0] = vc / 3 + 2
+    indices[ic + 1] = vc / 3 + 1
+    indices[ic + 2] = vc / 3 + 0
+    indices[ic + 3] = vc / 3 + 0
+    indices[ic + 4] = vc / 3 + 3
+    indices[ic + 5] = vc / 3 + 2
+    vc += 12
+    ic += 6
+
+    return { vertices, normals, indices }
+}

+ 28 - 16
src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts

@@ -24,17 +24,24 @@ import { SizeTheme } from '../../../theme';
 import { createMeshValues, updateMeshValues, updateRenderableState, createRenderableState, DefaultMeshProps } from '../../util';
 import { MeshBuilder } from '../../../shape/mesh-builder';
 import { getPolymerElementCount, PolymerTraceIterator } from './util/polymer';
-import { Vec3 } from 'mol-math/linear-algebra';
+import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { SecondaryStructureType, MoleculeType } from 'mol-model/structure/model/types';
-// import { radToDeg } from 'mol-math/misc';
+import { degToRad } from 'mol-math/misc';
+
+// TODO handle polymer ends properly
+// TODO avoid allocating Vec3, use global temp vars
 
 const tmpNormal = Vec3.zero()
 const tangentVec = Vec3.zero()
 const normalVec = Vec3.zero()
 const binormalVec = Vec3.zero()
-
 const prevNormal = Vec3.zero()
 
+const t = Mat4.identity()
+const rotX90 = Mat4.fromRotation(Mat4.identity(), degToRad(90), Vec3.create(1, 0, 0))
+const rotY90 = Mat4.fromRotation(Mat4.identity(), degToRad(90), Vec3.create(0, 1, 0))
+const rotXY90 = Mat4.mul(Mat4.identity(), rotX90, rotY90)
+
 const orthogonalizeTmpVec = Vec3.zero()
 /** Get a vector that is similar to b but orthogonal to a */
 function orthogonalize(out: Vec3, a: Vec3, b: Vec3) {
@@ -45,13 +52,9 @@ function orthogonalize(out: Vec3, a: Vec3, b: Vec3) {
 
 function interpolateNormals(controlPoints: Helpers.NumberArray, tangentVectors: Helpers.NumberArray, normalVectors: Helpers.NumberArray, binormalVectors: Helpers.NumberArray, firstNormalVector: Vec3, lastNormalVector: Vec3) {
     const n = controlPoints.length / 3
-    // const n1 = n - 1
 
-    // const angle = radToDeg(Math.acos(Vec3.dot(firstNormalVector, lastNormalVector)))
-    // console.log('angle', angle)
     if (Vec3.dot(firstNormalVector, lastNormalVector) < 0) {
         Vec3.scale(lastNormalVector, lastNormalVector, -1)
-        // console.log('flipped last normal vector')
     }
 
     Vec3.copy(prevNormal, firstNormalVector)
@@ -65,13 +68,6 @@ function interpolateNormals(controlPoints: Helpers.NumberArray, tangentVectors:
         orthogonalize(normalVec, tangentVec, tmpNormal)
         Vec3.toArray(normalVec, normalVectors, i * 3)
 
-        // const deltaAngle = radToDeg(Math.acos(Vec3.dot(prevNormal, normalVec)))
-        // if (deltaAngle > (angle / n1) * 5 && deltaAngle > 20) {
-        //     console.warn(i, 'large delta angle', deltaAngle)
-        // }
-        // if (Vec3.dot(normalVec, prevNormal) < 0) {
-        //     console.warn(i, 'flip compared to prev', radToDeg(Math.acos(Vec3.dot(prevNormal, normalVec))))
-        // }
         Vec3.copy(prevNormal, normalVec)
 
         Vec3.normalize(binormalVec, Vec3.cross(binormalVec, tangentVec, normalVec))
@@ -107,11 +103,11 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
     const polymerTraceIt = PolymerTraceIterator(unit)
     while (polymerTraceIt.hasNext) {
         const v = polymerTraceIt.move()
-        // builder.setId(elements[v.center.element])
         builder.setId(v.center.element)
 
         const isNucleic = v.moleculeType === MoleculeType.DNA || v.moleculeType === MoleculeType.RNA
         const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta)
+        const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix)
         const tension = (isNucleic || isSheet) ? 0.5 : 0.9
 
         for (let j = 0; j <= linearSegments; ++j) {
@@ -198,7 +194,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
             const arrowHeight = v.secStrucChange ? 1.7 : 0
             builder.addSheet(controlPoints, normalVectors, binormalVectors, linearSegments, width, height, arrowHeight, true, true)
         } else {
-            if (SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix)) {
+            if (isHelix) {
                 width = 0.2; height = 1.0
             } else if (isNucleic) {
                 width = 1.5; height = 0.3
@@ -206,6 +202,22 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
             builder.addTube(controlPoints, normalVectors, binormalVectors, linearSegments, radialSegments, width, height, 1, true, true)
         }
 
+        if ((isSheet && !v.secStrucChange) || !isSheet) {
+            const upVec = Vec3.zero()
+            let width = 0.5, height = 1.2, depth = 0.6
+            if (isNucleic) {
+                Vec3.fromArray(upVec, binormalVectors, Math.round(linearSegments / 2) * 3)
+                depth = 0.9
+            } else {
+                Vec3.fromArray(upVec, normalVectors, Math.round(linearSegments / 2) * 3)
+            }
+
+            Mat4.targetTo(t, v.t3, v.t1, upVec)
+            Mat4.mul(t, t, rotXY90)
+            Mat4.setTranslation(t, v.t2)
+            builder.addWedge(t, { width, height, depth })
+        }
+
         if (i % 10000 === 0 && ctx.shouldUpdate) {
             await ctx.update({ message: 'Polymer trace mesh', current: i, max: polymerElementCount });
         }

+ 17 - 5
src/mol-geo/shape/mesh-builder.ts

@@ -8,9 +8,11 @@ import { ValueCell } from 'mol-util/value-cell'
 import { Vec3, Mat4, Mat3 } from 'mol-math/linear-algebra';
 import { ChunkedArray } from 'mol-data/util';
 
-import Box, { BoxProps } from '../primitive/box';
-import Cylinder, { CylinderProps } from '../primitive/cylinder';
-import Icosahedron, { IcosahedronProps } from '../primitive/icosahedron';
+import { Box, BoxProps } from '../primitive/box';
+import { Plane, PlaneProps } from '../primitive/plane';
+import { Wedge, WedgeProps } from '../primitive/wedge';
+import { Cylinder, CylinderProps } from '../primitive/cylinder';
+import { Icosahedron, IcosahedronProps } from '../primitive/icosahedron';
 import { Mesh } from './mesh';
 import { getNormalMatrix } from '../util';
 import { addSheet } from '../primitive/sheet';
@@ -31,6 +33,8 @@ export interface MeshBuilderState {
 export interface MeshBuilder {
     add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): void
     addBox(t: Mat4, props?: BoxProps): void
+    addPlane(t: Mat4, props?: PlaneProps): void
+    addWedge(t: Mat4, props?: WedgeProps): void
     addCylinder(start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps): void
     addDoubleCylinder(start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps): void
     addFixedCountDashedCylinder(start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps): void
@@ -128,8 +132,16 @@ export namespace MeshBuilder {
         return {
             add,
             addBox: (t: Mat4, props?: BoxProps) => {
-                const box = Box(props)
-                add(t, box.vertices, box.normals, box.indices)
+                const { vertices, normals, indices } = Box(props)
+                add(t, vertices, normals, indices)
+            },
+            addPlane: (t: Mat4, props?: PlaneProps) => {
+                const { vertices, normals, indices } = Plane(props)
+                add(t, vertices, normals, indices)
+            },
+            addWedge: (t: Mat4, props?: WedgeProps) => {
+                const { vertices, normals, indices } = Wedge(props)
+                add(t, vertices, normals, indices)
             },
             addCylinder: (start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps) => {
                 const d = Vec3.distance(start, end) * lengthScale

+ 2 - 2
src/mol-view/stage.ts

@@ -81,9 +81,9 @@ export class Stage {
         // this.loadPdbid('4v5a') // ribosome
         // this.loadPdbid('3j3q') // ...
         // this.loadPdbid('2np2') // dna
-        this.loadPdbid('1d66') // dna
+        // this.loadPdbid('1d66') // dna
         // this.loadPdbid('9dna') // A form dna
-        // this.loadPdbid('1bna') // B form dna
+        this.loadPdbid('1bna') // B form dna
         // this.loadPdbid('199d') // C form dna
         // this.loadPdbid('4lb6') // Z form dna
         // this.loadPdbid('1egk') // 4-way dna-rna junction