element-point.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import { ValueCell } from 'mol-util/value-cell'
  8. import { createPointRenderObject, PointRenderObject } from 'mol-gl/render-object'
  9. import { Unit } from 'mol-model/structure';
  10. import { RuntimeContext } from 'mol-task'
  11. import { fillSerial } from 'mol-gl/renderable/util';
  12. import { UnitsVisual, DefaultStructureProps } from '../index';
  13. import VertexMap from '../../../shape/vertex-map';
  14. import { SizeTheme } from '../../../theme';
  15. import { markElement, getElementLoci } from './util/element';
  16. import { createTransforms, createColors, createSizes } from './util/common';
  17. import { deepEqual, defaults } from 'mol-util';
  18. import { SortedArray } from 'mol-data/int';
  19. import { RenderableState, PointValues } from 'mol-gl/renderable';
  20. import { PickingId } from '../../../util/picking';
  21. import { Loci } from 'mol-model/loci';
  22. import { MarkerAction, createMarkers } from '../../../util/marker-data';
  23. import { Vec3 } from 'mol-math/linear-algebra';
  24. export const DefaultPointProps = {
  25. ...DefaultStructureProps,
  26. sizeTheme: { name: 'physical' } as SizeTheme
  27. }
  28. export type PointProps = Partial<typeof DefaultPointProps>
  29. export function createPointVertices(unit: Unit) {
  30. const elements = unit.elements
  31. const elementCount = elements.length
  32. const vertices = new Float32Array(elementCount * 3)
  33. const pos = unit.conformation.invariantPosition
  34. const p = Vec3.zero()
  35. for (let i = 0; i < elementCount; i++) {
  36. const i3 = i * 3
  37. pos(elements[i], p)
  38. vertices[i3] = p[0]
  39. vertices[i3 + 1] = p[1]
  40. vertices[i3 + 2] = p[2]
  41. }
  42. return vertices
  43. }
  44. export default function PointVisual(): UnitsVisual<PointProps> {
  45. let renderObject: PointRenderObject
  46. let currentProps = DefaultPointProps
  47. let currentGroup: Unit.SymmetryGroup
  48. let _units: ReadonlyArray<Unit>
  49. let _elements: SortedArray
  50. return {
  51. get renderObject () { return renderObject },
  52. async create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: PointProps = {}) {
  53. currentProps = Object.assign({}, DefaultPointProps, props)
  54. currentGroup = group
  55. _units = group.units
  56. _elements = group.elements;
  57. const { colorTheme, sizeTheme } = currentProps
  58. const elementCount = _elements.length
  59. const instanceCount = group.units.length
  60. const vertexMap = VertexMap.create(
  61. elementCount,
  62. elementCount + 1,
  63. fillSerial(new Uint32Array(elementCount)),
  64. fillSerial(new Uint32Array(elementCount + 1))
  65. )
  66. const vertices = createPointVertices(_units[0])
  67. const transforms = createTransforms(group)
  68. const color = createColors(group, elementCount, colorTheme)
  69. const size = createSizes(group, vertexMap, sizeTheme)
  70. const marker = createMarkers(instanceCount * elementCount)
  71. const values: PointValues = {
  72. aPosition: ValueCell.create(vertices),
  73. aElementId: ValueCell.create(fillSerial(new Float32Array(elementCount))),
  74. aTransform: transforms,
  75. aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))),
  76. ...color,
  77. ...marker,
  78. ...size,
  79. uAlpha: ValueCell.create(defaults(props.alpha, 1.0)),
  80. uInstanceCount: ValueCell.create(instanceCount),
  81. uElementCount: ValueCell.create(group.elements.length),
  82. drawCount: ValueCell.create(vertices.length / 3),
  83. instanceCount: ValueCell.create(instanceCount),
  84. dPointSizeAttenuation: ValueCell.create(true),
  85. dUseFog: ValueCell.create(defaults(props.useFog, true)),
  86. }
  87. const state: RenderableState = {
  88. depthMask: defaults(props.depthMask, true),
  89. visible: defaults(props.visible, true)
  90. }
  91. renderObject = createPointRenderObject(values, state)
  92. },
  93. async update(ctx: RuntimeContext, props: PointProps) {
  94. if (!renderObject || !_units || !_elements) return false
  95. const newProps = { ...currentProps, ...props }
  96. if (deepEqual(currentProps, newProps)) {
  97. console.log('props identical, nothing to change')
  98. return true
  99. }
  100. if (!deepEqual(currentProps.colorTheme, newProps.colorTheme)) {
  101. console.log('colorTheme changed', currentProps.colorTheme, newProps.colorTheme)
  102. }
  103. if (!deepEqual(currentProps.sizeTheme, newProps.sizeTheme)) {
  104. console.log('sizeTheme changed', currentProps.sizeTheme, newProps.sizeTheme)
  105. }
  106. currentProps = newProps
  107. return false
  108. },
  109. getLoci(pickingId: PickingId) {
  110. return getElementLoci(renderObject.id, currentGroup, pickingId)
  111. },
  112. mark(loci: Loci, action: MarkerAction) {
  113. markElement(renderObject.values.tMarker, currentGroup, loci, action)
  114. },
  115. destroy() {
  116. // TODO
  117. }
  118. }
  119. }