Browse Source

wip, repr in-place-update

Alexander Rose 6 years ago
parent
commit
662daede8f

+ 4 - 5
src/mol-data/util/chunked-array.ts

@@ -135,11 +135,10 @@ namespace ChunkedArray {
         return ret;
     }
 
-    export function create<T, C extends Sizes = 1>(ctor: { new (size: number): ArrayLike<T> }, elementSize: C, chunkSize: number): ChunkedArray<T, C>
-    /** The size of the initial chunk is elementSize * initialCount */
-    export function create<T, C extends Sizes = 1>(ctor: { new (size: number): ArrayLike<T> }, elementSize: C, chunkSize: number, initialCount: number): ChunkedArray<T, C>
-    /** Use the provided array as the initial chunk. The size of the array must be divisible by the elementSize */
-    export function create<T, C extends Sizes = 1>(ctor: { new (size: number): ArrayLike<T> }, elementSize: C, chunkSize: number, initialChunk?: ArrayLike<T>): ChunkedArray<T, C>
+    /**
+     * The size of the initial chunk is elementSize * initialCount.
+     * Use the provided array as the initial chunk. The size of the array must be divisible by the elementSize.
+     */
     export function create<T, C extends Sizes = 1>(ctor: { new (size: number): ArrayLike<T> }, elementSize: C, chunkSize: number, initialChunkOrCount?: number | ArrayLike<T>): ChunkedArray<T, C> {
         const ret: ChunkedArray<T, C> = {
             ctor,

+ 1 - 1
src/mol-geo/representation/structure/point.ts

@@ -92,7 +92,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
                 const values: PointValues = {
                     aPosition: ValueCell.create(vertices),
                     aElementId: ValueCell.create(fillSerial(new Float32Array(elementCount))),
-                    aTransform: ValueCell.create(transforms),
+                    aTransform: transforms,
                     aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))),
                     ...color,
                     ...size,

+ 18 - 3
src/mol-geo/representation/structure/spacefill.ts

@@ -21,6 +21,7 @@ import { deepEqual, defaults } from 'mol-util';
 import { fillSerial } from 'mol-gl/renderable/util';
 import { RenderableState, MeshValues } from 'mol-gl/renderable';
 import { getMeshData } from '../../util/mesh-data';
+import { Mesh } from '../../shape/mesh';
 
 export const DefaultSpacefillProps = {
     ...DefaultStructureProps,
@@ -75,6 +76,8 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
     const renderObjects: RenderObject[] = []
     let spheres: MeshRenderObject
     let currentProps: typeof DefaultSpacefillProps
+    let mesh: Mesh
+    let currentGroup: Unit.SymmetryGroup
 
     return {
         renderObjects,
@@ -83,10 +86,11 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
 
             return Task.create('Spacefill.create', async ctx => {
                 renderObjects.length = 0 // clear
+                currentGroup = group
 
                 const { detail, colorTheme } = { ...DefaultSpacefillProps, ...props }
 
-                const mesh = await createSpacefillMesh(group.units[0], detail).runAsChild(ctx, 'Computing spacefill mesh')
+                mesh = await createSpacefillMesh(group.units[0], detail).runAsChild(ctx, 'Computing spacefill mesh')
                 // console.log(mesh)
 
                 const vertexMap = VertexMap.fromMesh(mesh)
@@ -101,7 +105,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
 
                 const values: MeshValues = {
                     ...getMeshData(mesh),
-                    aTransform: ValueCell.create(transforms),
+                    aTransform: transforms,
                     aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))),
                     ...color,
 
@@ -133,9 +137,20 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
 
             return Task.create('Spacefill.update', async ctx => {
                 if (!spheres) return false
-                if (newProps.detail !== currentProps.detail) return false
+                // if (newProps.detail !== currentProps.detail) return false
                 if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) return false
 
+                if (newProps.detail !== currentProps.detail) {
+                    await createSpacefillMesh(currentGroup.units[0], newProps.detail).runAsChild(ctx, 'Computing spacefill mesh')
+                    const vertexMap = VertexMap.fromMesh(mesh)
+
+                    await ctx.update('Computing spacefill transforms');
+                    createTransforms(currentGroup)
+
+                    await ctx.update('Computing spacefill colors');
+                    createColors(currentGroup, vertexMap, newProps.colorTheme)
+                }
+
                 ValueCell.update(spheres.values.uAlpha, newProps.alpha)
                 ValueCell.update(spheres.values.dDoubleSided, newProps.doubleSided)
                 spheres.state.visible = newProps.visible

+ 13 - 11
src/mol-geo/representation/structure/utils.ts

@@ -8,34 +8,36 @@
 import { Unit } from 'mol-model/structure';
 import { Mat4 } from 'mol-math/linear-algebra'
 
-import { createUniformColor } from '../../util/color-data';
+import { createUniformColor, ColorData } from '../../util/color-data';
 import { createUniformSize } from '../../util/size-data';
 import { elementSizeData } from '../../theme/structure/size/element';
 import VertexMap from '../../shape/vertex-map';
 import { ColorTheme, SizeTheme } from '../../theme';
 import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color';
+import { ValueCell } from 'mol-util';
 
-export function createTransforms({ units }: Unit.SymmetryGroup) {
+export function createTransforms({ units }: Unit.SymmetryGroup, transforms?: ValueCell<Float32Array>) {
     const unitCount = units.length
-    const transforms = new Float32Array(unitCount * 16)
+    const n = unitCount * 16
+    const array = transforms && transforms.ref.value.length >= n ? transforms.ref.value : new Float32Array(n)
     for (let i = 0; i < unitCount; i++) {
-        Mat4.toArray(units[i].conformation.operator.matrix, transforms, i * 16)
+        Mat4.toArray(units[i].conformation.operator.matrix, array, i * 16)
     }
-    return transforms
+    return transforms ? ValueCell.update(transforms, array) : ValueCell.create(array)
 }
 
-export function createColors(group: Unit.SymmetryGroup, vertexMap: VertexMap, props: ColorTheme) {
+export function createColors(group: Unit.SymmetryGroup, vertexMap: VertexMap, props: ColorTheme, colorData?: ColorData) {
     switch (props.name) {
         case 'atom-index':
-            return elementIndexColorData({ group, vertexMap })
+            return elementIndexColorData({ group, vertexMap }, colorData)
         case 'chain-id':
-            return chainIdColorData({ group, vertexMap })
+            return chainIdColorData({ group, vertexMap }, colorData)
         case 'element-symbol':
-            return elementSymbolColorData({ group, vertexMap })
+            return elementSymbolColorData({ group, vertexMap }, colorData)
         case 'instance-index':
-            return instanceIndexColorData({ group, vertexMap })
+            return instanceIndexColorData({ group, vertexMap }, colorData)
         case 'uniform':
-            return createUniformColor(props)
+            return createUniformColor(props, colorData)
     }
 }
 

+ 7 - 6
src/mol-geo/shape/mesh-builder.ts

@@ -33,13 +33,13 @@ const tmpV = Vec3.zero()
 // TODO cache primitives based on props
 
 export namespace MeshBuilder {
-    export function create(initialCount = 2048, chunkSize = 1024): MeshBuilder {
-        const vertices = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount);
-        const normals = ChunkedArray.create(Float32Array, 3, chunkSize, initialCount);
-        const indices = ChunkedArray.create(Uint32Array, 3, chunkSize * 3, initialCount * 3);
+    export function create(initialCount = 2048, chunkSize = 1024, mesh?: Mesh): MeshBuilder {
+        const vertices = ChunkedArray.create(Float32Array, 3, chunkSize, mesh ? mesh.vertexBuffer.ref.value : initialCount);
+        const normals = ChunkedArray.create(Float32Array, 3, chunkSize, mesh ? mesh.normalBuffer.ref.value : initialCount);
+        const indices = ChunkedArray.create(Uint32Array, 3, chunkSize * 3, mesh ? mesh.indexBuffer.ref.value : initialCount * 3);
 
-        const ids = ChunkedArray.create(Float32Array, 1, chunkSize, initialCount);
-        const offsets = ChunkedArray.create(Uint32Array, 1, chunkSize, initialCount);
+        const ids = ChunkedArray.create(Float32Array, 1, chunkSize, mesh ? mesh.idBuffer.ref.value : initialCount);
+        const offsets = ChunkedArray.create(Uint32Array, 1, chunkSize, mesh ? mesh.offsetBuffer.ref.value : initialCount);
 
         let currentId = -1
 
@@ -102,6 +102,7 @@ export namespace MeshBuilder {
                     idBuffer: ValueCell.create(ChunkedArray.compact(ids, true) as Float32Array),
                     offsetBuffer: ValueCell.create(ChunkedArray.compact(offsets, true) as Uint32Array),
                     normalsComputed: true,
+                    offsetsComputed: true,
                 }
                 return mesh
             }

+ 4 - 0
src/mol-geo/shape/mesh.ts

@@ -24,9 +24,13 @@ export interface Mesh {
     normalBuffer: ValueCell<Float32Array>,
     /** Id buffer as array of ids for each vertex wrapped in a value cell */
     idBuffer: ValueCell<Float32Array>,
+    /** Offset buffer as array of offsets for id ranges wrapped in a value cell */
+    offsetBuffer: ValueCell<Uint32Array>,
 
     /** Flag indicating if normals are computed for the current set of vertices */
     normalsComputed: boolean,
+    /** Flag indicating if offsets are computed for the current set of ids */
+    offsetsComputed: boolean,
 
     /** Bounding sphere of the mesh */
     boundingSphere?: Sphere3D

+ 3 - 3
src/mol-geo/theme/structure/color/chain-id.ts

@@ -7,7 +7,7 @@
 import { Unit, Queries, Element } from 'mol-model/structure';
 
 import { StructureColorDataProps } from '.';
-import { createAttributeOrElementColor } from '../../../util/color-data';
+import { createAttributeOrElementColor, ColorData } from '../../../util/color-data';
 import { ColorScale } from 'mol-util/color';
 import { Column } from 'mol-data/db';
 
@@ -38,7 +38,7 @@ function createChainIdMap(unit: Unit) {
     return { map, count: index }
 }
 
-export function chainIdColorData(props: StructureColorDataProps) {
+export function chainIdColorData(props: StructureColorDataProps, colorData?: ColorData) {
     const { group: { units, elements }, vertexMap } = props
     const unit = units[0]
 
@@ -63,5 +63,5 @@ export function chainIdColorData(props: StructureColorDataProps) {
             return scale.color(map.get(asym_id(l)) || 0)
         },
         vertexMap
-    })
+    }, colorData)
 }

+ 3 - 3
src/mol-geo/theme/structure/color/element-index.ts

@@ -6,9 +6,9 @@
 
 import { ColorScale } from 'mol-util/color';
 import { StructureColorDataProps } from '.';
-import { createElementInstanceColor } from '../../../util/color-data';
+import { createElementInstanceColor, ColorData } from '../../../util/color-data';
 
-export function elementIndexColorData(props: StructureColorDataProps) {
+export function elementIndexColorData(props: StructureColorDataProps, colorData?: ColorData) {
     const { group: { units, elements }, vertexMap } = props
     const instanceCount = units.length
     const elementCount = elements.length
@@ -19,5 +19,5 @@ export function elementIndexColorData(props: StructureColorDataProps) {
         colorFn: (instanceIdx, elementIdx) => scale.color(instanceIdx * elementCount + elementIdx),
         instanceCount,
         vertexMap
-    })
+    }, colorData)
 }

+ 3 - 3
src/mol-geo/theme/structure/color/element-symbol.ts

@@ -7,7 +7,7 @@
 import { ElementSymbol } from 'mol-model/structure/model/types';
 import { Color } from 'mol-util/color';
 import { StructureColorDataProps } from '.';
-import { createAttributeOrElementColor } from '../../../util/color-data';
+import { createAttributeOrElementColor, ColorData } from '../../../util/color-data';
 
 // from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)
 export const ElementSymbolColors: { [k: string]: Color } = {
@@ -21,7 +21,7 @@ export function elementSymbolColor(element: ElementSymbol): Color {
     return c === void 0 ? DefaultElementSymbolColor : c
 }
 
-export function elementSymbolColorData(props: StructureColorDataProps) {
+export function elementSymbolColorData(props: StructureColorDataProps, colorData?: ColorData) {
     const { group: { units, elements }, vertexMap } = props
     const { type_symbol } = units[0].model.atomicHierarchy.atoms
     return createAttributeOrElementColor(vertexMap, {
@@ -30,5 +30,5 @@ export function elementSymbolColorData(props: StructureColorDataProps) {
             return elementSymbolColor(type_symbol.value(e))
         },
         vertexMap
-    })
+    }, colorData)
 }

+ 3 - 3
src/mol-geo/theme/structure/color/instance-index.ts

@@ -6,9 +6,9 @@
 
 import { ColorScale } from 'mol-util/color';
 import { StructureColorDataProps } from '.';
-import { createInstanceColor } from '../../../util/color-data';
+import { createInstanceColor, ColorData } from '../../../util/color-data';
 
-export function instanceIndexColorData(props: StructureColorDataProps) {
+export function instanceIndexColorData(props: StructureColorDataProps, colorData?: ColorData) {
     const { group: { units } } = props
     const instanceCount = units.length
 
@@ -17,5 +17,5 @@ export function instanceIndexColorData(props: StructureColorDataProps) {
     return createInstanceColor({
         colorFn: scale.color,
         instanceCount
-    })
+    }, colorData)
 }

+ 48 - 29
src/mol-geo/util/color-data.ts

@@ -25,13 +25,19 @@ export interface UniformColorProps {
 }
 
 /** Creates color uniform */
-export function createUniformColor(props: UniformColorProps): ColorData {
-    return {
-        uColor: ValueCell.create(Color.toRgbNormalized(props.value) as Vec3),
-        aColor: ValueCell.create(new Float32Array(0)),
-        tColor: ValueCell.create(emptyTexture),
-        uColorTexSize: ValueCell.create(Vec2.zero()),
-        dColorType: ValueCell.create('uniform'),
+export function createUniformColor(props: UniformColorProps, colorData?: ColorData): ColorData {
+    if (colorData) {
+        ValueCell.update(colorData.uColor, Color.toRgbNormalized(props.value) as Vec3)
+        ValueCell.update(colorData.dColorType, 'uniform')
+        return colorData
+    } else {
+        return {
+            uColor: ValueCell.create(Color.toRgbNormalized(props.value) as Vec3),
+            aColor: ValueCell.create(new Float32Array(0)),
+            tColor: ValueCell.create(emptyTexture),
+            uColorTexSize: ValueCell.create(Vec2.zero()),
+            dColorType: ValueCell.create('uniform'),
+        }
     }
 }
 
@@ -41,7 +47,7 @@ export interface AttributeColorProps {
 }
 
 /** Creates color attribute with color for each element (i.e. shared across instances/units) */
-export function createAttributeColor(props: AttributeColorProps): ColorData {
+export function createAttributeColor(props: AttributeColorProps, colorData?: ColorData): ColorData {
     const { colorFn, vertexMap } = props
     const { idCount, offsetCount, offsets } = vertexMap
     const colors = new Float32Array(idCount * 3);
@@ -53,22 +59,35 @@ export function createAttributeColor(props: AttributeColorProps): ColorData {
             Color.toArrayNormalized(hexColor, colors, i * 3)
         }
     }
-    return {
-        uColor: ValueCell.create(Vec3.zero()),
-        aColor: ValueCell.create(colors),
-        tColor: ValueCell.create(emptyTexture),
-        uColorTexSize: ValueCell.create(Vec2.zero()),
-        dColorType: ValueCell.create('attribute'),
+    if (colorData) {
+        ValueCell.update(colorData.aColor, colors)
+        ValueCell.update(colorData.dColorType, 'attribute')
+        return colorData
+    } else {
+        return {
+            uColor: ValueCell.create(Vec3.zero()),
+            aColor: ValueCell.create(colors),
+            tColor: ValueCell.create(emptyTexture),
+            uColorTexSize: ValueCell.create(Vec2.zero()),
+            dColorType: ValueCell.create('attribute'),
+        }
     }
 }
 
-export function createTextureColor(colors: TextureImage, type: ColorType): ColorData {
-    return {
-        uColor: ValueCell.create(Vec3.zero()),
-        aColor: ValueCell.create(new Float32Array(0)),
-        tColor: ValueCell.create(colors),
-        uColorTexSize: ValueCell.create(Vec2.create(colors.width, colors.height)),
-        dColorType: ValueCell.create(type),
+export function createTextureColor(colors: TextureImage, type: ColorType, colorData?: ColorData): ColorData {
+    if (colorData) {
+        ValueCell.update(colorData.tColor, colors)
+        ValueCell.update(colorData.uColorTexSize, Vec2.create(colors.width, colors.height))
+        ValueCell.update(colorData.dColorType, type)
+        return colorData
+    } else {
+        return {
+            uColor: ValueCell.create(Vec3.zero()),
+            aColor: ValueCell.create(new Float32Array(0)),
+            tColor: ValueCell.create(colors),
+            uColorTexSize: ValueCell.create(Vec2.create(colors.width, colors.height)),
+            dColorType: ValueCell.create(type),
+        }
     }
 }
 
@@ -78,9 +97,9 @@ export interface InstanceColorProps {
 }
 
 /** Creates color texture with color for each instance/unit */
-export function createInstanceColor(props: InstanceColorProps): ColorData {
+export function createInstanceColor(props: InstanceColorProps, colorData?: ColorData): ColorData {
     const { colorFn, instanceCount} = props
-    const colors = createColorTexture(instanceCount)
+    const colors = colorData && colorData.tColor.ref.value.array.length >= instanceCount * 3 ? colorData.tColor.ref.value : createColorTexture(instanceCount)
     for (let i = 0; i < instanceCount; i++) {
         Color.toArray(colorFn(i), colors.array, i * 3)
     }
@@ -93,10 +112,10 @@ export interface ElementColorProps {
 }
 
 /** Creates color texture with color for each element (i.e. shared across instances/units) */
-export function createElementColor(props: ElementColorProps): ColorData {
+export function createElementColor(props: ElementColorProps, colorData?: ColorData): ColorData {
     const { colorFn, vertexMap } = props
     const elementCount = vertexMap.offsetCount - 1
-    const colors = createColorTexture(elementCount)
+    const colors = colorData && colorData.tColor.ref.value.array.length >= elementCount * 3 ? colorData.tColor.ref.value : createColorTexture(elementCount)
     for (let i = 0, il = elementCount; i < il; ++i) {
         Color.toArray(colorFn(i), colors.array, i * 3)
     }
@@ -110,11 +129,11 @@ export interface ElementInstanceColorProps {
 }
 
 /** Creates color texture with color for each element instance (i.e. for each unit) */
-export function createElementInstanceColor(props: ElementInstanceColorProps): ColorData {
+export function createElementInstanceColor(props: ElementInstanceColorProps, colorData?: ColorData): ColorData {
     const { colorFn, instanceCount, vertexMap } = props
     const elementCount = vertexMap.offsetCount - 1
     const count = instanceCount * elementCount
-    const colors = createColorTexture(count)
+    const colors = colorData && colorData.tColor.ref.value.array.length >= count * 3 ? colorData.tColor.ref.value : createColorTexture(count)
     let colorOffset = 0
     for (let i = 0; i < instanceCount; i++) {
         for (let j = 0, jl = elementCount; j < jl; ++j) {
@@ -126,6 +145,6 @@ export function createElementInstanceColor(props: ElementInstanceColorProps): Co
 }
 
 /** Create color attribute or texture, depending on the vertexMap */
-export function createAttributeOrElementColor(vertexMap: VertexMap, props: AttributeColorProps) {
-    return vertexMap.idCount < 4 * vertexMap.offsetCount ? createAttributeColor(props) : createElementColor(props)
+export function createAttributeOrElementColor(vertexMap: VertexMap, props: AttributeColorProps, colorData?: ColorData) {
+    return vertexMap.idCount < 4 * vertexMap.offsetCount ? createAttributeColor(props, colorData) : createElementColor(props, colorData)
 }

+ 3 - 1
src/mol-geo/util/marching-cubes/algorithm.ts

@@ -84,7 +84,9 @@ class MarchingCubesComputation {
                     ? ValueCell.update(os.idBuffer, ChunkedArray.compact(this.state.idBuffer) as Float32Array)
                     : ValueCell.create(ChunkedArray.compact(this.state.idBuffer) as Float32Array)
                 : ValueCell.create(new Float32Array(0)),
-            normalsComputed: false
+            offsetBuffer: os ? os.offsetBuffer : ValueCell.create(new Uint32Array(0)),
+            normalsComputed: false,
+            offsetsComputed: false
         }
 
         return ret;

+ 2 - 2
src/mol-view/stage.ts

@@ -22,8 +22,8 @@ import { SpacefillProps } from 'mol-geo/representation/structure/spacefill';
 
 const spacefillProps: SpacefillProps = {
     doubleSided: true,
-    detail: 2,
-    colorTheme: { name: 'instance-index' }
+    detail: 0,
+    colorTheme: { name: 'atom-index' }
 }
 
 export class Stage {