123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- * @author David Sehnal <david.sehnal@gmail.com>
- */
- import { ValueCell } from 'mol-util/value-cell'
- import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'
- import { Unit } from 'mol-model/structure';
- import { DefaultStructureProps, UnitsVisual } from '../index';
- import { RuntimeContext } from 'mol-task'
- import { createTransforms, createColors } from './util/common';
- import { createElementSphereMesh, markElement, getElementRadius, getElementLoci } from './util/element';
- import { deepEqual } from 'mol-util';
- import { MeshValues } from 'mol-gl/renderable';
- import { getMeshData } from '../../../util/mesh-data';
- import { Mesh } from '../../../shape/mesh';
- import { PickingId } from '../../../util/picking';
- import { createMarkers, MarkerAction } from '../../../util/marker-data';
- import { Loci } from 'mol-model/loci';
- import { SizeTheme } from '../../../theme';
- import { createMeshValues, updateMeshValues, updateRenderableState, createRenderableState, DefaultMeshProps } from '../../util';
- export const DefaultElementSphereProps = {
- ...DefaultMeshProps,
- ...DefaultStructureProps,
- sizeTheme: { name: 'physical', factor: 1 } as SizeTheme,
- detail: 0,
- unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[]
- }
- export type ElementSphereProps = Partial<typeof DefaultElementSphereProps>
- export function ElementSphereVisual(): UnitsVisual<ElementSphereProps> {
- let renderObject: MeshRenderObject
- let currentProps: typeof DefaultElementSphereProps
- let mesh: Mesh
- let currentGroup: Unit.SymmetryGroup
- return {
- get renderObject () { return renderObject },
- async create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: ElementSphereProps = {}) {
- currentProps = Object.assign({}, DefaultElementSphereProps, props)
- currentGroup = group
- const { detail, colorTheme, sizeTheme, unitKinds } = { ...DefaultElementSphereProps, ...props }
- const instanceCount = group.units.length
- const elementCount = group.elements.length
- const unit = group.units[0]
- const radius = getElementRadius(unit, sizeTheme)
- mesh = unitKinds.includes(unit.kind)
- ? await createElementSphereMesh(ctx, unit, radius, detail, mesh)
- : Mesh.createEmpty(mesh)
- const transforms = createTransforms(group)
- const color = createColors(group, elementCount, colorTheme)
- const marker = createMarkers(instanceCount * elementCount)
- const counts = { drawCount: mesh.triangleCount * 3, elementCount, instanceCount }
- const values: MeshValues = {
- ...getMeshData(mesh),
- ...color,
- ...marker,
- aTransform: transforms,
- elements: mesh.indexBuffer,
- ...createMeshValues(currentProps, counts),
- }
- const state = createRenderableState(currentProps)
- renderObject = createMeshRenderObject(values, state)
- },
- async update(ctx: RuntimeContext, props: ElementSphereProps) {
- const newProps = Object.assign({}, currentProps, props)
- if (!renderObject) return false
- let updateColor = false
- if (newProps.detail !== currentProps.detail) {
- const unit = currentGroup.units[0]
- const radius = getElementRadius(unit, newProps.sizeTheme)
- mesh = await createElementSphereMesh(ctx, unit, radius, newProps.detail, mesh)
- ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3)
- updateColor = true
- }
- if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) {
- updateColor = true
- }
- if (updateColor) {
- const elementCount = currentGroup.elements.length
- if (ctx.shouldUpdate) await ctx.update('Computing sphere colors');
- createColors(currentGroup, elementCount, newProps.colorTheme, renderObject.values)
- }
- updateMeshValues(renderObject.values, newProps)
- updateRenderableState(renderObject.state, newProps)
- currentProps = newProps
- return true
- },
- getLoci(pickingId: PickingId) {
- return getElementLoci(renderObject.id, currentGroup, pickingId)
- },
- mark(loci: Loci, action: MarkerAction) {
- markElement(renderObject.values.tMarker, currentGroup, loci, action)
- },
- destroy() {
- // TODO
- }
- }
- }
|