Skip to content
Snippets Groups Projects
Commit d0cd6352 authored by Alexander Rose's avatar Alexander Rose
Browse files

added wedge and plane primitives, added directiong wdges to cartoon

parent a96d0378
No related branches found
No related tags found
No related merge requests found
...@@ -17,7 +17,7 @@ export type BoxProps = Partial<typeof DefaultBoxProps> ...@@ -17,7 +17,7 @@ export type BoxProps = Partial<typeof DefaultBoxProps>
const tmpVector = Vec3.zero(); const tmpVector = Vec3.zero();
export default function Box(props?: BoxProps) { export function Box(props?: BoxProps) {
const { width, height, depth } = { ...DefaultBoxProps, ...props } const { width, height, depth } = { ...DefaultBoxProps, ...props }
// buffers // buffers
......
...@@ -21,7 +21,7 @@ export const DefaultCylinderProps = { ...@@ -21,7 +21,7 @@ export const DefaultCylinderProps = {
} }
export type CylinderProps = Partial<typeof 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 }; const { radiusTop, radiusBottom, height, radialSegments, heightSegments, topCap, bottomCap, thetaStart, thetaLength } = { ...DefaultCylinderProps, ...props };
// buffers // buffers
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// adapted from three.js, MIT License Copyright 2010-2018 three.js authors // 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; const t = ( 1 + Math.sqrt( 5 ) ) / 2;
...@@ -33,6 +33,6 @@ export const DefaultIcosahedronProps = { ...@@ -33,6 +33,6 @@ export const DefaultIcosahedronProps = {
} }
export type IcosahedronProps = Partial<typeof DefaultIcosahedronProps> export type IcosahedronProps = Partial<typeof DefaultIcosahedronProps>
export default function Icosahedron(props?: IcosahedronProps) { export function Icosahedron(props?: IcosahedronProps) {
return Polyhedron(vertices, indices, { ...DefaultIcosahedronProps, ...props }) return Polyhedron(vertices, indices, { ...DefaultIcosahedronProps, ...props })
} }
\ No newline at end of file
/**
* 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
])
}
}
\ No newline at end of file
...@@ -15,7 +15,7 @@ export const DefaultPolyhedronProps = { ...@@ -15,7 +15,7 @@ export const DefaultPolyhedronProps = {
} }
export type PolyhedronProps = Partial<typeof 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 { radius, detail } = { ...DefaultPolyhedronProps, ...props }
const builder = createBuilder() const builder = createBuilder()
const { vertices, indices } = builder const { vertices, indices } = builder
......
/**
* 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 }
}
\ No newline at end of file
...@@ -24,17 +24,24 @@ import { SizeTheme } from '../../../theme'; ...@@ -24,17 +24,24 @@ import { SizeTheme } from '../../../theme';
import { createMeshValues, updateMeshValues, updateRenderableState, createRenderableState, DefaultMeshProps } from '../../util'; import { createMeshValues, updateMeshValues, updateRenderableState, createRenderableState, DefaultMeshProps } from '../../util';
import { MeshBuilder } from '../../../shape/mesh-builder'; import { MeshBuilder } from '../../../shape/mesh-builder';
import { getPolymerElementCount, PolymerTraceIterator } from './util/polymer'; 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 { 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 tmpNormal = Vec3.zero()
const tangentVec = Vec3.zero() const tangentVec = Vec3.zero()
const normalVec = Vec3.zero() const normalVec = Vec3.zero()
const binormalVec = Vec3.zero() const binormalVec = Vec3.zero()
const prevNormal = 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() const orthogonalizeTmpVec = Vec3.zero()
/** Get a vector that is similar to b but orthogonal to a */ /** Get a vector that is similar to b but orthogonal to a */
function orthogonalize(out: Vec3, a: Vec3, b: Vec3) { function orthogonalize(out: Vec3, a: Vec3, b: Vec3) {
...@@ -45,13 +52,9 @@ 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) { function interpolateNormals(controlPoints: Helpers.NumberArray, tangentVectors: Helpers.NumberArray, normalVectors: Helpers.NumberArray, binormalVectors: Helpers.NumberArray, firstNormalVector: Vec3, lastNormalVector: Vec3) {
const n = controlPoints.length / 3 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) { if (Vec3.dot(firstNormalVector, lastNormalVector) < 0) {
Vec3.scale(lastNormalVector, lastNormalVector, -1) Vec3.scale(lastNormalVector, lastNormalVector, -1)
// console.log('flipped last normal vector')
} }
Vec3.copy(prevNormal, firstNormalVector) Vec3.copy(prevNormal, firstNormalVector)
...@@ -65,13 +68,6 @@ function interpolateNormals(controlPoints: Helpers.NumberArray, tangentVectors: ...@@ -65,13 +68,6 @@ function interpolateNormals(controlPoints: Helpers.NumberArray, tangentVectors:
orthogonalize(normalVec, tangentVec, tmpNormal) orthogonalize(normalVec, tangentVec, tmpNormal)
Vec3.toArray(normalVec, normalVectors, i * 3) 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.copy(prevNormal, normalVec)
Vec3.normalize(binormalVec, Vec3.cross(binormalVec, tangentVec, normalVec)) Vec3.normalize(binormalVec, Vec3.cross(binormalVec, tangentVec, normalVec))
...@@ -107,11 +103,11 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me ...@@ -107,11 +103,11 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
const polymerTraceIt = PolymerTraceIterator(unit) const polymerTraceIt = PolymerTraceIterator(unit)
while (polymerTraceIt.hasNext) { while (polymerTraceIt.hasNext) {
const v = polymerTraceIt.move() const v = polymerTraceIt.move()
// builder.setId(elements[v.center.element])
builder.setId(v.center.element) builder.setId(v.center.element)
const isNucleic = v.moleculeType === MoleculeType.DNA || v.moleculeType === MoleculeType.RNA const isNucleic = v.moleculeType === MoleculeType.DNA || v.moleculeType === MoleculeType.RNA
const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta) 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 const tension = (isNucleic || isSheet) ? 0.5 : 0.9
for (let j = 0; j <= linearSegments; ++j) { for (let j = 0; j <= linearSegments; ++j) {
...@@ -198,7 +194,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me ...@@ -198,7 +194,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me
const arrowHeight = v.secStrucChange ? 1.7 : 0 const arrowHeight = v.secStrucChange ? 1.7 : 0
builder.addSheet(controlPoints, normalVectors, binormalVectors, linearSegments, width, height, arrowHeight, true, true) builder.addSheet(controlPoints, normalVectors, binormalVectors, linearSegments, width, height, arrowHeight, true, true)
} else { } else {
if (SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix)) { if (isHelix) {
width = 0.2; height = 1.0 width = 0.2; height = 1.0
} else if (isNucleic) { } else if (isNucleic) {
width = 1.5; height = 0.3 width = 1.5; height = 0.3
...@@ -206,6 +202,22 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, mesh?: Me ...@@ -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) 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) { if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Polymer trace mesh', current: i, max: polymerElementCount }); await ctx.update({ message: 'Polymer trace mesh', current: i, max: polymerElementCount });
} }
......
...@@ -8,9 +8,11 @@ import { ValueCell } from 'mol-util/value-cell' ...@@ -8,9 +8,11 @@ import { ValueCell } from 'mol-util/value-cell'
import { Vec3, Mat4, Mat3 } from 'mol-math/linear-algebra'; import { Vec3, Mat4, Mat3 } from 'mol-math/linear-algebra';
import { ChunkedArray } from 'mol-data/util'; import { ChunkedArray } from 'mol-data/util';
import Box, { BoxProps } from '../primitive/box'; import { Box, BoxProps } from '../primitive/box';
import Cylinder, { CylinderProps } from '../primitive/cylinder'; import { Plane, PlaneProps } from '../primitive/plane';
import Icosahedron, { IcosahedronProps } from '../primitive/icosahedron'; import { Wedge, WedgeProps } from '../primitive/wedge';
import { Cylinder, CylinderProps } from '../primitive/cylinder';
import { Icosahedron, IcosahedronProps } from '../primitive/icosahedron';
import { Mesh } from './mesh'; import { Mesh } from './mesh';
import { getNormalMatrix } from '../util'; import { getNormalMatrix } from '../util';
import { addSheet } from '../primitive/sheet'; import { addSheet } from '../primitive/sheet';
...@@ -31,6 +33,8 @@ export interface MeshBuilderState { ...@@ -31,6 +33,8 @@ export interface MeshBuilderState {
export interface MeshBuilder { export interface MeshBuilder {
add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): void add(t: Mat4, _vertices: Float32Array, _normals: Float32Array, _indices?: Uint32Array): void
addBox(t: Mat4, props?: BoxProps): 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 addCylinder(start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps): void
addDoubleCylinder(start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, 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 addFixedCountDashedCylinder(start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps): void
...@@ -128,8 +132,16 @@ export namespace MeshBuilder { ...@@ -128,8 +132,16 @@ export namespace MeshBuilder {
return { return {
add, add,
addBox: (t: Mat4, props?: BoxProps) => { addBox: (t: Mat4, props?: BoxProps) => {
const box = Box(props) const { vertices, normals, indices } = Box(props)
add(t, box.vertices, box.normals, box.indices) 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) => { addCylinder: (start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps) => {
const d = Vec3.distance(start, end) * lengthScale const d = Vec3.distance(start, end) * lengthScale
......
...@@ -81,9 +81,9 @@ export class Stage { ...@@ -81,9 +81,9 @@ export class Stage {
// this.loadPdbid('4v5a') // ribosome // this.loadPdbid('4v5a') // ribosome
// this.loadPdbid('3j3q') // ... // this.loadPdbid('3j3q') // ...
// this.loadPdbid('2np2') // dna // this.loadPdbid('2np2') // dna
this.loadPdbid('1d66') // dna // this.loadPdbid('1d66') // dna
// this.loadPdbid('9dna') // A form 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('199d') // C form dna
// this.loadPdbid('4lb6') // Z form dna // this.loadPdbid('4lb6') // Z form dna
// this.loadPdbid('1egk') // 4-way dna-rna junction // this.loadPdbid('1egk') // 4-way dna-rna junction
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment