|
@@ -5,48 +5,103 @@
|
|
|
*/
|
|
|
|
|
|
import { ValueCell } from 'mol-util';
|
|
|
-import VertexMap from '../shape/vertex-map';
|
|
|
+import { Vec2 } from 'mol-math/linear-algebra';
|
|
|
+import { TextureImage, createTextureImage } from 'mol-gl/renderable/util';
|
|
|
+import { LocationIterator } from '../representation/structure/visual/util/location-iterator';
|
|
|
+import { Location, NullLocation } from 'mol-model/location';
|
|
|
+
|
|
|
+export type SizeType = 'uniform' | 'instance' | 'element' | 'elementInstance'
|
|
|
|
|
|
export type SizeData = {
|
|
|
uSize: ValueCell<number>,
|
|
|
aSize: ValueCell<Float32Array>,
|
|
|
+ tSize: ValueCell<TextureImage>,
|
|
|
+ uSizeTexSize: ValueCell<Vec2>,
|
|
|
dSizeType: ValueCell<string>,
|
|
|
}
|
|
|
|
|
|
-export interface UniformSizeProps {
|
|
|
- value: number
|
|
|
-}
|
|
|
+export type LocationSize = (location: Location) => number
|
|
|
|
|
|
-/** Creates size uniform */
|
|
|
-export function createUniformSize(props: UniformSizeProps): SizeData {
|
|
|
+const emptySizeTexture = { array: new Uint8Array(1), width: 1, height: 1 }
|
|
|
+function createEmptySizeTexture() {
|
|
|
return {
|
|
|
- uSize: ValueCell.create(props.value),
|
|
|
- aSize: ValueCell.create(new Float32Array(0)),
|
|
|
- dSizeType: ValueCell.create('uniform'),
|
|
|
+ tSize: ValueCell.create(emptySizeTexture),
|
|
|
+ uSizeTexSize: ValueCell.create(Vec2.create(1, 1))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export function createValueSize(value: number, sizeData?: SizeData): SizeData {
|
|
|
+ if (sizeData) {
|
|
|
+ ValueCell.update(sizeData.uSize, value)
|
|
|
+ if (sizeData.dSizeType.ref.value !== 'uniform') {
|
|
|
+ ValueCell.update(sizeData.dSizeType, 'uniform')
|
|
|
+ }
|
|
|
+ return sizeData
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ uSize: ValueCell.create(value),
|
|
|
+ aSize: ValueCell.create(new Float32Array(0)),
|
|
|
+ ...createEmptySizeTexture(),
|
|
|
+ dSizeType: ValueCell.create('uniform'),
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-export interface AttributeSizeProps {
|
|
|
- sizeFn: (elementIdx: number) => number
|
|
|
- vertexMap: VertexMap
|
|
|
+/** Creates size uniform */
|
|
|
+export function createUniformSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
|
|
|
+ return createValueSize(sizeFn(NullLocation), sizeData)
|
|
|
}
|
|
|
|
|
|
-/** Creates size attribute with size for each element (i.e. shared across indtances/units) */
|
|
|
-export function createAttributeSize(props: AttributeSizeProps): SizeData {
|
|
|
- const { sizeFn, vertexMap } = props
|
|
|
- const { idCount, offsetCount, offsets } = vertexMap
|
|
|
- const sizes = new Float32Array(idCount);
|
|
|
- for (let i = 0, il = offsetCount - 1; i < il; ++i) {
|
|
|
- const start = offsets[i]
|
|
|
- const end = offsets[i + 1]
|
|
|
- const size = sizeFn(i)
|
|
|
- for (let i = start, il = end; i < il; ++i) {
|
|
|
- sizes[i] = size
|
|
|
+export function createTextureSize(sizes: TextureImage, type: SizeType, sizeData?: SizeData): SizeData {
|
|
|
+ if (sizeData) {
|
|
|
+ ValueCell.update(sizeData.tSize, sizes)
|
|
|
+ ValueCell.update(sizeData.uSizeTexSize, Vec2.create(sizes.width, sizes.height))
|
|
|
+ if (sizeData.dSizeType.ref.value !== type) {
|
|
|
+ ValueCell.update(sizeData.dSizeType, type)
|
|
|
+ }
|
|
|
+ return sizeData
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ uSize: ValueCell.create(0),
|
|
|
+ aSize: ValueCell.create(new Float32Array(0)),
|
|
|
+ tSize: ValueCell.create(sizes),
|
|
|
+ uSizeTexSize: ValueCell.create(Vec2.create(sizes.width, sizes.height)),
|
|
|
+ dSizeType: ValueCell.create(type),
|
|
|
}
|
|
|
}
|
|
|
- return {
|
|
|
- uSize: ValueCell.create(0),
|
|
|
- aSize: ValueCell.create(sizes),
|
|
|
- dSizeType: ValueCell.create('attribute'),
|
|
|
+}
|
|
|
+
|
|
|
+/** Creates size texture with size for each instance/unit */
|
|
|
+export function createInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
|
|
|
+ const { instanceCount} = locationIt
|
|
|
+ const sizes = sizeData && sizeData.tSize.ref.value.array.length >= instanceCount ? sizeData.tSize.ref.value : createTextureImage(instanceCount, 1)
|
|
|
+ while (locationIt.hasNext && !locationIt.isNextNewInstance) {
|
|
|
+ const v = locationIt.move()
|
|
|
+ sizes.array[v.instanceIndex] = sizeFn(v.location)
|
|
|
+ locationIt.skipInstance()
|
|
|
+ }
|
|
|
+ return createTextureSize(sizes, 'instance', sizeData)
|
|
|
+}
|
|
|
+
|
|
|
+/** Creates size texture with size for each element (i.e. shared across instances/units) */
|
|
|
+export function createElementSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
|
|
|
+ const { elementCount } = locationIt
|
|
|
+ const sizes = sizeData && sizeData.tSize.ref.value.array.length >= elementCount ? sizeData.tSize.ref.value : createTextureImage(elementCount, 1)
|
|
|
+ while (locationIt.hasNext && !locationIt.isNextNewInstance) {
|
|
|
+ const v = locationIt.move()
|
|
|
+ sizes.array[v.elementIndex] = sizeFn(v.location)
|
|
|
+ }
|
|
|
+ return createTextureSize(sizes, 'element', sizeData)
|
|
|
+}
|
|
|
+
|
|
|
+/** Creates size texture with size for each element instance (i.e. for each unit) */
|
|
|
+export function createElementInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData {
|
|
|
+ const { elementCount, instanceCount } = locationIt
|
|
|
+ const count = instanceCount * elementCount
|
|
|
+ const sizes = sizeData && sizeData.tSize.ref.value.array.length >= count ? sizeData.tSize.ref.value : createTextureImage(count, 1)
|
|
|
+ while (locationIt.hasNext && !locationIt.isNextNewInstance) {
|
|
|
+ const v = locationIt.move()
|
|
|
+ sizes.array[v.index] = sizeFn(v.location)
|
|
|
}
|
|
|
+ return createTextureSize(sizes, 'elementInstance', sizeData)
|
|
|
}
|