diff --git a/src/apps/canvas/index.ts b/src/apps/canvas/index.ts index 8eccc6e3ca305930da0819164b54bdef15723717..a886ec738436f30173ec17924acd86d639617608 100644 --- a/src/apps/canvas/index.ts +++ b/src/apps/canvas/index.ts @@ -8,7 +8,7 @@ import './index.html' import Viewer from 'mol-view/viewer'; import CIF, { CifBlock } from 'mol-io/reader/cif' -import { parse as parseObj } from 'mol-io/reader/obj/parser' +// import { parse as parseObj } from 'mol-io/reader/obj/parser' import { readUrlAs } from 'mol-util/read' import { Model, Format, Structure, StructureSymmetry } from 'mol-model/structure'; import { CartoonRepresentation } from 'mol-geo/representation/structure/representation/cartoon'; @@ -17,9 +17,11 @@ import { EveryLoci } from 'mol-model/loci'; import { MarkerAction } from 'mol-geo/util/marker-data'; import { labelFirst } from 'mol-view/label'; import { Queries as Q, StructureProperties as SP, StructureSelection, StructureQuery } from 'mol-model/structure'; -import { MeshBuilder } from 'mol-geo/shape/mesh-builder'; -import { CustomRepresentation } from 'mol-geo/representation/custom'; -import { Vec3 } from 'mol-math/linear-algebra'; +import { MeshBuilder } from 'mol-geo/mesh/mesh-builder'; +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'; const container = document.getElementById('container') if (!container) throw new Error('Can not find element with id "container".') @@ -50,13 +52,13 @@ viewer.input.move.subscribe(({x, y, inside, buttons}) => { }) -async function getObjFromUrl(url: string) { - const data = await readUrlAs(url, false) as string - const comp = parseObj(data) - const parsed = await comp.run() - if (parsed.isError) throw parsed - return parsed.result -} +// async function getObjFromUrl(url: string) { +// const data = await readUrlAs(url, false) as string +// const comp = parseObj(data) +// const parsed = await comp.run() +// if (parsed.isError) throw parsed +// return parsed.result +// } async function getCifFromUrl(url: string) { const data = await readUrlAs(url, false) @@ -111,18 +113,34 @@ async function init() { }).run() viewer.add(ballStickRepr) - // create a custom mesh + // create a mesh const meshBuilder = MeshBuilder.create(256, 128) - meshBuilder.setId(0) + const groupColors: Color[] = [] + const groupLabels: string[] = [] + // red sphere + meshBuilder.setGroup(0) + groupColors[0] = Color(0xFF2233) + groupLabels[0] = 'red sphere' meshBuilder.addSphere(Vec3.create(0, 0, 0), 4, 2) + // green cube + meshBuilder.setGroup(1) + groupColors[1] = Color(0x2233FF) + groupLabels[1] = 'blue cube' + const t = Mat4.identity() + Mat4.setTranslation(t, Vec3.create(10, 0, 0)) + Mat4.scale(t, t, Vec3.create(3, 3, 3)) + meshBuilder.addBox(t) const mesh = meshBuilder.getMesh() - // Mesh.computeNormalsImmediate(mesh) + // const mesh = getObjFromUrl('mesh.obj') - // mesh = getObjFromUrl('mesh.obj') + // create shape from mesh + const shape = Shape.create(mesh, 'myShape', group => groupColors[group], group => groupLabels[group]) - // add representation from custom mesh - const customRepr = CustomRepresentation() - await customRepr.create(mesh, { + // add representation from shape + const customRepr = ShapeRepresentation() + await customRepr.create(shape, { + colorTheme: { name: 'shape-group' }, + // colorTheme: { name: 'uniform', value: Color(0xFFCC22) }, useFog: false // TODO fog not working properly }).run() viewer.add(customRepr) diff --git a/src/mol-app/ui/visualization/viewport.tsx b/src/mol-app/ui/visualization/viewport.tsx index ba402a6d7d1f6e81e1968b11a02d635bc78c209c..d23f182e1b5bbfa3731d1f98edc7fa2cb9243692 100644 --- a/src/mol-app/ui/visualization/viewport.tsx +++ b/src/mol-app/ui/visualization/viewport.tsx @@ -151,7 +151,7 @@ export class Viewport extends View<ViewportController, ViewportState, { noWebGl? images: { 'object': viewer.getImageData('pickObject'), 'instance': viewer.getImageData('pickInstance'), - 'element': viewer.getImageData('pickElement') + 'group': viewer.getImageData('pickGroup') } }) }) @@ -168,7 +168,7 @@ export class Viewport extends View<ViewportController, ViewportState, { noWebGl? // TODO use LabelLoci event and make configurable const label = labelFirst(loci) - const info = `Object: ${p.objectId}, Instance: ${p.instanceId}, Element: ${p.elementId}, Label: ${label}` + const info = `Object: ${p.objectId}, Instance: ${p.instanceId}, Group: ${p.groupId}, Label: ${label}` this.setState({ info }) }) diff --git a/src/mol-geo/shape/mesh-builder.ts b/src/mol-geo/mesh/mesh-builder.ts similarity index 90% rename from src/mol-geo/shape/mesh-builder.ts rename to src/mol-geo/mesh/mesh-builder.ts index f3dafe8a41d33153039a6af87bb1dee4bfd44e81..c34b2ea477f5ce98f0fe5c49108f46fbe865827c 100644 --- a/src/mol-geo/shape/mesh-builder.ts +++ b/src/mol-geo/mesh/mesh-builder.ts @@ -19,7 +19,7 @@ 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, PerforatedOctagonalPyramide } from '../primitive/pyramid'; +import { OctagonalPyramide, PerforatedOctagonalPyramid } from '../primitive/pyramid'; import { PerforatedBox, Box } from '../primitive/box'; import { Wedge } from '../primitive/wedge'; @@ -49,7 +49,7 @@ export interface MeshBuilder { 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 - setId(id: number): void + setGroup(id: number): void getMesh(): Mesh } @@ -114,10 +114,9 @@ export namespace MeshBuilder { const indices = ChunkedArray.create(Uint32Array, 3, chunkSize * 3, mesh ? mesh.indexBuffer.ref.value : initialCount * 3); const state: MeshBuilderState = { vertices, normals, indices }; - const ids = ChunkedArray.create(Float32Array, 1, chunkSize, mesh ? mesh.idBuffer.ref.value : initialCount); - const offsets = ChunkedArray.create(Uint32Array, 1, chunkSize, mesh ? mesh.offsetBuffer.ref.value : initialCount); + const groups = ChunkedArray.create(Float32Array, 1, chunkSize, mesh ? mesh.groupBuffer.ref.value : initialCount); - let currentId = -1 + let currentGroup = -1 function add(t: Mat4, _vertices: ArrayLike<number>, _normals: ArrayLike<number>, _indices: ArrayLike<number>) { const { elementCount } = vertices @@ -131,8 +130,8 @@ export namespace MeshBuilder { Vec3.fromArray(tmpV, _normals, i) Vec3.transformMat3(tmpV, tmpV, n) ChunkedArray.add3(normals, tmpV[0], tmpV[1], tmpV[2]); - // id - ChunkedArray.add(ids, currentId); + // group + ChunkedArray.add(groups, currentGroup); } for (let i = 0, il = _indices.length; i < il; i += 3) { ChunkedArray.add3(indices, _indices[i] + elementCount, _indices[i + 1] + elementCount, _indices[i + 2] + elementCount); @@ -174,7 +173,7 @@ export namespace MeshBuilder { add(t, vertices, normals, indices) }, addPerforatedOctagonalPyramid: (t: Mat4) => { - const { vertices, normals, indices } = PerforatedOctagonalPyramide() + const { vertices, normals, indices } = PerforatedOctagonalPyramid() add(t, vertices, normals, indices) }, addStar: (t: Mat4, props?: StarProps) => { @@ -242,36 +241,28 @@ export namespace MeshBuilder { }, 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(ids, currentId); + 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(ids, currentId); + for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup); }, - setId: (id: number) => { - if (currentId !== id) { - currentId = id - ChunkedArray.add(offsets, vertices.elementCount) - } + setGroup: (group: number) => { + currentGroup = group }, getMesh: () => { - ChunkedArray.add(offsets, vertices.elementCount) const vb = ChunkedArray.compact(vertices, true) as Float32Array const ib = ChunkedArray.compact(indices, true) as Uint32Array const nb = ChunkedArray.compact(normals, true) as Float32Array - const idb = ChunkedArray.compact(ids, true) as Float32Array - const ob = ChunkedArray.compact(offsets, true) as Uint32Array + const idb = ChunkedArray.compact(groups, true) as Float32Array return { vertexCount: vertices.elementCount, triangleCount: indices.elementCount, - offsetCount: offsets.elementCount, vertexBuffer: mesh ? ValueCell.update(mesh.vertexBuffer, vb) : ValueCell.create(vb), indexBuffer: mesh ? ValueCell.update(mesh.indexBuffer, ib) : ValueCell.create(ib), normalBuffer: mesh ? ValueCell.update(mesh.normalBuffer, nb) : ValueCell.create(nb), - idBuffer: mesh ? ValueCell.update(mesh.idBuffer, idb) : ValueCell.create(idb), - offsetBuffer: mesh ? ValueCell.update(mesh.offsetBuffer, ob) : ValueCell.create(ob), + groupBuffer: mesh ? ValueCell.update(mesh.groupBuffer, idb) : ValueCell.create(idb), normalsComputed: true, - offsetsComputed: true, } } } diff --git a/src/mol-geo/shape/mesh.ts b/src/mol-geo/mesh/mesh.ts similarity index 91% rename from src/mol-geo/shape/mesh.ts rename to src/mol-geo/mesh/mesh.ts index 9447404a353e906a8ee0d27708bd6b7743509160..7b525f6e753f875e4c96869124d7f859ecbed196 100644 --- a/src/mol-geo/shape/mesh.ts +++ b/src/mol-geo/mesh/mesh.ts @@ -15,8 +15,6 @@ export interface Mesh { vertexCount: number, /** Number of triangles in the mesh */ triangleCount: number, - /** Number of offsets in the mesh */ - offsetCount: number, /** Vertex buffer as array of xyz values wrapped in a value cell */ vertexBuffer: ValueCell<Float32Array>, @@ -24,15 +22,11 @@ export interface Mesh { indexBuffer: ValueCell<Uint32Array>, /** Normal buffer as array of xyz values for each vertex wrapped in a value cell */ normalBuffer: ValueCell<Float32Array>, - /** Id buffer as array of ids for each vertex wrapped in a value cell */ - idBuffer: ValueCell<Float32Array>, - /** Offset buffer as array of offsets for id ranges wrapped in a value cell */ - offsetBuffer: ValueCell<Uint32Array>, + /** Group buffer as array of group ids for each vertex wrapped in a value cell */ + groupBuffer: ValueCell<Float32Array>, /** Flag indicating if normals are computed for the current set of vertices */ normalsComputed: boolean, - /** Flag indicating if offsets are computed for the current set of ids */ - offsetsComputed: boolean, /** Bounding sphere of the mesh */ boundingSphere?: Sphere3D @@ -43,19 +37,15 @@ export namespace Mesh { const vb = mesh ? mesh.vertexBuffer.ref.value : new Float32Array(0) const ib = mesh ? mesh.indexBuffer.ref.value : new Uint32Array(0) const nb = mesh ? mesh.normalBuffer.ref.value : new Float32Array(0) - const idb = mesh ? mesh.idBuffer.ref.value : new Float32Array(0) - const ob = mesh ? mesh.offsetBuffer.ref.value : new Uint32Array(0) + const idb = mesh ? mesh.groupBuffer.ref.value : new Float32Array(0) return { vertexCount: 0, triangleCount: 0, - offsetCount: 0, vertexBuffer: mesh ? ValueCell.update(mesh.vertexBuffer, vb) : ValueCell.create(vb), indexBuffer: mesh ? ValueCell.update(mesh.indexBuffer, ib) : ValueCell.create(ib), normalBuffer: mesh ? ValueCell.update(mesh.normalBuffer, nb) : ValueCell.create(nb), - idBuffer: mesh ? ValueCell.update(mesh.idBuffer, idb) : ValueCell.create(idb), - offsetBuffer: mesh ? ValueCell.update(mesh.offsetBuffer, ob) : ValueCell.create(ob), + groupBuffer: mesh ? ValueCell.update(mesh.groupBuffer, idb) : ValueCell.create(idb), normalsComputed: true, - offsetsComputed: true, } } diff --git a/src/mol-geo/primitive/pyramid.ts b/src/mol-geo/primitive/pyramid.ts index 1a0fb1ae9bf801d9eb575f1c0e67950be5288d70..f865a923658eec18d9bd29d2729ec31edca8cc24 100644 --- a/src/mol-geo/primitive/pyramid.ts +++ b/src/mol-geo/primitive/pyramid.ts @@ -62,7 +62,7 @@ export function OctagonalPyramide() { // let perforatedOctagonalPyramide: Primitive -export function PerforatedOctagonalPyramide() { +export function PerforatedOctagonalPyramid() { if (!perforatedOctagonalPyramide) { const points = polygon(8, true) const vertices = new Float32Array(8 * 3 + 6) diff --git a/src/mol-geo/primitive/sheet.ts b/src/mol-geo/primitive/sheet.ts index e4130a5be57e25d9204754ed0dcf265b5f26ab66..e2da5dfc08d1bcbe30f635edcb0081d2421ab847 100644 --- a/src/mol-geo/primitive/sheet.ts +++ b/src/mol-geo/primitive/sheet.ts @@ -7,7 +7,7 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { ChunkedArray } from 'mol-data/util'; -import { MeshBuilderState } from '../shape/mesh-builder'; +import { MeshBuilderState } from '../mesh/mesh-builder'; const tA = Vec3.zero() const tB = Vec3.zero() diff --git a/src/mol-geo/primitive/tube.ts b/src/mol-geo/primitive/tube.ts index 92d8a182cd787892cc7b0a7b55f193edcd942eda..333b7cc8718b435ffb60a6982aefa478dbc790d1 100644 --- a/src/mol-geo/primitive/tube.ts +++ b/src/mol-geo/primitive/tube.ts @@ -7,7 +7,7 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { ChunkedArray } from 'mol-data/util'; -import { MeshBuilderState } from '../shape/mesh-builder'; +import { MeshBuilderState } from '../mesh/mesh-builder'; const normalVector = Vec3.zero() const binormalVector = Vec3.zero() diff --git a/src/mol-geo/representation/custom/index.ts b/src/mol-geo/representation/custom/index.ts deleted file mode 100644 index 4189a143f0e87a1a4bc3f93e3bab9373828397ed..0000000000000000000000000000000000000000 --- a/src/mol-geo/representation/custom/index.ts +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import { Task } from 'mol-task' -import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'; -import { RepresentationProps, Representation } from '..'; -import { PickingId } from '../../util/picking'; -import { Loci, EmptyLoci, CustomLoci, isCustomLoci, isEveryLoci } from 'mol-model/loci'; -import { MarkerAction, applyMarkerAction, createMarkers } from '../../util/marker-data'; -import { createRenderableState, createMeshValues, createIdentityTransform, DefaultMeshProps } from '../util'; -import { Mesh } from '../../shape/mesh'; -import { getMeshData } from '../../util/mesh-data'; -import { MeshValues } from 'mol-gl/renderable'; -import { createValueColor } from '../../util/color-data'; -import { Color } from 'mol-util/color'; -import { CustomLocation } from 'mol-model/location'; -import { ValueCell } from 'mol-util'; - -export interface CustomRepresentation<P extends RepresentationProps = {}> extends Representation<Mesh, P> { } - -export const DefaultCustomProps = { - ...DefaultMeshProps, -} -export type CustomProps = typeof DefaultCustomProps - -export function CustomRepresentation<P extends CustomProps>(): CustomRepresentation<P> { - const renderObjects: RenderObject[] = [] - let _renderObject: MeshRenderObject - let _mesh: Mesh - let _props: P - - function create(mesh: Mesh, props: Partial<P> = {}) { - _props = Object.assign({}, DefaultCustomProps, _props, props) - return Task.create('CustomRepresentation.create', async ctx => { - renderObjects.length = 0 - _mesh = mesh - - const elementCount = mesh.triangleCount - const instanceCount = 1 - - const color = createValueColor(Color(0x7ec0ee)) - const marker = createMarkers(instanceCount * elementCount) - const counts = { drawCount: mesh.triangleCount * 3, elementCount, instanceCount } - - const values: MeshValues = { - ...getMeshData(mesh), - ...createMeshValues(_props, counts), - aTransform: createIdentityTransform(), - ...color, - ...marker, - - elements: mesh.indexBuffer, - } - const state = createRenderableState(_props) - - _renderObject = createMeshRenderObject(values, state) - renderObjects.push(_renderObject) - }); - } - - function update(props: Partial<P>) { - return Task.create('CustomRepresentation.update', async ctx => { - // TODO - }) - } - - return { - get renderObjects () { return renderObjects }, - get props () { return _props }, - create, - update, - getLoci(pickingId: PickingId) { - const { objectId, elementId } = pickingId - if (_renderObject.id === objectId) { - return CustomLoci([ CustomLocation(_mesh, elementId) ]) - } - return EmptyLoci - }, - mark(loci: Loci, action: MarkerAction) { - const { tMarker } = _renderObject.values - let changed = false - if (isEveryLoci(loci)) { - if (applyMarkerAction(tMarker.ref.value.array, 0, _mesh.triangleCount, action)) changed = true - changed = true - } else if (isCustomLoci(loci)) { - for (const l of loci.locations) { - if (l.data === _mesh) { - if (applyMarkerAction(tMarker.ref.value.array, 0, _mesh.triangleCount, action)) changed = true - // TODO - // const idx = l.key - // if (idx !== undefined) { - // if (applyMarkerAction(tMarker.ref.value.array, idx, idx + 1, action)) changed = true - // } - } - } - } - if (changed) { - ValueCell.update(tMarker, tMarker.ref.value) - } - }, - destroy() { - // TODO - } - } -} \ No newline at end of file diff --git a/src/mol-geo/representation/shape/index.ts b/src/mol-geo/representation/shape/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..ea5faf1d688a942bc983594217d69dff2f14ceaa --- /dev/null +++ b/src/mol-geo/representation/shape/index.ts @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Task } from 'mol-task' +import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'; +import { RepresentationProps, Representation } from '..'; +import { PickingId } from '../../util/picking'; +import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci'; +import { MarkerAction, applyMarkerAction, createMarkers } from '../../util/marker-data'; +import { createRenderableState, createMeshValues, createIdentityTransform, DefaultMeshProps } from '../util'; +import { getMeshData } from '../../util/mesh-data'; +import { MeshValues } from 'mol-gl/renderable'; +import { ValueCell } from 'mol-util'; +import { ColorThemeProps } from 'mol-view/theme/color'; +import { Shape } from 'mol-model/shape'; +import { LocationIterator } from '../../util/location-iterator'; +import { arrayMax } from 'mol-util/array'; +import { createColors } from '../structure/visual/util/common'; +import { OrderedSet, Interval } from 'mol-data/int'; + +export interface ShapeRepresentation<P extends RepresentationProps = {}> extends Representation<Shape, P> { } + +export const DefaultShapeProps = { + ...DefaultMeshProps, + colorTheme: { name: 'shape-group' } as ColorThemeProps +} +export type ShapeProps = typeof DefaultShapeProps + +export function ShapeRepresentation<P extends ShapeProps>(): ShapeRepresentation<P> { + const renderObjects: RenderObject[] = [] + let _renderObject: MeshRenderObject + let _shape: Shape + let _props: P + + function create(shape: Shape, props: Partial<P> = {}) { + _props = Object.assign({}, DefaultShapeProps, _props, props) + _shape = shape + + return Task.create('ShapeRepresentation.create', async ctx => { + renderObjects.length = 0 + + const mesh = shape.mesh + const locationIt = ShapeGroupIterator.fromShape(shape) + const { groupCount, instanceCount } = locationIt + + const color = createColors(locationIt, _props.colorTheme) + const marker = createMarkers(instanceCount * groupCount) + const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount } + + const values: MeshValues = { + ...getMeshData(mesh), + ...createMeshValues(_props, counts), + aTransform: createIdentityTransform(), + ...color, + ...marker, + + elements: mesh.indexBuffer, + } + const state = createRenderableState(_props) + + _renderObject = createMeshRenderObject(values, state) + console.log(_renderObject) + renderObjects.push(_renderObject) + }); + } + + function update(props: Partial<P>) { + return Task.create('ShapeRepresentation.update', async ctx => { + // TODO + }) + } + + return { + get renderObjects () { return renderObjects }, + get props () { return _props }, + create, + update, + getLoci(pickingId: PickingId) { + const { objectId, groupId } = pickingId + if (_renderObject.id === objectId) { + return Shape.Loci([ { shape: _shape, ids: OrderedSet.ofSingleton(groupId) } ]) + } + return EmptyLoci + }, + mark(loci: Loci, action: MarkerAction) { + const { tMarker } = _renderObject.values + let changed = false + if (isEveryLoci(loci)) { + if (applyMarkerAction(tMarker.ref.value.array, 0, _shape.mesh.triangleCount, action)) changed = true + } else if (Shape.isLoci(loci)) { + for (const g of loci.groups) { + if (Interval.is(g.ids)) { + const start = Interval.start(g.ids) + const end = Interval.end(g.ids) + if (applyMarkerAction(tMarker.ref.value.array, start, end, action)) changed = true + } else { + for (let i = 0, _i = g.ids.length; i < _i; i++) { + const idx = g.ids[i]; + if (applyMarkerAction(tMarker.ref.value.array, idx, idx + 1, action)) changed = true + } + } + } + } + if (changed) { + ValueCell.update(tMarker, tMarker.ref.value) + } + }, + destroy() { + // TODO + } + } +} + +export namespace ShapeGroupIterator { + export function fromShape(shape: Shape): LocationIterator { + const groupCount = arrayMax(shape.mesh.groupBuffer.ref.value) + 1 + const instanceCount = 1 + const location = Shape.Location(shape) + const getLocation = (groupIndex: number) => { + location.group = groupIndex + return location + } + return LocationIterator(groupCount, instanceCount, getLocation) + } +} \ No newline at end of file diff --git a/src/mol-geo/representation/structure/complex-representation.ts b/src/mol-geo/representation/structure/complex-representation.ts index d19f96b263525cd4fe6ac280e3cd890ccd675391..6a258b24ca99cf9ccc9edc5d1297b306ac483051 100644 --- a/src/mol-geo/representation/structure/complex-representation.ts +++ b/src/mol-geo/representation/structure/complex-representation.ts @@ -22,7 +22,7 @@ export function ComplexRepresentation<P extends StructureProps>(visualCtor: () = function create(structure: Structure, props: Partial<P> = {}) { _props = Object.assign({}, DefaultStructureProps, _props, props, getQualityProps(props, structure)) - _props.colorTheme!.structure = structure + _props.colorTheme.structure = structure return Task.create('Creating StructureRepresentation', async ctx => { if (!_structure) { @@ -44,7 +44,7 @@ export function ComplexRepresentation<P extends StructureProps>(visualCtor: () = function update(props: Partial<P>) { return Task.create('Updating StructureRepresentation', async ctx => { _props = Object.assign({}, DefaultStructureProps, _props, props, getQualityProps(props, _structure)) - _props.colorTheme!.structure = _structure + _props.colorTheme.structure = _structure if (!await visual.update(ctx, _props)) { await visual.create(ctx, _structure, _props) diff --git a/src/mol-geo/representation/structure/complex-visual.ts b/src/mol-geo/representation/structure/complex-visual.ts index 083a610e728721a6c293aa595f0ce1b44ac84a78..063ecf36dc20499485644fb736b9f853f2b1b4bf 100644 --- a/src/mol-geo/representation/structure/complex-visual.ts +++ b/src/mol-geo/representation/structure/complex-visual.ts @@ -7,9 +7,9 @@ import { Structure } from 'mol-model/structure'; import { Visual } from '..'; import { MeshRenderObject } from 'mol-gl/render-object'; -import { Mesh } from '../../shape/mesh'; +import { Mesh } from '../../mesh/mesh'; import { RuntimeContext } from 'mol-task'; -import { LocationIterator } from './visual/util/location-iterator'; +import { LocationIterator } from '../../util/location-iterator'; import { createComplexMeshRenderObject, createColors } from './visual/util/common'; import { StructureProps, DefaultStructureMeshProps, MeshUpdateState } from '.'; import { deepEqual, ValueCell } from 'mol-util'; @@ -96,7 +96,7 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe }, mark(loci: Loci, action: MarkerAction) { const { tMarker } = renderObject.values - const { elementCount, instanceCount } = locationIt + const { groupCount, instanceCount } = locationIt function apply(interval: Interval) { const start = Interval.start(interval) @@ -106,7 +106,7 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe let changed = false if (isEveryLoci(loci)) { - apply(Interval.ofBounds(0, elementCount * instanceCount)) + apply(Interval.ofBounds(0, groupCount * instanceCount)) changed = true } else { changed = mark(loci, currentStructure, apply) diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts index 9118f2b48afdc14ae21957ac2f56f8e8a3c563d6..d7ebb4b9bc5ccc140c3091671ba836e8fbc87f6a 100644 --- a/src/mol-geo/representation/structure/units-visual.ts +++ b/src/mol-geo/representation/structure/units-visual.ts @@ -9,8 +9,8 @@ import { RepresentationProps, Visual } from '..'; import { DefaultStructureMeshProps, MeshUpdateState } from '.'; import { RuntimeContext } from 'mol-task'; import { PickingId } from '../../util/picking'; -import { LocationIterator } from './visual/util/location-iterator'; -import { Mesh } from '../../shape/mesh'; +import { LocationIterator } from '../../util/location-iterator'; +import { Mesh } from '../../mesh/mesh'; import { MarkerAction, applyMarkerAction } from '../../util/marker-data'; import { Loci, isEveryLoci } from 'mol-model/loci'; import { MeshRenderObject } from 'mol-gl/render-object'; @@ -101,7 +101,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu }, mark(loci: Loci, action: MarkerAction) { const { tMarker } = renderObject.values - const { elementCount, instanceCount } = locationIt + const { groupCount, instanceCount } = locationIt function apply(interval: Interval) { const start = Interval.start(interval) @@ -111,7 +111,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu let changed = false if (isEveryLoci(loci)) { - apply(Interval.ofBounds(0, elementCount * instanceCount)) + apply(Interval.ofBounds(0, groupCount * instanceCount)) changed = true } else { changed = mark(loci, currentGroup, apply) diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts index a315ba72dbc38bc18bc8ea4116f4ca100e02155e..6526391f04326d93df99dd68f5c35c69de5d16c0 100644 --- a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts @@ -7,12 +7,12 @@ import { Unit, Structure, Link, StructureElement } from 'mol-model/structure'; import { DefaultStructureProps, ComplexVisual, MeshUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../shape/mesh'; +import { Mesh } from '../../../mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { DefaultMeshProps } from '../../util'; import { Vec3 } from 'mol-math/linear-algebra'; -import { LocationIterator } from './util/location-iterator'; +import { LocationIterator } from '../../../util/location-iterator'; import { createLinkCylinderMesh, DefaultLinkCylinderProps, LinkCylinderProps } from './util/link'; import { OrderedSet, Interval } from 'mol-data/int'; import { ComplexMeshVisual } from '../complex-visual'; @@ -85,11 +85,11 @@ export function CarbohydrateLinkVisual(): ComplexVisual<CarbohydrateLinkProps> { function CarbohydrateLinkIterator(structure: Structure): LocationIterator { const { elements, links } = structure.carbohydrates - const elementCount = links.length + const groupCount = links.length const instanceCount = 1 const location = Link.Location() - const getLocation = (elementIndex: number, instanceIndex: number) => { - const link = links[elementIndex] + const getLocation = (groupIndex: number) => { + const link = links[groupIndex] const carbA = elements[link.carbohydrateIndexA] const carbB = elements[link.carbohydrateIndexB] const indexA = OrderedSet.findPredecessorIndex(carbA.unit.elements, carbA.anomericCarbon) @@ -100,14 +100,14 @@ function CarbohydrateLinkIterator(structure: Structure): LocationIterator { location.bIndex = indexB as StructureElement.UnitIndex return location } - return LocationIterator(elementCount, instanceCount, getLocation) + return LocationIterator(groupCount, instanceCount, getLocation) } function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, elementId } = pickingId + const { objectId, groupId } = pickingId if (id === objectId) { const { links, elements } = structure.carbohydrates - const l = links[elementId] + const l = links[groupId] const carbA = elements[l.carbohydrateIndexA] const carbB = elements[l.carbohydrateIndexB] const indexA = OrderedSet.findPredecessorIndex(carbA.unit.elements, carbA.anomericCarbon) diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts index 142791e62b0ad390e04ce01df6aee8b0a25f4a7b..7832c86b0dce966cec6b87d13d634e4f3e273074 100644 --- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts +++ b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts @@ -7,13 +7,13 @@ import { Unit, Structure, StructureElement } from 'mol-model/structure'; import { ComplexVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../shape/mesh'; +import { Mesh } from '../../../mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { MeshBuilder } from '../../../shape/mesh-builder'; +import { MeshBuilder } from '../../../mesh/mesh-builder'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/structure/carbohydrates/constants'; -import { LocationIterator } from './util/location-iterator'; +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'; @@ -49,7 +49,7 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru Mat4.targetTo(t, center, pd, normal) Mat4.setTranslation(t, center) - builder.setId(i * 2) + builder.setGroup(i * 2) switch (shapeType) { case SaccharideShapes.FilledSphere: @@ -63,7 +63,7 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru Mat4.scaleUniformly(t, t, side) builder.addPerforatedBox(t) Mat4.mul(t, t, Mat4.rotZ90X180) - builder.setId(i * 2 + 1) + builder.setGroup(i * 2 + 1) builder.addPerforatedBox(t) break; case SaccharideShapes.FilledCone: @@ -74,7 +74,7 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru Mat4.scaleUniformly(t, t, side * 1.2) builder.addPerforatedOctagonalPyramid(t) Mat4.mul(t, t, Mat4.rotZ90) - builder.setId(i * 2 + 1) + builder.setGroup(i * 2 + 1) builder.addPerforatedOctagonalPyramid(t) break case SaccharideShapes.FlatBox: @@ -96,7 +96,7 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4)) builder.addPerforatedOctahedron(t) Mat4.mul(t, t, Mat4.rotY90) - builder.setId(i * 2 + 1) + builder.setGroup(i * 2 + 1) builder.addPerforatedOctahedron(t) break case SaccharideShapes.FlatDiamond: @@ -142,11 +142,11 @@ export function CarbohydrateSymbolVisual(): ComplexVisual<CarbohydrateSymbolProp function CarbohydrateElementIterator(structure: Structure): LocationIterator { const carbElements = structure.carbohydrates.elements - const elementCount = carbElements.length * 2 + const groupCount = carbElements.length * 2 const instanceCount = 1 const location = StructureElement.create() - function getLocation (elementIndex: number, instanceIndex: number) { - const carb = carbElements[Math.floor(elementIndex / 2)] + function getLocation (groupIndex: number, instanceIndex: number) { + const carb = carbElements[Math.floor(groupIndex / 2)] location.unit = carb.unit location.element = carb.anomericCarbon return location @@ -154,13 +154,13 @@ function CarbohydrateElementIterator(structure: Structure): LocationIterator { function isSecondary (elementIndex: number, instanceIndex: number) { return (elementIndex % 2) === 1 } - return LocationIterator(elementCount, instanceCount, getLocation, isSecondary) + return LocationIterator(groupCount, instanceCount, getLocation, isSecondary) } function getCarbohydrateLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, elementId } = pickingId + const { objectId, groupId } = pickingId if (id === objectId) { - const carb = structure.carbohydrates.elements[Math.floor(elementId / 2)] + const carb = structure.carbohydrates.elements[Math.floor(groupId / 2)] const { unit } = carb const index = OrderedSet.findPredecessorIndex(unit.elements, carb.anomericCarbon) const indices = OrderedSet.ofSingleton(index as StructureElement.UnitIndex) diff --git a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts index de81e58df39a4d2da5573d99895442b6b651fbca..6bd885217c6132fbbdce6ed6ed481aeb68afda33 100644 --- a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts @@ -8,12 +8,12 @@ import { Link, Structure, StructureElement } from 'mol-model/structure'; import { ComplexVisual, MeshUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh } from './util/link'; -import { Mesh } from '../../../shape/mesh'; +import { Mesh } from '../../../mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual'; -import { LocationIterator } from './util/location-iterator'; +import { LocationIterator } from '../../../util/location-iterator'; import { Interval } from 'mol-data/int'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { BitFlags } from 'mol-util'; @@ -73,24 +73,24 @@ export function CrossLinkRestraintVisual(): ComplexVisual<CrossLinkRestraintProp function CrossLinkRestraintIterator(structure: Structure): LocationIterator { const { pairs } = structure.crossLinkRestraints - const elementCount = pairs.length + const groupCount = pairs.length const instanceCount = 1 const location = Link.Location() - const getLocation = (elementIndex: number) => { - const pair = pairs[elementIndex] + const getLocation = (groupIndex: number) => { + const pair = pairs[groupIndex] location.aUnit = pair.unitA location.aIndex = pair.indexA location.bUnit = pair.unitB location.bIndex = pair.indexB return location } - return LocationIterator(elementCount, instanceCount, getLocation) + return LocationIterator(groupCount, instanceCount, getLocation) } function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, elementId } = pickingId + const { objectId, groupId } = pickingId if (id === objectId) { - const pair = structure.crossLinkRestraints.pairs[elementId] + const pair = structure.crossLinkRestraints.pairs[groupId] if (pair) { return Link.Loci([ Link.Location(pair.unitA, pair.indexA, pair.unitB, pair.indexB) ]) } diff --git a/src/mol-geo/representation/structure/visual/element-point.ts b/src/mol-geo/representation/structure/visual/element-point.ts index 57306c4b9765092b471cead32cb6342c20023c26..e58f1bee17d71ac6a7605317fb6000a6ce448ca4 100644 --- a/src/mol-geo/representation/structure/visual/element-point.ts +++ b/src/mol-geo/representation/structure/visual/element-point.ts @@ -11,7 +11,7 @@ import { Unit } from 'mol-model/structure'; import { RuntimeContext } from 'mol-task' import { UnitsVisual, DefaultStructureProps } from '..'; -import { getElementLoci } from './util/element'; +import { getElementLoci, StructureElementIterator } from './util/element'; import { createTransforms, createColors, createSizes } from './util/common'; import { deepEqual, defaults } from 'mol-util'; import { SortedArray } from 'mol-data/int'; @@ -21,7 +21,6 @@ import { Loci } from 'mol-model/loci'; import { MarkerAction, createMarkers } from '../../../util/marker-data'; import { Vec3 } from 'mol-math/linear-algebra'; import { fillSerial } from 'mol-util/array'; -import { StructureElementIterator } from './util/location-iterator'; import { SizeThemeProps } from 'mol-view/theme/size'; export const DefaultPointProps = { @@ -79,16 +78,16 @@ export default function PointVisual(): UnitsVisual<PointProps> { const values: PointValues = { aPosition: ValueCell.create(vertices), - aElementId: ValueCell.create(fillSerial(new Float32Array(elementCount))), + aGroup: ValueCell.create(fillSerial(new Float32Array(elementCount))), aTransform: transforms, - aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), + aInstance: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, ...marker, ...size, uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), uInstanceCount: ValueCell.create(instanceCount), - uElementCount: ValueCell.create(group.elements.length), + uGroupCount: ValueCell.create(group.elements.length), drawCount: ValueCell.create(vertices.length / 3), instanceCount: ValueCell.create(instanceCount), diff --git a/src/mol-geo/representation/structure/visual/element-sphere.ts b/src/mol-geo/representation/structure/visual/element-sphere.ts index 8f151ccf110b1511946edc83bb8c8f255dd701cc..523e19e1e3d62d8cc1a0c0ce6c3d1fdc4b699c14 100644 --- a/src/mol-geo/representation/structure/visual/element-sphere.ts +++ b/src/mol-geo/representation/structure/visual/element-sphere.ts @@ -6,8 +6,7 @@ */ import { UnitsVisual, MeshUpdateState } from '..'; -import { createElementSphereMesh, markElement, getElementLoci } from './util/element'; -import { StructureElementIterator } from './util/location-iterator'; +import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator } from './util/element'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; export const DefaultElementSphereProps = { diff --git a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts index 40d6c5709e25357a57971fc5195683f53437671b..813da2a3b9ce6864298fe0e8424972e05ab97b7a 100644 --- a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts @@ -7,12 +7,11 @@ import { Link, Structure, StructureElement } from 'mol-model/structure'; import { ComplexVisual, MeshUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh } from './util/link'; -import { Mesh } from '../../../shape/mesh'; +import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link'; +import { Mesh } from '../../../mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { LinkIterator } from './util/location-iterator'; import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual'; import { Interval } from 'mol-data/int'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; @@ -70,9 +69,9 @@ export function InterUnitLinkVisual(): ComplexVisual<InterUnitLinkProps> { } function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, elementId } = pickingId + const { objectId, groupId } = pickingId if (id === objectId) { - const bond = structure.links.bonds[elementId] + const bond = structure.links.bonds[groupId] return Link.Loci([ Link.Location( bond.unitA, bond.indexA as StructureElement.UnitIndex, diff --git a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts index 12c1a7c0cc0734e417fc6cfabf1b9d5194e30a74..bf3e964bc6788f9b2f36e47324de31e147e6eb40 100644 --- a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts @@ -8,12 +8,11 @@ import { Unit, Link, StructureElement } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { DefaultLinkCylinderProps, LinkCylinderProps, createLinkCylinderMesh } from './util/link'; -import { Mesh } from '../../../shape/mesh'; +import { DefaultLinkCylinderProps, LinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link'; +import { Mesh } from '../../../mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { LinkIterator } from './util/location-iterator'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; import { Interval } from 'mol-data/int'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; @@ -82,13 +81,13 @@ export function IntraUnitLinkVisual(): UnitsVisual<IntraUnitLinkProps> { } function getLinkLoci(pickingId: PickingId, group: Unit.SymmetryGroup, id: number) { - const { objectId, instanceId, elementId } = pickingId + const { objectId, instanceId, groupId } = pickingId const unit = group.units[instanceId] if (id === objectId && Unit.isAtomic(unit)) { return Link.Loci([ Link.Location( - unit, unit.links.a[elementId] as StructureElement.UnitIndex, - unit, unit.links.b[elementId] as StructureElement.UnitIndex + unit, unit.links.a[groupId] as StructureElement.UnitIndex, + unit, unit.links.b[groupId] as StructureElement.UnitIndex ) ]) } diff --git a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts index eb4ffed1f450e0c598a74142f4fe8a5168c3f07b..29659c6d6a5a9070015e74f2a0cfb89be99c1346 100644 --- a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts @@ -7,14 +7,13 @@ import { Unit } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../shape/mesh'; -import { MeshBuilder } from '../../../shape/mesh-builder'; -import { getElementLoci, markElement } from './util/element'; +import { Mesh } from '../../../mesh/mesh'; +import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { getElementLoci, markElement, StructureElementIterator } from './util/element'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; 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 { StructureElementIterator } from './util/location-iterator'; import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; const p1 = Vec3.zero() @@ -30,6 +29,7 @@ const center = Vec3.zero() const t = Mat4.identity() const sVec = Vec3.zero() +// TODO define props, should be scalable async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, props: {}, mesh?: Mesh) { if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) @@ -88,7 +88,7 @@ async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, props: Vec3.scaleAndAdd(center, p1, v12, height / 2 - 0.2) Mat4.scale(t, t, Vec3.set(sVec, width, depth, height)) Mat4.setTranslation(t, center) - builder.setId(SortedArray.findPredecessorIndex(elements, idx6)) + builder.setGroup(SortedArray.findPredecessorIndex(elements, idx6)) builder.addBox(t) builder.addCylinder(p5, p6, 1, { radiusTop: 0.2, radiusBottom: 0.2 }) } diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts index a80dae5b8a1882a6e93e797c749797873a1f8367..ed141df814c330834c3ef894ee5388e4ed1e579a 100644 --- a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts @@ -7,12 +7,11 @@ import { Unit } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../shape/mesh'; -import { MeshBuilder } from '../../../shape/mesh-builder'; +import { Mesh } from '../../../mesh/mesh'; +import { MeshBuilder } from '../../../mesh/mesh-builder'; import { getPolymerElementCount, PolymerBackboneIterator } from './util/polymer'; -import { getElementLoci, markElement } from './util/element'; +import { getElementLoci, markElement, StructureElementIterator } from './util/element'; import { Vec3 } from 'mol-math/linear-algebra'; -import { StructureElementIterator } from './util/location-iterator'; import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { CylinderProps } from '../../../primitive/cylinder'; @@ -47,11 +46,11 @@ async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit pos(centerB.element, pB) cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerA) - builder.setId(OrderedSet.findPredecessorIndex(elements, centerA.element)) + builder.setGroup(OrderedSet.findPredecessorIndex(elements, centerA.element)) builder.addCylinder(pA, pB, 0.5, cylinderProps) cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(centerB) - builder.setId(OrderedSet.findPredecessorIndex(elements, centerB.element)) + builder.setGroup(OrderedSet.findPredecessorIndex(elements, centerB.element)) builder.addCylinder(pB, pA, 0.5, cylinderProps) if (i % 10000 === 0 && ctx.shouldUpdate) { diff --git a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts index b6eaf79647a2004288a76212be17ce0f6090618a..07b965453e6ed83a4a291a37ec9130ab941d3e3a 100644 --- a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts +++ b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts @@ -7,13 +7,12 @@ import { Unit } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { markElement, getElementLoci } from './util/element'; -import { Mesh } from '../../../shape/mesh'; -import { MeshBuilder } from '../../../shape/mesh-builder'; +import { markElement, getElementLoci, StructureElementIterator } from './util/element'; +import { Mesh } from '../../../mesh/mesh'; +import { MeshBuilder } from '../../../mesh/mesh-builder'; import { getPolymerElementCount, PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment } from './util/polymer'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { SecondaryStructureType, MoleculeType } from 'mol-model/structure/model/types'; -import { StructureElementIterator } from './util/location-iterator'; import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { OrderedSet } from 'mol-data/int'; @@ -49,7 +48,7 @@ async function createPolymerDirectionWedgeMesh(ctx: RuntimeContext, unit: Unit, const polymerTraceIt = PolymerTraceIterator(unit) while (polymerTraceIt.hasNext) { const v = polymerTraceIt.move() - builder.setId(OrderedSet.findPredecessorIndex(unit.elements, v.center.element)) + builder.setGroup(OrderedSet.findPredecessorIndex(unit.elements, v.center.element)) const isNucleic = v.moleculeType === MoleculeType.DNA || v.moleculeType === MoleculeType.RNA const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta) diff --git a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts index f5a12fdc6673a805a0e2a2c252ac2dc3b54476a1..e01feada50bdbb3e72ed9ea9bbd45bdfec4c36c6 100644 --- a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts @@ -7,12 +7,11 @@ import { Unit, StructureElement } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../shape/mesh'; -import { MeshBuilder } from '../../../shape/mesh-builder'; +import { Mesh } from '../../../mesh/mesh'; +import { MeshBuilder } from '../../../mesh/mesh-builder'; import { getPolymerGapCount, PolymerGapIterator } from './util/polymer'; -import { getElementLoci, markElement } from './util/element'; +import { getElementLoci, markElement, StructureElementIterator } from './util/element'; import { Vec3 } from 'mol-math/linear-algebra'; -import { StructureElementIterator } from './util/location-iterator'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { CylinderProps } from '../../../primitive/cylinder'; @@ -48,7 +47,7 @@ async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, pro while (polymerGapIt.hasNext) { const { centerA, centerB } = polymerGapIt.move() if (centerA.element === centerB.element) { - builder.setId(centerA.element) + builder.setGroup(centerA.element) pos(elements[centerA.element], pA) builder.addSphere(pA, 0.6, 0) } else { @@ -59,12 +58,12 @@ async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, pro l.element = elmA cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(l) - builder.setId(centerA.element) + builder.setGroup(centerA.element) builder.addFixedCountDashedCylinder(pA, pB, 0.5, segmentCount, cylinderProps) l.element = elmB cylinderProps.radiusTop = cylinderProps.radiusBottom = sizeTheme.size(l) - builder.setId(centerB.element) + builder.setGroup(centerB.element) builder.addFixedCountDashedCylinder(pB, pA, 0.5, segmentCount, cylinderProps) } diff --git a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts index da04a008c769a1214ee024875f64ee4dbe317e84..eb8efab672a2858fa1248f4fbe1afc10ce01e618 100644 --- a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts @@ -7,12 +7,11 @@ import { Unit } from 'mol-model/structure'; import { UnitsVisual, MeshUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { markElement, getElementLoci } from './util/element'; -import { Mesh } from '../../../shape/mesh'; -import { MeshBuilder } from '../../../shape/mesh-builder'; +import { markElement, getElementLoci, StructureElementIterator } from './util/element'; +import { Mesh } from '../../../mesh/mesh'; +import { MeshBuilder } from '../../../mesh/mesh-builder'; import { getPolymerElementCount, PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment } from './util/polymer'; import { SecondaryStructureType, MoleculeType } from 'mol-model/structure/model/types'; -import { StructureElementIterator } from './util/location-iterator'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { OrderedSet } from 'mol-data/int'; @@ -44,7 +43,7 @@ async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, props: Po const polymerTraceIt = PolymerTraceIterator(unit) while (polymerTraceIt.hasNext) { const v = polymerTraceIt.move() - builder.setId(OrderedSet.findPredecessorIndex(unit.elements, v.center.element)) + builder.setGroup(OrderedSet.findPredecessorIndex(unit.elements, v.center.element)) const isNucleic = v.moleculeType === MoleculeType.DNA || v.moleculeType === MoleculeType.RNA const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta) diff --git a/src/mol-geo/representation/structure/visual/util/common.ts b/src/mol-geo/representation/structure/visual/util/common.ts index 406abfd2e93c228f20e54db68ee8e7b29f4a7154..e069563c8771d3a7d6281a4f91720be24a3b6c27 100644 --- a/src/mol-geo/representation/structure/visual/util/common.ts +++ b/src/mol-geo/representation/structure/visual/util/common.ts @@ -8,11 +8,11 @@ import { Unit, Structure } from 'mol-model/structure'; import { Mat4 } from 'mol-math/linear-algebra' -import { createUniformColor, ColorData, createElementColor, createElementInstanceColor, createInstanceColor } from '../../../../util/color-data'; -import { createUniformSize, SizeData, createElementSize, createElementInstanceSize, createInstanceSize } from '../../../../util/size-data'; +import { createUniformColor, ColorData, createGroupColor, createGroupInstanceColor, createInstanceColor } from '../../../../util/color-data'; +import { createUniformSize, SizeData, createGroupSize, createGroupInstanceSize, createInstanceSize } from '../../../../util/size-data'; import { ValueCell } from 'mol-util'; -import { LocationIterator } from './location-iterator'; -import { Mesh } from '../../../../shape/mesh'; +import { LocationIterator } from '../../../../util/location-iterator'; +import { Mesh } from '../../../../mesh/mesh'; import { MeshValues } from 'mol-gl/renderable'; import { getMeshData } from '../../../../util/mesh-data'; import { MeshProps, createMeshValues, createRenderableState, createIdentityTransform } from '../../../util'; @@ -36,8 +36,8 @@ export function createColors(locationIt: LocationIterator, props: ColorThemeProp const colorTheme = ColorTheme(props) switch (colorTheme.kind) { case 'uniform': return createUniformColor(locationIt, colorTheme.color, colorData) - case 'element': return createElementColor(locationIt, colorTheme.color, colorData) - case 'elementInstance': return createElementInstanceColor(locationIt, colorTheme.color, colorData) + case 'group': return createGroupColor(locationIt, colorTheme.color, colorData) + case 'groupInstance': return createGroupInstanceColor(locationIt, colorTheme.color, colorData) case 'instance': return createInstanceColor(locationIt, colorTheme.color, colorData) } } @@ -46,8 +46,8 @@ export function createSizes(locationIt: LocationIterator, props: SizeThemeProps, const sizeTheme = SizeTheme(props) switch (sizeTheme.kind) { case 'uniform': return createUniformSize(locationIt, sizeTheme.size, sizeData) - case 'element': return createElementSize(locationIt, sizeTheme.size, sizeData) - case 'elementInstance': return createElementInstanceSize(locationIt, sizeTheme.size, sizeData) + case 'group': return createGroupSize(locationIt, sizeTheme.size, sizeData) + case 'groupInstance': return createGroupInstanceSize(locationIt, sizeTheme.size, sizeData) case 'instance': return createInstanceSize(locationIt, sizeTheme.size, sizeData) } } @@ -55,11 +55,11 @@ export function createSizes(locationIt: LocationIterator, props: SizeThemeProps, type StructureMeshProps = Required<MeshProps & StructureProps> function _createMeshValues(transforms: ValueCell<Float32Array>, mesh: Mesh, locationIt: LocationIterator, props: StructureMeshProps): MeshValues { - const { instanceCount, elementCount } = locationIt + const { instanceCount, groupCount } = locationIt const color = createColors(locationIt, props.colorTheme) - const marker = createMarkers(instanceCount * elementCount) + const marker = createMarkers(instanceCount * groupCount) - const counts = { drawCount: mesh.triangleCount * 3, elementCount, instanceCount } + const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount } return { ...getMeshData(mesh), diff --git a/src/mol-geo/representation/structure/visual/util/element.ts b/src/mol-geo/representation/structure/visual/util/element.ts index 89934754869f743e1321cadd11697e14e4296517..dd1ea7d1314e10815b4eefdd0829973c3dbff467 100644 --- a/src/mol-geo/representation/structure/visual/util/element.ts +++ b/src/mol-geo/representation/structure/visual/util/element.ts @@ -8,12 +8,13 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Unit, StructureElement } from 'mol-model/structure'; import { RuntimeContext } from 'mol-task'; import { sphereVertexCount } from '../../../../primitive/sphere'; -import { Mesh } from '../../../../shape/mesh'; -import { MeshBuilder } from '../../../../shape/mesh-builder'; +import { Mesh } from '../../../../mesh/mesh'; +import { MeshBuilder } from '../../../../mesh/mesh-builder'; import { Loci, EmptyLoci } from 'mol-model/loci'; 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'; export interface ElementSphereMeshProps { sizeTheme: SizeThemeProps, @@ -38,7 +39,7 @@ export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, p l.element = elements[i] pos(elements[i], v) - meshBuilder.setId(i) + meshBuilder.setGroup(i) meshBuilder.addSphere(v, sizeTheme.size(l), detail) if (i % 10000 === 0 && ctx.shouldUpdate) { @@ -74,11 +75,25 @@ export function markElement(loci: Loci, group: Unit.SymmetryGroup, apply: (inter } export function getElementLoci(pickingId: PickingId, group: Unit.SymmetryGroup, id: number) { - const { objectId, instanceId, elementId } = pickingId + const { objectId, instanceId, groupId } = pickingId if (id === objectId) { const unit = group.units[instanceId] - const indices = OrderedSet.ofSingleton(elementId as StructureElement.UnitIndex); + const indices = OrderedSet.ofSingleton(groupId as StructureElement.UnitIndex); return StructureElement.Loci([{ unit, indices }]) } return EmptyLoci +} + +export namespace StructureElementIterator { + export function fromGroup(group: Unit.SymmetryGroup): LocationIterator { + const unit = group.units[0] + const groupCount = group.elements.length + const instanceCount = group.units.length + const location = StructureElement.create(unit) + const getLocation = (groupIndex: number) => { + location.element = unit.elements[groupIndex] + return location + } + return LocationIterator(groupCount, instanceCount, getLocation) + } } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-geo/representation/structure/visual/util/link.ts index fa687917bbe58f663a6f17704de70c78d5a1341e..f41776cfc29091f0beb02c9bdb9cc5e86bcf4ddd 100644 --- a/src/mol-geo/representation/structure/visual/util/link.ts +++ b/src/mol-geo/representation/structure/visual/util/link.ts @@ -6,12 +6,14 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { RuntimeContext } from 'mol-task'; -import { Mesh } from '../../../../shape/mesh'; -import { MeshBuilder } from '../../../../shape/mesh-builder'; +import { Mesh } from '../../../../mesh/mesh'; +import { MeshBuilder } from '../../../../mesh/mesh-builder'; import { LinkType } from 'mol-model/structure/model/types'; import { DefaultMeshProps } from '../../../util'; 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'; export const DefaultLinkCylinderProps = { ...DefaultMeshProps, @@ -87,7 +89,7 @@ export async function createLinkCylinderMesh(ctx: RuntimeContext, linkBuilder: L const linkRadius = radius(edgeIndex) const o = order(edgeIndex) const f = flags(edgeIndex) - meshBuilder.setId(edgeIndex) + meshBuilder.setGroup(edgeIndex) if (LinkType.is(f, LinkType.Flag.MetallicCoordination)) { // show metall coordinations with dashed cylinders @@ -116,4 +118,33 @@ export async function createLinkCylinderMesh(ctx: RuntimeContext, linkBuilder: L } return meshBuilder.getMesh() +} + +export namespace LinkIterator { + export function fromGroup(group: Unit.SymmetryGroup): LocationIterator { + const unit = group.units[0] + const groupCount = Unit.isAtomic(unit) ? unit.links.edgeCount * 2 : 0 + const instanceCount = group.units.length + const location = StructureElement.create(unit) + const getLocation = (groupIndex: number) => { + location.element = unit.elements[(unit as Unit.Atomic).links.a[groupIndex]] + return location + } + return LocationIterator(groupCount, instanceCount, getLocation) + } + + export function fromStructure(structure: Structure): LocationIterator { + const groupCount = structure.links.bondCount + const instanceCount = 1 + const location = Link.Location() + const getLocation = (groupIndex: number) => { + const bond = structure.links.bonds[groupIndex] + location.aUnit = bond.unitA + location.aIndex = bond.indexA as StructureElement.UnitIndex + location.bUnit = bond.unitB + location.bIndex = bond.indexB as StructureElement.UnitIndex + return location + } + return LocationIterator(groupCount, instanceCount, getLocation) + } } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/util/location-iterator.ts b/src/mol-geo/representation/structure/visual/util/location-iterator.ts deleted file mode 100644 index aad0da64abdedce9ec3d4221379b91f56e256255..0000000000000000000000000000000000000000 --- a/src/mol-geo/representation/structure/visual/util/location-iterator.ts +++ /dev/null @@ -1,141 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import { Iterator } from 'mol-data'; -import { Unit, StructureElement, Structure, Link } from 'mol-model/structure'; -import { NullLocation, Location } from 'mol-model/location'; - -export interface LocationValue { - location: Location - index: number - elementIndex: number - instanceIndex: number - isSecondary: boolean -} - -export const NullLocationValue: LocationValue = { - location: NullLocation, - index: 0, - elementIndex: 0, - instanceIndex: 0, - isSecondary: false -} - -export interface LocationIterator extends Iterator<LocationValue> { - readonly hasNext: boolean - readonly isNextNewInstance: boolean - readonly elementCount: number - readonly instanceCount: number - move(): LocationValue - reset(): void - skipInstance(): void -} - -type LocationGetter = (elementIndex: number, instanceIndex: number) => Location -type IsSecondaryGetter = (elementIndex: number, instanceIndex: number) => boolean - -export function LocationIterator(elementCount: number, instanceCount: number, getLocation: LocationGetter, isSecondary: IsSecondaryGetter = () => false): LocationIterator { - const value: LocationValue = { - location: NullLocation as Location, - index: 0, - elementIndex: 0, - instanceIndex: 0, - isSecondary: false - } - - let hasNext = value.elementIndex < elementCount - let isNextNewInstance = false - let elementIndex = 0 - let instanceIndex = 0 - - return { - get hasNext () { return hasNext }, - get isNextNewInstance () { return isNextNewInstance }, - get elementCount () { return elementCount }, - get instanceCount () { return instanceCount }, - move() { - if (hasNext) { - value.elementIndex = elementIndex - value.instanceIndex = instanceIndex - value.index = instanceIndex * elementCount + elementIndex - value.location = getLocation(elementIndex, instanceIndex) - value.isSecondary = isSecondary(elementIndex, instanceIndex) - ++elementIndex - if (elementIndex === elementCount) { - ++instanceIndex - isNextNewInstance = true - if (instanceIndex < instanceCount) elementIndex = 0 - } else { - isNextNewInstance = false - } - hasNext = elementIndex < elementCount - } - return value - }, - reset() { - value.location = NullLocation - value.index = 0 - value.elementIndex = 0 - value.instanceIndex = 0 - value.isSecondary = false - - hasNext = value.elementIndex < elementCount - isNextNewInstance = false - elementIndex = 0 - instanceIndex = 0 - }, - skipInstance() { - if (hasNext && value.instanceIndex === instanceIndex) { - ++instanceIndex - elementIndex = 0 - hasNext = instanceIndex < instanceCount - } - } - } -} - -export namespace StructureElementIterator { - export function fromGroup(group: Unit.SymmetryGroup): LocationIterator { - const unit = group.units[0] - const elementCount = group.elements.length - const instanceCount = group.units.length - const location = StructureElement.create(unit) - const getLocation = (elementIndex: number) => { - location.element = unit.elements[elementIndex] - return location - } - return LocationIterator(elementCount, instanceCount, getLocation) - } -} - -export namespace LinkIterator { - export function fromGroup(group: Unit.SymmetryGroup): LocationIterator { - const unit = group.units[0] - const elementCount = Unit.isAtomic(unit) ? unit.links.edgeCount * 2 : 0 - const instanceCount = group.units.length - const location = StructureElement.create(unit) - const getLocation = (elementIndex: number) => { - location.element = unit.elements[(unit as Unit.Atomic).links.a[elementIndex]] - return location - } - return LocationIterator(elementCount, instanceCount, getLocation) - } - - export function fromStructure(structure: Structure): LocationIterator { - const elementCount = structure.links.bondCount - const instanceCount = 1 - const location = Link.Location() - const getLocation = (elementIndex: number) => { - const bond = structure.links.bonds[elementIndex] - location.aUnit = bond.unitA - location.aIndex = bond.indexA as StructureElement.UnitIndex - location.bUnit = bond.unitB - location.bIndex = bond.indexB as StructureElement.UnitIndex - return location - } - return LocationIterator(elementCount, instanceCount, getLocation) - } -} \ No newline at end of file diff --git a/src/mol-geo/representation/util.ts b/src/mol-geo/representation/util.ts index 410623a925372b241e4c3e4f28e5f6c578b99b10..4edca150e52f42e76d67a5b28fd3f76754d4ed19 100644 --- a/src/mol-geo/representation/util.ts +++ b/src/mol-geo/representation/util.ts @@ -35,14 +35,14 @@ export function createIdentityTransform(transforms?: ValueCell<Float32Array>) { return transforms ? ValueCell.update(transforms, identityTransform) : ValueCell.create(identityTransform) } -type Counts = { drawCount: number, elementCount: number, instanceCount: number } +type Counts = { drawCount: number, groupCount: number, instanceCount: number } export function createBaseValues(props: Required<BaseProps>, counts: Counts) { return { uAlpha: ValueCell.create(props.alpha), uInstanceCount: ValueCell.create(counts.instanceCount), - uElementCount: ValueCell.create(counts.elementCount), - aInstanceId: ValueCell.create(fillSerial(new Float32Array(counts.instanceCount))), + uGroupCount: ValueCell.create(counts.groupCount), + aInstance: ValueCell.create(fillSerial(new Float32Array(counts.instanceCount))), drawCount: ValueCell.create(counts.drawCount), instanceCount: ValueCell.create(counts.instanceCount), } diff --git a/src/mol-geo/representation/volume/surface.ts b/src/mol-geo/representation/volume/surface.ts index 82e1a5e25afe79e404090c57ccc08157740ebed8..1d289273d6e5783431b9185c98c8d09c3d1778ae 100644 --- a/src/mol-geo/representation/volume/surface.ts +++ b/src/mol-geo/representation/volume/surface.ts @@ -8,7 +8,7 @@ import { VolumeData, VolumeIsoValue } from 'mol-model/volume' import { Task, RuntimeContext } from 'mol-task' import { computeMarchingCubes } from '../../util/marching-cubes/algorithm'; -import { Mesh } from '../../shape/mesh'; +import { Mesh } from '../../mesh/mesh'; import { VolumeVisual } from '.'; import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'; import { ValueCell, defaults } from 'mol-util'; @@ -72,13 +72,13 @@ export default function SurfaceVisual(): VolumeVisual<SurfaceProps> { const values: MeshValues = { ...getMeshData(mesh), aTransform: ValueCell.create(new Float32Array(Mat4.identity())), - aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), + aInstance: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, ...marker, uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), uInstanceCount: ValueCell.create(instanceCount), - uElementCount: ValueCell.create(mesh.triangleCount), + uGroupCount: ValueCell.create(mesh.triangleCount), elements: mesh.indexBuffer, diff --git a/src/mol-geo/shape/vertex-map.ts b/src/mol-geo/shape/vertex-map.ts deleted file mode 100644 index 0211ed33334dc08b5a065d9dc7250d88fc156450..0000000000000000000000000000000000000000 --- a/src/mol-geo/shape/vertex-map.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import { ChunkedArray } from 'mol-data/util'; -import { Mesh } from './mesh'; - -/** Mapping between vertices and ids */ -interface VertexMap { - idCount: number, - offsetCount: number, - ids: Helpers.NumberArray - offsets: Uint32Array, -} - -function createOffsets(idCount: number, ids: Helpers.NumberArray) { - const offsets = ChunkedArray.create(Uint32Array, 1, 1024, 2048); - let prevId = ids[0] - ChunkedArray.add(offsets, 0) - for (let i = 1; i < idCount; ++i) { - if (prevId !== ids[i]) { - prevId = ids[i] - ChunkedArray.add(offsets, i) - } - } - ChunkedArray.add(offsets, idCount) - return ChunkedArray.compact(offsets, false) as Uint32Array -} - -namespace VertexMap { - export function create(idCount: number, offsetCount: number, ids: Helpers.NumberArray, offsets: Uint32Array): VertexMap { - return { - idCount, - offsetCount, - ids, - offsets - } - } - - export function fromMesh(mesh: Mesh) { - const ids = mesh.idBuffer.ref.value - const offsets = createOffsets(mesh.vertexCount, ids) - return create(mesh.vertexCount, offsets.length, ids, offsets) - } - - export function rangeFromId (id: number, vertexMap: VertexMap) { - return [0, 0] - } -} - -export default VertexMap \ No newline at end of file diff --git a/src/mol-geo/util/color-data.ts b/src/mol-geo/util/color-data.ts index 47e7eaf1d2383bdcc81eebf46a45d6864b1fb913..d8f0c3d2e72397637ce8d6064e6d834e31dfeb8b 100644 --- a/src/mol-geo/util/color-data.ts +++ b/src/mol-geo/util/color-data.ts @@ -8,16 +8,16 @@ import { ValueCell } from 'mol-util'; import { TextureImage, createTextureImage } from 'mol-gl/renderable/util'; import { Color } from 'mol-util/color'; import { Vec2, Vec3 } from 'mol-math/linear-algebra'; -import { LocationIterator } from '../representation/structure/visual/util/location-iterator'; +import { LocationIterator } from './location-iterator'; import { Location, NullLocation } from 'mol-model/location'; -export type ColorType = 'uniform' | 'instance' | 'element' | 'elementInstance' +export type ColorType = 'uniform' | 'instance' | 'group' | 'groupInstance' export type ColorData = { uColor: ValueCell<Vec3>, aColor: ValueCell<Float32Array>, tColor: ValueCell<TextureImage>, - uColorTexSize: ValueCell<Vec2>, + uColorTexDim: ValueCell<Vec2>, dColorType: ValueCell<string>, } @@ -27,7 +27,7 @@ const emptyColorTexture = { array: new Uint8Array(3), width: 1, height: 1 } function createEmptyColorTexture() { return { tColor: ValueCell.create(emptyColorTexture), - uColorTexSize: ValueCell.create(Vec2.create(1, 1)) + uColorTexDim: ValueCell.create(Vec2.create(1, 1)) } } @@ -56,7 +56,7 @@ export function createUniformColor(locationIt: LocationIterator, colorFn: Locati export function createTextureColor(colors: TextureImage, type: ColorType, colorData?: ColorData): ColorData { if (colorData) { ValueCell.update(colorData.tColor, colors) - ValueCell.update(colorData.uColorTexSize, Vec2.create(colors.width, colors.height)) + ValueCell.update(colorData.uColorTexDim, Vec2.create(colors.width, colors.height)) if (colorData.dColorType.ref.value !== type) { ValueCell.update(colorData.dColorType, type) } @@ -66,7 +66,7 @@ export function createTextureColor(colors: TextureImage, type: ColorType, colorD uColor: ValueCell.create(Vec3.zero()), aColor: ValueCell.create(new Float32Array(0)), tColor: ValueCell.create(colors), - uColorTexSize: ValueCell.create(Vec2.create(colors.width, colors.height)), + uColorTexDim: ValueCell.create(Vec2.create(colors.width, colors.height)), dColorType: ValueCell.create(type), } } @@ -84,25 +84,25 @@ export function createInstanceColor(locationIt: LocationIterator, colorFn: Locat return createTextureColor(colors, 'instance', colorData) } -/** Creates color texture with color for each element (i.e. shared across instances/units) */ -export function createElementColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData { - const { elementCount } = locationIt - const colors = colorData && colorData.tColor.ref.value.array.length >= elementCount * 3 ? colorData.tColor.ref.value : createTextureImage(elementCount, 3) +/** Creates color texture with color for each group (i.e. shared across instances/units) */ +export function createGroupColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData { + const { groupCount } = locationIt + const colors = colorData && colorData.tColor.ref.value.array.length >= groupCount * 3 ? colorData.tColor.ref.value : createTextureImage(groupCount, 3) while (locationIt.hasNext && !locationIt.isNextNewInstance) { - const { location, isSecondary, elementIndex } = locationIt.move() - Color.toArray(colorFn(location, isSecondary), colors.array, elementIndex * 3) + const { location, isSecondary, groupIndex } = locationIt.move() + Color.toArray(colorFn(location, isSecondary), colors.array, groupIndex * 3) } - return createTextureColor(colors, 'element', colorData) + return createTextureColor(colors, 'group', colorData) } -/** Creates color texture with color for each element instance (i.e. for each unit) */ -export function createElementInstanceColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData { - const { elementCount, instanceCount } = locationIt - const count = instanceCount * elementCount +/** Creates color texture with color for each group in each instance (i.e. for each unit) */ +export function createGroupInstanceColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData { + const { groupCount, instanceCount } = locationIt + const count = instanceCount * groupCount const colors = colorData && colorData.tColor.ref.value.array.length >= count * 3 ? colorData.tColor.ref.value : createTextureImage(count, 3) while (locationIt.hasNext && !locationIt.isNextNewInstance) { const { location, isSecondary, index } = locationIt.move() Color.toArray(colorFn(location, isSecondary), colors.array, index * 3) } - return createTextureColor(colors, 'elementInstance', colorData) + return createTextureColor(colors, 'groupInstance', colorData) } \ No newline at end of file diff --git a/src/mol-geo/util/location-iterator.ts b/src/mol-geo/util/location-iterator.ts new file mode 100644 index 0000000000000000000000000000000000000000..435d0c45c3be8181456098ec99331c4cf7f579d5 --- /dev/null +++ b/src/mol-geo/util/location-iterator.ts @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Iterator } from 'mol-data'; +import { NullLocation, Location } from 'mol-model/location'; + +export interface LocationValue { + location: Location + index: number + groupIndex: number + instanceIndex: number + isSecondary: boolean +} + +export const NullLocationValue: LocationValue = { + location: NullLocation, + index: 0, + groupIndex: 0, + instanceIndex: 0, + isSecondary: false +} + +export interface LocationIterator extends Iterator<LocationValue> { + readonly hasNext: boolean + readonly isNextNewInstance: boolean + readonly groupCount: number + readonly instanceCount: number + move(): LocationValue + reset(): void + skipInstance(): void +} + +type LocationGetter = (groupIndex: number, instanceIndex: number) => Location +type IsSecondaryGetter = (groupIndex: number, instanceIndex: number) => boolean + +export function LocationIterator(groupCount: number, instanceCount: number, getLocation: LocationGetter, isSecondary: IsSecondaryGetter = () => false): LocationIterator { + const value: LocationValue = { + location: NullLocation as Location, + index: 0, + groupIndex: 0, + instanceIndex: 0, + isSecondary: false + } + + let hasNext = value.groupIndex < groupCount + let isNextNewInstance = false + let groupIndex = 0 + let instanceIndex = 0 + + return { + get hasNext () { return hasNext }, + get isNextNewInstance () { return isNextNewInstance }, + get groupCount () { return groupCount }, + get instanceCount () { return instanceCount }, + move() { + if (hasNext) { + value.groupIndex = groupIndex + value.instanceIndex = instanceIndex + value.index = instanceIndex * groupCount + groupIndex + value.location = getLocation(groupIndex, instanceIndex) + value.isSecondary = isSecondary(groupIndex, instanceIndex) + ++groupIndex + if (groupIndex === groupCount) { + ++instanceIndex + isNextNewInstance = true + if (instanceIndex < instanceCount) groupIndex = 0 + } else { + isNextNewInstance = false + } + hasNext = groupIndex < groupCount + } + return value + }, + reset() { + value.location = NullLocation + value.index = 0 + value.groupIndex = 0 + value.instanceIndex = 0 + value.isSecondary = false + + hasNext = value.groupIndex < groupCount + isNextNewInstance = false + groupIndex = 0 + instanceIndex = 0 + }, + skipInstance() { + if (hasNext && value.instanceIndex === instanceIndex) { + ++instanceIndex + groupIndex = 0 + hasNext = instanceIndex < instanceCount + } + } + } +} \ No newline at end of file diff --git a/src/mol-geo/util/marching-cubes/algorithm.ts b/src/mol-geo/util/marching-cubes/algorithm.ts index 4b2eaf964996164cd06ccdebd141e8a57b8a20ce..f636ff582c8160ce384eea92873779f726301a0f 100644 --- a/src/mol-geo/util/marching-cubes/algorithm.ts +++ b/src/mol-geo/util/marching-cubes/algorithm.ts @@ -7,7 +7,7 @@ import { Task, RuntimeContext } from 'mol-task' import { ChunkedArray } from 'mol-data/util' import { Tensor } from 'mol-math/linear-algebra' -import { Mesh } from '../../shape/mesh' +import { Mesh } from '../../mesh/mesh' import { Index, EdgeIdInfo, CubeEdges, EdgeTable, TriTable } from './tables' import { ValueCell } from 'mol-util' @@ -76,18 +76,15 @@ class MarchingCubesComputation { const ret: Mesh = { vertexCount: this.state.vertexCount, triangleCount: this.state.triangleCount, - offsetCount: 0, vertexBuffer: os ? ValueCell.update(os.vertexBuffer, vb) : ValueCell.create(vb), indexBuffer: os ? ValueCell.update(os.indexBuffer, ib) : ValueCell.create(ib), normalBuffer: os ? os.normalBuffer : ValueCell.create(new Float32Array(0)), - idBuffer: this.state.assignIds - ? os && os.idBuffer - ? ValueCell.update(os.idBuffer, ChunkedArray.compact(this.state.idBuffer) as Float32Array) + groupBuffer: this.state.assignIds + ? os && os.groupBuffer + ? ValueCell.update(os.groupBuffer, ChunkedArray.compact(this.state.idBuffer) as Float32Array) : ValueCell.create(ChunkedArray.compact(this.state.idBuffer) as Float32Array) : ValueCell.create(new Float32Array(0)), - offsetBuffer: os ? os.offsetBuffer : ValueCell.create(new Uint32Array(0)), - normalsComputed: false, - offsetsComputed: false + normalsComputed: false } return ret; diff --git a/src/mol-geo/util/marker-data.ts b/src/mol-geo/util/marker-data.ts index 93fa6b5c21fd5684735d1784d6602d9239e30756..55dc2494560d9bc734dba5a1a11f73f835f797b7 100644 --- a/src/mol-geo/util/marker-data.ts +++ b/src/mol-geo/util/marker-data.ts @@ -10,7 +10,7 @@ import { TextureImage, createTextureImage } from 'mol-gl/renderable/util'; export type MarkerData = { tMarker: ValueCell<TextureImage> - uMarkerTexSize: ValueCell<Vec2> + uMarkerTexDim: ValueCell<Vec2> } export enum MarkerAction { @@ -77,26 +77,26 @@ export function createMarkers(count: number, markerData?: MarkerData): MarkerDat : createTextureImage(count, 1) if (markerData) { ValueCell.update(markerData.tMarker, markers) - ValueCell.update(markerData.uMarkerTexSize, Vec2.create(markers.width, markers.height)) + ValueCell.update(markerData.uMarkerTexDim, Vec2.create(markers.width, markers.height)) return markerData } else { return { tMarker: ValueCell.create(markers), - uMarkerTexSize: ValueCell.create(Vec2.create(markers.width, markers.height)), + uMarkerTexDim: ValueCell.create(Vec2.create(markers.width, markers.height)), } } } const emptyMarkerTexture = { array: new Uint8Array(1), width: 1, height: 1 } -export function createEmptyMarkers(markerData?: MarkerData) { +export function createEmptyMarkers(markerData?: MarkerData): MarkerData { if (markerData) { ValueCell.update(markerData.tMarker, emptyMarkerTexture) - ValueCell.update(markerData.uMarkerTexSize, Vec2.create(1, 1)) + ValueCell.update(markerData.uMarkerTexDim, Vec2.create(1, 1)) return markerData } else { return { tMarker: ValueCell.create(emptyMarkerTexture), - uMarkerTexSize: ValueCell.create(Vec2.create(1, 1)), + uMarkerTexDim: ValueCell.create(Vec2.create(1, 1)), } } } \ No newline at end of file diff --git a/src/mol-geo/util/mesh-data.ts b/src/mol-geo/util/mesh-data.ts index 9fd9add8ec596c4dc8bd917b777adcaf4a9d2784..0451ee98a8bfee2d7e2790c69a40a3144ca6ba69 100644 --- a/src/mol-geo/util/mesh-data.ts +++ b/src/mol-geo/util/mesh-data.ts @@ -5,18 +5,18 @@ */ import { ValueCell } from 'mol-util/value-cell' -import { Mesh } from '../shape/mesh'; +import { Mesh } from '../mesh/mesh'; type MeshData = { aPosition: ValueCell<Float32Array>, aNormal: ValueCell<Float32Array>, - aElementId: ValueCell<Float32Array>, + aGroup: ValueCell<Float32Array>, } export function getMeshData(mesh: Mesh): MeshData { return { aPosition: mesh.vertexBuffer, aNormal: mesh.normalBuffer, - aElementId: mesh.idBuffer, + aGroup: mesh.groupBuffer, } } \ No newline at end of file diff --git a/src/mol-geo/util/picking.ts b/src/mol-geo/util/picking.ts index 00d12d6fd6d297ad232fb81720eb0dc8dd63f252..07f2bf743ea1d5b18717a002910ce1a246684cb0 100644 --- a/src/mol-geo/util/picking.ts +++ b/src/mol-geo/util/picking.ts @@ -18,7 +18,7 @@ export function decodeIdRGBA(r: number, g: number, b: number) { export interface PickingId { objectId: number instanceId: number - elementId: number + groupId: number } export interface PickingInfo { diff --git a/src/mol-geo/util/size-data.ts b/src/mol-geo/util/size-data.ts index 25573107e59c5a52ba3541af8b41e649207c6a3a..f1a59a8fa6448b1931576d5d8c3b3b2f4e0af48c 100644 --- a/src/mol-geo/util/size-data.ts +++ b/src/mol-geo/util/size-data.ts @@ -7,16 +7,16 @@ import { ValueCell } from 'mol-util'; import { Vec2 } from 'mol-math/linear-algebra'; import { TextureImage, createTextureImage } from 'mol-gl/renderable/util'; -import { LocationIterator } from '../representation/structure/visual/util/location-iterator'; +import { LocationIterator } from './location-iterator'; import { Location, NullLocation } from 'mol-model/location'; -export type SizeType = 'uniform' | 'instance' | 'element' | 'elementInstance' +export type SizeType = 'uniform' | 'instance' | 'group' | 'groupInstance' export type SizeData = { uSize: ValueCell<number>, aSize: ValueCell<Float32Array>, tSize: ValueCell<TextureImage>, - uSizeTexSize: ValueCell<Vec2>, + uSizeTexDim: ValueCell<Vec2>, dSizeType: ValueCell<string>, } @@ -26,7 +26,7 @@ const emptySizeTexture = { array: new Uint8Array(1), width: 1, height: 1 } function createEmptySizeTexture() { return { tSize: ValueCell.create(emptySizeTexture), - uSizeTexSize: ValueCell.create(Vec2.create(1, 1)) + uSizeTexDim: ValueCell.create(Vec2.create(1, 1)) } } @@ -55,7 +55,7 @@ export function createUniformSize(locationIt: LocationIterator, sizeFn: Location export function createTextureSize(sizes: TextureImage, type: SizeType, sizeData?: SizeData): SizeData { if (sizeData) { ValueCell.update(sizeData.tSize, sizes) - ValueCell.update(sizeData.uSizeTexSize, Vec2.create(sizes.width, sizes.height)) + ValueCell.update(sizeData.uSizeTexDim, Vec2.create(sizes.width, sizes.height)) if (sizeData.dSizeType.ref.value !== type) { ValueCell.update(sizeData.dSizeType, type) } @@ -65,7 +65,7 @@ export function createTextureSize(sizes: TextureImage, type: SizeType, sizeData? uSize: ValueCell.create(0), aSize: ValueCell.create(new Float32Array(0)), tSize: ValueCell.create(sizes), - uSizeTexSize: ValueCell.create(Vec2.create(sizes.width, sizes.height)), + uSizeTexDim: ValueCell.create(Vec2.create(sizes.width, sizes.height)), dSizeType: ValueCell.create(type), } } @@ -83,25 +83,25 @@ export function createInstanceSize(locationIt: LocationIterator, sizeFn: Locatio return createTextureSize(sizes, 'instance', sizeData) } -/** Creates size texture with size for each element (i.e. shared across instances/units) */ -export function createElementSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { - const { elementCount } = locationIt - const sizes = sizeData && sizeData.tSize.ref.value.array.length >= elementCount ? sizeData.tSize.ref.value : createTextureImage(elementCount, 1) +/** Creates size texture with size for each group (i.e. shared across instances/units) */ +export function createGroupSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { + const { groupCount } = locationIt + const sizes = sizeData && sizeData.tSize.ref.value.array.length >= groupCount ? sizeData.tSize.ref.value : createTextureImage(groupCount, 1) while (locationIt.hasNext && !locationIt.isNextNewInstance) { const v = locationIt.move() - sizes.array[v.elementIndex] = sizeFn(v.location) + sizes.array[v.groupIndex] = sizeFn(v.location) } - return createTextureSize(sizes, 'element', sizeData) + return createTextureSize(sizes, 'group', sizeData) } -/** Creates size texture with size for each element instance (i.e. for each unit) */ -export function createElementInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { - const { elementCount, instanceCount } = locationIt - const count = instanceCount * elementCount +/** Creates size texture with size for each group in each instance (i.e. for each unit) */ +export function createGroupInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { + const { groupCount, instanceCount } = locationIt + const count = instanceCount * groupCount const sizes = sizeData && sizeData.tSize.ref.value.array.length >= count ? sizeData.tSize.ref.value : createTextureImage(count, 1) while (locationIt.hasNext && !locationIt.isNextNewInstance) { const v = locationIt.move() sizes.array[v.index] = sizeFn(v.location) } - return createTextureSize(sizes, 'elementInstance', sizeData) + return createTextureSize(sizes, 'groupInstance', sizeData) } \ No newline at end of file diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts index f6474217fbdd9a30d4a59a4e184843b37192a348..e4d5b6c6cbf4230d2d8618c3a47fbd4dd9a5fe3f 100644 --- a/src/mol-gl/_spec/renderer.spec.ts +++ b/src/mol-gl/_spec/renderer.spec.ts @@ -46,8 +46,8 @@ function createRenderer(gl: WebGLRenderingContext) { function createPoints() { const aPosition = ValueCell.create(new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0])) - const aElementId = ValueCell.create(fillSerial(new Float32Array(3))) - const aInstanceId = ValueCell.create(fillSerial(new Float32Array(1))) + const aGroup = ValueCell.create(fillSerial(new Float32Array(3))) + const aInstance = ValueCell.create(fillSerial(new Float32Array(1))) const color = createValueColor(Color(0xFF0000)) const size = createValueSize(1) const marker = createEmptyMarkers() @@ -58,16 +58,16 @@ function createPoints() { const values: PointValues = { aPosition, - aElementId, + aGroup, aTransform, - aInstanceId, + aInstance, ...color, ...marker, ...size, uAlpha: ValueCell.create(1.0), uInstanceCount: ValueCell.create(1), - uElementCount: ValueCell.create(3), + uGroupCount: ValueCell.create(3), drawCount: ValueCell.create(3), instanceCount: ValueCell.create(1), diff --git a/src/mol-gl/renderable/point.ts b/src/mol-gl/renderable/point.ts index 155c3f2069d12c341cd12f3db63412e33daf3fa4..f229413889610ccd4ff9a160476debd2fcc33b9b 100644 --- a/src/mol-gl/renderable/point.ts +++ b/src/mol-gl/renderable/point.ts @@ -15,7 +15,7 @@ export const PointSchema = { ...BaseSchema, aSize: AttributeSpec('float32', 1, 0), uSize: UniformSpec('f'), - uSizeTexSize: UniformSpec('v2'), + uSizeTexDim: UniformSpec('v2'), tSize: TextureSpec('alpha', 'ubyte'), dSizeType: DefineSpec('string', ['uniform', 'attribute']), dPointSizeAttenuation: DefineSpec('boolean'), diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index adfa5985b56104dc556ab8938b7d672fdc9a8ab7..7364e731b384e90cfe0224981c202a60e232f4ee 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -142,18 +142,18 @@ export const InternalSchema = { } export const BaseSchema = { - aInstanceId: AttributeSpec('float32', 1, 1), + aInstance: AttributeSpec('float32', 1, 1), aPosition: AttributeSpec('float32', 3, 0), - aElementId: AttributeSpec('float32', 1, 0), + aGroup: AttributeSpec('float32', 1, 0), aTransform: AttributeSpec('float32', 16, 1), aColor: AttributeSpec('float32', 3, 0), uAlpha: UniformSpec('f'), uInstanceCount: UniformSpec('i'), - uElementCount: UniformSpec('i'), + uGroupCount: UniformSpec('i'), uColor: UniformSpec('v3'), - uColorTexSize: UniformSpec('v2'), - uMarkerTexSize: UniformSpec('v2'), + uColorTexDim: UniformSpec('v2'), + uMarkerTexDim: UniformSpec('v2'), tColor: TextureSpec('rgb', 'ubyte'), tMarker: TextureSpec('alpha', 'ubyte'), @@ -161,7 +161,7 @@ export const BaseSchema = { drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), - dColorType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'element', 'element_instance']), + dColorType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']), dUseFog: DefineSpec('boolean'), } export type BaseSchema = typeof BaseSchema diff --git a/src/mol-gl/shader/chunks/assign-color-varying.glsl b/src/mol-gl/shader/chunks/assign-color-varying.glsl index b5848197a89b908cb5664869d1206f90eb222042..f4f5dad7358e2e52f052023500745156e891bd75 100644 --- a/src/mol-gl/shader/chunks/assign-color-varying.glsl +++ b/src/mol-gl/shader/chunks/assign-color-varying.glsl @@ -1,15 +1,15 @@ #if defined(dColorType_attribute) vColor.rgb = aColor; #elif defined(dColorType_instance) - vColor.rgb = readFromTexture(tColor, aInstanceId, uColorTexSize).rgb; -#elif defined(dColorType_element) - vColor.rgb = readFromTexture(tColor, aElementId, uColorTexSize).rgb; -#elif defined(dColorType_elementInstance) - vColor.rgb = readFromTexture(tColor, aInstanceId * float(uElementCount) + aElementId, uColorTexSize).rgb; + vColor.rgb = readFromTexture(tColor, aInstance, uColorTexDim).rgb; +#elif defined(dColorType_group) + vColor.rgb = readFromTexture(tColor, aGroup, uColorTexDim).rgb; +#elif defined(dColorType_groupInstance) + vColor.rgb = readFromTexture(tColor, aGroup * float(uGroupCount) + aGroup, uColorTexDim).rgb; #elif defined(dColorType_objectPicking) vColor = encodeIdRGBA(float(uObjectId)); #elif defined(dColorType_instancePicking) - vColor = encodeIdRGBA(aInstanceId); -#elif defined(dColorType_elementPicking) - vColor = encodeIdRGBA(aElementId); + vColor = encodeIdRGBA(aInstance); +#elif defined(dColorType_groupPicking) + vColor = encodeIdRGBA(aGroup); #endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-marker-varying.glsl b/src/mol-gl/shader/chunks/assign-marker-varying.glsl index 1afbdd7cfbeca72ebeb83a4bcaef4c91063874cd..38c3e0a474debc92226378e42368c7b42362f693 100644 --- a/src/mol-gl/shader/chunks/assign-marker-varying.glsl +++ b/src/mol-gl/shader/chunks/assign-marker-varying.glsl @@ -1 +1 @@ -vMarker = readFromTexture(tMarker, aInstanceId * float(uElementCount) + aElementId, uMarkerTexSize).a; \ No newline at end of file +vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + aGroup, uMarkerTexDim).a; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-material-color.glsl b/src/mol-gl/shader/chunks/assign-material-color.glsl index fa0ecfad09dbbcc4ce57d156b4e488381407b690..5969c88c34b534a0556d2da9f30e6b22f41a557e 100644 --- a/src/mol-gl/shader/chunks/assign-material-color.glsl +++ b/src/mol-gl/shader/chunks/assign-material-color.glsl @@ -1,5 +1,5 @@ #if defined(dColorType_uniform) vec4 material = vec4(uColor, 1.0); -#elif defined(dColorType_attribute) || defined(dColorType_instance) || defined(dColorType_element) || defined(dColorType_elementInstance) || defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_elementPicking) +#elif defined(dColorType_attribute) || defined(dColorType_instance) || defined(dColorType_group) || defined(dColorType_groupInstance) || defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_groupPicking) vec4 material = vColor; #endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-frag-params.glsl b/src/mol-gl/shader/chunks/color-frag-params.glsl index 55731de96863282a6d664f51276b3e19d335dc87..caa12c98d9c2eea2a48767fcea185a419b761fe0 100644 --- a/src/mol-gl/shader/chunks/color-frag-params.glsl +++ b/src/mol-gl/shader/chunks/color-frag-params.glsl @@ -1,5 +1,5 @@ #if defined(dColorType_uniform) uniform vec3 uColor; -#elif defined(dColorType_attribute) || defined(dColorType_instance) || defined(dColorType_element) || defined(dColorType_elementInstance) || defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_elementPicking) +#elif defined(dColorType_attribute) || defined(dColorType_instance) || defined(dColorType_group) || defined(dColorType_groupInstance) || defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_groupPicking) varying vec4 vColor; #endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-vert-params.glsl b/src/mol-gl/shader/chunks/color-vert-params.glsl index 8f49becee4630b39320a3660dcae7adc8a6aafcd..63318ea3c6c4caac90718bae39ae37267a77b860 100644 --- a/src/mol-gl/shader/chunks/color-vert-params.glsl +++ b/src/mol-gl/shader/chunks/color-vert-params.glsl @@ -3,11 +3,11 @@ #elif defined(dColorType_attribute) varying vec4 vColor; attribute vec3 aColor; -#elif defined(dColorType_instance) || defined(dColorType_element) || defined(dColorType_elementInstance) +#elif defined(dColorType_instance) || defined(dColorType_group) || defined(dColorType_groupInstance) varying vec4 vColor; - uniform vec2 uColorTexSize; + uniform vec2 uColorTexDim; uniform sampler2D tColor; -#elif defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_elementPicking) +#elif defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_groupPicking) varying vec4 vColor; #pragma glslify: encodeIdRGBA = require(../utils/encode-id-rgba.glsl) #endif \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl b/src/mol-gl/shader/chunks/common-frag-params.glsl index 7470f1041311568d7010e15b2f73c67d09651585..a1b1b64d8eb9b2a560e4de1b101bb5cc331748ab 100644 --- a/src/mol-gl/shader/chunks/common-frag-params.glsl +++ b/src/mol-gl/shader/chunks/common-frag-params.glsl @@ -1,6 +1,6 @@ uniform int uObjectId; uniform int uInstanceCount; -uniform int uElementCount; +uniform int uGroupCount; uniform vec3 uHighlightColor; uniform vec3 uSelectColor; diff --git a/src/mol-gl/shader/chunks/common-vert-params.glsl b/src/mol-gl/shader/chunks/common-vert-params.glsl index 27d1dd0b338b166efc5479233cd2670fc489f62c..30bc2caea18865056975654eeccac9b43348ba66 100644 --- a/src/mol-gl/shader/chunks/common-vert-params.glsl +++ b/src/mol-gl/shader/chunks/common-vert-params.glsl @@ -2,9 +2,9 @@ uniform mat4 uProjection, uModel, uView; uniform int uObjectId; uniform int uInstanceCount; -uniform int uElementCount; +uniform int uGroupCount; -uniform vec2 uMarkerTexSize; +uniform vec2 uMarkerTexDim; uniform sampler2D tMarker; varying float vMarker; #pragma glslify: readFromTexture = require(../utils/read-from-texture.glsl) \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.frag b/src/mol-gl/shader/mesh.frag index cc387cb22b293464889921d6f48c91bdd9b1a7f2..ce282933ea1281f35e1699e3d0acc373ec3a814f 100644 --- a/src/mol-gl/shader/mesh.frag +++ b/src/mol-gl/shader/mesh.frag @@ -38,7 +38,7 @@ void main() { // material color #pragma glslify: import('./chunks/assign-material-color.glsl') - #if defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_elementPicking) + #if defined(dColorType_objectPicking) || defined(dColorType_instancePicking) || defined(dColorType_groupPicking) // gl_FragColor = vec4(material.r, material.g, material.a, 1.0); gl_FragColor = material; #else diff --git a/src/mol-gl/shader/mesh.vert b/src/mol-gl/shader/mesh.vert index 0f7b837d2cd7569c1997ff057ca32cc4fc2f4e5a..af38be41e65a3be4d05412a1cadd618ce5d38438 100644 --- a/src/mol-gl/shader/mesh.vert +++ b/src/mol-gl/shader/mesh.vert @@ -12,8 +12,8 @@ precision highp int; attribute vec3 aPosition; attribute mat4 aTransform; -attribute float aInstanceId; -attribute float aElementId; +attribute float aInstance; +attribute float aGroup; #ifndef dFlatShaded attribute vec3 aNormal; diff --git a/src/mol-gl/shader/point.vert b/src/mol-gl/shader/point.vert index f8061d9587c4139f22e8cc723c604152e3387658..950ba3db17bef0d249d56e2ebac4e63a0222d3fb 100644 --- a/src/mol-gl/shader/point.vert +++ b/src/mol-gl/shader/point.vert @@ -21,8 +21,8 @@ uniform float uViewportHeight; attribute vec3 aPosition; attribute mat4 aTransform; -attribute float aInstanceId; -attribute float aElementId; +attribute float aInstance; +attribute float aGroup; void main(){ #pragma glslify: import('./chunks/assign-color-varying.glsl') @@ -33,11 +33,11 @@ void main(){ #elif defined(dSizeType_attribute) float size = aSize; #elif defined(dSizeType_instance) - float size = readFromTexture(tSize, aInstanceId, uSizeTexSize).r; - #elif defined(dSizeType_element) - float size = readFromTexture(tSize, aElementId, uSizeTexSize).r; - #elif defined(dSizeType_elementInstance) - float size = readFromTexture(tSize, aInstanceId * float(uElementCount) + aElementId, uSizeTexSize).r; + float size = readFromTexture(tSize, aInstance, uSizeTexDim).r; + #elif defined(dSizeType_group) + float size = readFromTexture(tSize, aGroup, uSizeTexDim).r; + #elif defined(dSizeType_groupInstance) + float size = readFromTexture(tSize, aInstance * float(uGroupCount) + aGroup, uSizeTexDim).r; #endif #ifdef dPointSizeAttenuation diff --git a/src/mol-gl/shader/utils/read-from-texture.glsl b/src/mol-gl/shader/utils/read-from-texture.glsl index 10b4e9d60c09519c17cd0b5a3fe60e27a8bb7fe6..a43c9d528af35cd1a2be41dfb2d18d3b2c240bf1 100644 --- a/src/mol-gl/shader/utils/read-from-texture.glsl +++ b/src/mol-gl/shader/utils/read-from-texture.glsl @@ -4,10 +4,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -vec4 readFromTexture (const in sampler2D tex, const in float i, const in vec2 size) { - float x = mod(i, size.x); - float y = floor(i / size.x); - vec2 uv = (vec2(x, y) + 0.5) / size; +vec4 readFromTexture (const in sampler2D tex, const in float i, const in vec2 dim) { + float x = mod(i, dim.x); + float y = floor(i / dim.x); + vec2 uv = (vec2(x, y) + 0.5) / dim; return texture2D(tex, uv); } #pragma glslify: export(readFromTexture) \ No newline at end of file diff --git a/src/mol-gl/webgl/render-item.ts b/src/mol-gl/webgl/render-item.ts index a9a8244b0571a8877afbb116b711e18902fcbe36..284591374c09de8e144518f3bff698b72036fc20 100644 --- a/src/mol-gl/webgl/render-item.ts +++ b/src/mol-gl/webgl/render-item.ts @@ -45,7 +45,7 @@ const RenderVariantDefines = { 'draw': {}, 'pickObject': { dColorType: ValueCell.create('objectPicking') }, 'pickInstance': { dColorType: ValueCell.create('instancePicking') }, - 'pickElement': { dColorType: ValueCell.create('elementPicking') } + 'pickGroup': { dColorType: ValueCell.create('groupPicking') } } export type RenderVariant = keyof typeof RenderVariantDefines diff --git a/src/mol-io/reader/obj/parser.ts b/src/mol-io/reader/obj/parser.ts index 10dafa091ab984da0e002885ce905d38b3320921..46cd16ccb151b1fb0ab69afa873c83f33a09e0b8 100644 --- a/src/mol-io/reader/obj/parser.ts +++ b/src/mol-io/reader/obj/parser.ts @@ -6,12 +6,13 @@ import Result from '../result' import { Task, RuntimeContext } from 'mol-task' -import { Mesh } from 'mol-geo/shape/mesh'; +import { Mesh } from 'mol-geo/mesh/mesh'; async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Mesh>> { // TODO - const result: Mesh = Mesh.createEmpty(); - return Result.success(result); + const mesh: Mesh = Mesh.createEmpty(); + // Mesh.computeNormalsImmediate(mesh) + return Result.success(mesh); } export function parse(data: string) { diff --git a/src/mol-model/location.ts b/src/mol-model/location.ts index 2ce2fdb16040b042398f90421ab997213b2576d8..39546ddac69d0642e20e7f5d232b824d798e2c90 100644 --- a/src/mol-model/location.ts +++ b/src/mol-model/location.ts @@ -6,6 +6,7 @@ import { StructureElement } from './structure' import { Link } from './structure/structure/unit/links' +import { Shape } from './shape/shape'; /** A null value Location */ export const NullLocation = { kind: 'null-location' as 'null-location' } @@ -14,17 +15,4 @@ export function isNullLocation(x: any): x is NullLocation { return !!x && x.kind === 'null-location'; } -/** A custom Location */ -export interface CustomLocation<D = any, K = any> { - readonly kind: 'custom-location' - data: D - key: K -} -export function CustomLocation<D, K>(data: D, key: K): CustomLocation<D, K> { - return { kind: 'custom-location', data, key } -} -export function isCustomLocation(x: any): x is CustomLocation<any, any> { - return !!x && x.kind === 'custom-location'; -} - -export type Location = StructureElement | Link.Location | NullLocation | CustomLocation \ No newline at end of file +export type Location = StructureElement | Link.Location | Shape.Location | NullLocation \ No newline at end of file diff --git a/src/mol-model/loci.ts b/src/mol-model/loci.ts index 47c737cee1fa03301264ac6a94840e8be3d7a6e4..d84498e133ae0e709429c81c6b57a5a715f981b2 100644 --- a/src/mol-model/loci.ts +++ b/src/mol-model/loci.ts @@ -6,7 +6,7 @@ import { StructureElement } from './structure' import { Link } from './structure/structure/unit/links' -import { CustomLocation } from './location'; +import { Shape } from './shape'; /** A Loci that includes every loci */ export const EveryLoci = { kind: 'every-loci' as 'every-loci' } @@ -22,16 +22,4 @@ export function isEmptyLoci(x: any): x is EmptyLoci { return !!x && x.kind === 'empty-loci'; } -/** A Loci of custom locations */ -export interface CustomLoci<D = any, K = any> { - readonly kind: 'custom-loci' - readonly locations: ReadonlyArray<CustomLocation> -} -export function CustomLoci<D, K>(locations: CustomLocation<D, K>[]): CustomLoci<D, K> { - return { kind: 'custom-loci', locations } -} -export function isCustomLoci(x: any): x is CustomLoci { - return !!x && x.kind === 'custom-loci'; -} - -export type Loci = StructureElement.Loci | Link.Loci | EveryLoci | EmptyLoci | CustomLoci \ No newline at end of file +export type Loci = StructureElement.Loci | Link.Loci | EveryLoci | EmptyLoci | Shape.Loci \ No newline at end of file diff --git a/src/mol-model/shape.ts b/src/mol-model/shape.ts new file mode 100644 index 0000000000000000000000000000000000000000..fc1125ad411cce5f45eef76efc8f423fbeb09512 --- /dev/null +++ b/src/mol-model/shape.ts @@ -0,0 +1,7 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +export * from './shape/shape' \ No newline at end of file diff --git a/src/mol-model/shape/shape.ts b/src/mol-model/shape/shape.ts new file mode 100644 index 0000000000000000000000000000000000000000..16aa5b0fcb2a714d8809d3118ff30b04d8d2ecc9 --- /dev/null +++ b/src/mol-model/shape/shape.ts @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Mesh } from 'mol-geo/mesh/mesh'; +import { Color } from 'mol-util/color'; +import { UUID } from 'mol-util'; +import { OrderedSet } from 'mol-data/int'; + +export interface Shape { + readonly id: UUID + readonly name: string + readonly mesh: Mesh + getColor(group: number): Color + getLabel(group: number): string +} + +export namespace Shape { + export function create(mesh: Mesh, name: string, getColor: (group: number) => Color, getLabel: (group: number) => string): Shape { + return { id: UUID.create(), name, mesh, getColor, getLabel } + } + + export interface Location { + readonly kind: 'group-location' + shape: Shape + group: number + } + + export function Location(shape?: Shape, group?: number): Location { + return { kind: 'group-location', shape: shape!, group: group || 0 }; + } + + export function isLocation(x: any): x is Location { + return !!x && x.kind === 'group-location'; + } + + export interface Loci { + readonly kind: 'group-loci', + readonly groups: ReadonlyArray<{ + shape: Shape, + ids: OrderedSet<number> + }> + } + + export function Loci(groups: ArrayLike<{ shape: Shape, ids: OrderedSet<number> }>): Loci { + return { kind: 'group-loci', groups: groups as Loci['groups'] }; + } + + export function isLoci(x: any): x is Loci { + return !!x && x.kind === 'group-loci'; + } +} \ No newline at end of file diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts index 6c31ccd7483b52d341fea903aedbccf6df848d34..0c83fbcd981cba97b08393086738f339d080aa4b 100644 --- a/src/mol-model/structure/structure/element.ts +++ b/src/mol-model/structure/structure/element.ts @@ -18,7 +18,7 @@ interface StructureElement<U = Unit> { namespace StructureElement { export function create(unit?: Unit, element?: ElementIndex): StructureElement { - return { kind: 'element-location', unit: unit as any, element: element || (0 as ElementIndex) }; + return { kind: 'element-location', unit: unit!, element: element || (0 as ElementIndex) }; } // TODO: when nominal types are available, make this indexed by UnitIndex diff --git a/src/mol-util/array.ts b/src/mol-util/array.ts index d3dfa14a95f7bc2e030ef609e5effaf8a8f1ff08..11998ff2d6d9391ca612620e34f2e5d5706bb641 100644 --- a/src/mol-util/array.ts +++ b/src/mol-util/array.ts @@ -4,6 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ +// TODO move to mol-math as Vector??? + +/** Get the maximum value in an array */ export function arrayMax(array: Helpers.NumberArray) { let max = -Infinity for (let i = 0, il = array.length; i < il; ++i) { @@ -12,6 +15,7 @@ export function arrayMax(array: Helpers.NumberArray) { return max } +/** Get the minimum value in an array */ export function arrayMin(array: Helpers.NumberArray) { let min = Infinity for (let i = 0, il = array.length; i < il; ++i) { @@ -20,6 +24,7 @@ export function arrayMin(array: Helpers.NumberArray) { return min } +/** Get the sum of values in an array */ export function arraySum(array: Helpers.NumberArray, stride = 1, offset = 0) { const n = array.length let sum = 0 @@ -29,10 +34,12 @@ export function arraySum(array: Helpers.NumberArray, stride = 1, offset = 0) { return sum } +/** Get the mean of values in an array */ export function arrayMean(array: Helpers.NumberArray, stride = 1, offset = 0) { return arraySum(array, stride, offset) / (array.length / stride) } +/** Get the root mean square of values in an array */ export function arrayRms(array: Helpers.NumberArray) { const n = array.length let sumSq = 0 @@ -43,6 +50,7 @@ export function arrayRms(array: Helpers.NumberArray) { return Math.sqrt(sumSq / n) } +/** Fill an array with serial numbers starting from 0 */ export function fillSerial<T extends Helpers.NumberArray> (array: T) { const n = array.length for (let i = 0; i < n; ++i) array[ i ] = i diff --git a/src/mol-view/label.ts b/src/mol-view/label.ts index 2211c5da2bd184ac13702bb1d0829dfb15fbceda..baeb1eccfff71247e3889d7cefe4910433882b68 100644 --- a/src/mol-view/label.ts +++ b/src/mol-view/label.ts @@ -12,7 +12,7 @@ import { OrderedSet } from 'mol-data/int'; const elementLocA = StructureElement.create() const elementLocB = StructureElement.create() -function setElementLocation(loc: StructureElement, unit: Unit, index: number) { +function setElementLocation(loc: StructureElement, unit: Unit, index: StructureElement.UnitIndex) { loc.unit = unit loc.element = unit.elements[index] } @@ -36,8 +36,13 @@ export function labelFirst(loci: Loci): string { } else { return 'Unknown' } - case 'custom-loci': - return 'Custom' + case 'group-loci': + const g = loci.groups[0] + if (g) { + return g.shape.getLabel(OrderedSet.getAt(g.ids, 0)) + } else { + return 'Unknown' + } case 'every-loci': return 'Everything' case 'empty-loci': diff --git a/src/mol-view/theme/color.ts b/src/mol-view/theme/color.ts index ba8fec56a0fa4883ffe7e4121f73fdb974b20154..f02f54b3a11d757f1d636d71a99a12f8d414ee1f 100644 --- a/src/mol-view/theme/color.ts +++ b/src/mol-view/theme/color.ts @@ -15,6 +15,7 @@ import { ElementSymbolColorTheme } from './color/element-symbol'; import { UnitIndexColorTheme } from './color/unit-index'; import { UniformColorTheme } from './color/uniform'; import { CrossLinkColorTheme } from './color/cross-link'; +import { ShapeGroupColorTheme } from './color/shape-group'; export interface ColorTheme { kind: ColorType @@ -30,6 +31,7 @@ export function ColorTheme(props: ColorThemeProps): ColorTheme { case 'element-symbol': return ElementSymbolColorTheme(props) case 'unit-index': return UnitIndexColorTheme(props) case 'uniform': return UniformColorTheme(props) + case 'shape-group': return ShapeGroupColorTheme(props) } } @@ -47,7 +49,8 @@ export const ColorThemeInfo = { 'chain-id': {}, 'element-symbol': {}, 'unit-index': {}, - 'uniform': {} + 'uniform': {}, + 'shape-group': {} } export type ColorThemeName = keyof typeof ColorThemeInfo export const ColorThemeNames = Object.keys(ColorThemeInfo) \ No newline at end of file diff --git a/src/mol-view/theme/color/carbohydrate-symbol.ts b/src/mol-view/theme/color/carbohydrate-symbol.ts index 8ccdf51d91b9dde4fb39bc7fead5f459f687a65e..7c3093a0b2ffce1e3e8ac4e865516bf8976f1ce7 100644 --- a/src/mol-view/theme/color/carbohydrate-symbol.ts +++ b/src/mol-view/theme/color/carbohydrate-symbol.ts @@ -47,7 +47,7 @@ export function CarbohydrateSymbolColorTheme(props: ColorThemeProps): ColorTheme } return { - kind: 'element', + kind: 'group', color: colorFn } } \ No newline at end of file diff --git a/src/mol-view/theme/color/chain-id.ts b/src/mol-view/theme/color/chain-id.ts index 8a40badbf5188c939212c49153421b2ec58ecfc9..9e15eec0f430d12805b680c155c03033cc7223e8 100644 --- a/src/mol-view/theme/color/chain-id.ts +++ b/src/mol-view/theme/color/chain-id.ts @@ -43,7 +43,7 @@ export function ChainIdColorTheme(props: ColorThemeProps): ColorTheme { } return { - kind: 'element', + kind: 'group', color: colorFn } } \ No newline at end of file diff --git a/src/mol-view/theme/color/cross-link.ts b/src/mol-view/theme/color/cross-link.ts index aa80d8b26557a24d0f5951dc6160f45dfe7ac95f..5a4709dc550531cafeb512eef140987399612dfd 100644 --- a/src/mol-view/theme/color/cross-link.ts +++ b/src/mol-view/theme/color/cross-link.ts @@ -42,7 +42,7 @@ export function CrossLinkColorTheme(props: ColorThemeProps): ColorTheme { } return { - kind: 'element', + kind: 'group', color: colorFn } } \ No newline at end of file diff --git a/src/mol-view/theme/color/element-index.ts b/src/mol-view/theme/color/element-index.ts index 78daf537ace4e0efd16eec0641c374c7c4d4b367..f6abd54f3cdee2a02e2531e660a9b93449d831ba 100644 --- a/src/mol-view/theme/color/element-index.ts +++ b/src/mol-view/theme/color/element-index.ts @@ -44,7 +44,7 @@ export function ElementIndexColorTheme(props: ColorThemeProps): ColorTheme { } return { - kind: 'elementInstance', + kind: 'groupInstance', color: colorFn } } \ No newline at end of file diff --git a/src/mol-view/theme/color/element-symbol.ts b/src/mol-view/theme/color/element-symbol.ts index 0a8be64caea01c68611df96b29ce9c10d5fdd743..eaa64ebb687eff4b8b8d2d9888ff5215a298eba6 100644 --- a/src/mol-view/theme/color/element-symbol.ts +++ b/src/mol-view/theme/color/element-symbol.ts @@ -39,7 +39,7 @@ export function ElementSymbolColorTheme(props: ColorThemeProps): ColorTheme { } return { - kind: 'element', + kind: 'group', color: colorFn } } \ No newline at end of file diff --git a/src/mol-view/theme/color/shape-group.ts b/src/mol-view/theme/color/shape-group.ts new file mode 100644 index 0000000000000000000000000000000000000000..815ab6dbbd515f180c5c416706c91ef1837920df --- /dev/null +++ b/src/mol-view/theme/color/shape-group.ts @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { ColorTheme, ColorThemeProps } from '../color'; +import { Color } from 'mol-util/color'; +import { Location } from 'mol-model/location'; +import { Shape } from 'mol-model/shape'; + +const DefaultColor = 0xCCCCCC as Color + +export function ShapeGroupColorTheme(props: ColorThemeProps): ColorTheme { + return { + kind: 'group', + color: (location: Location): Color => { + if (Shape.isLocation(location)) { + return location.shape.getColor(location.group) + } + return DefaultColor + } + } +} \ No newline at end of file diff --git a/src/mol-view/theme/size/physical.ts b/src/mol-view/theme/size/physical.ts index e034b5c2c0670bc7641e2d26102e7d500d91066a..87c7ccefe0c8ebe717d9269bf032fa077d7b7668 100644 --- a/src/mol-view/theme/size/physical.ts +++ b/src/mol-view/theme/size/physical.ts @@ -42,7 +42,7 @@ export function PhysicalSizeTheme(props: SizeThemeProps): SizeTheme { } return { - kind: 'element', + kind: 'group', size: sizeFn } } \ No newline at end of file diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts index addf444decb7f26f324fa726c3cfa1f306e8a0f4..d3eb6d3d22ebb55237a9c35a776fe7b698307bde 100644 --- a/src/mol-view/viewer.ts +++ b/src/mol-view/viewer.ts @@ -109,7 +109,7 @@ namespace Viewer { const pickHeight = Math.round(canvas.height * pickScale) const objectPickTarget = createRenderTarget(ctx, pickWidth, pickHeight) const instancePickTarget = createRenderTarget(ctx, pickWidth, pickHeight) - const elementPickTarget = createRenderTarget(ctx, pickWidth, pickHeight) + const groupPickTarget = createRenderTarget(ctx, pickWidth, pickHeight) let pickDirty = true let drawPending = false @@ -165,7 +165,7 @@ namespace Viewer { switch (variant) { case 'pickObject': objectPickTarget.bind(); break; case 'pickInstance': instancePickTarget.bind(); break; - case 'pickElement': elementPickTarget.bind(); break; + case 'pickGroup': groupPickTarget.bind(); break; case 'draw': ctx.unbindFramebuffer(); renderer.setViewport(0, 0, canvas.width, canvas.height); @@ -210,7 +210,7 @@ namespace Viewer { function pick() { render('pickObject', pickDirty) render('pickInstance', pickDirty) - render('pickElement', pickDirty) + render('pickGroup', pickDirty) pickDirty = false } @@ -232,11 +232,11 @@ namespace Viewer { ctx.readPixels(xp, yp, 1, 1, buffer) const instanceId = decodeIdRGBA(buffer[0], buffer[1], buffer[2]) - elementPickTarget.bind() + groupPickTarget.bind() ctx.readPixels(xp, yp, 1, 1, buffer) - const elementId = decodeIdRGBA(buffer[0], buffer[1], buffer[2]) + const groupId = decodeIdRGBA(buffer[0], buffer[1], buffer[2]) - return { objectId, instanceId, elementId } + return { objectId, instanceId, groupId } } handleResize() @@ -303,7 +303,7 @@ namespace Viewer { case 'draw': return renderer.getImageData() case 'pickObject': return objectPickTarget.getImageData() case 'pickInstance': return instancePickTarget.getImageData() - case 'pickElement': return elementPickTarget.getImageData() + case 'pickGroup': return groupPickTarget.getImageData() } }, reprCount, @@ -334,7 +334,7 @@ namespace Viewer { const pickHeight = Math.round(canvas.height * pickScale) objectPickTarget.setSize(pickWidth, pickHeight) instancePickTarget.setSize(pickWidth, pickHeight) - elementPickTarget.setSize(pickWidth, pickHeight) + groupPickTarget.setSize(pickWidth, pickHeight) } } }