color-data.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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';
  7. import { TextureImage, createTextureImage } from 'mol-gl/renderable/util';
  8. import { Color } from 'mol-util/color';
  9. import { Vec2, Vec3 } from 'mol-math/linear-algebra';
  10. import { LocationIterator } from './location-iterator';
  11. import { NullLocation } from 'mol-model/location';
  12. import { LocationColor, ColorType } from 'mol-view/theme/color';
  13. export type ColorData = {
  14. uColor: ValueCell<Vec3>,
  15. aColor: ValueCell<Float32Array>,
  16. tColor: ValueCell<TextureImage>,
  17. uColorTexDim: ValueCell<Vec2>,
  18. dColorType: ValueCell<string>,
  19. }
  20. const emptyColorTexture = { array: new Uint8Array(3), width: 1, height: 1 }
  21. function createEmptyColorTexture() {
  22. return {
  23. tColor: ValueCell.create(emptyColorTexture),
  24. uColorTexDim: ValueCell.create(Vec2.create(1, 1))
  25. }
  26. }
  27. export function createValueColor(value: Color, colorData?: ColorData): ColorData {
  28. if (colorData) {
  29. ValueCell.update(colorData.uColor, Color.toRgbNormalized(value) as Vec3)
  30. if (colorData.dColorType.ref.value !== 'uniform') {
  31. ValueCell.update(colorData.dColorType, 'uniform')
  32. }
  33. return colorData
  34. } else {
  35. return {
  36. uColor: ValueCell.create(Color.toRgbNormalized(value) as Vec3),
  37. aColor: ValueCell.create(new Float32Array(0)),
  38. ...createEmptyColorTexture(),
  39. dColorType: ValueCell.create('uniform'),
  40. }
  41. }
  42. }
  43. /** Creates color uniform */
  44. export function createUniformColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData {
  45. return createValueColor(colorFn(NullLocation, false), colorData)
  46. }
  47. export function createTextureColor(colors: TextureImage, type: ColorType, colorData?: ColorData): ColorData {
  48. if (colorData) {
  49. ValueCell.update(colorData.tColor, colors)
  50. ValueCell.update(colorData.uColorTexDim, Vec2.create(colors.width, colors.height))
  51. if (colorData.dColorType.ref.value !== type) {
  52. ValueCell.update(colorData.dColorType, type)
  53. }
  54. return colorData
  55. } else {
  56. return {
  57. uColor: ValueCell.create(Vec3.zero()),
  58. aColor: ValueCell.create(new Float32Array(0)),
  59. tColor: ValueCell.create(colors),
  60. uColorTexDim: ValueCell.create(Vec2.create(colors.width, colors.height)),
  61. dColorType: ValueCell.create(type),
  62. }
  63. }
  64. }
  65. /** Creates color texture with color for each instance/unit */
  66. export function createInstanceColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData {
  67. const { instanceCount} = locationIt
  68. const colors = colorData && colorData.tColor.ref.value.array.length >= instanceCount * 3 ? colorData.tColor.ref.value : createTextureImage(instanceCount, 3)
  69. while (locationIt.hasNext && !locationIt.isNextNewInstance) {
  70. const { location, isSecondary, instanceIndex } = locationIt.move()
  71. Color.toArray(colorFn(location, isSecondary), colors.array, instanceIndex * 3)
  72. locationIt.skipInstance()
  73. }
  74. return createTextureColor(colors, 'instance', colorData)
  75. }
  76. /** Creates color texture with color for each group (i.e. shared across instances/units) */
  77. export function createGroupColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData {
  78. const { groupCount } = locationIt
  79. const colors = colorData && colorData.tColor.ref.value.array.length >= groupCount * 3 ? colorData.tColor.ref.value : createTextureImage(groupCount, 3)
  80. while (locationIt.hasNext && !locationIt.isNextNewInstance) {
  81. const { location, isSecondary, groupIndex } = locationIt.move()
  82. Color.toArray(colorFn(location, isSecondary), colors.array, groupIndex * 3)
  83. }
  84. return createTextureColor(colors, 'group', colorData)
  85. }
  86. /** Creates color texture with color for each group in each instance (i.e. for each unit) */
  87. export function createGroupInstanceColor(locationIt: LocationIterator, colorFn: LocationColor, colorData?: ColorData): ColorData {
  88. const { groupCount, instanceCount } = locationIt
  89. const count = instanceCount * groupCount
  90. const colors = colorData && colorData.tColor.ref.value.array.length >= count * 3 ? colorData.tColor.ref.value : createTextureImage(count, 3)
  91. while (locationIt.hasNext && !locationIt.isNextNewInstance) {
  92. const { location, isSecondary, index } = locationIt.move()
  93. Color.toArray(colorFn(location, isSecondary), colors.array, index * 3)
  94. }
  95. return createTextureColor(colors, 'groupInstance', colorData)
  96. }