Browse Source

wip, spheres renderable in visuals

Alexander Rose 6 years ago
parent
commit
01e0ae4e9f

+ 49 - 1
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() { }
+        }
+    }
 }

+ 9 - 19
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'

+ 2 - 2
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),
 }

+ 3 - 3
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),

+ 30 - 20
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> { }
 

+ 22 - 3
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,

+ 12 - 2
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>) {

+ 24 - 0
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

+ 4 - 6
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)