Browse Source

wip, size theme

Alexander Rose 6 years ago
parent
commit
5f594a08d7
27 changed files with 230 additions and 172 deletions
  1. 3 3
      src/mol-app/ui/transform/backbone.tsx
  2. 3 3
      src/mol-app/ui/transform/ball-and-stick.tsx
  3. 3 3
      src/mol-app/ui/transform/carbohydrate.tsx
  4. 3 3
      src/mol-app/ui/transform/cartoon.tsx
  5. 3 3
      src/mol-app/ui/transform/distance-restraint.tsx
  6. 3 3
      src/mol-app/ui/transform/spacefill.tsx
  7. 2 2
      src/mol-geo/representation/structure/index.ts
  8. 2 2
      src/mol-geo/representation/structure/representation/ball-and-stick.ts
  9. 2 2
      src/mol-geo/representation/structure/representation/distance-restraint.ts
  10. 2 2
      src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts
  11. 2 2
      src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts
  12. 2 2
      src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts
  13. 5 11
      src/mol-geo/representation/structure/visual/element-point.ts
  14. 2 2
      src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts
  15. 2 2
      src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts
  16. 11 12
      src/mol-geo/representation/structure/visual/util/common.ts
  17. 6 18
      src/mol-geo/representation/structure/visual/util/element.ts
  18. 12 8
      src/mol-geo/theme/index.ts
  19. 13 6
      src/mol-geo/theme/structure/size/index.ts
  20. 31 16
      src/mol-geo/theme/structure/size/physical.ts
  21. 22 0
      src/mol-geo/theme/structure/size/uniform.ts
  22. 2 36
      src/mol-geo/util/color-data.ts
  23. 1 1
      src/mol-geo/util/marker-data.ts
  24. 82 27
      src/mol-geo/util/size-data.ts
  25. 2 2
      src/mol-gl/_spec/renderer.spec.ts
  26. 3 1
      src/mol-gl/renderable/point.ts
  27. 6 0
      src/mol-gl/shader/point.vert

+ 3 - 3
src/mol-app/ui/transform/backbone.tsx

@@ -15,7 +15,7 @@ import { Toggle } from '../controls/common';
 import { BackboneEntity } from 'mol-view/state/entity';
 import { BackboneUpdate } from 'mol-view/state/transform'
 import { StateContext } from 'mol-view/state/context';
-import { ColorThemeProps, SizeTheme, ColorThemeNames, ColorThemeName } from 'mol-geo/theme';
+import { ColorThemeProps, SizeThemeProps, ColorThemeNames, ColorThemeName } from 'mol-geo/theme';
 import { Color, ColorNames } from 'mol-util/color';
 import { Slider } from '../controls/slider';
 import { VisualQuality } from 'mol-geo/representation/util';
@@ -28,7 +28,7 @@ interface BackboneState {
     detail: number
     colorTheme: ColorThemeProps
     colorValue: Color
-    sizeTheme: SizeTheme
+    sizeTheme: SizeThemeProps
     visible: boolean
     alpha: number
     depthMask: boolean
@@ -45,7 +45,7 @@ export class Backbone extends View<Controller<any>, BackboneState, { transform:
         detail: 2,
         colorTheme: { name: 'element-symbol' } as ColorThemeProps,
         colorValue: 0x000000,
-        sizeTheme: { name: 'uniform' } as SizeTheme,
+        sizeTheme: { name: 'uniform' } as SizeThemeProps,
         visible: true,
         alpha: 1,
         depthMask: true,

+ 3 - 3
src/mol-app/ui/transform/ball-and-stick.tsx

@@ -15,7 +15,7 @@ import { Toggle } from '../controls/common';
 import { DistanceRestraintEntity } from 'mol-view/state/entity';
 import { DistanceRestraintUpdate } from 'mol-view/state/transform'
 import { StateContext } from 'mol-view/state/context';
-import { ColorThemeProps, SizeTheme, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
+import { ColorThemeProps, SizeThemeProps, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
 import { Color, ColorNames } from 'mol-util/color';
 import { Slider } from '../controls/slider';
 import { VisualQuality } from 'mol-geo/representation/util';
@@ -27,7 +27,7 @@ interface BallAndStickState {
     flatShaded: boolean
     colorTheme: ColorThemeProps
     colorValue: Color
-    sizeTheme: SizeTheme
+    sizeTheme: SizeThemeProps
     visible: boolean
     alpha: number
     depthMask: boolean
@@ -48,7 +48,7 @@ export class BallAndStick extends View<Controller<any>, BallAndStickState, { tra
         flatShaded: false,
         colorTheme: { name: 'element-symbol' } as ColorThemeProps,
         colorValue: 0x000000,
-        sizeTheme: { name: 'uniform' } as SizeTheme,
+        sizeTheme: { name: 'uniform' } as SizeThemeProps,
         visible: true,
         alpha: 1,
         depthMask: true,

+ 3 - 3
src/mol-app/ui/transform/carbohydrate.tsx

@@ -15,7 +15,7 @@ import { Toggle } from '../controls/common';
 import { CarbohydrateEntity } from 'mol-view/state/entity';
 import { CarbohydrateUpdate } from 'mol-view/state/transform'
 import { StateContext } from 'mol-view/state/context';
-import { ColorThemeProps, SizeTheme, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
+import { ColorThemeProps, SizeThemeProps, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
 import { Color, ColorNames } from 'mol-util/color';
 import { Slider } from '../controls/slider';
 import { VisualQuality } from 'mol-geo/representation/util';
@@ -28,7 +28,7 @@ interface CarbohydrateState {
     detail: number
     colorTheme: ColorThemeProps
     colorValue: Color
-    sizeTheme: SizeTheme
+    sizeTheme: SizeThemeProps
     visible: boolean
     alpha: number
     depthMask: boolean
@@ -49,7 +49,7 @@ export class Carbohydrate extends View<Controller<any>, CarbohydrateState, { tra
         detail: 2,
         colorTheme: { name: 'element-symbol' } as ColorThemeProps,
         colorValue: 0x000000,
-        sizeTheme: { name: 'uniform' } as SizeTheme,
+        sizeTheme: { name: 'uniform' } as SizeThemeProps,
         visible: true,
         alpha: 1,
         depthMask: true,

+ 3 - 3
src/mol-app/ui/transform/cartoon.tsx

@@ -15,7 +15,7 @@ import { Toggle } from '../controls/common';
 import { CartoonEntity } from 'mol-view/state/entity';
 import { CartoonUpdate } from 'mol-view/state/transform'
 import { StateContext } from 'mol-view/state/context';
-import { ColorThemeProps, SizeTheme, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
+import { ColorThemeProps, SizeThemeProps, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
 import { Color, ColorNames } from 'mol-util/color';
 import { Slider } from '../controls/slider';
 import { VisualQuality } from 'mol-geo/representation/util';
@@ -28,7 +28,7 @@ interface CartoonState {
     detail: number
     colorTheme: ColorThemeProps
     colorValue: Color
-    sizeTheme: SizeTheme
+    sizeTheme: SizeThemeProps
     visible: boolean
     alpha: number
     depthMask: boolean
@@ -45,7 +45,7 @@ export class Cartoon extends View<Controller<any>, CartoonState, { transform: Ca
         detail: 2,
         colorTheme: { name: 'element-symbol' } as ColorThemeProps,
         colorValue: 0x000000,
-        sizeTheme: { name: 'uniform' } as SizeTheme,
+        sizeTheme: { name: 'uniform' } as SizeThemeProps,
         visible: true,
         alpha: 1,
         depthMask: true,

+ 3 - 3
src/mol-app/ui/transform/distance-restraint.tsx

@@ -15,7 +15,7 @@ import { Toggle } from '../controls/common';
 import { DistanceRestraintEntity } from 'mol-view/state/entity';
 import { DistanceRestraintUpdate } from 'mol-view/state/transform'
 import { StateContext } from 'mol-view/state/context';
-import { ColorThemeProps, SizeTheme, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
+import { ColorThemeProps, SizeThemeProps, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
 import { Color, ColorNames } from 'mol-util/color';
 import { Slider } from '../controls/slider';
 import { VisualQuality } from 'mol-geo/representation/util';
@@ -27,7 +27,7 @@ interface DistanceRestraintState {
     flatShaded: boolean
     colorTheme: ColorThemeProps
     colorValue: Color
-    sizeTheme: SizeTheme
+    sizeTheme: SizeThemeProps
     visible: boolean
     alpha: number
     depthMask: boolean
@@ -48,7 +48,7 @@ export class DistanceRestraint extends View<Controller<any>, DistanceRestraintSt
         flatShaded: false,
         colorTheme: { name: 'element-symbol' } as ColorThemeProps,
         colorValue: 0x000000,
-        sizeTheme: { name: 'uniform' } as SizeTheme,
+        sizeTheme: { name: 'uniform' } as SizeThemeProps,
         visible: true,
         alpha: 1,
         depthMask: true,

+ 3 - 3
src/mol-app/ui/transform/spacefill.tsx

@@ -15,7 +15,7 @@ import { Toggle } from '../controls/common';
 import { SpacefillEntity } from 'mol-view/state/entity';
 import { SpacefillUpdate } from 'mol-view/state/transform'
 import { StateContext } from 'mol-view/state/context';
-import { ColorThemeProps, SizeTheme, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
+import { ColorThemeProps, SizeThemeProps, ColorThemeName, ColorThemeNames } from 'mol-geo/theme';
 import { Color, ColorNames } from 'mol-util/color';
 import { Slider } from '../controls/slider';
 import { VisualQuality } from 'mol-geo/representation/util';
@@ -28,7 +28,7 @@ interface SpacefillState {
     detail: number
     colorTheme: ColorThemeProps
     colorValue: Color
-    sizeTheme: SizeTheme
+    sizeTheme: SizeThemeProps
     visible: boolean
     alpha: number
     depthMask: boolean
@@ -45,7 +45,7 @@ export class Spacefill extends View<Controller<any>, SpacefillState, { transform
         detail: 2,
         colorTheme: { name: 'element-symbol' } as ColorThemeProps,
         colorValue: 0x000000,
-        sizeTheme: { name: 'uniform' } as SizeTheme,
+        sizeTheme: { name: 'uniform' } as SizeThemeProps,
         visible: true,
         alpha: 1,
         depthMask: true,

+ 2 - 2
src/mol-geo/representation/structure/index.ts

@@ -7,7 +7,7 @@
 
 import { Structure } from 'mol-model/structure';
 import { Representation, RepresentationProps } from '..';
-import { ColorThemeProps, SizeTheme } from '../../theme';
+import { ColorThemeProps, SizeThemeProps } from '../../theme';
 import { DefaultBaseProps, DefaultMeshProps } from '../util';
 
 export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { }
@@ -15,7 +15,7 @@ export interface StructureRepresentation<P extends RepresentationProps = {}> ext
 export const DefaultStructureProps = {
     ...DefaultBaseProps,
     colorTheme: { name: 'unit-index' } as ColorThemeProps,
-    sizeTheme: { name: 'physical' } as SizeTheme,
+    sizeTheme: { name: 'physical' } as SizeThemeProps,
 }
 export type StructureProps = typeof DefaultStructureProps
 

+ 2 - 2
src/mol-geo/representation/structure/representation/ball-and-stick.ts

@@ -12,14 +12,14 @@ import { Structure, Unit } from 'mol-model/structure';
 import { Task } from 'mol-task';
 import { Loci, isEmptyLoci } from 'mol-model/loci';
 import { MarkerAction } from '../../../util/marker-data';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { InterUnitLinkVisual } from '../visual/inter-unit-link-cylinder';
 
 export const DefaultBallAndStickProps = {
     ...DefaultElementSphereProps,
     ...DefaultIntraUnitLinkProps,
 
-    sizeTheme: { name: 'uniform', value: 0.25 } as SizeTheme,
+    sizeTheme: { name: 'uniform', value: 0.25 } as SizeThemeProps,
     unitKinds: [ Unit.Kind.Atomic ] as Unit.Kind[]
 }
 export type BallAndStickProps = typeof DefaultBallAndStickProps

+ 2 - 2
src/mol-geo/representation/structure/representation/distance-restraint.ts

@@ -10,12 +10,12 @@ import { Structure } from 'mol-model/structure';
 import { Task } from 'mol-task';
 import { Loci } from 'mol-model/loci';
 import { MarkerAction } from '../../../util/marker-data';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { CrossLinkRestraintVisual, DefaultCrossLinkRestraintProps } from '../visual/cross-link-restraint-cylinder';
 
 export const DefaultDistanceRestraintProps = {
     ...DefaultCrossLinkRestraintProps,
-    sizeTheme: { name: 'uniform', value: 0.25 } as SizeTheme,
+    sizeTheme: { name: 'uniform', value: 0.25 } as SizeThemeProps,
 }
 export type DistanceRestraintProps = typeof DefaultDistanceRestraintProps
 

+ 2 - 2
src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts

@@ -10,7 +10,7 @@ import { RuntimeContext } from 'mol-task'
 import { Mesh } from '../../../shape/mesh';
 import { PickingId } from '../../../util/picking';
 import { Loci, EmptyLoci } from 'mol-model/loci';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { DefaultMeshProps } from '../../util';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { LocationIterator } from './util/location-iterator';
@@ -52,7 +52,7 @@ export const DefaultCarbohydrateLinkProps = {
     ...DefaultMeshProps,
     ...DefaultStructureProps,
     ...DefaultLinkCylinderProps,
-    sizeTheme: { name: 'physical', factor: 1 } as SizeTheme,
+    sizeTheme: { name: 'physical', factor: 1 } as SizeThemeProps,
     detail: 0,
     unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[]
 }

+ 2 - 2
src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts

@@ -10,7 +10,7 @@ import { RuntimeContext } from 'mol-task'
 import { Mesh } from '../../../shape/mesh';
 import { PickingId } from '../../../util/picking';
 import { Loci, EmptyLoci } from 'mol-model/loci';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { DefaultMeshProps } from '../../util';
 import { MeshBuilder } from '../../../shape/mesh-builder';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
@@ -115,7 +115,7 @@ async function createCarbohydrateSymbolMesh(ctx: RuntimeContext, structure: Stru
 export const DefaultCarbohydrateSymbolProps = {
     ...DefaultMeshProps,
     ...DefaultStructureProps,
-    sizeTheme: { name: 'physical', factor: 1 } as SizeTheme,
+    sizeTheme: { name: 'physical', factor: 1 } as SizeThemeProps,
     detail: 0,
     unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[]
 }

+ 2 - 2
src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts

@@ -12,7 +12,7 @@ import { Mesh } from '../../../shape/mesh';
 import { PickingId } from '../../../util/picking';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { ComplexMeshVisual } from '../complex-visual';
 import { LocationIterator } from './util/location-iterator';
 import { Interval } from 'mol-data/int';
@@ -43,7 +43,7 @@ async function createCrossLinkRestraintCylinderMesh(ctx: RuntimeContext, structu
 export const DefaultCrossLinkRestraintProps = {
     ...DefaultStructureProps,
     ...DefaultLinkCylinderProps,
-    sizeTheme: { name: 'physical', factor: 0.3 } as SizeTheme,
+    sizeTheme: { name: 'physical', factor: 0.3 } as SizeThemeProps,
     flipSided: false,
     flatShaded: false,
 }

+ 5 - 11
src/mol-geo/representation/structure/visual/element-point.ts

@@ -11,8 +11,7 @@ import { Unit } from 'mol-model/structure';
 import { RuntimeContext } from 'mol-task'
 
 import { UnitsVisual, DefaultStructureProps } from '..';
-import VertexMap from '../../../shape/vertex-map';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { getElementLoci } from './util/element';
 import { createTransforms, createColors, createSizes } from './util/common';
 import { deepEqual, defaults } from 'mol-util';
@@ -27,7 +26,7 @@ import { StructureElementIterator } from './util/location-iterator';
 
 export const DefaultPointProps = {
     ...DefaultStructureProps,
-    sizeTheme: { name: 'physical' } as SizeTheme
+    sizeTheme: { name: 'physical' } as SizeThemeProps
 }
 export type PointProps = Partial<typeof DefaultPointProps>
 
@@ -70,17 +69,12 @@ export default function PointVisual(): UnitsVisual<PointProps> {
             const elementCount = _elements.length
             const instanceCount = group.units.length
 
-            const vertexMap = VertexMap.create(
-                elementCount,
-                elementCount + 1,
-                fillSerial(new Uint32Array(elementCount)),
-                fillSerial(new Uint32Array(elementCount + 1))
-            )
+            const locationIt = StructureElementIterator.fromGroup(group)
 
             const vertices = createPointVertices(_units[0])
             const transforms = createTransforms(group)
-            const color = createColors(StructureElementIterator.fromGroup(group), colorTheme)
-            const size = createSizes(group, vertexMap, sizeTheme)
+            const color = createColors(locationIt, colorTheme)
+            const size = createSizes(locationIt, sizeTheme)
             const marker = createMarkers(instanceCount * elementCount)
 
             const values: PointValues = {

+ 2 - 2
src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts

@@ -12,7 +12,7 @@ import { Mesh } from '../../../shape/mesh';
 import { PickingId } from '../../../util/picking';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { LinkIterator } from './util/location-iterator';
 import { ComplexMeshVisual } from '../complex-visual';
 import { Interval } from 'mol-data/int';
@@ -42,7 +42,7 @@ async function createInterUnitLinkCylinderMesh(ctx: RuntimeContext, structure: S
 export const DefaultInterUnitLinkProps = {
     ...DefaultStructureProps,
     ...DefaultLinkCylinderProps,
-    sizeTheme: { name: 'physical', factor: 0.3 } as SizeTheme,
+    sizeTheme: { name: 'physical', factor: 0.3 } as SizeThemeProps,
 }
 export type InterUnitLinkProps = typeof DefaultInterUnitLinkProps
 

+ 2 - 2
src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts

@@ -13,7 +13,7 @@ import { Mesh } from '../../../shape/mesh';
 import { PickingId } from '../../../util/picking';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Loci, EmptyLoci } from 'mol-model/loci';
-import { SizeTheme } from '../../../theme';
+import { SizeThemeProps } from '../../../theme';
 import { LinkIterator } from './util/location-iterator';
 import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual';
 import { Interval } from 'mol-data/int';
@@ -58,7 +58,7 @@ async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit,
 export const DefaultIntraUnitLinkProps = {
     ...DefaultUnitsMeshProps,
     ...DefaultLinkCylinderProps,
-    sizeTheme: { name: 'physical', factor: 0.3 } as SizeTheme,
+    sizeTheme: { name: 'physical', factor: 0.3 } as SizeThemeProps,
 }
 export type IntraUnitLinkProps = typeof DefaultIntraUnitLinkProps
 

+ 11 - 12
src/mol-geo/representation/structure/visual/util/common.ts

@@ -9,12 +9,10 @@ import { Unit, Structure } from 'mol-model/structure';
 import { Mat4 } from 'mol-math/linear-algebra'
 
 import { createUniformColor, ColorData, createElementColor, createElementInstanceColor, createInstanceColor } from '../../../../util/color-data';
-import { createUniformSize, SizeData } from '../../../../util/size-data';
-import { physicalSizeData } from '../../../../theme/structure/size/physical';
-import VertexMap from '../../../../shape/vertex-map';
-import { ColorThemeProps, SizeTheme } from '../../../../theme';
+import { createUniformSize, SizeData, createElementSize, createElementInstanceSize, createInstanceSize } from '../../../../util/size-data';
+import { ColorThemeProps, SizeThemeProps } from '../../../../theme';
 import { ColorTheme } from '../../../../theme/structure/color';
-import { ValueCell, defaults } from 'mol-util';
+import { ValueCell } from 'mol-util';
 import { LocationIterator } from './location-iterator';
 import { Mesh } from '../../../../shape/mesh';
 import { MeshValues } from 'mol-gl/renderable';
@@ -23,6 +21,7 @@ import { MeshProps, createMeshValues, createRenderableState } from '../../../uti
 import { StructureProps } from '../..';
 import { createMarkers } from '../../../../util/marker-data';
 import { createMeshRenderObject } from 'mol-gl/render-object';
+import { SizeTheme } from '../../../../theme/structure/size';
 
 export function createTransforms({ units }: Unit.SymmetryGroup, transforms?: ValueCell<Float32Array>) {
     const unitCount = units.length
@@ -47,16 +46,16 @@ export function createColors(locationIt: LocationIterator, props: ColorThemeProp
         case 'element': return createElementColor(locationIt, colorTheme.color, colorData)
         case 'elementInstance': return createElementInstanceColor(locationIt, colorTheme.color, colorData)
         case 'instance': return createInstanceColor(locationIt, colorTheme.color, colorData)
-        case 'attribute': throw new Error('not implemented') // TODO
     }
 }
 
-export function createSizes(group: Unit.SymmetryGroup, vertexMap: VertexMap, props: SizeTheme): SizeData {
-    switch (props.name) {
-        case 'uniform':
-            return createUniformSize(props)
-        case 'physical':
-            return physicalSizeData(defaults(props.factor, 1), { group, vertexMap })
+export function createSizes(locationIt: LocationIterator, props: SizeThemeProps, sizeData?: SizeData): SizeData {
+    const sizeTheme = SizeTheme(props)
+    switch (sizeTheme.kind) {
+        case 'uniform': return createUniformSize(locationIt, sizeTheme.size, sizeData)
+        case 'element': return createElementSize(locationIt, sizeTheme.size, sizeData)
+        case 'elementInstance': return createElementInstanceSize(locationIt, sizeTheme.size, sizeData)
+        case 'instance': return createInstanceSize(locationIt, sizeTheme.size, sizeData)
     }
 }
 

+ 6 - 18
src/mol-geo/representation/structure/visual/util/element.ts

@@ -6,38 +6,26 @@
 
 import { Vec3 } from 'mol-math/linear-algebra';
 import { Unit, StructureElement } from 'mol-model/structure';
-import { SizeTheme } from '../../../../theme';
 import { RuntimeContext } from 'mol-task';
 import { sphereVertexCount } from '../../../../primitive/sphere';
 import { Mesh } from '../../../../shape/mesh';
 import { MeshBuilder } from '../../../../shape/mesh-builder';
-import { defaults } from 'mol-util';
 import { Loci, EmptyLoci } from 'mol-model/loci';
 import { Interval, OrderedSet } from 'mol-data/int';
-import { getPhysicalRadius } from '../../../../theme/structure/size/physical';
 import { PickingId } from '../../../../util/picking';
-
-export function getElementRadius(unit: Unit, props: SizeTheme): StructureElement.Property<number> {
-    switch (props.name) {
-        case 'uniform':
-            return () => props.value
-        case 'physical':
-            const radius = getPhysicalRadius(unit)
-            const factor = defaults(props.factor, 1)
-            return (l) => radius(l) * factor
-    }
-}
+import { SizeThemeProps } from '../../../../theme';
+import { SizeTheme } from '../../../../theme/structure/size';
 
 export interface ElementSphereMeshProps {
-    sizeTheme: SizeTheme,
+    sizeTheme: SizeThemeProps,
     detail: number,
 }
 
 export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, props: ElementSphereMeshProps, mesh?: Mesh) {
-    const { detail, sizeTheme } = props
+    const { detail } = props
 
     const { elements } = unit;
-    const radius = getElementRadius(unit, sizeTheme)
+    const sizeTheme = SizeTheme(props.sizeTheme)
     const elementCount = elements.length;
     const vertexCount = elementCount * sphereVertexCount(detail)
     const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
@@ -52,7 +40,7 @@ export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, p
         pos(elements[i], v)
 
         meshBuilder.setId(i)
-        meshBuilder.addSphere(v, radius(l), detail)
+        meshBuilder.addSphere(v, sizeTheme.size(l), detail)
 
         if (i % 10000 === 0 && ctx.shouldUpdate) {
             await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });

+ 12 - 8
src/mol-geo/theme/index.ts

@@ -25,14 +25,18 @@ export const ColorThemeInfo = {
 export type ColorThemeName = keyof typeof ColorThemeInfo
 export const ColorThemeNames = Object.keys(ColorThemeInfo)
 
-export interface UniformSizeTheme {
-    name: 'uniform',
-    value: number
-}
+//
 
-export interface ScaleSizeTheme {
-    name: 'physical' // van-der-Waals for atoms, given radius for coarse spheres
-    factor?: number // scaling factor
+export interface SizeThemeProps {
+    name: 'physical' | 'uniform'
+    value?: number
+    factor?: number
+    structure?: Structure
 }
 
-export type SizeTheme = UniformSizeTheme | ScaleSizeTheme
+export const SizeThemeInfo = {
+    'physical': {},
+    'uniform': {}
+}
+export type SizeThemeName = keyof typeof SizeThemeInfo
+export const SizeThemeNames = Object.keys(SizeThemeInfo)

+ 13 - 6
src/mol-geo/theme/structure/size/index.ts

@@ -4,12 +4,19 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Unit } from 'mol-model/structure';
-import VertexMap from '../../../shape/vertex-map';
+import { SizeType, LocationSize } from '../../../util/size-data';
+import { SizeThemeProps } from '../..';
+import { PhysicalSizeTheme } from './physical';
+import { UniformSizeTheme } from './uniform';
 
-export interface StructureSizeDataProps {
-    group: Unit.SymmetryGroup,
-    vertexMap: VertexMap
+export interface SizeTheme {
+    kind: SizeType
+    size: LocationSize
 }
 
-export { physicalSizeData } from './physical'
+export function SizeTheme(props: SizeThemeProps): SizeTheme {
+    switch (props.name) {
+        case 'physical': return PhysicalSizeTheme(props)
+        case 'uniform': return UniformSizeTheme(props)
+    }
+}

+ 31 - 16
src/mol-geo/theme/structure/size/physical.ts

@@ -4,9 +4,13 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { StructureElement, Unit, StructureProperties } from 'mol-model/structure';
-import { StructureSizeDataProps } from '.';
-import { createAttributeSize } from '../../../util/size-data';
+import { StructureElement, Unit, StructureProperties, Link } from 'mol-model/structure';
+import { Location } from 'mol-model/location';
+import { SizeTheme } from '.';
+import { SizeThemeProps } from '../..';
+
+const DefaultSize = 1
+const DefaultFactor = 1
 
 export function getPhysicalRadius(unit: Unit): StructureElement.Property<number> {
     if (Unit.isAtomic(unit)) {
@@ -22,18 +26,29 @@ export function getPhysicalRadius(unit: Unit): StructureElement.Property<number>
  * Create attribute data with the physical size of an element,
  * i.e. vdw for atoms and radius for coarse spheres
  */
-export function physicalSizeData(factor: number, props: StructureSizeDataProps) {
-    const { group, vertexMap } = props
-    const unit = group.units[0]
-    const elements = group.elements;
-    const radius = getPhysicalRadius(unit)
+export function PhysicalSizeTheme(props: SizeThemeProps): SizeTheme {
+    const factor = props.factor || DefaultFactor
     const l = StructureElement.create()
-    l.unit = unit
-    return createAttributeSize({
-        sizeFn: (elementIdx: number) => {
-            l.element = elements[elementIdx]
-            return radius(l) * factor
-        },
-        vertexMap
-    })
+
+    function sizeFn(location: Location): number {
+        if (StructureElement.isLocation(location)) {
+            if (Unit.isAtomic(location.unit)) {
+                const radius = getPhysicalRadius(location.unit)
+                return factor * radius(location)
+            }
+        } else if (Link.isLocation(location)) {
+            if (Unit.isAtomic(location.aUnit)) {
+                const radius = getPhysicalRadius(location.aUnit)
+                l.unit = location.aUnit
+                l.element = location.aUnit.elements[location.aIndex]
+                return factor * radius(l)
+            }
+        }
+        return DefaultSize
+    }
+
+    return {
+        kind: 'element',
+        size: sizeFn
+    }
 }

+ 22 - 0
src/mol-geo/theme/structure/size/uniform.ts

@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { SizeThemeProps } from '../..';
+import { SizeTheme } from '.';
+
+const DefaultSize = 1
+const DefaultFactor = 1
+
+export function UniformSizeTheme(props: SizeThemeProps): SizeTheme {
+    const value = props.value || DefaultSize
+    const factor = props.factor || DefaultFactor
+    const size = value * factor
+
+    return {
+        kind: 'uniform',
+        size: () => size
+    }
+}

+ 2 - 36
src/mol-geo/util/color-data.ts

@@ -11,7 +11,7 @@ import { Vec2, Vec3 } from 'mol-math/linear-algebra';
 import { LocationIterator } from '../representation/structure/visual/util/location-iterator';
 import { Location, NullLocation } from 'mol-model/location';
 
-export type ColorType = 'uniform' | 'attribute' | 'instance' | 'element' | 'elementInstance'
+export type ColorType = 'uniform' | 'instance' | 'element' | 'elementInstance'
 
 export type ColorData = {
     uColor: ValueCell<Vec3>,
@@ -53,40 +53,6 @@ export function createUniformColor(locationIt: LocationIterator, colorFn: Locati
     return createValueColor(colorFn(NullLocation, false), colorData)
 }
 
-// export interface AttributeColorProps {
-//     colorFn: (elementIdx: number) => Color
-//     vertexMap: VertexMap
-// }
-
-// /** Creates color attribute with color for each element (i.e. shared across instances/units) */
-// export function createAttributeColor(props: AttributeColorProps, colorData?: ColorData): ColorData {
-//     const { colorFn, vertexMap } = props
-//     const { idCount, offsetCount, offsets } = vertexMap
-//     const colors = new Float32Array(idCount * 3);
-//     for (let i = 0, il = offsetCount - 1; i < il; ++i) {
-//         const start = offsets[i]
-//         const end = offsets[i + 1]
-//         const hexColor = colorFn(i)
-//         for (let i = start, il = end; i < il; ++i) {
-//             Color.toArrayNormalized(hexColor, colors, i * 3)
-//         }
-//     }
-//     if (colorData) {
-//         ValueCell.update(colorData.aColor, colors)
-//         if (colorData.dColorType.ref.value !== 'attribute') {
-//             ValueCell.update(colorData.dColorType, 'attribute')
-//         }
-//         return colorData
-//     } else {
-//         return {
-//             uColor: ValueCell.create(Vec3.zero()),
-//             aColor: ValueCell.create(colors),
-//             ...createEmptyColorTexture(),
-//             dColorType: ValueCell.create('attribute'),
-//         }
-//     }
-// }
-
 export function createTextureColor(colors: TextureImage, type: ColorType, colorData?: ColorData): ColorData {
     if (colorData) {
         ValueCell.update(colorData.tColor, colors)
@@ -112,7 +78,7 @@ export function createInstanceColor(locationIt: LocationIterator, colorFn: Locat
     const colors = colorData && colorData.tColor.ref.value.array.length >= instanceCount * 3 ? colorData.tColor.ref.value : createTextureImage(instanceCount, 3)
     while (locationIt.hasNext && !locationIt.isNextNewInstance) {
         const v = locationIt.move()
-        Color.toArray(colorFn(v.location, v.isSecondary), colors.array, v.index * 3)
+        Color.toArray(colorFn(v.location, v.isSecondary), colors.array, v.instanceIndex * 3)
         locationIt.skipInstance()
     }
     return createTextureColor(colors, 'instance', colorData)

+ 1 - 1
src/mol-geo/util/marker-data.ts

@@ -37,7 +37,7 @@ export function applyMarkerAction(array: Uint8Array, start: number, end: number,
                 if (v % 2 !== 0) {
                     v -= 1
                     changed = true
-                } 
+                }
                 break
             case MarkerAction.Select:
                 v += 2

+ 82 - 27
src/mol-geo/util/size-data.ts

@@ -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)
 }

+ 2 - 2
src/mol-gl/_spec/renderer.spec.ts

@@ -12,7 +12,7 @@ import { ValueCell } from 'mol-util';
 
 import Renderer from '../renderer';
 import { createValueColor } from 'mol-geo/util/color-data';
-import { createUniformSize } from 'mol-geo/util/size-data';
+import { createValueSize } from 'mol-geo/util/size-data';
 import { createContext } from '../webgl/context';
 import { RenderableState } from '../renderable';
 import { createPointRenderObject } from '../render-object';
@@ -48,7 +48,7 @@ function createPoints() {
     const aElementId = ValueCell.create(fillSerial(new Float32Array(3)))
     const aInstanceId = ValueCell.create(fillSerial(new Float32Array(1)))
     const color = createValueColor(0xFF0000)
-    const size = createUniformSize({ value: 1 })
+    const size = createValueSize(1)
     const marker = createEmptyMarkers()
 
     const aTransform = ValueCell.create(new Float32Array(16))

+ 3 - 1
src/mol-gl/renderable/point.ts

@@ -7,7 +7,7 @@
 import { Renderable, RenderableState, createRenderable } from '../renderable'
 import { Context } from '../webgl/context';
 import { createRenderItem } from '../webgl/render-item';
-import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, DefineSpec, Values, InternalSchema } from './schema';
+import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, DefineSpec, Values, InternalSchema, TextureSpec } from './schema';
 import { PointShaderCode } from '../shader-code';
 import { ValueCell } from 'mol-util';
 
@@ -15,6 +15,8 @@ export const PointSchema = {
     ...BaseSchema,
     aSize: AttributeSpec('float32', 1, 0),
     uSize: UniformSpec('f'),
+    uSizeTexSize: UniformSpec('v2'),
+    tSize: TextureSpec('alpha', 'ubyte'),
     dSizeType: DefineSpec('string', ['uniform', 'attribute']),
     dPointSizeAttenuation: DefineSpec('boolean'),
 }

+ 6 - 0
src/mol-gl/shader/point.vert

@@ -32,6 +32,12 @@ void main(){
         float size = uSize;
     #elif defined(dSizeType_attribute)
         float size = aSize;
+    #elif defined(dSizeType_instance)
+        float size = readFromTexture(tSize, aInstanceId, uSizeTexSize).r;
+    #elif defined(dSizeType_element)
+        float size = readFromTexture(tSize, aElementId, uSizeTexSize).r;
+    #elif defined(dSizeType_elementInstance)
+        float size = readFromTexture(tSize, aInstanceId * float(uElementCount) + aElementId, uSizeTexSize).r;
     #endif
 
     #ifdef dPointSizeAttenuation