point.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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, RenderObject, PointRenderObject } from 'mol-gl/scene'
  9. import { Unit, Element } from 'mol-model/structure';
  10. import { Task } from 'mol-task'
  11. import { fillSerial } from 'mol-gl/renderable/util';
  12. import { UnitsRepresentation } from './index';
  13. import VertexMap from '../../shape/vertex-map';
  14. import { ColorTheme, SizeTheme } from '../../theme';
  15. import { createTransforms, createColors, createSizes } from './utils';
  16. import { deepEqual } from 'mol-util';
  17. import { SortedArray } from 'mol-data/int';
  18. export const DefaultPointProps = {
  19. colorTheme: { name: 'instance-index' } as ColorTheme,
  20. sizeTheme: { name: 'vdw' } as SizeTheme,
  21. alpha: 1,
  22. visible: true,
  23. depthMask: true
  24. }
  25. export type PointProps = Partial<typeof DefaultPointProps>
  26. export function createPointVertices(unit: Unit) {
  27. const elements = unit.elements
  28. const elementCount = elements.length
  29. const vertices = new Float32Array(elementCount * 3)
  30. const { x, y, z } = unit.conformation
  31. const l = Element.Location()
  32. l.unit = unit
  33. for (let i = 0; i < elementCount; i++) {
  34. l.element = elements[i];
  35. const i3 = i * 3
  36. vertices[i3] = x(l.element)
  37. vertices[i3 + 1] = y(l.element)
  38. vertices[i3 + 2] = z(l.element)
  39. }
  40. return vertices
  41. }
  42. export default function Point(): UnitsRepresentation<PointProps> {
  43. const renderObjects: RenderObject[] = []
  44. let points: PointRenderObject
  45. let curProps = DefaultPointProps
  46. let _units: ReadonlyArray<Unit>
  47. let _elements: SortedArray
  48. return {
  49. renderObjects,
  50. create(group: Unit.SymmetryGroup, props: PointProps = {}) {
  51. return Task.create('Point.create', async ctx => {
  52. renderObjects.length = 0 // clear
  53. curProps = { ...DefaultPointProps, ...props }
  54. _units = group.units
  55. _elements = group.elements;
  56. const { colorTheme, sizeTheme, alpha, visible, depthMask } = curProps
  57. const elementCount = _elements.length
  58. const unitCount = _units.length
  59. const vertexMap = VertexMap.create(
  60. elementCount,
  61. elementCount + 1,
  62. fillSerial(new Uint32Array(elementCount)),
  63. fillSerial(new Uint32Array(elementCount + 1))
  64. )
  65. await ctx.update('Computing point vertices');
  66. const vertices = createPointVertices(_units[0])
  67. await ctx.update('Computing point transforms');
  68. const transforms = createTransforms(group)
  69. await ctx.update('Computing point colors');
  70. const color = createColors(group, vertexMap, colorTheme)
  71. await ctx.update('Computing point sizes');
  72. const size = createSizes(group, vertexMap, sizeTheme)
  73. points = createPointRenderObject({
  74. objectId: 0,
  75. alpha,
  76. visible,
  77. depthMask,
  78. position: ValueCell.create(vertices),
  79. id: ValueCell.create(fillSerial(new Float32Array(elementCount))),
  80. size: size,
  81. color: color,
  82. transform: ValueCell.create(transforms),
  83. instanceCount: unitCount,
  84. elementCount,
  85. positionCount: vertices.length / 3,
  86. usePointSizeAttenuation: true
  87. })
  88. renderObjects.push(points)
  89. })
  90. },
  91. update(props: PointProps) {
  92. return Task.create('Point.update', async ctx => {
  93. if (!points || !_units || !_elements) return false
  94. const newProps = { ...curProps, ...props }
  95. if (deepEqual(curProps, newProps)) {
  96. console.log('props identical, nothing to change')
  97. return true
  98. }
  99. // const elementCount = OrderedSet.size(_elementGroup.elements)
  100. // const unitCount = _units.length
  101. // const vertexMap = VertexMap.create(
  102. // elementCount,
  103. // elementCount + 1,
  104. // fillSerial(new Uint32Array(elementCount)),
  105. // fillSerial(new Uint32Array(elementCount + 1))
  106. // )
  107. if (!deepEqual(curProps.colorTheme, newProps.colorTheme)) {
  108. console.log('colorTheme changed', curProps.colorTheme, newProps.colorTheme)
  109. // await ctx.update('Computing point colors');
  110. // const color = createColors(_units, _elementGroup, vertexMap, newProps.colorTheme)
  111. // ValueCell.update(points.props.color, color)
  112. }
  113. if (!deepEqual(curProps.sizeTheme, newProps.sizeTheme)) {
  114. console.log('sizeTheme changed', curProps.sizeTheme, newProps.sizeTheme)
  115. }
  116. curProps = newProps
  117. return false
  118. })
  119. }
  120. }
  121. }