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

refactored mesh-builder

parent e7943bcb
No related branches found
No related tags found
No related merge requests found
Showing
with 218 additions and 223 deletions
......@@ -22,6 +22,8 @@ import { ShapeRepresentation } from 'mol-geo/representation/shape';
import { Vec3, Mat4 } from 'mol-math/linear-algebra';
import { Shape } from 'mol-model/shape';
import { Color } from 'mol-util/color';
import { addSphere } from 'mol-geo/mesh/builder/sphere';
import { Box } from 'mol-geo/primitive/box';
const container = document.getElementById('container')
if (!container) throw new Error('Can not find element with id "container".')
......@@ -121,7 +123,7 @@ async function init() {
meshBuilder.setGroup(0)
colors[0] = Color(0xFF2233)
labels[0] = 'red sphere'
meshBuilder.addSphere(Vec3.create(0, 0, 0), 4, 2)
addSphere(meshBuilder, Vec3.create(0, 0, 0), 4, 2)
// green cube
meshBuilder.setGroup(1)
colors[1] = Color(0x2233FF)
......@@ -129,7 +131,7 @@ async function init() {
const t = Mat4.identity()
Mat4.fromTranslation(t, Vec3.create(10, 0, 0))
Mat4.scale(t, t, Vec3.create(3, 3, 3))
meshBuilder.addBox(t)
meshBuilder.add(t, Box())
const mesh = meshBuilder.getMesh()
// const mesh = getObjFromUrl('mesh.obj')
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Vec3, Mat4 } from 'mol-math/linear-algebra';
import { MeshBuilder } from '../mesh-builder';
import { Primitive } from '../../primitive/primitive';
import { Cylinder, CylinderProps } from '../../primitive/cylinder';
const cylinderMap = new Map<string, Primitive>()
const up = Vec3.create(0, 1, 0)
const tmpCylinderDir = Vec3.zero()
const tmpCylinderMatDir = Vec3.zero()
const tmpCylinderCenter = Vec3.zero()
const tmpCylinderMat = Mat4.zero()
const tmpCylinderStart = Vec3.zero()
const tmpUp = Vec3.zero()
function setCylinderMat(m: Mat4, start: Vec3, dir: Vec3, length: number) {
Vec3.setMagnitude(tmpCylinderMatDir, dir, length / 2)
Vec3.add(tmpCylinderCenter, start, tmpCylinderMatDir)
// ensure the direction used to create the rotation is always pointing in the same
// direction so the triangles of adjacent cylinder will line up
Vec3.copy(tmpUp, up)
if (Vec3.dot(tmpCylinderMatDir, tmpUp) < 0) Vec3.scale(tmpUp, tmpUp, -1)
Vec3.makeRotation(m, tmpUp, tmpCylinderMatDir)
return Mat4.setTranslation(m, tmpCylinderCenter)
}
function getCylinder(props: CylinderProps) {
const key = JSON.stringify(props)
let cylinder = cylinderMap.get(key)
if (cylinder === undefined) {
cylinder = Cylinder(props)
cylinderMap.set(key, cylinder)
}
return cylinder
}
export function addCylinder(builder: MeshBuilder, start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps) {
const d = Vec3.distance(start, end) * lengthScale
props.height = d
Vec3.sub(tmpCylinderDir, end, start)
setCylinderMat(tmpCylinderMat, start, tmpCylinderDir, d)
builder.add(tmpCylinderMat, getCylinder(props))
}
export function addDoubleCylinder(builder: MeshBuilder, start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps) {
const d = Vec3.distance(start, end) * lengthScale
props.height = d
const cylinder = getCylinder(props)
Vec3.sub(tmpCylinderDir, end, start)
// positivly shifted cylinder
Vec3.add(tmpCylinderStart, start, shift)
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d)
builder.add(tmpCylinderMat, cylinder)
// negativly shifted cylinder
Vec3.sub(tmpCylinderStart, start, shift)
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d)
builder.add(tmpCylinderMat, cylinder)
}
export function addFixedCountDashedCylinder(builder: MeshBuilder, start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps) {
const s = Math.floor(segmentCount / 2)
const step = 1 / segmentCount
// automatically adjust length so links/bonds that are rendered as two half cylinders
// have evenly spaced dashed cylinders
if (lengthScale < 1) {
const bias = lengthScale / 2 / segmentCount
lengthScale += segmentCount % 2 === 1 ? bias : -bias
}
const d = Vec3.distance(start, end) * lengthScale
props.height = d * step
const cylinder = getCylinder(props)
Vec3.sub(tmpCylinderDir, end, start)
for (let j = 0; j < s; ++j) {
const f = step * (j * 2 + 1)
Vec3.setMagnitude(tmpCylinderDir, tmpCylinderDir, d * f)
Vec3.add(tmpCylinderStart, start, tmpCylinderDir)
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d * step)
builder.add(tmpCylinderMat, cylinder)
}
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
import { Vec3 } from 'mol-math/linear-algebra';
import { ChunkedArray } from 'mol-data/util';
import { MeshBuilderState } from './mesh-builder';
import { MeshBuilder } from '../mesh-builder';
const tA = Vec3.zero()
const tB = Vec3.zero()
......@@ -25,8 +25,8 @@ const p2 = Vec3.zero()
const p3 = Vec3.zero()
const p4 = Vec3.zero()
export function addSheet(controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
const { vertices, normals, indices } = state
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
let vertexCount = vertices.elementCount
let offsetLength = 0
......@@ -173,5 +173,6 @@ export function addSheet(controlPoints: ArrayLike<number>, normalVectors: ArrayL
ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2);
}
return (linearSegments + 1) * 8 + (startCap ? 4 : 0) + (endCap && arrowHeight === 0 ? 4 : 0)
const addedVertexCount = (linearSegments + 1) * 8 + (startCap ? 4 : 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
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Vec3, Mat4 } from 'mol-math/linear-algebra';
import { MeshBuilder } from '../mesh-builder';
import { Primitive } from '../../primitive/primitive';
import { Sphere } from '../../primitive/sphere';
const sphereMap = new Map<number, Primitive>()
const tmpSphereMat = Mat4.identity()
function setSphereMat(m: Mat4, center: Vec3, radius: number) {
return Mat4.scaleUniformly(m, Mat4.fromTranslation(m, center), radius)
}
function getSphere(detail: number) {
let sphere = sphereMap.get(detail)
if (sphere === undefined) {
sphere = Sphere(detail)
sphereMap.set(detail, sphere)
}
return sphere
}
export function addSphere(builder: MeshBuilder, center: Vec3, radius: number, detail: number) {
builder.add(setSphereMat(tmpSphereMat, center, radius), getSphere(detail))
}
\ No newline at end of file
......@@ -7,7 +7,7 @@
import { Vec3 } from 'mol-math/linear-algebra';
import { ChunkedArray } from 'mol-data/util';
import { MeshBuilderState } from '../mesh/mesh-builder';
import { MeshBuilder } from '../mesh-builder';
const normalVector = Vec3.zero()
const binormalVector = Vec3.zero()
......@@ -18,8 +18,8 @@ const b = Vec3.zero()
const u = Vec3.zero()
const v = Vec3.zero()
export function addTube(controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean, state: MeshBuilderState) {
const { vertices, normals, indices } = state
export function addTube(builder: MeshBuilder, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean) {
const { currentGroup, vertices, normals, indices, groups } = builder.state
let vertexCount = vertices.elementCount
const di = 1 / linearSegments
......@@ -127,7 +127,7 @@ export function addTube(controlPoints: ArrayLike<number>, normalVectors: ArrayLi
vertexCount = vertices.elementCount
for (let i = 0; i < radialSegments; ++i) {
const t = 2 * Math.PI * i / radialSegments;
const t = 2 * Math.PI * i / radialSegments
Vec3.copy(a, u)
Vec3.copy(b, v)
......@@ -150,5 +150,6 @@ export function addTube(controlPoints: ArrayLike<number>, normalVectors: ArrayLi
}
}
return (linearSegments + 1) * radialSegments + (startCap ? radialSegments + 1 : 0) + (endCap ? radialSegments + 1 : 0)
const addedVertexCount = (linearSegments + 1) * radialSegments + (startCap ? radialSegments + 1 : 0) + (endCap ? radialSegments + 1 : 0)
for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup)
}
\ No newline at end of file
......@@ -7,119 +7,39 @@
import { ValueCell } from 'mol-util/value-cell'
import { Vec3, Mat4, Mat3 } from 'mol-math/linear-algebra';
import { ChunkedArray } from 'mol-data/util';
import { Plane } from '../primitive/plane';
import { Cylinder, CylinderProps } from '../primitive/cylinder';
import { Sphere } from '../primitive/sphere';
import { Mesh } from './mesh';
import { getNormalMatrix } from '../util';
import { addSheet } from './sheet';
import { addTube } from './tube';
import { StarProps, Star } from '../primitive/star';
import { Octahedron, PerforatedOctahedron } from '../primitive/octahedron';
import { Primitive } from '../primitive/primitive';
import { DiamondPrism, PentagonalPrism, HexagonalPrism } from '../primitive/prism';
import { OctagonalPyramide, PerforatedOctagonalPyramid } from '../primitive/pyramid';
import { PerforatedBox, Box } from '../primitive/box';
import { Wedge } from '../primitive/wedge';
export interface MeshBuilderState {
vertices: ChunkedArray<number, 3>
normals: ChunkedArray<number, 3>
indices: ChunkedArray<number, 3>
readonly currentGroup: number
readonly vertices: ChunkedArray<number, 3>
readonly normals: ChunkedArray<number, 3>
readonly indices: ChunkedArray<number, 3>
readonly groups: ChunkedArray<number, 1>
}
export interface MeshBuilder {
add(t: Mat4, _vertices: ArrayLike<number>, _normals: ArrayLike<number>, _indices?: ArrayLike<number>): void
addPrimitive(t: Mat4, primitive: Primitive): void,
addBox(t: Mat4): void
addPerforatedBox(t: Mat4): void
addPlane(t: Mat4): void
addWedge(t: Mat4): void
addDiamondPrism(t: Mat4): void
addPentagonalPrism(t: Mat4): void
addHexagonalPrism(t: Mat4): void
addOctagonalPyramid(t: Mat4): void
addPerforatedOctagonalPyramid(t: Mat4): void
addStar(t: Mat4, props?: StarProps): void
addOctahedron(t: Mat4): void
addPerforatedOctahedron(t: Mat4): 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
addSphere(center: Vec3, radius: number, detail: number): void
addTube(centers: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean): void
addSheet(centers: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean): void
state: MeshBuilderState
add(t: Mat4, primitive: Primitive): void
setGroup(id: number): void
getMesh(): Mesh
}
const cylinderMap = new Map<string, Primitive>()
const sphereMap = new Map<number, Primitive>()
const up = Vec3.create(0, 1, 0)
const tmpV = Vec3.zero()
const tmpMat3 = Mat3.zero()
const tmpCylinderDir = Vec3.zero()
const tmpCylinderMatDir = Vec3.zero()
const tmpCylinderCenter = Vec3.zero()
const tmpCylinderMat = Mat4.zero()
const tmpCylinderStart = Vec3.zero()
const tmpUp = Vec3.zero()
function setCylinderMat(m: Mat4, start: Vec3, dir: Vec3, length: number) {
Vec3.setMagnitude(tmpCylinderMatDir, dir, length / 2)
Vec3.add(tmpCylinderCenter, start, tmpCylinderMatDir)
// ensure the direction used to create the rotation is always pointing in the same
// direction so the triangles of adjacent cylinder will line up
Vec3.copy(tmpUp, up)
if (Vec3.dot(tmpCylinderMatDir, tmpUp) < 0) Vec3.scale(tmpUp, tmpUp, -1)
Vec3.makeRotation(m, tmpUp, tmpCylinderMatDir)
return Mat4.setTranslation(m, tmpCylinderCenter)
}
function getCylinder(props: CylinderProps) {
const key = JSON.stringify(props)
let cylinder = cylinderMap.get(key)
if (cylinder === undefined) {
cylinder = Cylinder(props)
cylinderMap.set(key, cylinder)
}
return cylinder
}
const tmpSphereMat = Mat4.identity()
function setSphereMat(m: Mat4, center: Vec3, radius: number) {
return Mat4.scaleUniformly(m, Mat4.fromTranslation(m, center), radius)
}
function getSphere(detail: number) {
let sphere = sphereMap.get(detail)
if (sphere === undefined) {
sphere = Sphere(detail)
sphereMap.set(detail, sphere)
}
return sphere
}
export namespace MeshBuilder {
export function create(initialCount = 2048, chunkSize = 1024, mesh?: Mesh): MeshBuilder {
const vertices = ChunkedArray.create(Float32Array, 3, chunkSize, mesh ? mesh.vertexBuffer.ref.value : initialCount);
const normals = ChunkedArray.create(Float32Array, 3, chunkSize, mesh ? mesh.normalBuffer.ref.value : initialCount);
const indices = ChunkedArray.create(Uint32Array, 3, chunkSize * 3, mesh ? mesh.indexBuffer.ref.value : initialCount * 3);
const state: MeshBuilderState = { vertices, normals, indices };
const groups = ChunkedArray.create(Float32Array, 1, chunkSize, mesh ? mesh.groupBuffer.ref.value : initialCount);
let currentGroup = -1
function add(t: Mat4, va: ArrayLike<number>, na: ArrayLike<number>, ia: ArrayLike<number>) {
function add(t: Mat4, primitive: Primitive) {
const { vertices: va, normals: na, indices: ia } = primitive
const offset = vertices.elementCount
const n = getNormalMatrix(tmpMat3, t)
for (let i = 0, il = va.length; i < il; i += 3) {
......@@ -137,89 +57,10 @@ export namespace MeshBuilder {
}
}
function addPrimitive(t: Mat4, primitive: Primitive) {
const { vertices, normals, indices } = primitive
add(t, vertices, normals, indices)
}
return {
state: { get currentGroup() { return currentGroup }, vertices, normals, indices, groups },
add,
addPrimitive,
addBox: (t: Mat4) => addPrimitive(t, Box()),
addPerforatedBox: (t: Mat4) => addPrimitive(t, PerforatedBox()),
addPlane: (t: Mat4) => addPrimitive(t, Plane()),
addWedge: (t: Mat4) => addPrimitive(t, Wedge()),
addDiamondPrism: (t: Mat4) => addPrimitive(t, DiamondPrism()),
addPentagonalPrism: (t: Mat4) => addPrimitive(t, PentagonalPrism()),
addHexagonalPrism: (t: Mat4) => addPrimitive(t, HexagonalPrism()),
addOctagonalPyramid: (t: Mat4) => addPrimitive(t, OctagonalPyramide()),
addPerforatedOctagonalPyramid: (t: Mat4) => addPrimitive(t, PerforatedOctagonalPyramid()),
addStar: (t: Mat4, props?: StarProps) => addPrimitive(t, Star(props)),
addOctahedron: (t: Mat4) => addPrimitive(t, Octahedron()),
addPerforatedOctahedron: (t: Mat4) => addPrimitive(t, PerforatedOctahedron()),
addCylinder: (start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps) => {
const d = Vec3.distance(start, end) * lengthScale
props.height = d
Vec3.sub(tmpCylinderDir, end, start)
setCylinderMat(tmpCylinderMat, start, tmpCylinderDir, d)
addPrimitive(tmpCylinderMat, getCylinder(props))
},
addDoubleCylinder: (start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps) => {
const d = Vec3.distance(start, end) * lengthScale
props.height = d
const cylinder = getCylinder(props)
Vec3.sub(tmpCylinderDir, end, start)
// positivly shifted cylinder
Vec3.add(tmpCylinderStart, start, shift)
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d)
addPrimitive(tmpCylinderMat, cylinder)
// negativly shifted cylinder
Vec3.sub(tmpCylinderStart, start, shift)
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d)
addPrimitive(tmpCylinderMat, cylinder)
},
addFixedCountDashedCylinder: (start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps) => {
const s = Math.floor(segmentCount / 2)
const step = 1 / segmentCount
// automatically adjust length so links/bonds that are rendered as two half cylinders
// have evenly spaced dashed cylinders
if (lengthScale < 1) {
const bias = lengthScale / 2 / segmentCount
lengthScale += segmentCount % 2 === 1 ? bias : -bias
}
const d = Vec3.distance(start, end) * lengthScale
props.height = d * step
const cylinder = getCylinder(props)
Vec3.sub(tmpCylinderDir, end, start)
for (let j = 0; j < s; ++j) {
const f = step * (j * 2 + 1)
Vec3.setMagnitude(tmpCylinderDir, tmpCylinderDir, d * f)
Vec3.add(tmpCylinderStart, start, tmpCylinderDir)
setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d * step)
addPrimitive(tmpCylinderMat, cylinder)
}
},
addSphere: (center: Vec3, radius: number, detail: number) => {
addPrimitive(setSphereMat(tmpSphereMat, center, radius), getSphere(detail))
},
addTube: (centers: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, radialSegments: number, width: number, height: number, waveFactor: number, startCap: boolean, endCap: boolean) => {
const addedVertexCount = addTube(centers, normals, binormals, linearSegments, radialSegments, width, height, waveFactor, startCap, endCap, state)
for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup);
},
addSheet: (controls: ArrayLike<number>, normals: ArrayLike<number>, binormals: ArrayLike<number>, linearSegments: number, width: number, height: number, arrowHeight: number, startCap: boolean, endCap: boolean) => {
const addedVertexCount = addSheet(controls, normals, binormals, linearSegments, width, height, arrowHeight, startCap, endCap, state)
for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup);
},
setGroup: (group: number) => {
currentGroup = group
},
setGroup: (group: number) => { currentGroup = group },
getMesh: () => {
const vb = ChunkedArray.compact(vertices, true) as Float32Array
const ib = ChunkedArray.compact(indices, true) as Uint32Array
......
......@@ -12,9 +12,9 @@ const on = Vec3.create(0, 0, -0.5), op = Vec3.create(0, 0, 0.5)
const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero()
/**
* Create a pyramide with a poligonal base
* Create a pyramid with a poligonal base
*/
export function Pyramide(points: ArrayLike<number>): Primitive {
export function Pyramid(points: ArrayLike<number>): Primitive {
const sideCount = points.length / 2
const baseCount = sideCount === 3 ? 1 : sideCount === 4 ? 2 : sideCount
const count = 2 * baseCount + 2 * sideCount
......@@ -53,17 +53,17 @@ export function Pyramide(points: ArrayLike<number>): Primitive {
return builder.getPrimitive()
}
let octagonalPyramide: Primitive
export function OctagonalPyramide() {
if (!octagonalPyramide) octagonalPyramide = Pyramide(polygon(8, true))
return octagonalPyramide
let octagonalPyramid: Primitive
export function OctagonalPyramid() {
if (!octagonalPyramid) octagonalPyramid = Pyramid(polygon(8, true))
return octagonalPyramid
}
//
let perforatedOctagonalPyramide: Primitive
let perforatedOctagonalPyramid: Primitive
export function PerforatedOctagonalPyramid() {
if (!perforatedOctagonalPyramide) {
if (!perforatedOctagonalPyramid) {
const points = polygon(8, true)
const vertices = new Float32Array(8 * 3 + 6)
for (let i = 0; i < 8; ++i) {
......@@ -81,7 +81,7 @@ export function PerforatedOctagonalPyramid() {
0, 1, 8, 1, 2, 8, 4, 5, 8, 5, 6, 8,
2, 3, 9, 3, 4, 9, 6, 7, 9, 7, 0, 9
];
perforatedOctagonalPyramide = createPrimitive(vertices, indices)
perforatedOctagonalPyramid = createPrimitive(vertices, indices)
}
return perforatedOctagonalPyramide
return perforatedOctagonalPyramid
}
\ No newline at end of file
......@@ -17,6 +17,12 @@ import { LocationIterator } from '../../../util/location-iterator';
import { OrderedSet, Interval } from 'mol-data/int';
import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual';
import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size';
import { addSphere } from '../../../mesh/builder/sphere';
import { Box, PerforatedBox } from '../../../primitive/box';
import { OctagonalPyramid, PerforatedOctagonalPyramid } from '../../../primitive/pyramid';
import { Star } from '../../../primitive/star';
import { Octahedron, PerforatedOctahedron } from '../../../primitive/octahedron';
import { DiamondPrism, PentagonalPrism, HexagonalPrism } from '../../../primitive/prism';
const t = Mat4.identity()
const sVec = Vec3.zero()
......@@ -25,6 +31,17 @@ const pd = Vec3.zero()
const sideFactor = 1.75 * 2 * 0.806; // 0.806 == Math.cos(Math.PI / 4)
const radiusFactor = 1.75
const box = Box()
const perforatedBox = PerforatedBox()
const octagonalPyramid = OctagonalPyramid()
const perforatedOctagonalPyramid = PerforatedOctagonalPyramid()
const star = Star({ outerRadius: 1, innerRadius: 0.5, thickness: 0.5, pointCount: 5 })
const octahedron = Octahedron()
const perforatedOctahedron = PerforatedOctahedron()
const diamondPrism = DiamondPrism()
const pentagonalPrism = PentagonalPrism()
const hexagonalPrism = HexagonalPrism()
async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Structure, props: CarbohydrateSymbolProps, mesh?: Mesh) {
const builder = MeshBuilder.create(256, 128, mesh)
......@@ -53,67 +70,68 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
switch (shapeType) {
case SaccharideShapes.FilledSphere:
builder.addSphere(center, radius, detail)
addSphere(builder, center, radius, detail)
break;
case SaccharideShapes.FilledCube:
Mat4.scaleUniformly(t, t, side)
builder.addBox(t)
builder.add(t, box)
break;
case SaccharideShapes.CrossedCube:
Mat4.scaleUniformly(t, t, side)
builder.addPerforatedBox(t)
builder.add(t, perforatedBox)
Mat4.mul(t, t, Mat4.rotZ90X180)
builder.setGroup(i * 2 + 1)
builder.addPerforatedBox(t)
builder.add(t, perforatedBox)
break;
case SaccharideShapes.FilledCone:
Mat4.scaleUniformly(t, t, side * 1.2)
builder.addOctagonalPyramid(t)
builder.add(t, octagonalPyramid)
break
case SaccharideShapes.DevidedCone:
Mat4.scaleUniformly(t, t, side * 1.2)
builder.addPerforatedOctagonalPyramid(t)
builder.add(t, perforatedOctagonalPyramid)
Mat4.mul(t, t, Mat4.rotZ90)
builder.setGroup(i * 2 + 1)
builder.addPerforatedOctagonalPyramid(t)
builder.add(t, perforatedOctagonalPyramid)
break
case SaccharideShapes.FlatBox:
Mat4.mul(t, t, Mat4.rotZY90)
Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
builder.addBox(t)
builder.add(t, box)
break
case SaccharideShapes.FilledStar:
Mat4.scaleUniformly(t, t, side)
Mat4.mul(t, t, Mat4.rotZY90)
builder.addStar(t, { outerRadius: side, innerRadius: side / 2, thickness: side / 2, pointCount: 5 })
builder.add(t, star)
break
case SaccharideShapes.FilledDiamond:
Mat4.mul(t, t, Mat4.rotZY90)
Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4))
builder.addOctahedron(t)
builder.add(t, octahedron)
break
case SaccharideShapes.DividedDiamond:
Mat4.mul(t, t, Mat4.rotZY90)
Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4))
builder.addPerforatedOctahedron(t)
builder.add(t, perforatedOctahedron)
Mat4.mul(t, t, Mat4.rotY90)
builder.setGroup(i * 2 + 1)
builder.addPerforatedOctahedron(t)
builder.add(t, perforatedOctahedron)
break
case SaccharideShapes.FlatDiamond:
Mat4.mul(t, t, Mat4.rotZY90)
Mat4.scale(t, t, Vec3.set(sVec, side, side / 2, side / 2))
builder.addDiamondPrism(t)
builder.add(t, diamondPrism)
break
case SaccharideShapes.Pentagon:
Mat4.mul(t, t, Mat4.rotZY90)
Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2))
builder.addPentagonalPrism(t)
builder.add(t, pentagonalPrism)
break
case SaccharideShapes.FlatHexagon:
default:
Mat4.mul(t, t, Mat4.rotZYZ90)
Mat4.scale(t, t, Vec3.set(sVec, side / 1.5, side , side / 2))
builder.addHexagonalPrism(t)
builder.add(t, hexagonalPrism)
break
}
}
......
......@@ -15,6 +15,8 @@ import { Segmentation, SortedArray } from 'mol-data/int';
import { MoleculeType, isNucleic, isPurinBase, isPyrimidineBase } from 'mol-model/structure/model/types';
import { getElementIndexForAtomId, getElementIndexForAtomRole } from 'mol-model/structure/util';
import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual';
import { addCylinder } from '../../../mesh/builder/cylinder';
import { Box } from '../../../primitive/box';
const p1 = Vec3.zero()
const p2 = Vec3.zero()
......@@ -28,6 +30,7 @@ const vC = Vec3.zero()
const center = Vec3.zero()
const t = Mat4.identity()
const sVec = Vec3.zero()
const box = Box()
// TODO define props, should be scalable
async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, props: {}, mesh?: Mesh) {
......@@ -89,8 +92,8 @@ async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, props:
Mat4.scale(t, t, Vec3.set(sVec, width, depth, height))
Mat4.setTranslation(t, center)
builder.setGroup(SortedArray.findPredecessorIndex(elements, idx6))
builder.addBox(t)
builder.addCylinder(p5, p6, 1, { radiusTop: 0.2, radiusBottom: 0.2 })
builder.add(t, box)
addCylinder(builder, p5, p6, 1, { radiusTop: 0.2, radiusBottom: 0.2 })
}
}
......
......@@ -16,6 +16,7 @@ import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual';
import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size';
import { CylinderProps } from '../../../primitive/cylinder';
import { OrderedSet } from 'mol-data/int';
import { addCylinder } from '../../../mesh/builder/cylinder';
export interface PolymerBackboneCylinderProps {
sizeTheme: SizeThemeProps
......@@ -47,11 +48,11 @@ async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit
cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerA)
builder.setGroup(OrderedSet.findPredecessorIndex(elements, centerA.element))
builder.addCylinder(pA, pB, 0.5, cylinderProps)
addCylinder(builder, pA, pB, 0.5, cylinderProps)
cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerB)
builder.setGroup(OrderedSet.findPredecessorIndex(elements, centerB.element))
builder.addCylinder(pB, pA, 0.5, cylinderProps)
addCylinder(builder, pB, pA, 0.5, cylinderProps)
if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Backbone mesh', current: i, max: polymerElementCount });
......
......@@ -16,6 +16,7 @@ import { SecondaryStructureType, MoleculeType } from 'mol-model/structure/model/
import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual';
import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size';
import { OrderedSet } from 'mol-data/int';
import { Wedge } from '../../../primitive/wedge';
const t = Mat4.identity()
const sVec = Vec3.zero()
......@@ -27,6 +28,8 @@ const depthFactor = 4
const widthFactor = 4
const heightFactor = 6
const wedge = Wedge()
export interface PolymerDirectionWedgeProps {
sizeTheme: SizeThemeProps
}
......@@ -71,7 +74,7 @@ async function createPolymerDirectionWedgeMesh(ctx: RuntimeContext, unit: Unit,
Mat4.mul(t, t, Mat4.rotY90Z180)
Mat4.scale(t, t, Vec3.set(sVec, height, width, depth))
Mat4.setTranslation(t, v.p2)
builder.addWedge(t)
builder.add(t, wedge)
}
if (i % 10000 === 0 && ctx.shouldUpdate) {
......
......@@ -15,6 +15,8 @@ import { Vec3 } from 'mol-math/linear-algebra';
import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual';
import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size';
import { CylinderProps } from '../../../primitive/cylinder';
import { addSphere } from '../../../mesh/builder/sphere';
import { addFixedCountDashedCylinder } from '../../../mesh/builder/cylinder';
const segmentCount = 10
......@@ -49,7 +51,7 @@ async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, pro
if (centerA.element === centerB.element) {
builder.setGroup(centerA.element)
pos(elements[centerA.element], pA)
builder.addSphere(pA, 0.6, 0)
addSphere(builder, pA, 0.6, 0)
} else {
const elmA = elements[centerA.element]
const elmB = elements[centerB.element]
......@@ -59,12 +61,12 @@ async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, pro
l.element = elmA
cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(l)
builder.setGroup(centerA.element)
builder.addFixedCountDashedCylinder(pA, pB, 0.5, segmentCount, cylinderProps)
addFixedCountDashedCylinder(builder, pA, pB, 0.5, segmentCount, cylinderProps)
l.element = elmB
cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(l)
builder.setGroup(centerB.element)
builder.addFixedCountDashedCylinder(pB, pA, 0.5, segmentCount, cylinderProps)
addFixedCountDashedCylinder(builder, pB, pA, 0.5, segmentCount, cylinderProps)
}
if (i % 10000 === 0 && ctx.shouldUpdate) {
......
......@@ -15,6 +15,8 @@ import { SecondaryStructureType, MoleculeType } from 'mol-model/structure/model/
import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual';
import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size';
import { OrderedSet } from 'mol-data/int';
import { addSheet } from '../../../mesh/builder/sheet';
import { addTube } from '../../../mesh/builder/tube';
export interface PolymerTraceMeshProps {
sizeTheme: SizeThemeProps
......@@ -57,7 +59,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, props: Po
if (isSheet) {
const height = width * aspectRatio
const arrowHeight = v.secStrucChange ? height * arrowFactor : 0
builder.addSheet(curvePoints, normalVectors, binormalVectors, linearSegments, width, height, arrowHeight, true, true)
addSheet(builder, curvePoints, normalVectors, binormalVectors, linearSegments, width, height, arrowHeight, true, true)
} else {
let height: number
if (isHelix) {
......@@ -68,7 +70,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, props: Po
} else {
height = width
}
builder.addTube(curvePoints, normalVectors, binormalVectors, linearSegments, radialSegments, width, height, 1, true, true)
addTube(builder, curvePoints, normalVectors, binormalVectors, linearSegments, radialSegments, width, height, 1, true, true)
}
if (i % 10000 === 0 && ctx.shouldUpdate) {
......
......@@ -15,6 +15,7 @@ import { Interval, OrderedSet } from 'mol-data/int';
import { PickingId } from '../../../../util/picking';
import { SizeTheme, SizeThemeProps } from 'mol-view/theme/size';
import { LocationIterator } from '../../../../util/location-iterator';
import { addSphere } from '../../../../mesh/builder/sphere';
export interface ElementSphereMeshProps {
sizeTheme: SizeThemeProps,
......@@ -40,7 +41,7 @@ export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, p
pos(elements[i], v)
meshBuilder.setGroup(i)
meshBuilder.addSphere(v, sizeTheme.size(l), detail)
addSphere(meshBuilder, v, sizeTheme.size(l), detail)
if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
......
......@@ -14,6 +14,7 @@ import { SizeThemeProps } from 'mol-view/theme/size';
import { CylinderProps } from '../../../../primitive/cylinder';
import { LocationIterator } from '../../../../util/location-iterator';
import { Unit, StructureElement, Structure, Link } from 'mol-model/structure';
import { addFixedCountDashedCylinder, addCylinder, addDoubleCylinder } from '../../../../mesh/builder/cylinder';
export const DefaultLinkCylinderProps = {
...DefaultMeshProps,
......@@ -94,7 +95,7 @@ export async function createLinkCylinderMesh(ctx: RuntimeContext, linkBuilder: L
if (LinkType.is(f, LinkType.Flag.MetallicCoordination)) {
// show metall coordinations with dashed cylinders
cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius / 3
meshBuilder.addFixedCountDashedCylinder(va, vb, 0.5, 7, cylinderProps)
addFixedCountDashedCylinder(meshBuilder, va, vb, 0.5, 7, cylinderProps)
} else if (o === 2 || o === 3) {
// show bonds with order 2 or 3 using 2 or 3 parallel cylinders
const multiRadius = linkRadius * (linkScale / (0.5 * o))
......@@ -105,11 +106,11 @@ export async function createLinkCylinderMesh(ctx: RuntimeContext, linkBuilder: L
cylinderProps.radiusTop = cylinderProps.radiusBottom = multiRadius
if (o === 3) meshBuilder.addCylinder(va, vb, 0.5, cylinderProps)
meshBuilder.addDoubleCylinder(va, vb, 0.5, vShift, cylinderProps)
if (o === 3) addCylinder(meshBuilder, va, vb, 0.5, cylinderProps)
addDoubleCylinder(meshBuilder, va, vb, 0.5, vShift, cylinderProps)
} else {
cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius
meshBuilder.addCylinder(va, vb, 0.5, cylinderProps)
addCylinder(meshBuilder, va, vb, 0.5, cylinderProps)
}
if (edgeIndex % 10000 === 0 && ctx.shouldUpdate) {
......
......@@ -107,9 +107,9 @@ export class Stage {
// this.loadPdbid('1sfi') // contains cyclic peptid
// this.loadPdbid('3sn6') // discontinuous chains
// this.loadPdbid('2zex') // contains carbohydrate polymer
this.loadPdbid('3sgj') // contains carbohydrate polymer
// this.loadPdbid('3sgj') // contains carbohydrate polymer
// this.loadPdbid('3ina') // contains GlcN and IdoA
// this.loadPdbid('1umz') // contains Xyl (Xyloglucan)
this.loadPdbid('1umz') // contains Xyl (Xyloglucan)
// this.loadPdbid('1mfb') // contains Abe
// this.loadPdbid('2gdu') // contains sucrose
// this.loadPdbid('2fnc') // contains maltotriose
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment