color-data.ts 4.8 KB

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