Browse Source

immediate mode slider, alpha-orbitals improvements

David Sehnal 4 years ago
parent
commit
67a2594108

+ 18 - 10
src/examples/alpha-orbitals/index.ts

@@ -36,7 +36,8 @@ interface DemoInput {
 
 interface Params {
     orbitalIndex: number,
-    isoValue: number
+    isoValue: number,
+    staticIsovalues: boolean
 }
 
 export class AlphaOrbitalsExample {
@@ -71,7 +72,7 @@ export class AlphaOrbitalsExample {
     }
 
     readonly params = new BehaviorSubject<ParamDefinition.For<Params>>({ } as any);
-    readonly state = new BehaviorSubject<Params>({ orbitalIndex: 32, isoValue: 1 });
+    readonly state = new BehaviorSubject<Params>({ orbitalIndex: 32, isoValue: 1, staticIsovalues: true });
 
     private volume?: StateObjectSelector<PluginStateObject.Volume.Data, typeof CreateOrbitalVolume>;
     private positive?: StateObjectSelector<PluginStateObject.Volume.Representation3D, typeof StateTransforms.Representation.VolumeRepresentation3D>;
@@ -84,13 +85,19 @@ export class AlphaOrbitalsExample {
         const state = this.state.value;
         await this.plugin.build().to(this.volume).update(CreateOrbitalVolume, () => ({ index: state.orbitalIndex })).commit();
         this.currentParams.orbitalIndex = this.state.value.orbitalIndex;
-        this.isovalues = computeIsocontourValues(this.volume.data!.grid.cells.data as any, 0.85);
-        await this.setIsovalue();
+        this.currentParams.staticIsovalues = this.state.value.staticIsovalues;
+        this.currentParams.isoValue = this.state.value.isoValue;
+
+        if (!state.staticIsovalues) {
+            this.isovalues = computeIsocontourValues(this.volume.data!.grid.cells.data as any, 0.85);
+            await this.setIsovalue();
+        }
     }
 
     private setIsovalue() {
         const { positive, negative } = this.isovalues;
         this.currentParams.isoValue = this.state.value.isoValue;
+        this.currentParams.staticIsovalues = this.state.value.staticIsovalues;
         const update = this.plugin.build();
         update.to(this.positive!).update(this.volumeParams(positive, ColorNames.blue));
         update.to(this.negative!).update(this.volumeParams(negative, ColorNames.red));
@@ -100,14 +107,14 @@ export class AlphaOrbitalsExample {
     private volumeParams(value: number | undefined, color: Color) {
         return createVolumeRepresentationParams(this.plugin, this.volume!.data!, {
             // type: 'isosurface',
-            // typeParams: { isoValue: { kind: 'absolute', absoluteValue: positive } },
+            // typeParams: { isoValue: { kind: 'absolute', absoluteValue: (value ?? 1000) * this.state.value.isoValue } },
             // color: 'uniform',
             // colorParams: { value: ColorNames.blue }
             type: 'direct-volume',
             typeParams: {
                 renderMode: {
                     name: 'isosurface',
-                    params: { isoValue: { kind: 'absolute', absoluteValue: (value ?? 1000) * this.state.value.isoValue }, singleLayer: false }
+                    params: { isoValue: { kind: 'absolute', absoluteValue: (value ?? 1000) * this.state.value.isoValue }, singleLayer: true }
                 }
             },
             color: 'uniform',
@@ -151,12 +158,13 @@ export class AlphaOrbitalsExample {
         await repr.commit();
 
         this.params.next({
-            orbitalIndex: ParamDefinition.Numeric(this.currentParams.orbitalIndex, { min: 0, max: input.orbitals.length - 1 }),
-            isoValue: ParamDefinition.Numeric(1, { min: 0.5, max: 3, step: 0.1 })
+            orbitalIndex: ParamDefinition.Numeric(this.currentParams.orbitalIndex, { min: 0, max: input.orbitals.length - 1 }, { immediateUpdate: true, isEssential: true }),
+            isoValue: ParamDefinition.Numeric(this.currentParams.isoValue, { min: 0.5, max: 3, step: 0.1 }, { immediateUpdate: true, isEssential: false }),
+            staticIsovalues: ParamDefinition.Boolean(this.currentParams.staticIsovalues)
         });
 
-        this.state.pipe(skip(1), debounceTime(1000 / 30)).subscribe(async params => {
-            if (params.orbitalIndex !== this.currentParams.orbitalIndex) {
+        this.state.pipe(skip(1), debounceTime(1000 / 24)).subscribe(async params => {
+            if (params.orbitalIndex !== this.currentParams.orbitalIndex || params.staticIsovalues !== this.currentParams.staticIsovalues) {
                 this.setIndex();
             } else if (params.isoValue !== this.currentParams.isoValue) {
                 this.setIsovalue();

+ 1 - 0
src/examples/alpha-orbitals/transforms.ts

@@ -61,6 +61,7 @@ export const CreateOrbitalVolume = PluginStateTransform.BuiltIn({
                     [25, 0.4],
                     [0, 0.35],
                 ],
+                doNotComputeIsovalues: true
             }, plugin.canvas3d?.webgl).runInContext(ctx);
             const volume: Volume = {
                 grid: data.grid,

+ 13 - 7
src/extensions/alpha-orbitals/cubes.ts

@@ -27,7 +27,7 @@ export interface CubeGridInfo {
 
 export interface CubeGrid {
     grid: Grid;
-    isovalues: { negative?: number; positive?: number };
+    isovalues?: { negative?: number; positive?: number };
 }
 
 export interface Basis {
@@ -59,6 +59,7 @@ export interface SphericalCollocationParams {
     boxExpand: number;
     gridSpacing: number | [atomCountThreshold: number, spacing: number][];
     alphaOrbitals: number[];
+    doNotComputeIsovalues?: boolean
 }
 
 export function createSphericalCollocationGrid(
@@ -106,13 +107,13 @@ export function createSphericalCollocationGrid(
         //     }
         // }
 
-        return createCubeGrid(cParams.grid, matrixGL, [0, 1, 2]);
+        return createCubeGrid(cParams.grid, matrixGL, [0, 1, 2], !params.doNotComputeIsovalues);
     });
 }
 
 const BohrToAngstromFactor = 0.529177210859;
 
-function createCubeGrid(gridInfo: CubeGridInfo, values: Float32Array, axisOrder: number[]) {
+function createCubeGrid(gridInfo: CubeGridInfo, values: Float32Array, axisOrder: number[], computeIsovalues: boolean) {
     const boxSize = Box3D.size(Vec3(), gridInfo.box);
     const boxOrigin = Vec3.clone(gridInfo.box.min);
 
@@ -146,11 +147,16 @@ function createCubeGrid(gridInfo: CubeGridInfo, values: Float32Array, axisOrder:
 
     // TODO: when using GPU rendering, the cumulative sum can be computed
     // along the ray on the fly
-    console.time('iso');
-    const isovalues = computeIsocontourValues(values, 0.85);
-    console.timeEnd('iso');
 
-    console.log(isovalues);
+    let isovalues: { negative?: number, positive?: number } | undefined;
+
+    if (computeIsovalues) {
+        console.time('iso');
+        const isovalues = computeIsocontourValues(values, 0.85);
+        console.timeEnd('iso');
+        console.log(isovalues);
+    }
+
 
     return { grid, isovalues };
 }

+ 2 - 1
src/mol-plugin-ui/controls/parameters.tsx

@@ -368,7 +368,8 @@ export class NumberRangeControl extends SimpleParam<PD.Numeric> {
     renderControl() {
         const value = typeof this.props.value === 'undefined' ? this.props.param.defaultValue : this.props.value;
         return <Slider value={value} min={this.props.param.min!} max={this.props.param.max!}
-            step={this.props.param.step} onChange={this.onChange} disabled={this.props.isDisabled} onEnter={this.props.onEnter} />;
+            step={this.props.param.step} onChange={this.onChange} onChangeImmediate={this.props.param.immediateUpdate ? this.onChange : void 0}
+            disabled={this.props.isDisabled} onEnter={this.props.onEnter} />;
     }
 }
 

+ 2 - 0
src/mol-plugin-ui/controls/slider.tsx

@@ -15,6 +15,7 @@ export class Slider extends React.Component<{
     value: number,
     step?: number,
     onChange: (v: number) => void,
+    onChangeImmediate?: (v: number) => void,
     disabled?: boolean,
     onEnter?: () => void
 }, { isChanging: boolean, current: number }> {
@@ -37,6 +38,7 @@ export class Slider extends React.Component<{
 
     updateCurrent = (current: number) => {
         this.setState({ current });
+        this.props.onChangeImmediate?.(current);
     }
 
     updateManually = (v: number) => {

+ 6 - 3
src/mol-util/param-definition.ts

@@ -199,10 +199,13 @@ export namespace ParamDefinition {
     }
 
     export interface Numeric extends Base<number>, Range {
-        type: 'number'
+        type: 'number',
+        immediateUpdate?: boolean
     }
-    export function Numeric(defaultValue: number, range?: { min?: number, max?: number, step?: number }, info?: Info): Numeric {
-        return setInfo<Numeric>(setRange({ type: 'number', defaultValue }, range), info);
+    export function Numeric(defaultValue: number, range?: { min?: number, max?: number, step?: number }, info?: Info & { immediateUpdate?: boolean }): Numeric {
+        const ret = setInfo<Numeric>(setRange({ type: 'number', defaultValue }, range), info);
+        if (info?.immediateUpdate) ret.immediateUpdate = true;
+        return ret;
     }
 
     export interface Interval extends Base<[number, number]>, Range {