util.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. */
  6. import { ValueCell } from 'mol-util/value-cell'
  7. import { BaseValues } from 'mol-gl/renderable/schema';
  8. import { MeshValues, RenderableState } from 'mol-gl/renderable';
  9. import { defaults } from 'mol-util';
  10. import { Structure } from 'mol-model/structure';
  11. import { fillSerial } from 'mol-util/array';
  12. export const DefaultBaseProps = {
  13. alpha: 1,
  14. visible: true,
  15. depthMask: true,
  16. useFog: true,
  17. quality: 'auto' as VisualQuality
  18. }
  19. export type BaseProps = typeof DefaultBaseProps
  20. export const DefaultMeshProps = {
  21. ...DefaultBaseProps,
  22. doubleSided: false,
  23. flipSided: false,
  24. flatShaded: false,
  25. }
  26. export type MeshProps = typeof DefaultMeshProps
  27. type Counts = { drawCount: number, elementCount: number, instanceCount: number }
  28. export function createBaseValues(props: Required<BaseProps>, counts: Counts) {
  29. return {
  30. uAlpha: ValueCell.create(props.alpha),
  31. uInstanceCount: ValueCell.create(counts.instanceCount),
  32. uElementCount: ValueCell.create(counts.elementCount),
  33. aInstanceId: ValueCell.create(fillSerial(new Float32Array(counts.instanceCount))),
  34. drawCount: ValueCell.create(counts.drawCount),
  35. instanceCount: ValueCell.create(counts.instanceCount),
  36. }
  37. }
  38. export function createMeshValues(props: Required<MeshProps>, counts: Counts) {
  39. return {
  40. ...createBaseValues(props, counts),
  41. dDoubleSided: ValueCell.create(props.doubleSided),
  42. dFlatShaded: ValueCell.create(props.flatShaded),
  43. dFlipSided: ValueCell.create(props.flipSided),
  44. dUseFog: ValueCell.create(props.useFog),
  45. }
  46. }
  47. export function createRenderableState(props: Required<BaseProps>): RenderableState {
  48. return {
  49. visible: props.visible,
  50. depthMask: props.depthMask
  51. }
  52. }
  53. export function updateBaseValues(values: BaseValues, props: Required<BaseProps>) {
  54. ValueCell.updateIfChanged(values.uAlpha, props.alpha)
  55. }
  56. export function updateMeshValues(values: MeshValues, props: Required<MeshProps>) {
  57. updateBaseValues(values, props)
  58. ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided)
  59. ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded)
  60. ValueCell.updateIfChanged(values.dFlipSided, props.flipSided)
  61. ValueCell.updateIfChanged(values.dUseFog, props.useFog)
  62. }
  63. export function updateRenderableState(state: RenderableState, props: Required<BaseProps>) {
  64. state.visible = props.visible
  65. state.depthMask = props.depthMask
  66. }
  67. export type VisualQuality = 'custom' | 'auto' | 'highest' | 'high' | 'medium' | 'low' | 'lowest'
  68. interface QualityProps {
  69. quality: VisualQuality
  70. detail: number
  71. radialSegments: number
  72. }
  73. export function getQualityProps(props: Partial<QualityProps>, structure: Structure) {
  74. let quality = defaults(props.quality, 'auto' as VisualQuality)
  75. let detail = 1
  76. let radialSegments = 12
  77. if (quality === 'auto') {
  78. const score = structure.elementCount
  79. if (score > 500_000) {
  80. quality = 'lowest'
  81. } else if (score > 100_000) {
  82. quality = 'low'
  83. } else if (score > 30_000) {
  84. quality = 'medium'
  85. } else {
  86. quality = 'high'
  87. }
  88. }
  89. switch (quality) {
  90. case 'highest':
  91. detail = 2
  92. radialSegments = 36
  93. break
  94. case 'high':
  95. detail = 1
  96. radialSegments = 24
  97. break
  98. case 'medium':
  99. detail = 0
  100. radialSegments = 12
  101. break
  102. case 'low':
  103. detail = 0
  104. radialSegments = 5
  105. break
  106. case 'lowest':
  107. detail = 0
  108. radialSegments = 3
  109. break
  110. case 'custom':
  111. detail = defaults(props.detail, 1)
  112. radialSegments = defaults(props.radialSegments, 12)
  113. break
  114. }
  115. return {
  116. detail,
  117. radialSegments
  118. }
  119. }