diff --git a/src/mol-repr/representation.ts b/src/mol-repr/representation.ts index 7c323b3d98b55be7c904b6b2b6f828fe87754539..c206d7149a5d70d8f763e90209ea79e77de95760 100644 --- a/src/mol-repr/representation.ts +++ b/src/mol-repr/representation.ts @@ -5,7 +5,7 @@ */ import { Task } from 'mol-task' -import { RenderObject } from 'mol-gl/render-object' +import { RenderObject, GraphicsRenderObject } from 'mol-gl/render-object' import { PickingId } from '../mol-geo/geometry/picking'; import { Loci, isEmptyLoci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../mol-geo/geometry/marker-data'; @@ -17,6 +17,7 @@ import { SizeTheme } from 'mol-theme/size'; import { Theme, ThemeRegistryContext, createEmptyTheme } from 'mol-theme/theme'; import { Subject } from 'rxjs'; import { Mat4 } from 'mol-math/linear-algebra'; +import { Geometry } from 'mol-geo/geometry/geometry'; // export interface RepresentationProps { // visuals?: string[] @@ -240,4 +241,51 @@ namespace Representation { } } } + + export function fromRenderObject(label: string, renderObject: GraphicsRenderObject): Representation<GraphicsRenderObject, Geometry.Params> { + let version = 0 + const updated = new Subject<number>() + const currentState = Representation.createState() + const currentTheme = createEmptyTheme() + + const currentParams = PD.clone(Geometry.Params) + const currentProps = PD.getDefaultValues(Geometry.Params) + + return { + label, + updated, + get groupCount() { return renderObject.values.uGroupCount.ref.value }, + get renderObjects() { return [renderObject] }, + get props() { return currentProps }, + get params() { return currentParams }, + createOrUpdate: (props: Partial<PD.Values<Geometry.Params>> = {}) => { + const qualityProps = getQualityProps(Object.assign({}, currentProps, props)) + Object.assign(currentProps, props, qualityProps) + + return Task.create(`Updating '${label}' representation`, async runtime => { + // TODO + updated.next(version++) + }) + }, + get state() { return currentState }, + get theme() { return currentTheme }, + getLoci: () => { + // TODO + return EmptyLoci + }, + mark: (loci: Loci, action: MarkerAction) => { + // TODO + return false + }, + setState: (state: Partial<State>) => { + if (state.visible !== undefined) renderObject.state.visible = state.visible + if (state.pickable !== undefined) renderObject.state.pickable = state.pickable + // TODO transform + + Representation.updateState(currentState, state) + }, + setTheme: () => { }, + destroy() { } + } + } } \ No newline at end of file diff --git a/src/mol-repr/structure/representation.ts b/src/mol-repr/structure/representation.ts index bd9cfd6ece8e262d4ee8a070544f39a9e65a6659..ae35178342399c80509b7b73a0f855791acfb494 100644 --- a/src/mol-repr/structure/representation.ts +++ b/src/mol-repr/structure/representation.ts @@ -13,6 +13,7 @@ import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { Points } from 'mol-geo/geometry/points/points'; import { Lines } from 'mol-geo/geometry/lines/lines'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; +import { Spheres } from 'mol-geo/geometry/spheres/spheres'; export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { } @@ -20,33 +21,22 @@ export type StructureRepresentationProvider<P extends PD.Params> = Representatio // -export const StructureParams = { - ...Geometry.Params, -} +export const StructureParams = { ...Geometry.Params } export type StructureParams = typeof StructureParams -export const StructureMeshParams = { - ...Mesh.Params, - ...StructureParams, -} +export const StructureMeshParams = { ...Mesh.Params, ...StructureParams } export type StructureMeshParams = typeof StructureMeshParams -export const StructurePointsParams = { - ...Points.Params, - ...StructureParams, -} +export const StructureSpheresParams = { ...Spheres.Params, ...StructureParams } +export type StructureSpheresParams = typeof StructureSpheresParams + +export const StructurePointsParams = { ...Points.Params, ...StructureParams } export type StructurePointsParams = typeof StructurePointsParams -export const StructureLinesParams = { - ...Lines.Params, - ...StructureParams, -} +export const StructureLinesParams = { ...Lines.Params, ...StructureParams } export type StructureLinesParams = typeof StructureLinesParams -export const StructureDirectVolumeParams = { - ...DirectVolume.Params, - ...StructureParams, -} +export const StructureDirectVolumeParams = { ...DirectVolume.Params, ...StructureParams } export type StructureDirectVolumeParams = typeof StructureDirectVolumeParams export { ComplexRepresentation } from './complex-representation' diff --git a/src/mol-repr/structure/representation/ball-and-stick.ts b/src/mol-repr/structure/representation/ball-and-stick.ts index a12848cb64368590662015cc2477b950460c1ff4..0146c906126da9efed2b514cc62eb0e70f0a0dec 100644 --- a/src/mol-repr/structure/representation/ball-and-stick.ts +++ b/src/mol-repr/structure/representation/ball-and-stick.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere'; +import { getElementSphereVisual, ElementSphereParams } from '../visual/element-sphere'; import { IntraUnitLinkVisual, IntraUnitLinkParams } from '../visual/intra-unit-link-cylinder'; import { InterUnitLinkVisual, InterUnitLinkParams } from '../visual/inter-unit-link-cylinder'; import { ParamDefinition as PD } from 'mol-util/param-definition'; @@ -17,7 +17,7 @@ import { Structure } from 'mol-model/structure'; import { UnitKind, UnitKindOptions } from '../visual/util/common'; const BallAndStickVisuals = { - 'element-sphere': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementSphereParams>) => UnitsRepresentation('Element sphere mesh', ctx, getParams, ElementSphereVisual), + 'element-sphere': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementSphereParams>) => UnitsRepresentation('Element sphere mesh', ctx, getParams, getElementSphereVisual(ctx.webgl)), 'intra-link': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, IntraUnitLinkParams>) => UnitsRepresentation('Intra-unit link cylinder', ctx, getParams, IntraUnitLinkVisual), 'inter-link': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InterUnitLinkParams>) => ComplexRepresentation('Inter-unit link cylinder', ctx, getParams, InterUnitLinkVisual), } diff --git a/src/mol-repr/structure/representation/spacefill.ts b/src/mol-repr/structure/representation/spacefill.ts index b4de348557884d50be444846dce1e69f07c3f5db..ad310ca55c54e09d6e747ba231115701c83eaf36 100644 --- a/src/mol-repr/structure/representation/spacefill.ts +++ b/src/mol-repr/structure/representation/spacefill.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ElementSphereVisual, ElementSphereParams } from '../visual/element-sphere'; +import { getElementSphereVisual, ElementSphereParams } from '../visual/element-sphere'; import { UnitsRepresentation } from '../units-representation'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { StructureRepresentation, StructureRepresentationProvider } from '../representation'; @@ -14,7 +14,7 @@ import { Structure } from 'mol-model/structure'; import { UnitKind, UnitKindOptions } from '../visual/util/common'; const SpacefillVisuals = { - 'element-sphere': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementSphereParams>) => UnitsRepresentation('Sphere mesh', ctx, getParams, ElementSphereVisual), + 'element-sphere': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementSphereParams>) => UnitsRepresentation('Sphere mesh', ctx, getParams, getElementSphereVisual(ctx.webgl)), } export const SpacefillParams = { @@ -33,7 +33,7 @@ export function SpacefillRepresentation(ctx: RepresentationContext, getParams: R export const SpacefillRepresentationProvider: StructureRepresentationProvider<SpacefillParams> = { label: 'Spacefill', - description: 'Displays atoms as spheres.', + description: 'Displays atomic/coarse elements as spheres.', factory: SpacefillRepresentation, getParams: getSpacefillParams, defaultValues: PD.getDefaultValues(SpacefillParams), diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index 8b3427321ec7cb4bc3dbb49c7a48e50a0163254a..715008417c0e38f878676d41955b66feda248dec 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/src/mol-repr/structure/units-visual.ts @@ -7,10 +7,10 @@ import { Unit, Structure } from 'mol-model/structure'; import { RepresentationProps } from '../representation'; import { Visual, VisualContext } from '../visual'; -import { StructureMeshParams, StructurePointsParams, StructureLinesParams, StructureDirectVolumeParams } from './representation'; +import { StructureMeshParams, StructurePointsParams, StructureLinesParams, StructureDirectVolumeParams, StructureSpheresParams } from './representation'; import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci'; -import { MeshRenderObject, PointsRenderObject, LinesRenderObject, DirectVolumeRenderObject } from 'mol-gl/render-object'; -import { createUnitsMeshRenderObject, createUnitsPointsRenderObject, createUnitsTransform, createUnitsLinesRenderObject, createUnitsDirectVolumeRenderObject, includesUnitKind } from './visual/util/common'; +import { MeshRenderObject, PointsRenderObject, LinesRenderObject, DirectVolumeRenderObject, SpheresRenderObject } from 'mol-gl/render-object'; +import { createUnitsMeshRenderObject, createUnitsPointsRenderObject, createUnitsTransform, createUnitsLinesRenderObject, createUnitsDirectVolumeRenderObject, includesUnitKind, createUnitsSpheresRenderObject } from './visual/util/common'; import { deepEqual, ValueCell } from 'mol-util'; import { Interval } from 'mol-data/int'; import { ParamDefinition as PD } from 'mol-util/param-definition'; @@ -32,12 +32,13 @@ import { SizeTheme } from 'mol-theme/size'; import { UnitsParams } from './units-representation'; import { RenderableState } from 'mol-gl/renderable'; import { Mat4 } from 'mol-math/linear-algebra'; +import { Spheres } from 'mol-geo/geometry/spheres/spheres'; export type StructureGroup = { structure: Structure, group: Unit.SymmetryGroup } export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { } -type UnitsRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | DirectVolumeRenderObject +type UnitsRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | SpheresRenderObject | DirectVolumeRenderObject interface UnitsVisualBuilder<P extends UnitsParams, G extends Geometry> { defaultProps: PD.Values<P> @@ -257,10 +258,7 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB // mesh -export const UnitsMeshParams = { - ...StructureMeshParams, - ...UnitsParams, -} +export const UnitsMeshParams = { ...StructureMeshParams, ...UnitsParams } export type UnitsMeshParams = typeof UnitsMeshParams export interface UnitsMeshVisualBuilder<P extends UnitsMeshParams> extends UnitsVisualBuilder<P, Mesh> { } @@ -279,12 +277,30 @@ export function UnitsMeshVisual<P extends UnitsMeshParams>(builder: UnitsMeshVis }) } -// points +// spheres -export const UnitsPointsParams = { - ...StructurePointsParams, - ...UnitsParams, +export const UnitsSpheresParams = { ...StructureSpheresParams, ...UnitsParams } +export type UnitsSpheresParams = typeof UnitsSpheresParams +export interface UnitsSpheresVisualBuilder<P extends UnitsSpheresParams> extends UnitsVisualBuilder<P, Spheres> { } + +export function UnitsSpheresVisual<P extends UnitsSpheresParams>(builder: UnitsSpheresVisualBuilder<P>): UnitsVisual<P> { + return UnitsVisual<StructureSpheresParams & UnitsParams>({ + ...builder, + setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme) => { + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme) + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true + }, + createEmptyGeometry: Spheres.createEmpty, + createRenderObject: createUnitsSpheresRenderObject, + updateValues: Spheres.updateValues, + updateBoundingSphere: Spheres.updateBoundingSphere, + updateRenderableState: Geometry.updateRenderableState + }) } + +// points + +export const UnitsPointsParams = { ...StructurePointsParams, ...UnitsParams } export type UnitsPointsParams = typeof UnitsPointsParams export interface UnitsPointVisualBuilder<P extends UnitsPointsParams> extends UnitsVisualBuilder<P, Points> { } @@ -305,10 +321,7 @@ export function UnitsPointsVisual<P extends UnitsPointsParams>(builder: UnitsPoi // lines -export const UnitsLinesParams = { - ...StructureLinesParams, - ...UnitsParams, -} +export const UnitsLinesParams = { ...StructureLinesParams, ...UnitsParams } export type UnitsLinesParams = typeof UnitsLinesParams export interface UnitsLinesVisualBuilder<P extends UnitsLinesParams> extends UnitsVisualBuilder<P, Lines> { } @@ -329,10 +342,7 @@ export function UnitsLinesVisual<P extends UnitsLinesParams>(builder: UnitsLines // direct-volume -export const UnitsDirectVolumeParams = { - ...StructureDirectVolumeParams, - ...UnitsParams, -} +export const UnitsDirectVolumeParams = { ...StructureDirectVolumeParams, ...UnitsParams } export type UnitsDirectVolumeParams = typeof UnitsDirectVolumeParams export interface UnitsDirectVolumeVisualBuilder<P extends UnitsDirectVolumeParams> extends UnitsVisualBuilder<P, DirectVolume> { } diff --git a/src/mol-repr/structure/visual/element-sphere.ts b/src/mol-repr/structure/visual/element-sphere.ts index 2b2f09c0ff7c95822b4c65f843cae686454f2a7e..4608121fc85792e2a9036afd7339f6774fb64491 100644 --- a/src/mol-repr/structure/visual/element-sphere.ts +++ b/src/mol-repr/structure/visual/element-sphere.ts @@ -7,18 +7,37 @@ import { UnitsVisual } from '../representation'; import { VisualUpdateState } from '../../util'; -import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator } from './util/element'; -import { UnitsMeshVisual, UnitsMeshParams } from '../units-visual'; +import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator, createElementSphereImpostor } from './util/element'; +import { UnitsMeshVisual, UnitsMeshParams, UnitsSpheresVisual, UnitsSpheresParams } from '../units-visual'; import { ParamDefinition as PD } from 'mol-util/param-definition'; +import { WebGLContext } from 'mol-gl/webgl/context'; export const ElementSphereParams = { ...UnitsMeshParams, + ...UnitsSpheresParams, sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }), detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }), } export type ElementSphereParams = typeof ElementSphereParams -export function ElementSphereVisual(): UnitsVisual<ElementSphereParams> { +export function getElementSphereVisual(webgl?: WebGLContext) { + return webgl && webgl.extensions.fragDepth ? ElementSphereImpostorVisual : ElementSphereMeshVisual +} + +export function ElementSphereImpostorVisual(): UnitsVisual<ElementSphereParams> { + return UnitsSpheresVisual<ElementSphereParams>({ + defaultProps: PD.getDefaultValues(ElementSphereParams), + createGeometry: createElementSphereImpostor, + createLocationIterator: StructureElementIterator.fromGroup, + getLoci: getElementLoci, + mark: markElement, + setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementSphereParams>, currentProps: PD.Values<ElementSphereParams>) => { + + } + }) +} + +export function ElementSphereMeshVisual(): UnitsVisual<ElementSphereParams> { return UnitsMeshVisual<ElementSphereParams>({ defaultProps: PD.getDefaultValues(ElementSphereParams), createGeometry: createElementSphereMesh, diff --git a/src/mol-repr/structure/visual/util/common.ts b/src/mol-repr/structure/visual/util/common.ts index fae67ef50fb969b7bf82e079d10f50553f55d3a4..b77ab1958180f44151d1094def2575b5cc998f22 100644 --- a/src/mol-repr/structure/visual/util/common.ts +++ b/src/mol-repr/structure/visual/util/common.ts @@ -5,7 +5,7 @@ */ import { Unit, Structure, ElementIndex, StructureElement } from 'mol-model/structure'; -import { createMeshRenderObject, createPointsRenderObject, createLinesRenderObject, createDirectVolumeRenderObject } from 'mol-gl/render-object'; +import { createMeshRenderObject, createPointsRenderObject, createLinesRenderObject, createDirectVolumeRenderObject, createSpheresRenderObject } from 'mol-gl/render-object'; import { Mat4 } from 'mol-math/linear-algebra'; import { TransformData, createTransform, createIdentityTransform } from 'mol-geo/geometry/transform-data'; import { Mesh } from 'mol-geo/geometry/mesh/mesh'; @@ -16,9 +16,10 @@ import { Lines } from 'mol-geo/geometry/lines/lines'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; import { Theme } from 'mol-theme/theme'; import { ParamDefinition as PD } from 'mol-util/param-definition'; -import { StructureMeshParams, StructurePointsParams, StructureLinesParams, StructureDirectVolumeParams } from 'mol-repr/structure/representation'; +import { StructureMeshParams, StructurePointsParams, StructureLinesParams, StructureDirectVolumeParams, StructureSpheresParams } from 'mol-repr/structure/representation'; import { OrderedSet, SortedArray } from 'mol-data/int'; import { EmptyLoci, Loci } from 'mol-model/loci'; +import { Spheres } from 'mol-geo/geometry/spheres/spheres'; /** Return a Loci for the elements of a whole residue the elementIndex belongs to. */ export function getResidueLoci(structure: Structure, unit: Unit, elementIndex: ElementIndex): Loci { @@ -83,6 +84,15 @@ export function createUnitsMeshRenderObject(group: Unit.SymmetryGroup, mesh: Mes return createMeshRenderObject(values, state) } +// spheres + +export function createUnitsSpheresRenderObject(group: Unit.SymmetryGroup, spheres: Spheres, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructureSpheresParams>) { + const transform = createUnitsTransform(group) + const values = Spheres.createValues(spheres, transform, locationIt, theme, props) + const state = Geometry.createRenderableState(props) + return createSpheresRenderObject(values, state) +} + // points export function createUnitsPointsRenderObject(group: Unit.SymmetryGroup, points: Points, locationIt: LocationIterator, theme: Theme, props: PD.Values<StructurePointsParams>) { diff --git a/src/mol-repr/structure/visual/util/element.ts b/src/mol-repr/structure/visual/util/element.ts index ca721b769066e6c8b819c3e15de8521473ded340..81fa4a5e16c3da255ea84efd938e7ac0fae9cf42 100644 --- a/src/mol-repr/structure/visual/util/element.ts +++ b/src/mol-repr/structure/visual/util/element.ts @@ -17,6 +17,8 @@ import { LocationIterator } from 'mol-geo/util/location-iterator'; import { VisualContext } from 'mol-repr/visual'; import { Theme } from 'mol-theme/theme'; import { StructureGroup } from 'mol-repr/structure/units-visual'; +import { Spheres } from 'mol-geo/geometry/spheres/spheres'; +import { SpheresBuilder } from 'mol-geo/geometry/spheres/spheres-builder'; export interface ElementSphereMeshProps { detail: number, @@ -47,6 +49,28 @@ export function createElementSphereMesh(ctx: VisualContext, unit: Unit, structur return MeshBuilder.getMesh(builderState) } +export interface ElementSphereImpostorProps { } + +export function createElementSphereImpostor(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementSphereImpostorProps, spheres?: Spheres) { + + const { elements } = unit; + const elementCount = elements.length; + const builder = SpheresBuilder.create(elementCount, elementCount / 2) + + const v = Vec3.zero() + const pos = unit.conformation.invariantPosition + const l = StructureElement.create() + l.unit = unit + + for (let i = 0; i < elementCount; i++) { + l.element = elements[i] + pos(elements[i], v) + builder.add(v[0], v[1], v[2], i) + } + + return builder.getSpheres() +} + export function markElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { let changed = false if (!StructureElement.isLoci(loci)) return false diff --git a/src/mol-repr/visual.ts b/src/mol-repr/visual.ts index 79a378b1e37e52edf72a728474f83a9c679d74f6..1a2f5a369be09fa83e62e416283f25d01368b90a 100644 --- a/src/mol-repr/visual.ts +++ b/src/mol-repr/visual.ts @@ -5,7 +5,7 @@ */ import { RuntimeContext } from 'mol-task' -import { RenderObject, MeshRenderObject, LinesRenderObject, PointsRenderObject, DirectVolumeRenderObject } from 'mol-gl/render-object' +import { RenderObject, GraphicsRenderObject } from 'mol-gl/render-object' import { PickingId } from '../mol-geo/geometry/picking'; import { Loci } from 'mol-model/loci'; import { MarkerAction } from '../mol-geo/geometry/marker-data'; @@ -23,8 +23,6 @@ export interface VisualContext { } // export type VisualFactory<D, P extends PD.Params> = (ctx: VisualContext) => Visual<D, P> -type VisualRenderObject = MeshRenderObject | LinesRenderObject | PointsRenderObject | DirectVolumeRenderObject - export { Visual } interface Visual<D, P extends PD.Params> { /** Number of addressable groups in all instances of the visual */ @@ -39,15 +37,15 @@ interface Visual<D, P extends PD.Params> { destroy: () => void } namespace Visual { - export function setVisibility(renderObject: VisualRenderObject | undefined, value: boolean) { + export function setVisibility(renderObject: GraphicsRenderObject | undefined, value: boolean) { if (renderObject) renderObject.state.visible = value } - export function setPickable(renderObject: VisualRenderObject | undefined, value: boolean) { + export function setPickable(renderObject: GraphicsRenderObject | undefined, value: boolean) { if (renderObject) renderObject.state.pickable = value } - export function setTransform(renderObject: VisualRenderObject | undefined, value: Mat4) { + export function setTransform(renderObject: GraphicsRenderObject | undefined, value: Mat4) { if (renderObject) { const { values } = renderObject setTransformData(value, values)