diff --git a/src/mol-geo/representation/index.ts b/src/mol-geo/representation/index.ts index aa17e39ad6b079e92dde5a4d6ddf5739f751c747..09c1b9fbef7f2103163764be29955a78699772c6 100644 --- a/src/mol-geo/representation/index.ts +++ b/src/mol-geo/representation/index.ts @@ -12,6 +12,23 @@ import { MarkerAction } from '../util/marker-data'; export type VisualQuality = 'custom' | 'auto' | 'highest' | 'high' | 'medium' | 'low' | 'lowest' +export const DefaultBaseProps = { + alpha: 1, + visible: true, + depthMask: true, + useFog: true, + quality: 'auto' as VisualQuality +} +export type BaseProps = Partial<typeof DefaultBaseProps> + +export const DefaultMeshProps = { + ...DefaultBaseProps, + doubleSided: false, + flipSided: false, + flatShaded: false, +} +export type MeshProps = Partial<typeof DefaultMeshProps> + export interface RepresentationProps {} export interface Representation<D, P extends RepresentationProps = {}> { diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts index 4ed40c07f36ba579c7c624817cf12368469bcb83..719a13c19e2ef768a164c5fded9b6b040acde93c 100644 --- a/src/mol-geo/representation/structure/index.ts +++ b/src/mol-geo/representation/structure/index.ts @@ -8,7 +8,7 @@ import { Structure, StructureSymmetry, Unit } from 'mol-model/structure'; import { Task } from 'mol-task' import { RenderObject } from 'mol-gl/render-object'; -import { Representation, RepresentationProps, Visual, VisualQuality } from '..'; +import { Representation, RepresentationProps, Visual, VisualQuality, DefaultBaseProps } from '..'; import { ColorTheme, SizeTheme } from '../../theme'; import { PickingId } from '../../util/picking'; import { Loci, EmptyLoci, isEmptyLoci } from 'mol-model/loci'; @@ -78,14 +78,9 @@ function getQualityProps(props: Partial<QualityProps>, structure: Structure) { } export const DefaultStructureProps = { + ...DefaultBaseProps, colorTheme: { name: 'instance-index' } as ColorTheme, sizeTheme: { name: 'physical' } as SizeTheme, - alpha: 1, - visible: true, - doubleSided: false, - depthMask: true, - useFog: true, - quality: 'auto' as VisualQuality } export type StructureProps = Partial<typeof DefaultStructureProps> @@ -99,7 +94,6 @@ export function StructureRepresentation<P extends StructureProps>(unitsVisualCto function create(structure: Structure, props: P = {} as P) { _props = Object.assign({}, DefaultStructureProps, _props, props, getQualityProps(props, structure)) - console.log('create struct', (_props as any).detail, (_props as any).radialSegments) return Task.create('Creating StructureRepresentation', async ctx => { if (!_structure) { diff --git a/src/mol-geo/representation/structure/visual/element-sphere.ts b/src/mol-geo/representation/structure/visual/element-sphere.ts index f4ef2b6050e9986beaaa7f06be429529a4581f67..e991ad536e97c708f1324ca4db60b56a449beebf 100644 --- a/src/mol-geo/representation/structure/visual/element-sphere.ts +++ b/src/mol-geo/representation/structure/visual/element-sphere.ts @@ -13,9 +13,8 @@ import { DefaultStructureProps, UnitsVisual } from '../index'; import { RuntimeContext } from 'mol-task' import { createTransforms, createColors } from '../visual/util/common'; import { createElementSphereMesh, markElement, getElementRadius } from '../visual/util/element'; -import { deepEqual, defaults } from 'mol-util'; -import { fillSerial } from 'mol-gl/renderable/util'; -import { RenderableState, MeshValues } from 'mol-gl/renderable'; +import { deepEqual } from 'mol-util'; +import { MeshValues } from 'mol-gl/renderable'; import { getMeshData } from '../../../util/mesh-data'; import { Mesh } from '../../../shape/mesh'; import { PickingId } from '../../../util/picking'; @@ -23,12 +22,13 @@ import { OrderedSet } from 'mol-data/int'; import { createMarkers, MarkerAction } from '../../../util/marker-data'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { SizeTheme } from '../../../theme'; +import { DefaultMeshProps } from '../..'; +import { createMeshValues, updateMeshValues, updateRenderableState, createRenderableState } from '../../util'; export const DefaultElementSphereProps = { + ...DefaultMeshProps, ...DefaultStructureProps, sizeTheme: { name: 'physical', factor: 1 } as SizeTheme, - flipSided: false, - flatShaded: false, detail: 0, } export type ElementSphereProps = Partial<typeof DefaultElementSphereProps> @@ -65,31 +65,17 @@ export function ElementSphereVisual(): UnitsVisual<ElementSphereProps> { if (ctx.shouldUpdate) await ctx.update('Computing spacefill marks'); const marker = createMarkers(instanceCount * elementCount) + const counts = { drawCount: mesh.triangleCount * 3, elementCount, instanceCount } + const values: MeshValues = { ...getMeshData(mesh), - aTransform: transforms, - aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, ...marker, - - uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), - uInstanceCount: ValueCell.create(instanceCount), - uElementCount: ValueCell.create(elementCount), - + aTransform: transforms, elements: mesh.indexBuffer, - - drawCount: ValueCell.create(mesh.triangleCount * 3), - instanceCount: ValueCell.create(instanceCount), - - dDoubleSided: ValueCell.create(defaults(props.doubleSided, true)), - dFlatShaded: ValueCell.create(defaults(props.flatShaded, false)), - dFlipSided: ValueCell.create(defaults(props.flipSided, false)), - dUseFog: ValueCell.create(defaults(props.useFog, true)), - } - const state: RenderableState = { - depthMask: defaults(props.depthMask, true), - visible: defaults(props.visible, true) + ...createMeshValues(currentProps, counts), } + const state = createRenderableState(currentProps) spheres = createMeshRenderObject(values, state) renderObjects.push(spheres) @@ -119,13 +105,8 @@ export function ElementSphereVisual(): UnitsVisual<ElementSphereProps> { createColors(currentGroup, elementCount, newProps.colorTheme, spheres.values) } - ValueCell.updateIfChanged(spheres.values.uAlpha, newProps.alpha) - ValueCell.updateIfChanged(spheres.values.dDoubleSided, newProps.doubleSided) - ValueCell.updateIfChanged(spheres.values.dFlipSided, newProps.flipSided) - ValueCell.updateIfChanged(spheres.values.dFlatShaded, newProps.flatShaded) - - spheres.state.visible = newProps.visible - spheres.state.depthMask = newProps.depthMask + updateMeshValues(spheres.values, newProps) + updateRenderableState(spheres.state, newProps) currentProps = newProps return true diff --git a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts index 4c4b69eb6ff11108b870c046dab510d7a14a146a..1ee582192a85e264e6722e62de9a2d4d8fbe7bcd 100644 --- a/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/inter-unit-link-cylinder.ts @@ -11,18 +11,17 @@ import { Link, Structure } from 'mol-model/structure'; import { DefaultStructureProps, StructureVisual } from '../index'; import { RuntimeContext } from 'mol-task' import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh } from './util/link'; -import { fillSerial } from 'mol-gl/renderable/util'; -import { RenderableState, MeshValues } from 'mol-gl/renderable'; +import { MeshValues } from 'mol-gl/renderable'; import { getMeshData } from '../../../util/mesh-data'; import { Mesh } from '../../../shape/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { createUniformColor } from '../../../util/color-data'; -import { defaults } from 'mol-util'; import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction, applyMarkerAction, createMarkers, MarkerData } from '../../../util/marker-data'; import { SizeTheme } from '../../../theme'; import { createIdentityTransform } from './util/common'; +import { updateMeshValues, updateRenderableState, createMeshValues, createRenderableState } from '../../util'; // import { chainIdLinkColorData } from '../../../theme/structure/color/chain-id'; async function createInterUnitLinkCylinderMesh(ctx: RuntimeContext, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) { @@ -51,8 +50,6 @@ export const DefaultInterUnitLinkProps = { ...DefaultStructureProps, ...DefaultLinkCylinderProps, sizeTheme: { name: 'physical', factor: 0.3 } as SizeTheme, - flipSided: false, - flatShaded: false, } export type InterUnitLinkProps = Partial<typeof DefaultInterUnitLinkProps> @@ -86,31 +83,17 @@ export function InterUnitLinkVisual(): StructureVisual<InterUnitLinkProps> { if (ctx.shouldUpdate) await ctx.update('Computing link marks'); const marker = createMarkers(instanceCount * elementCount) + const counts = { drawCount: mesh.triangleCount * 3, elementCount, instanceCount } + const values: MeshValues = { ...getMeshData(mesh), - aTransform: transforms, - aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, ...marker, - - uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), - uInstanceCount: ValueCell.create(instanceCount), - uElementCount: ValueCell.create(elementCount), - + aTransform: transforms, elements: mesh.indexBuffer, - - drawCount: ValueCell.create(mesh.triangleCount * 3), - instanceCount: ValueCell.create(instanceCount), - - dDoubleSided: ValueCell.create(defaults(props.doubleSided, true)), - dFlatShaded: ValueCell.create(defaults(props.flatShaded, false)), - dFlipSided: ValueCell.create(defaults(props.flipSided, false)), - dUseFog: ValueCell.create(defaults(props.useFog, true)), - } - const state: RenderableState = { - depthMask: defaults(props.depthMask, true), - visible: defaults(props.visible, true) + ...createMeshValues(currentProps, counts), } + const state = createRenderableState(currentProps) cylinders = createMeshRenderObject(values, state) renderObjects.push(cylinders) @@ -118,16 +101,13 @@ export function InterUnitLinkVisual(): StructureVisual<InterUnitLinkProps> { async update(ctx: RuntimeContext, props: InterUnitLinkProps) { const newProps = Object.assign({}, currentProps, props) - if (!cylinders || currentProps.radialSegments !== newProps.radialSegments) return false - // TODO + if (!cylinders) return false - ValueCell.updateIfChanged(cylinders.values.uAlpha, newProps.alpha) - ValueCell.updateIfChanged(cylinders.values.dDoubleSided, newProps.doubleSided) - ValueCell.updateIfChanged(cylinders.values.dFlipSided, newProps.flipSided) - ValueCell.updateIfChanged(cylinders.values.dFlatShaded, newProps.flatShaded) + // TODO create in-place + if (currentProps.radialSegments !== newProps.radialSegments) return false - cylinders.state.visible = newProps.visible - cylinders.state.depthMask = newProps.depthMask + updateMeshValues(cylinders.values, newProps) + updateRenderableState(cylinders.state, newProps) return false }, diff --git a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts index d4652f10d02b256f788626a564f6211d06d09b4b..f6633c75dccdb4873b5e5ad2c0c031dd9fed4f63 100644 --- a/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/intra-unit-link-cylinder.ts @@ -12,19 +12,18 @@ import { Unit, Link } from 'mol-model/structure'; import { UnitsVisual, DefaultStructureProps } from '../index'; import { RuntimeContext } from 'mol-task' import { DefaultLinkCylinderProps, LinkCylinderProps, createLinkCylinderMesh } from './util/link'; -import { fillSerial } from 'mol-gl/renderable/util'; -import { RenderableState, MeshValues } from 'mol-gl/renderable'; +import { MeshValues } from 'mol-gl/renderable'; import { getMeshData } from '../../../util/mesh-data'; import { Mesh } from '../../../shape/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; // import { createUniformColor } from '../../../util/color-data'; -import { defaults } from 'mol-util'; import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction, applyMarkerAction, createMarkers, MarkerData } from '../../../util/marker-data'; import { SizeTheme } from '../../../theme'; import { chainIdLinkColorData } from '../../../theme/structure/color/chain-id'; import { createTransforms } from './util/common'; +import { createMeshValues, createRenderableState, updateMeshValues, updateRenderableState } from '../../util'; async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit, props: LinkCylinderProps, mesh?: Mesh) { if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) @@ -67,8 +66,6 @@ export const DefaultIntraUnitLinkProps = { ...DefaultStructureProps, ...DefaultLinkCylinderProps, sizeTheme: { name: 'physical', factor: 0.3 } as SizeTheme, - flipSided: false, - flatShaded: false, } export type IntraUnitLinkProps = Partial<typeof DefaultIntraUnitLinkProps> @@ -103,31 +100,17 @@ export function IntraUnitLinkVisual(): UnitsVisual<IntraUnitLinkProps> { if (ctx.shouldUpdate) await ctx.update('Computing link marks'); const marker = createMarkers(instanceCount * elementCount) + const counts = { drawCount: mesh.triangleCount * 3, elementCount, instanceCount } + const values: MeshValues = { ...getMeshData(mesh), - aTransform: transforms, - aInstanceId: ValueCell.create(fillSerial(new Float32Array(instanceCount))), ...color, ...marker, - - uAlpha: ValueCell.create(defaults(props.alpha, 1.0)), - uInstanceCount: ValueCell.create(instanceCount), - uElementCount: ValueCell.create(elementCount), - + aTransform: transforms, elements: mesh.indexBuffer, - - drawCount: ValueCell.create(mesh.triangleCount * 3), - instanceCount: ValueCell.create(instanceCount), - - dDoubleSided: ValueCell.create(defaults(props.doubleSided, true)), - dFlatShaded: ValueCell.create(defaults(props.flatShaded, false)), - dFlipSided: ValueCell.create(defaults(props.flipSided, false)), - dUseFog: ValueCell.create(defaults(props.useFog, true)), - } - const state: RenderableState = { - depthMask: defaults(props.depthMask, true), - visible: defaults(props.visible, true) + ...createMeshValues(currentProps, counts), } + const state = createRenderableState(currentProps) cylinders = createMeshRenderObject(values, state) renderObjects.push(cylinders) @@ -138,13 +121,8 @@ export function IntraUnitLinkVisual(): UnitsVisual<IntraUnitLinkProps> { if (!cylinders || currentProps.radialSegments !== newProps.radialSegments) return false // TODO - ValueCell.updateIfChanged(cylinders.values.uAlpha, newProps.alpha) - ValueCell.updateIfChanged(cylinders.values.dDoubleSided, newProps.doubleSided) - ValueCell.updateIfChanged(cylinders.values.dFlipSided, newProps.flipSided) - ValueCell.updateIfChanged(cylinders.values.dFlatShaded, newProps.flatShaded) - - cylinders.state.visible = newProps.visible - cylinders.state.depthMask = newProps.depthMask + updateMeshValues(cylinders.values, newProps) + updateRenderableState(cylinders.state, newProps) return true }, diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-geo/representation/structure/visual/util/link.ts index 4d23190b207f3cea2ca31bd5df6256758d01f6c3..16808dbc77c077633eba088eaa8ae41fa5bad891 100644 --- a/src/mol-geo/representation/structure/visual/util/link.ts +++ b/src/mol-geo/representation/structure/visual/util/link.ts @@ -9,8 +9,10 @@ import { RuntimeContext } from 'mol-task'; import { Mesh } from '../../../../shape/mesh'; import { MeshBuilder } from '../../../../shape/mesh-builder'; import { LinkType } from 'mol-model/structure/model/types'; +import { DefaultMeshProps } from '../../..'; export const DefaultLinkCylinderProps = { + ...DefaultMeshProps, linkScale: 0.4, linkSpacing: 1, linkRadius: 0.25, diff --git a/src/mol-geo/representation/util.ts b/src/mol-geo/representation/util.ts new file mode 100644 index 0000000000000000000000000000000000000000..cdcd133b883252032a9a2f64d93379e142477513 --- /dev/null +++ b/src/mol-geo/representation/util.ts @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { ValueCell } from 'mol-util/value-cell' +import { BaseValues } from 'mol-gl/renderable/schema'; +import { BaseProps, MeshProps } from '.'; +import { MeshValues, RenderableState } from 'mol-gl/renderable'; +import { fillSerial } from 'mol-gl/renderable/util'; + +type Counts = { drawCount: number, elementCount: number, instanceCount: number } + +export function createBaseValues(props: Required<BaseProps>, counts: Counts) { + return { + uAlpha: ValueCell.create(props.alpha), + uInstanceCount: ValueCell.create(counts.instanceCount), + uElementCount: ValueCell.create(counts.elementCount), + aInstanceId: ValueCell.create(fillSerial(new Float32Array(counts.instanceCount))), + drawCount: ValueCell.create(counts.drawCount), + instanceCount: ValueCell.create(counts.instanceCount), + } +} + +export function createMeshValues(props: Required<MeshProps>, counts: Counts) { + return { + ...createBaseValues(props, counts), + dDoubleSided: ValueCell.create(props.doubleSided), + dFlatShaded: ValueCell.create(props.flatShaded), + dFlipSided: ValueCell.create(props.flipSided), + dUseFog: ValueCell.create(props.useFog), + } +} + +export function createRenderableState(props: Required<BaseProps>): RenderableState { + return { + visible: props.visible, + depthMask: props.depthMask + } +} + +export function updateBaseValues(values: BaseValues, props: Required<BaseProps>) { + ValueCell.updateIfChanged(values.uAlpha, props.alpha) +} + +export function updateMeshValues(values: MeshValues, props: Required<MeshProps>) { + updateBaseValues(values, props) + ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided) + ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded) + ValueCell.updateIfChanged(values.dFlipSided, props.flipSided) + ValueCell.updateIfChanged(values.dUseFog, props.useFog) +} + +export function updateRenderableState(state: RenderableState, props: Required<BaseProps>) { + state.visible = props.visible + state.depthMask = props.depthMask +} \ No newline at end of file