Kaynağa Gözat

added size support to shape

Alexander Rose 6 yıl önce
ebeveyn
işleme
67eb957395

+ 5 - 2
src/mol-model/shape/shape.ts

@@ -23,12 +23,14 @@ export interface Shape<G extends Geometry = Geometry> {
     readonly groupCount: number
     /** Get color for a given group */
     getColor(groupId: number, instanceId: number): Color
-    /** Get color for a given group */
+    /** Get size for a given group */
+    getSize(groupId: number, instanceId: number): number
+    /** Get label for a given group */
     getLabel(groupId: number, instanceId: number): string
 }
 
 export namespace Shape {
-    export function create<G extends Geometry>(name: string, geometry: G, getColor: Shape['getColor'], getLabel: Shape['getLabel'], transforms?: Mat4[]): Shape<G> {
+    export function create<G extends Geometry>(name: string, geometry: G, getColor: Shape['getColor'], getSize: Shape['getSize'], getLabel: Shape['getLabel'], transforms?: Mat4[]): Shape<G> {
         return {
             id: UUID.create22(),
             name,
@@ -36,6 +38,7 @@ export namespace Shape {
             transforms: transforms || [Mat4.identity()],
             get groupCount() { return Geometry.getGroupCount(geometry) },
             getColor,
+            getSize,
             getLabel
         }
     }

+ 29 - 5
src/mol-repr/shape/representation.ts

@@ -24,6 +24,8 @@ import { createColors } from 'mol-geo/geometry/color-data';
 import { VisualUpdateState } from 'mol-repr/util';
 import { Mat4 } from 'mol-math/linear-algebra';
 import { Visual } from 'mol-repr/visual';
+import { createSizes } from 'mol-geo/geometry/size-data';
+import { ShapeGroupSizeTheme } from 'mol-theme/size/shape-group';
 
 export interface ShapeRepresentation<D, G extends Geometry, P extends Geometry.Params<G>> extends Representation<D, P> { }
 
@@ -43,7 +45,7 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
 
     const updateState = VisualUpdateState.create()
 
-    function prepareUpdate(shape?: Shape<G>) {
+    function prepareUpdate(props: Partial<PD.Values<P>> = {}, shape?: Shape<G>) {
         VisualUpdateState.reset(updateState)
 
         if (!shape && !_shape) {
@@ -59,9 +61,8 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
             updateState.updateTransform = true
         } else if (shape && _shape && shape.id !== _shape.id) {
             console.log('new shape')
-            // assume that ValueCells in geometry of new shape where re-used from the old one
-            updateState.updateColor = true
             updateState.updateTransform = true
+            updateState.createGeometry = true
         } else if (!shape) {
             console.log('only props')
             // nothing to set
@@ -72,6 +73,10 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
         if (updateState.updateTransform) {
             updateState.updateColor = true
         }
+
+        if (updateState.createGeometry) {
+            updateState.updateColor = true
+        }
     }
 
     function createOrUpdate(props: Partial<PD.Values<P>> = {}, data?: D) {
@@ -79,11 +84,12 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
             const newProps = Object.assign(currentProps, props)
             const shape = data ? await getShape(runtime, data, newProps, _shape) : undefined
 
-            prepareUpdate(shape)
+            prepareUpdate(props, shape)
 
             if (shape) {
                 _shape = shape
                 _theme.color = ShapeGroupColorTheme({ shape: _shape }, {})
+                _theme.size = ShapeGroupSizeTheme({ shape: _shape }, {})
             }
 
             if (updateState.createNew) {
@@ -108,11 +114,29 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
                     createMarkers(instanceCount * groupCount, _renderObject.values)
                 }
 
+                if (updateState.createGeometry) {
+                    // console.log('update geometry')
+                    ValueCell.update(_renderObject.values.drawCount, Geometry.getDrawCount(_shape.geometry))
+                }
+
+                if (updateState.updateTransform || updateState.createGeometry) {
+                    // console.log('updateBoundingSphere')
+                    geometryUtils.updateBoundingSphere(_renderObject.values, _shape.geometry)
+                }
+
                 if (updateState.updateColor) {
                     // console.log('update color')
                     createColors(locationIt, _theme.color, _renderObject.values)
                 }
 
+                if (updateState.updateSize) {
+                    // not all geometries have size data, so check here
+                    if ('uSize' in _renderObject.values) {
+                        console.log('update size')
+                        createSizes(locationIt, _theme.size, _renderObject.values)
+                    }
+                }
+
                 geometryUtils.updateValues(_renderObject.values, newProps)
                 geometryUtils.updateRenderableState(_renderObject.state, newProps)
             }
@@ -176,7 +200,7 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
             Representation.updateState(_state, state)
         },
         setTheme(theme: Theme) {
-            console.warn('The `ShapeRepresentation` theme is fixed to `ShapeGroupColorTheme`. Colors are taken from `Shape.getColor`.')
+            console.warn('The `ShapeRepresentation` theme is fixed to `ShapeGroupColorTheme` and `ShapeGroupSizeTheme`. Colors are taken from `Shape.getColor` and sizes from `Shape.getSize`')
         },
         destroy() {
             // TODO

+ 2 - 0
src/mol-theme/size.ts

@@ -10,6 +10,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
 import { ThemeDataContext, ThemeRegistry, ThemeProvider } from 'mol-theme/theme';
 import { PhysicalSizeThemeProvider } from './size/physical';
 import { deepEqual } from 'mol-util';
+import { ShapeGroupSizeThemeProvider } from './size/shape-group';
 
 export { SizeTheme }
 interface SizeTheme<P extends PD.Params> {
@@ -40,5 +41,6 @@ namespace SizeTheme {
 
 export const BuiltInSizeThemes = {
     'physical': PhysicalSizeThemeProvider,
+    'shape-group': ShapeGroupSizeThemeProvider,
     'uniform': UniformSizeThemeProvider
 }

+ 43 - 0
src/mol-theme/size/shape-group.ts

@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Location } from 'mol-model/location';
+import { Shape } from 'mol-model/shape';
+import { ParamDefinition as PD } from 'mol-util/param-definition'
+import { ThemeDataContext } from 'mol-theme/theme';
+import { SizeTheme } from 'mol-theme/size';
+
+const DefaultSize = 1
+const Description = 'Assigns sizes as defined by the shape object.'
+
+export const ShapeGroupSizeThemeParams = {}
+export type ShapeGroupSizeThemeParams = typeof ShapeGroupSizeThemeParams
+export function getShapeGroupSizeThemeParams(ctx: ThemeDataContext) {
+    return ShapeGroupSizeThemeParams // TODO return copy
+}
+
+export function ShapeGroupSizeTheme(ctx: ThemeDataContext, props: PD.Values<ShapeGroupSizeThemeParams>): SizeTheme<ShapeGroupSizeThemeParams> {
+    return {
+        factory: ShapeGroupSizeTheme,
+        granularity: 'groupInstance',
+        size: (location: Location): number => {
+            if (Shape.isLocation(location)) {
+                return location.shape.getSize(location.group, location.instance)
+            }
+            return DefaultSize
+        },
+        props,
+        description: Description
+    }
+}
+
+export const ShapeGroupSizeThemeProvider: SizeTheme.Provider<ShapeGroupSizeThemeParams> = {
+    label: 'Shape Group',
+    factory: ShapeGroupSizeTheme,
+    getParams: getShapeGroupSizeThemeParams,
+    defaultValues: PD.getDefaultValues(ShapeGroupSizeThemeParams),
+    isApplicable: (ctx: ThemeDataContext) => !!ctx.shape
+}

+ 3 - 2
src/tests/browser/render-shape.ts

@@ -86,8 +86,9 @@ async function getShape(ctx: RuntimeContext, data: MyData, props: {}, shape?: Sh
     const groupCount = centers.length / 3
     return shape || Shape.create(
         'test', mesh,
-        (groupId: number) => colors[groupId], // per group, same for instances
-        (groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId], // per group and instance
+        (groupId: number) => colors[groupId], // color: per group, same for instances
+        () => 1, // size: constant
+        (groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId], // label: per group and instance
         transforms
     )
 }