Forráskód Böngészése

material improvements

- material helpers
- material in structure component manager
Alexander Rose 3 éve
szülő
commit
ceaf238322

+ 8 - 6
src/mol-geo/geometry/base.ts

@@ -16,6 +16,7 @@ import { NullLocation } from '../../mol-model/location';
 import { UniformColorTheme } from '../../mol-theme/color/uniform';
 import { UniformSizeTheme } from '../../mol-theme/size/uniform';
 import { smoothstep } from '../../mol-math/interpolate';
+import { Material } from '../../mol-util/material';
 
 export const VisualQualityInfo = {
     'custom': {},
@@ -79,8 +80,7 @@ export namespace BaseGeometry {
     export const Params = {
         alpha: PD.Numeric(1, { min: 0, max: 1, step: 0.01 }, { label: 'Opacity', isEssential: true, description: 'How opaque/transparent the representation is rendered.' }),
         quality: PD.Select<VisualQuality>('auto', VisualQualityOptions, { isEssential: true, description: 'Visual/rendering quality of the representation.' }),
-        metalness: PD.Numeric(0.0, { min: 0.0, max: 1.0, step: 0.01 }, MaterialCategory),
-        roughness: PD.Numeric(1.0, { min: 0.0, max: 1.0, step: 0.01 }, MaterialCategory),
+        material: Material.getParam(),
     };
     export type Params = typeof Params
 
@@ -97,22 +97,24 @@ export namespace BaseGeometry {
     }
 
     export function createValues(props: PD.Values<Params>, counts: Counts) {
+        const { metalness, roughness } = Material.toObjectNormalized(props.material);
         return {
             alpha: ValueCell.create(props.alpha),
             uAlpha: ValueCell.create(props.alpha),
             uVertexCount: ValueCell.create(counts.vertexCount),
             uGroupCount: ValueCell.create(counts.groupCount),
             drawCount: ValueCell.create(counts.drawCount),
-            uMetalness: ValueCell.create(props.metalness),
-            uRoughness: ValueCell.create(props.roughness),
+            uMetalness: ValueCell.create(metalness),
+            uRoughness: ValueCell.create(roughness),
             dLightCount: ValueCell.create(1),
         };
     }
 
     export function updateValues(values: BaseValues, props: PD.Values<Params>) {
+        const { metalness, roughness } = Material.toObjectNormalized(props.material);
         ValueCell.updateIfChanged(values.alpha, props.alpha); // `uAlpha` is set in renderable.render
-        ValueCell.updateIfChanged(values.uMetalness, props.metalness);
-        ValueCell.updateIfChanged(values.uRoughness, props.roughness);
+        ValueCell.updateIfChanged(values.uMetalness, metalness);
+        ValueCell.updateIfChanged(values.uRoughness, roughness);
     }
 
     export function createRenderableState(props: Partial<PD.Values<Params>> = {}): RenderableState {

+ 1 - 2
src/mol-geo/geometry/direct-volume/direct-volume.ts

@@ -319,8 +319,7 @@ export namespace DirectVolume {
     }
 
     function updateValues(values: DirectVolumeValues, props: PD.Values<Params>) {
-        ValueCell.updateIfChanged(values.alpha, props.alpha);
-        ValueCell.updateIfChanged(values.uAlpha, props.alpha);
+        BaseGeometry.updateValues(values, props);
         ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided);
         ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded);
         ValueCell.updateIfChanged(values.dFlipSided, props.flipSided);

+ 10 - 6
src/mol-plugin-state/manager/structure/component.ts

@@ -30,6 +30,7 @@ import { Clipping } from '../../../mol-theme/clipping';
 import { setStructureClipping } from '../../helpers/structure-clipping';
 import { setStructureTransparency } from '../../helpers/structure-transparency';
 import { StructureFocusRepresentation } from '../../../mol-plugin/behavior/dynamic/selection/structure-focus-representation';
+import { Material } from '../../../mol-util/material';
 
 export { StructureComponentManager };
 
@@ -67,22 +68,24 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
             await update.commit();
             await this.plugin.state.updateBehavior(StructureFocusRepresentation, p => {
                 p.ignoreHydrogens = !options.showHydrogens;
+                p.material = options.materialStyle;
             });
             if (interactionChanged) await this.updateInterationProps();
         });
     }
 
     private updateReprParams(update: StateBuilder.Root, component: StructureComponentRef) {
-        const { showHydrogens, visualQuality: quality } = this.state.options;
+        const { showHydrogens, visualQuality: quality, materialStyle: material } = this.state.options;
         const ignoreHydrogens = !showHydrogens;
         for (const r of component.representations) {
             if (r.cell.transform.transformer !== StructureRepresentation3D) continue;
 
             const params = r.cell.transform.params as StateTransformer.Params<StructureRepresentation3D>;
-            if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.quality !== quality) {
+            if (!!params.type.params.ignoreHydrogens !== ignoreHydrogens || params.type.params.quality !== quality || params.type.params.material !== material) {
                 update.to(r.cell).update(old => {
                     old.type.params.ignoreHydrogens = ignoreHydrogens;
                     old.type.params.quality = quality;
+                    old.type.params.material = material;
                 });
             }
         }
@@ -301,9 +304,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
     addRepresentation(components: ReadonlyArray<StructureComponentRef>, type: string) {
         if (components.length === 0) return;
 
-        const { showHydrogens, visualQuality: quality } = this.state.options;
+        const { showHydrogens, visualQuality: quality, materialStyle: material } = this.state.options;
         const ignoreHydrogens = !showHydrogens;
-        const typeParams = { ignoreHydrogens, quality };
+        const typeParams = { ignoreHydrogens, quality, material };
 
         return this.plugin.dataTransaction(async () => {
             for (const component of components) {
@@ -338,9 +341,9 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
             const xs = structures || this.currentStructures;
             if (xs.length === 0) return;
 
-            const { showHydrogens, visualQuality: quality } = this.state.options;
+            const { showHydrogens, visualQuality: quality, materialStyle: material } = this.state.options;
             const ignoreHydrogens = !showHydrogens;
-            const typeParams = { ignoreHydrogens, quality };
+            const typeParams = { ignoreHydrogens, quality, material };
 
             const componentKey = UUID.create22();
             for (const s of xs) {
@@ -445,6 +448,7 @@ namespace StructureComponentManager {
     export const OptionsParams = {
         showHydrogens: PD.Boolean(true, { description: 'Toggle display of hydrogen atoms in representations' }),
         visualQuality: PD.Select('auto', VisualQualityOptions, { description: 'Control the visual/rendering quality of representations' }),
+        materialStyle: Material.getParam(),
         interactions: PD.Group(InteractionsProvider.defaultParams, { label: 'Non-covalent Interactions' }),
     };
     export type Options = PD.Values<typeof OptionsParams>

+ 4 - 2
src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts

@@ -18,6 +18,7 @@ import { SizeTheme } from '../../../../mol-theme/size';
 import { ParamDefinition as PD } from '../../../../mol-util/param-definition';
 import { PluginCommands } from '../../../commands';
 import { PluginContext } from '../../../context';
+import { Material } from '../../../../mol-util/material';
 
 const StructureFocusRepresentationParams = (plugin: PluginContext) => {
     const reprParams = StateTransforms.Representation.StructureRepresentation3D.definition.params!(void 0, plugin) as PD.Params;
@@ -41,7 +42,8 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => {
         }),
         components: PD.MultiSelect(FocusComponents, PD.arrayToOptions(FocusComponents)),
         excludeTargetFromSurroundings: PD.Boolean(false, { label: 'Exclude Target', description: 'Exclude the focus "target" from the surroudings component.' }),
-        ignoreHydrogens: PD.Boolean(false)
+        ignoreHydrogens: PD.Boolean(false),
+        material: Material.getParam(),
     };
 };
 
@@ -67,7 +69,7 @@ class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscriber
             ...this.params.targetParams,
             type: {
                 name: reprParams.type.name,
-                params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens }
+                params: { ...reprParams.type.params, ignoreHydrogens: this.params.ignoreHydrogens, material: this.params.material }
             }
         };
     }

+ 56 - 0
src/mol-util/material.ts

@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { NumberArray } from './type-helpers';
+import { ParamDefinition as PD } from './param-definition';
+import { toPrecision } from './number';
+
+/** Material properties expressed as a single number */
+export type Material = { readonly '@type': 'material' } & number
+
+export function Material(hex: number) { return hex as Material; }
+
+export namespace Material {
+    export function fromNormalized(metalness: number, roughness: number): Material {
+        return (((metalness * 255) << 16) | ((roughness * 255) << 8)) as Material;
+    }
+
+    export function fromObjectNormalized(v: { metalness: number, roughness: number }): Material {
+        return fromNormalized(v.metalness, v.roughness);
+    }
+
+    export function toObjectNormalized(material: Material, precision?: number) {
+        const metalness = (material >> 16 & 255) / 255;
+        const roughness = (material >> 8 & 255) / 255;
+        return {
+            metalness: precision ? toPrecision(metalness, precision) : metalness,
+            roughness: precision ? toPrecision(roughness, precision) : roughness
+        };
+    }
+
+    export function toArray(material: Material, array: NumberArray, offset: number) {
+        array[offset] = (material >> 16 & 255);
+        array[offset + 1] = (material >> 8 & 255);
+        return array;
+    }
+
+    export function toString(material: Material) {
+        const metalness = (material >> 16 & 255) / 255;
+        const roughness = (material >> 8 & 255) / 255;
+        return `M ${metalness} | R ${roughness}`;
+    }
+
+    export function getParam(info?: { isExpanded?: boolean, isFlat?: boolean }) {
+        return PD.Converted(
+            (v: Material) => toObjectNormalized(v, 2),
+            (v: { metalness: number, roughness: number }) => fromObjectNormalized(v),
+            PD.Group({
+                metalness: PD.Numeric(0, { min: 0, max: 1, step: 0.1 }),
+                roughness: PD.Numeric(1, { min: 0, max: 1, step: 0.1 }),
+            }, info)
+        );
+    }
+}