diff --git a/src/apps/canvas/assembly-symmetry.ts b/src/apps/canvas/assembly-symmetry.ts index 69fee7dd07fd6acfb60c87a354f719dd556a2493..ee4d6832753ef4a2f379f5004ede22078ff26eab 100644 --- a/src/apps/canvas/assembly-symmetry.ts +++ b/src/apps/canvas/assembly-symmetry.ts @@ -7,10 +7,10 @@ import { AssemblySymmetry } from 'mol-model-props/rcsb/symmetry'; import { Table } from 'mol-data/db'; import { Color, ColorScale } from 'mol-util/color'; -import { MeshBuilder } from 'mol-geo/mesh/mesh-builder'; +import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder'; import { Tensor } from 'mol-math/linear-algebra'; -import { addSphere } from 'mol-geo/mesh/builder/sphere'; -import { addCylinder } from 'mol-geo/mesh/builder/cylinder'; +import { addSphere } from 'mol-geo/geometry/mesh/builder/sphere'; +import { addCylinder } from 'mol-geo/geometry/mesh/builder/cylinder'; import { Shape } from 'mol-model/shape'; import { ColorTheme } from 'mol-view/theme/color'; import { Location } from 'mol-model/location'; diff --git a/src/apps/canvas/component/structure-representation.tsx b/src/apps/canvas/component/structure-representation.tsx index d81cc3f3d1a179dcd825217bddb3de60403dfad6..d282e8e41fd53d705dd00990bd519263f80daf8a 100644 --- a/src/apps/canvas/component/structure-representation.tsx +++ b/src/apps/canvas/component/structure-representation.tsx @@ -7,10 +7,10 @@ import * as React from 'react' import { StructureRepresentation, StructureProps } from 'mol-geo/representation/structure'; import Viewer from 'mol-view/viewer'; -import { VisualQuality, VisualQualityNames } from 'mol-geo/representation/util'; import { ColorThemeProps, ColorThemeName, ColorThemeNames, ColorTheme } from 'mol-view/theme/color'; import { Color } from 'mol-util/color'; import { Progress } from 'mol-task'; +import { VisualQuality, VisualQualityNames } from 'mol-geo/geometry/geometry'; export interface StructureRepresentationComponentProps { viewer: Viewer @@ -165,7 +165,7 @@ export class StructureRepresentationComponent extends React.Component<StructureR <span>Iso Value </span> <input type='range' defaultValue={this.state.isoValue.toString()} - min='0.1' + min='1' max='3' step='0.1' onInput={(e) => this.update({ isoValue: parseFloat(e.currentTarget.value) })} diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts index d13cfb6ef6852840cf2241900d7d67f5f68cbe32..62ef041ddfb753af90e335284ec85e431ae03c3e 100644 --- a/src/apps/canvas/structure-view.ts +++ b/src/apps/canvas/structure-view.ts @@ -25,7 +25,7 @@ import { BehaviorSubject } from 'rxjs'; import { SpacefillRepresentation } from 'mol-geo/representation/structure/representation/spacefill'; import { DistanceRestraintRepresentation } from 'mol-geo/representation/structure/representation/distance-restraint'; import { SurfaceRepresentation } from 'mol-geo/representation/structure/representation/surface'; -import { Progress } from 'mol-task'; +// import { Progress } from 'mol-task'; export interface StructureView { readonly viewer: Viewer @@ -210,7 +210,7 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> for (const k in structureRepresentations) { if (active[k]) { await structureRepresentations[k].createOrUpdate({}, structure).run( - progress => console.log(Progress.format(progress)) + // progress => console.log(Progress.format(progress)) ) viewer.add(structureRepresentations[k]) } else { diff --git a/src/mol-app/ui/transform/backbone.tsx b/src/mol-app/ui/transform/backbone.tsx index 76270473768242f05fbe3744541c7aed9243ee49..93a4a3392618673ea30514e515ef0d8f3dff0d6c 100644 --- a/src/mol-app/ui/transform/backbone.tsx +++ b/src/mol-app/ui/transform/backbone.tsx @@ -19,8 +19,8 @@ import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme import { SizeThemeProps } from 'mol-view/theme/size'; import { Color, ColorNames } from 'mol-util/color'; import { Slider } from '../controls/slider'; -import { VisualQuality } from 'mol-geo/representation/util'; import { Unit } from 'mol-model/structure'; +import { VisualQuality } from 'mol-geo/geometry/geometry'; interface BackboneState { doubleSided: boolean diff --git a/src/mol-app/ui/transform/ball-and-stick.tsx b/src/mol-app/ui/transform/ball-and-stick.tsx index 61d621f988f5d6aa7f89e89fe5309dc2d6c7c63b..38320c2b07341ef93674381c3cb52718b9008af0 100644 --- a/src/mol-app/ui/transform/ball-and-stick.tsx +++ b/src/mol-app/ui/transform/ball-and-stick.tsx @@ -19,8 +19,8 @@ import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme import { SizeThemeProps } from 'mol-view/theme/size'; import { Color, ColorNames } from 'mol-util/color'; import { Slider } from '../controls/slider'; -import { VisualQuality } from 'mol-geo/representation/util'; import { Unit } from 'mol-model/structure'; +import { VisualQuality } from 'mol-geo/geometry/geometry'; interface BallAndStickState { doubleSided: boolean diff --git a/src/mol-app/ui/transform/carbohydrate.tsx b/src/mol-app/ui/transform/carbohydrate.tsx index 66e4b3a4c02c3a5ad99bb582097252666821a979..e725131474ef63d60261eab264c4c925a3f8ad31 100644 --- a/src/mol-app/ui/transform/carbohydrate.tsx +++ b/src/mol-app/ui/transform/carbohydrate.tsx @@ -19,8 +19,8 @@ import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme import { SizeThemeProps } from 'mol-view/theme/size'; import { Color, ColorNames } from 'mol-util/color'; import { Slider } from '../controls/slider'; -import { VisualQuality } from 'mol-geo/representation/util'; import { Unit } from 'mol-model/structure'; +import { VisualQuality } from 'mol-geo/geometry/geometry'; interface CarbohydrateState { doubleSided: boolean diff --git a/src/mol-app/ui/transform/cartoon.tsx b/src/mol-app/ui/transform/cartoon.tsx index b78e8c91e8969d254e06e9c877c7ee20a157e9a9..994934214126b6fbf9909791a65ac5777b883fdd 100644 --- a/src/mol-app/ui/transform/cartoon.tsx +++ b/src/mol-app/ui/transform/cartoon.tsx @@ -19,8 +19,8 @@ import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme import { SizeThemeProps } from 'mol-view/theme/size'; import { Color, ColorNames } from 'mol-util/color'; import { Slider } from '../controls/slider'; -import { VisualQuality } from 'mol-geo/representation/util'; import { Unit } from 'mol-model/structure'; +import { VisualQuality } from 'mol-geo/geometry/geometry'; interface CartoonState { doubleSided: boolean diff --git a/src/mol-app/ui/transform/distance-restraint.tsx b/src/mol-app/ui/transform/distance-restraint.tsx index 981cd83ef69d1b188259428233a782414f37ec52..037532629bf76078090abee3e4600f5cc8698ce2 100644 --- a/src/mol-app/ui/transform/distance-restraint.tsx +++ b/src/mol-app/ui/transform/distance-restraint.tsx @@ -19,8 +19,8 @@ import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme import { SizeThemeProps } from 'mol-view/theme/size'; import { Color, ColorNames } from 'mol-util/color'; import { Slider } from '../controls/slider'; -import { VisualQuality } from 'mol-geo/representation/util'; import { Unit } from 'mol-model/structure'; +import { VisualQuality } from 'mol-geo/geometry/geometry'; interface DistanceRestraintState { doubleSided: boolean diff --git a/src/mol-app/ui/transform/spacefill.tsx b/src/mol-app/ui/transform/spacefill.tsx index 53c22660e267a2f66cab426cb531bd54b8454478..d9694e10eae9c0b7bd3e392112290a40bd1b85a7 100644 --- a/src/mol-app/ui/transform/spacefill.tsx +++ b/src/mol-app/ui/transform/spacefill.tsx @@ -19,8 +19,8 @@ import { ColorThemeProps, ColorThemeNames, ColorThemeName } from 'mol-view/theme import { SizeThemeProps } from 'mol-view/theme/size'; import { Color, ColorNames } from 'mol-util/color'; import { Slider } from '../controls/slider'; -import { VisualQuality } from 'mol-geo/representation/util'; import { Unit } from 'mol-model/structure'; +import { VisualQuality } from 'mol-geo/geometry/geometry'; interface SpacefillState { doubleSided: boolean diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2f6f940808f3be306625f02329e422eb05c0712 --- /dev/null +++ b/src/mol-geo/geometry/geometry.ts @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Mesh } from './mesh/mesh'; +import { Point } from './point/point'; +import { PointValues, MeshValues, RenderableState } from 'mol-gl/renderable'; +import { MeshRenderObject, PointRenderObject } from 'mol-gl/render-object'; +import { ValueCell } from 'mol-util'; +import { BaseValues } from 'mol-gl/renderable/schema'; + +export type GeometryKindType = { 'mesh': Mesh, 'point': Point } +export type GeometryKind = keyof GeometryKindType +export type Geometry = Helpers.ValueOf<GeometryKindType> + +export type GeometryDef = { + 'mesh': { 'props': MeshProps, 'values': MeshValues, 'renderObject': MeshRenderObject } + 'point': { 'props': PointProps, 'values': PointValues, 'renderObject': PointRenderObject } +} + +export namespace Geometry { + export function getDrawCount(geometry: Geometry) { + switch (geometry.kind) { + case 'mesh': return geometry.triangleCount * 3 + case 'point': return geometry.vertexCount + } + } +} + +// + +export const VisualQualityInfo = { + 'custom': {}, + 'auto': {}, + 'highest': {}, + 'high': {}, + 'medium': {}, + 'low': {}, + 'lowest': {}, +} +export type VisualQuality = keyof typeof VisualQualityInfo +export const VisualQualityNames = Object.keys(VisualQualityInfo) + +// + +export const DefaultBaseProps = { + alpha: 1, + visible: true, + depthMask: true, + useFog: false, + quality: 'auto' as VisualQuality +} +export type BaseProps = typeof DefaultBaseProps + +export const DefaultMeshProps = { + ...DefaultBaseProps, + doubleSided: false, + flipSided: false, + flatShaded: false, +} +export type MeshProps = typeof DefaultMeshProps + +export const DefaultPointProps = { + ...DefaultBaseProps, + pointSizeAttenuation: true +} +export type PointProps = typeof DefaultPointProps + +type Counts = { drawCount: number, groupCount: number, instanceCount: number } + +export function createBaseValues(props: BaseProps, counts: Counts) { + return { + uAlpha: ValueCell.create(props.alpha), + uGroupCount: ValueCell.create(counts.groupCount), + drawCount: ValueCell.create(counts.drawCount), + dUseFog: ValueCell.create(props.useFog), + } +} + +export function createMeshValues(props: MeshProps, counts: Counts) { + return { + ...createBaseValues(props, counts), + dDoubleSided: ValueCell.create(props.doubleSided), + dFlatShaded: ValueCell.create(props.flatShaded), + dFlipSided: ValueCell.create(props.flipSided), + } +} + +export function createPointValues(props: PointProps, counts: Counts) { + return { + ...createBaseValues(props, counts), + dPointSizeAttenuation: ValueCell.create(props.pointSizeAttenuation), + } +} + +export function createRenderableState(props: BaseProps): RenderableState { + return { + visible: props.visible, + depthMask: props.depthMask + } +} + +export function updateBaseValues(values: BaseValues, props: BaseProps) { + ValueCell.updateIfChanged(values.uAlpha, props.alpha) + ValueCell.updateIfChanged(values.dUseFog, props.useFog) +} + +export function updateMeshValues(values: MeshValues, props: MeshProps) { + updateBaseValues(values, props) + ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided) + ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded) + ValueCell.updateIfChanged(values.dFlipSided, props.flipSided) +} + +export function updatePointValues(values: PointValues, props: PointProps) { + updateBaseValues(values, props) + ValueCell.updateIfChanged(values.dPointSizeAttenuation, props.pointSizeAttenuation) +} + +export function updateRenderableState(state: RenderableState, props: BaseProps) { + state.visible = props.visible + state.depthMask = props.depthMask +} \ No newline at end of file diff --git a/src/mol-geo/geometry/line/line-builder.ts b/src/mol-geo/geometry/line/line-builder.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ffdd02fcbce683e436c0030ffe0517135c6ceda --- /dev/null +++ b/src/mol-geo/geometry/line/line-builder.ts @@ -0,0 +1 @@ +// TODO \ No newline at end of file diff --git a/src/mol-geo/geometry/line/line.ts b/src/mol-geo/geometry/line/line.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ffdd02fcbce683e436c0030ffe0517135c6ceda --- /dev/null +++ b/src/mol-geo/geometry/line/line.ts @@ -0,0 +1 @@ +// TODO \ No newline at end of file diff --git a/src/mol-geo/mesh/builder/bounding-box.ts b/src/mol-geo/geometry/mesh/builder/bounding-box.ts similarity index 97% rename from src/mol-geo/mesh/builder/bounding-box.ts rename to src/mol-geo/geometry/mesh/builder/bounding-box.ts index ba36360454d6d689d8b392631543a2be861ff9cb..0781953361505721dd31b15aef6279f4a4d6b83a 100644 --- a/src/mol-geo/mesh/builder/bounding-box.ts +++ b/src/mol-geo/geometry/mesh/builder/bounding-box.ts @@ -7,7 +7,7 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Box3D } from 'mol-math/geometry'; import { MeshBuilder } from '../mesh-builder'; -import { CylinderProps } from '../../primitive/cylinder'; +import { CylinderProps } from '../../../primitive/cylinder'; import { addCylinder } from './cylinder'; import { addSphere } from './sphere'; diff --git a/src/mol-geo/mesh/builder/cylinder.ts b/src/mol-geo/geometry/mesh/builder/cylinder.ts similarity index 96% rename from src/mol-geo/mesh/builder/cylinder.ts rename to src/mol-geo/geometry/mesh/builder/cylinder.ts index b4538c1c81a0a802392a622ece8199e2f997e77e..a4b978f3fd4e2ed7e8770278034e47d210d136a2 100644 --- a/src/mol-geo/mesh/builder/cylinder.ts +++ b/src/mol-geo/geometry/mesh/builder/cylinder.ts @@ -6,8 +6,8 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { MeshBuilder } from '../mesh-builder'; -import { Primitive } from '../../primitive/primitive'; -import { Cylinder, CylinderProps } from '../../primitive/cylinder'; +import { Primitive } from '../../../primitive/primitive'; +import { Cylinder, CylinderProps } from '../../../primitive/cylinder'; const cylinderMap = new Map<string, Primitive>() const up = Vec3.create(0, 1, 0) diff --git a/src/mol-geo/mesh/builder/sheet.ts b/src/mol-geo/geometry/mesh/builder/sheet.ts similarity index 100% rename from src/mol-geo/mesh/builder/sheet.ts rename to src/mol-geo/geometry/mesh/builder/sheet.ts diff --git a/src/mol-geo/mesh/builder/sphere.ts b/src/mol-geo/geometry/mesh/builder/sphere.ts similarity index 88% rename from src/mol-geo/mesh/builder/sphere.ts rename to src/mol-geo/geometry/mesh/builder/sphere.ts index d9196c3a2840223e833369e133c79c237b3e4c63..4d04616b642e2819432c4463c5346c409bc618c7 100644 --- a/src/mol-geo/mesh/builder/sphere.ts +++ b/src/mol-geo/geometry/mesh/builder/sphere.ts @@ -6,8 +6,8 @@ import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { MeshBuilder } from '../mesh-builder'; -import { Primitive } from '../../primitive/primitive'; -import { Sphere } from '../../primitive/sphere'; +import { Primitive } from '../../../primitive/primitive'; +import { Sphere } from '../../../primitive/sphere'; const sphereMap = new Map<number, Primitive>() const tmpSphereMat = Mat4.identity() diff --git a/src/mol-geo/mesh/builder/tube.ts b/src/mol-geo/geometry/mesh/builder/tube.ts similarity index 100% rename from src/mol-geo/mesh/builder/tube.ts rename to src/mol-geo/geometry/mesh/builder/tube.ts diff --git a/src/mol-geo/mesh/mesh-builder.ts b/src/mol-geo/geometry/mesh/mesh-builder.ts similarity index 96% rename from src/mol-geo/mesh/mesh-builder.ts rename to src/mol-geo/geometry/mesh/mesh-builder.ts index d7d264bfc777b0a5548aa229e43b620862c6af95..ecd8dfeec52c1d756ff3c5e45b4c9e215084ce75 100644 --- a/src/mol-geo/mesh/mesh-builder.ts +++ b/src/mol-geo/geometry/mesh/mesh-builder.ts @@ -8,8 +8,8 @@ import { ValueCell } from 'mol-util/value-cell' import { Vec3, Mat4, Mat3 } from 'mol-math/linear-algebra'; import { ChunkedArray } from 'mol-data/util'; import { Mesh } from './mesh'; -import { getNormalMatrix } from '../util'; -import { Primitive } from '../primitive/primitive'; +import { getNormalMatrix } from '../../util'; +import { Primitive } from '../../primitive/primitive'; export interface MeshBuilderState { readonly currentGroup: number @@ -67,6 +67,7 @@ export namespace MeshBuilder { const nb = ChunkedArray.compact(normals, true) as Float32Array const gb = ChunkedArray.compact(groups, true) as Float32Array return { + kind: 'mesh', vertexCount: vertices.elementCount, triangleCount: indices.elementCount, vertexBuffer: mesh ? ValueCell.update(mesh.vertexBuffer, vb) : ValueCell.create(vb), diff --git a/src/mol-geo/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts similarity index 99% rename from src/mol-geo/mesh/mesh.ts rename to src/mol-geo/geometry/mesh/mesh.ts index adb7cae231e800863e5b4d7d5fa53b69d1e4246e..e600eef6370dfc6460926a66853199a5734a010f 100644 --- a/src/mol-geo/mesh/mesh.ts +++ b/src/mol-geo/geometry/mesh/mesh.ts @@ -8,9 +8,11 @@ import { Task } from 'mol-task' import { ValueCell } from 'mol-util' import { Vec3, Mat4 } from 'mol-math/linear-algebra' import { Sphere3D } from 'mol-math/geometry' -import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../util'; +import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util'; export interface Mesh { + readonly kind: 'mesh', + /** Number of vertices in the mesh */ vertexCount: number, /** Number of triangles in the mesh */ @@ -39,6 +41,7 @@ export namespace Mesh { const nb = mesh ? mesh.normalBuffer.ref.value : new Float32Array(0) const gb = mesh ? mesh.groupBuffer.ref.value : new Float32Array(0) return { + kind: 'mesh', vertexCount: 0, triangleCount: 0, vertexBuffer: mesh ? ValueCell.update(mesh.vertexBuffer, vb) : ValueCell.create(vb), diff --git a/src/mol-geo/geometry/point/point-builder.ts b/src/mol-geo/geometry/point/point-builder.ts new file mode 100644 index 0000000000000000000000000000000000000000..e00a9e06e3da840a267c19100e9ffb412242ccdd --- /dev/null +++ b/src/mol-geo/geometry/point/point-builder.ts @@ -0,0 +1,38 @@ +/** + * 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 { ChunkedArray } from 'mol-data/util'; +import { Point } from './point'; + +export interface PointBuilder { + add(x: number, y: number, z: number, group: number): void + getPoint(): Point +} + +export namespace PointBuilder { + export function create(initialCount = 2048, chunkSize = 1024, point?: Point): PointBuilder { + const vertices = ChunkedArray.create(Float32Array, 3, chunkSize, point ? point.vertexBuffer.ref.value : initialCount); + const groups = ChunkedArray.create(Float32Array, 1, chunkSize, point ? point.groupBuffer.ref.value : initialCount); + + return { + add: (x: number, y: number, z: number, group: number) => { + ChunkedArray.add3(vertices, x, y, z); + ChunkedArray.add(groups, group); + }, + getPoint: () => { + const vb = ChunkedArray.compact(vertices, true) as Float32Array + const gb = ChunkedArray.compact(groups, true) as Float32Array + return { + kind: 'point', + vertexCount: vertices.elementCount, + vertexBuffer: point ? ValueCell.update(point.vertexBuffer, vb) : ValueCell.create(vb), + groupBuffer: point ? ValueCell.update(point.groupBuffer, gb) : ValueCell.create(gb), + } + } + } + } +} \ No newline at end of file diff --git a/src/mol-geo/geometry/point/point.ts b/src/mol-geo/geometry/point/point.ts new file mode 100644 index 0000000000000000000000000000000000000000..2b5a810e6a95a3bcbc078663da46f21d502c7f9c --- /dev/null +++ b/src/mol-geo/geometry/point/point.ts @@ -0,0 +1,43 @@ +/** + * 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' +import { Mat4 } from 'mol-math/linear-algebra' +import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util'; + +/** Point cloud */ +export interface Point { + readonly kind: 'point', + /** Number of vertices in the point cloud */ + vertexCount: number, + /** Vertex buffer as array of xyz values wrapped in a value cell */ + readonly vertexBuffer: ValueCell<Float32Array>, + /** Group buffer as array of group ids for each vertex wrapped in a value cell */ + readonly groupBuffer: ValueCell<Float32Array>, +} + +export namespace Point { + export function createEmpty(point?: Point): Point { + const vb = point ? point.vertexBuffer.ref.value : new Float32Array(0) + const gb = point ? point.groupBuffer.ref.value : new Float32Array(0) + return { + kind: 'point', + vertexCount: 0, + vertexBuffer: point ? ValueCell.update(point.vertexBuffer, vb) : ValueCell.create(vb), + groupBuffer: point ? ValueCell.update(point.groupBuffer, gb) : ValueCell.create(gb), + } + } + + export function transformImmediate(point: Point, t: Mat4) { + transformRangeImmediate(point, t, 0, point.vertexCount) + } + + export function transformRangeImmediate(point: Point, t: Mat4, offset: number, count: number) { + const v = point.vertexBuffer.ref.value + transformPositionArray(t, v, offset, count) + ValueCell.update(point.vertexBuffer, v); + } +} \ No newline at end of file diff --git a/src/mol-geo/representation/shape/index.ts b/src/mol-geo/representation/shape/index.ts index c5b86178a700bd021cbd759e1dcfe36ee43c5df2..fcb1800524150c6262e0cd3966377c4944456418 100644 --- a/src/mol-geo/representation/shape/index.ts +++ b/src/mol-geo/representation/shape/index.ts @@ -10,7 +10,6 @@ import { RepresentationProps, Representation } from '..'; import { PickingId } from '../../util/picking'; import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci'; import { MarkerAction, applyMarkerAction, createMarkers } from '../../util/marker-data'; -import { createRenderableState, createMeshValues, DefaultMeshProps } from '../util'; import { getMeshData } from '../../util/mesh-data'; import { MeshValues } from 'mol-gl/renderable'; import { ValueCell } from 'mol-util'; @@ -20,6 +19,7 @@ import { LocationIterator } from '../../util/location-iterator'; import { createColors } from '../structure/visual/util/common'; import { OrderedSet, Interval } from 'mol-data/int'; import { createIdentityTransform } from '../../util/transform-data'; +import { DefaultMeshProps, createMeshValues, createRenderableState } from '../../geometry/geometry'; export interface ShapeRepresentation<P extends RepresentationProps = {}> extends Representation<Shape, P> { } diff --git a/src/mol-geo/representation/structure/complex-visual.ts b/src/mol-geo/representation/structure/complex-visual.ts index 53a59c6d4ed75890f3a3463971c138f14445192b..e9bf510643a5c30bb7b25fd173b3ce41fc18a0f8 100644 --- a/src/mol-geo/representation/structure/complex-visual.ts +++ b/src/mol-geo/representation/structure/complex-visual.ts @@ -7,17 +7,17 @@ import { Structure } from 'mol-model/structure'; import { Visual } from '..'; import { MeshRenderObject } from 'mol-gl/render-object'; -import { Mesh } from '../../mesh/mesh'; +import { Mesh } from '../../geometry/mesh/mesh'; import { RuntimeContext } from 'mol-task'; import { LocationIterator } from '../../util/location-iterator'; import { createComplexMeshRenderObject, createColors } from './visual/util/common'; -import { StructureProps, DefaultStructureMeshProps, MeshUpdateState } from '.'; +import { StructureProps, DefaultStructureMeshProps, VisualUpdateState } from '.'; import { deepEqual, ValueCell } from 'mol-util'; -import { updateMeshValues, updateRenderableState } from '../util'; import { PickingId } from '../../util/picking'; import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction, applyMarkerAction } from '../../util/marker-data'; import { Interval } from 'mol-data/int'; +import { updateMeshValues, updateRenderableState } from '../../geometry/geometry'; export interface ComplexVisual<P extends StructureProps> extends Visual<Structure, P> { } @@ -32,12 +32,12 @@ export interface ComplexMeshVisualBuilder<P extends ComplexMeshProps> { createLocationIterator(structure: Structure): LocationIterator getLoci(pickingId: PickingId, structure: Structure, id: number): Loci mark(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean): boolean, - setUpdateState(state: MeshUpdateState, newProps: P, currentProps: P): void + setUpdateState(state: VisualUpdateState, newProps: P, currentProps: P): void } export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMeshVisualBuilder<P>): ComplexVisual<P> { const { defaultProps, createMesh, createLocationIterator, getLoci, mark, setUpdateState } = builder - const updateState = MeshUpdateState.create() + const updateState = VisualUpdateState.create() let renderObject: MeshRenderObject | undefined let currentProps: P @@ -65,22 +65,22 @@ export function ComplexMeshVisual<P extends ComplexMeshProps>(builder: ComplexMe if (!renderObject) return false locationIt.reset() - MeshUpdateState.reset(updateState) + VisualUpdateState.reset(updateState) setUpdateState(updateState, newProps, currentProps) const newConformationHash = Structure.conformationHash(currentStructure) if (newConformationHash !== conformationHash) { conformationHash = newConformationHash - updateState.createMesh = true + updateState.createGeometry = true } - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.createMesh = true + if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.createGeometry = true if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateState.updateColor = true // if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createMesh = true // TODO // - if (updateState.createMesh) { + if (updateState.createGeometry) { mesh = await createMesh(ctx, currentStructure, newProps, mesh) ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3) updateState.updateColor = true diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts index 7628d9e084ba81ff6ef7e9705638532e73ee2c77..e6f6610418cb9fbf08a3669fc0157cc62bcd828a 100644 --- a/src/mol-geo/representation/structure/index.ts +++ b/src/mol-geo/representation/structure/index.ts @@ -9,7 +9,7 @@ import { Structure } from 'mol-model/structure'; import { ColorThemeProps } from 'mol-view/theme/color'; import { SizeThemeProps } from 'mol-view/theme/size'; import { Representation, RepresentationProps } from '..'; -import { DefaultBaseProps, DefaultMeshProps } from '../util'; +import { DefaultMeshProps, DefaultBaseProps, DefaultPointProps } from '../../geometry/geometry'; export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P> { } @@ -26,23 +26,32 @@ export const DefaultStructureMeshProps = { } export type StructureMeshProps = typeof DefaultStructureMeshProps -export interface MeshUpdateState { +export const DefaultStructurePointProps = { + ...DefaultStructureProps, + ...DefaultPointProps +} +export type StructurePointProps = typeof DefaultStructurePointProps + +export interface VisualUpdateState { updateTransform: boolean updateColor: boolean - createMesh: boolean + updateSize: boolean + createGeometry: boolean } -export namespace MeshUpdateState { - export function create(): MeshUpdateState { +export namespace VisualUpdateState { + export function create(): VisualUpdateState { return { updateTransform: false, updateColor: false, - createMesh: false + updateSize: false, + createGeometry: false } } - export function reset(state: MeshUpdateState) { + export function reset(state: VisualUpdateState) { state.updateTransform = false state.updateColor = false - state.createMesh = false + state.updateSize = false + state.createGeometry = false } } diff --git a/src/mol-geo/representation/structure/representation/surface.ts b/src/mol-geo/representation/structure/representation/surface.ts index 7e95466e6ffa51421b7973b8436b2a5ef1e9a6d8..92a0d48e2d610244eb7e0e1dc1e32e326ba3a52c 100644 --- a/src/mol-geo/representation/structure/representation/surface.ts +++ b/src/mol-geo/representation/structure/representation/surface.ts @@ -11,9 +11,12 @@ import { Structure } from 'mol-model/structure'; import { MarkerAction } from '../../../util/marker-data'; import { Loci } from 'mol-model/loci'; import { PickingId } from '../../../util/picking'; +import { Task } from 'mol-task'; +import { GaussianDensityPointVisual, DefaultGaussianDensityPointProps } from '../visual/gaussian-density-point'; export const DefaultSurfaceProps = { ...DefaultGaussianSurfaceProps, + ...DefaultGaussianDensityPointProps, } export type SurfaceProps = typeof DefaultSurfaceProps @@ -21,27 +24,32 @@ export type SurfaceRepresentation = StructureRepresentation<SurfaceProps> export function SurfaceRepresentation(): SurfaceRepresentation { let currentProps: SurfaceProps - const gaussianRepr = UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual) + const gaussianSurfaceRepr = UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual) + const gaussianPointRepr = UnitsRepresentation('Gaussian point grid', GaussianDensityPointVisual) return { label: 'Surface', get renderObjects() { - return [ ...gaussianRepr.renderObjects ] + return [ ...gaussianSurfaceRepr.renderObjects, ...gaussianPointRepr.renderObjects ] }, get props() { - return { ...gaussianRepr.props } + return { ...gaussianSurfaceRepr.props, ...gaussianPointRepr.props } }, createOrUpdate: (props: Partial<SurfaceProps> = {}, structure?: Structure) => { currentProps = Object.assign({}, DefaultSurfaceProps, currentProps, props) - return gaussianRepr.createOrUpdate(currentProps, structure) + return Task.create('Creating SurfaceRepresentation', async ctx => { + await gaussianSurfaceRepr.createOrUpdate(currentProps, structure).runInContext(ctx) + await gaussianPointRepr.createOrUpdate(currentProps, structure).runInContext(ctx) + }) }, getLoci: (pickingId: PickingId) => { - return gaussianRepr.getLoci(pickingId) + return gaussianSurfaceRepr.getLoci(pickingId) }, mark: (loci: Loci, action: MarkerAction) => { - return gaussianRepr.mark(loci, action) + return gaussianSurfaceRepr.mark(loci, action) }, destroy() { - gaussianRepr.destroy() + gaussianSurfaceRepr.destroy() + gaussianPointRepr.destroy() } } } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/units-visual.ts b/src/mol-geo/representation/structure/units-visual.ts index e017c8494135ebee56678f719378cbd6e4abba51..b7feb79de7a9ed01693317afc8517d9d115857d3 100644 --- a/src/mol-geo/representation/structure/units-visual.ts +++ b/src/mol-geo/representation/structure/units-visual.ts @@ -5,20 +5,21 @@ */ import { Unit, Structure } from 'mol-model/structure'; -import { RepresentationProps, Visual } from '..'; -import { DefaultStructureMeshProps, MeshUpdateState } from '.'; +import { RepresentationProps, Visual } from '../'; +import { DefaultStructureMeshProps, VisualUpdateState, DefaultStructurePointProps } from '.'; import { RuntimeContext } from 'mol-task'; import { PickingId } from '../../util/picking'; import { LocationIterator } from '../../util/location-iterator'; -import { Mesh } from '../../mesh/mesh'; +import { Mesh } from '../../geometry/mesh/mesh'; import { MarkerAction, applyMarkerAction, createMarkers } from '../../util/marker-data'; import { Loci, isEveryLoci, EmptyLoci } from 'mol-model/loci'; -import { MeshRenderObject } from 'mol-gl/render-object'; -import { createUnitsMeshRenderObject, createColors } from './visual/util/common'; +import { MeshRenderObject, PointRenderObject } from 'mol-gl/render-object'; +import { createUnitsMeshRenderObject, createColors, createUnitsPointRenderObject } from './visual/util/common'; import { deepEqual, ValueCell, UUID } from 'mol-util'; -import { updateMeshValues, updateRenderableState } from '../util'; import { Interval } from 'mol-data/int'; import { createTransforms } from '../../util/transform-data'; +import { updateMeshValues, updateRenderableState, updatePointValues } from '../../geometry/geometry'; +import { Point } from '../../geometry/point/point'; export type StructureGroup = { structure: Structure, group: Unit.SymmetryGroup } @@ -36,12 +37,12 @@ export interface UnitsMeshVisualBuilder<P extends UnitsMeshProps> { createLocationIterator(group: Unit.SymmetryGroup): LocationIterator getLoci(pickingId: PickingId, group: Unit.SymmetryGroup, id: number): Loci mark(loci: Loci, group: Unit.SymmetryGroup, apply: (interval: Interval) => boolean): boolean - setUpdateState(state: MeshUpdateState, newProps: P, currentProps: P): void + setUpdateState(state: VisualUpdateState, newProps: P, currentProps: P): void } export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisualBuilder<P>): UnitsVisual<P> { const { defaultProps, createMesh, createLocationIterator, getLoci, mark, setUpdateState } = builder - const updateState = MeshUpdateState.create() + const updateState = VisualUpdateState.create() let renderObject: MeshRenderObject | undefined let currentProps: P @@ -75,20 +76,20 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu const unit = currentGroup.units[0] locationIt.reset() - MeshUpdateState.reset(updateState) + VisualUpdateState.reset(updateState) setUpdateState(updateState, newProps, currentProps) const newConformationId = Unit.conformationId(unit) if (newConformationId !== currentConformationId) { currentConformationId = newConformationId - updateState.createMesh = true + updateState.createGeometry = true } if (currentGroup.units.length !== locationIt.instanceCount) updateState.updateTransform = true - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.createMesh = true + if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.createGeometry = true if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateState.updateColor = true - if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createMesh = true + if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createGeometry = true // @@ -100,7 +101,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu updateState.updateColor = true } - if (updateState.createMesh) { + if (updateState.createGeometry) { mesh = newProps.unitKinds.includes(unit.kind) ? await createMesh(ctx, unit, currentStructure, newProps, mesh) : Mesh.createEmpty(mesh) @@ -112,8 +113,9 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) } - updateMeshValues(renderObject.values, newProps) - updateRenderableState(renderObject.state, newProps) + // TODO why do I need to cast here? + updateMeshValues(renderObject.values, newProps as UnitsMeshProps) + updateRenderableState(renderObject.state, newProps as UnitsMeshProps) currentProps = newProps } @@ -177,4 +179,155 @@ function sameGroupConformation(groupA: Unit.SymmetryGroup, groupB: Unit.Symmetry groupA.units.length === groupB.units.length && Unit.conformationId(groupA.units[0]) === Unit.conformationId(groupB.units[0]) ) +} + +// + +export const DefaultUnitsPointProps = { + ...DefaultStructurePointProps, + unitKinds: [ Unit.Kind.Atomic, Unit.Kind.Spheres ] as Unit.Kind[] +} +export type UnitsPointProps = typeof DefaultUnitsPointProps + +export interface UnitsPointVisualBuilder<P extends UnitsPointProps> { + defaultProps: P + createPoint(ctx: RuntimeContext, unit: Unit, structure: Structure, props: P, point?: Point): Promise<Point> + createLocationIterator(group: Unit.SymmetryGroup): LocationIterator + getLoci(pickingId: PickingId, group: Unit.SymmetryGroup, id: number): Loci + mark(loci: Loci, group: Unit.SymmetryGroup, apply: (interval: Interval) => boolean): boolean + setUpdateState(state: VisualUpdateState, newProps: P, currentProps: P): void +} + +export function UnitsPointVisual<P extends UnitsPointProps>(builder: UnitsPointVisualBuilder<P>): UnitsVisual<P> { + const { defaultProps, createPoint, createLocationIterator, getLoci, mark, setUpdateState } = builder + const updateState = VisualUpdateState.create() + + let renderObject: PointRenderObject | undefined + let currentProps: P + let point: Point + let currentGroup: Unit.SymmetryGroup + let currentStructure: Structure + let locationIt: LocationIterator + let currentConformationId: UUID + + async function create(ctx: RuntimeContext, group: Unit.SymmetryGroup, props: Partial<P> = {}) { + currentProps = Object.assign({}, defaultProps, props) + currentProps.colorTheme.structure = currentStructure + currentGroup = group + + const unit = group.units[0] + currentConformationId = Unit.conformationId(unit) + point = currentProps.unitKinds.includes(unit.kind) + ? await createPoint(ctx, unit, currentStructure, currentProps, point) + : Point.createEmpty(point) + + // TODO create empty location iterator when not in unitKinds + locationIt = createLocationIterator(group) + renderObject = await createUnitsPointRenderObject(ctx, group, point, locationIt, currentProps) + } + + async function update(ctx: RuntimeContext, props: Partial<P> = {}) { + if (!renderObject) return + + const newProps = Object.assign({}, currentProps, props) + newProps.colorTheme.structure = currentStructure + const unit = currentGroup.units[0] + + locationIt.reset() + VisualUpdateState.reset(updateState) + setUpdateState(updateState, newProps, currentProps) + + const newConformationId = Unit.conformationId(unit) + if (newConformationId !== currentConformationId) { + currentConformationId = newConformationId + updateState.createGeometry = true + } + + if (currentGroup.units.length !== locationIt.instanceCount) updateState.updateTransform = true + + if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateState.createGeometry = true + if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateState.updateColor = true + if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) updateState.createGeometry = true + + // + + if (updateState.updateTransform) { + locationIt = createLocationIterator(currentGroup) + const { instanceCount, groupCount } = locationIt + createTransforms(currentGroup, renderObject.values) + createMarkers(instanceCount * groupCount, renderObject.values) + updateState.updateColor = true + } + + if (updateState.createGeometry) { + point = newProps.unitKinds.includes(unit.kind) + ? await createPoint(ctx, unit, currentStructure, newProps, point) + : Point.createEmpty(point) + ValueCell.update(renderObject.values.drawCount, point.vertexCount) + updateState.updateColor = true + } + + if (updateState.updateColor) { + await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) + } + + // TODO why do I need to cast here? + updatePointValues(renderObject.values, newProps as UnitsPointProps) + updateRenderableState(renderObject.state, newProps as UnitsPointProps) + + currentProps = newProps + } + + return { + get renderObject () { return renderObject }, + async createOrUpdate(ctx: RuntimeContext, props: Partial<P> = {}, structureGroup?: StructureGroup) { + if (structureGroup) currentStructure = structureGroup.structure + const group = structureGroup ? structureGroup.group : undefined + if (!group && !currentGroup) { + throw new Error('missing group') + } else if (group && (!currentGroup || !renderObject)) { + // console.log('unit-visual first create') + await create(ctx, group, props) + } else if (group && group.hashCode !== currentGroup.hashCode) { + // console.log('unit-visual group.hashCode !== currentGroup.hashCode') + await create(ctx, group, props) + } else { + // console.log('unit-visual update') + if (group && !sameGroupConformation(group, currentGroup)) { + // console.log('unit-visual new conformation') + currentGroup = group + } + await update(ctx, props) + } + }, + getLoci(pickingId: PickingId) { + return renderObject ? getLoci(pickingId, currentGroup, renderObject.id) : EmptyLoci + }, + mark(loci: Loci, action: MarkerAction) { + if (!renderObject) return false + const { tMarker } = renderObject.values + const { groupCount, instanceCount } = locationIt + + function apply(interval: Interval) { + const start = Interval.start(interval) + const end = Interval.end(interval) + return applyMarkerAction(tMarker.ref.value.array, start, end, action) + } + + let changed = false + if (isEveryLoci(loci)) { + changed = apply(Interval.ofBounds(0, groupCount * instanceCount)) + } else { + changed = mark(loci, currentGroup, apply) + } + if (changed) { + ValueCell.update(tMarker, tMarker.ref.value) + } + return changed + }, + destroy() { + // TODO + renderObject = undefined + } + } } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts index 185835c629e4bcca92a85f02008992f9466199df..d4270f02ebad1f6632c44d65ea24c91c1a2ddfa2 100644 --- a/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/carbohydrate-link-cylinder.ts @@ -5,12 +5,11 @@ */ import { Unit, Structure, Link, StructureElement } from 'mol-model/structure'; -import { DefaultStructureProps, ComplexVisual, MeshUpdateState } from '..'; +import { DefaultStructureProps, ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; +import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { DefaultMeshProps } from '../../util'; import { Vec3 } from 'mol-math/linear-algebra'; import { LocationIterator } from '../../../util/location-iterator'; import { createLinkCylinderMesh, DefaultLinkCylinderProps, LinkCylinderProps } from './util/link'; @@ -19,6 +18,7 @@ import { ComplexMeshVisual } from '../complex-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { LinkType } from 'mol-model/structure/model/types'; import { BitFlags } from 'mol-util'; +import { DefaultMeshProps } from '../../../geometry/geometry'; // TODO create seperate visual // for (let i = 0, il = carbohydrates.terminalLinks.length; i < il; ++i) { @@ -77,8 +77,8 @@ export function CarbohydrateLinkVisual(): ComplexVisual<CarbohydrateLinkProps> { createLocationIterator: CarbohydrateLinkIterator, getLoci: getLinkLoci, mark: markLink, - setUpdateState: (state: MeshUpdateState, newProps: CarbohydrateLinkProps, currentProps: CarbohydrateLinkProps) => { - state.createMesh = newProps.radialSegments !== currentProps.radialSegments + setUpdateState: (state: VisualUpdateState, newProps: CarbohydrateLinkProps, currentProps: CarbohydrateLinkProps) => { + state.createGeometry = newProps.radialSegments !== currentProps.radialSegments } }) } diff --git a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts index 13d568ccb73cd097c659a36a8281c9e600b4aa85..fd6603b25e7caf6683e571e98638fc56141cbd52 100644 --- a/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts +++ b/src/mol-geo/representation/structure/visual/carbohydrate-symbol-mesh.ts @@ -5,19 +5,19 @@ */ import { Unit, Structure, StructureElement } from 'mol-model/structure'; -import { ComplexVisual, MeshUpdateState } from '..'; +import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; +import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; -import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { getSaccharideShape, SaccharideShapes } from 'mol-model/structure/structure/carbohydrates/constants'; import { LocationIterator } from '../../../util/location-iterator'; import { OrderedSet, Interval } from 'mol-data/int'; import { ComplexMeshVisual, DefaultComplexMeshProps } from '../complex-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; -import { addSphere } from '../../../mesh/builder/sphere'; +import { addSphere } from '../../../geometry/mesh/builder/sphere'; import { Box, PerforatedBox } from '../../../primitive/box'; import { OctagonalPyramid, PerforatedOctagonalPyramid } from '../../../primitive/pyramid'; import { Star } from '../../../primitive/star'; @@ -154,8 +154,8 @@ export function CarbohydrateSymbolVisual(): ComplexVisual<CarbohydrateSymbolProp createLocationIterator: CarbohydrateElementIterator, getLoci: getCarbohydrateLoci, mark: markCarbohydrate, - setUpdateState: (state: MeshUpdateState, newProps: CarbohydrateSymbolProps, currentProps: CarbohydrateSymbolProps) => { - state.createMesh = newProps.detail !== currentProps.detail + setUpdateState: (state: VisualUpdateState, newProps: CarbohydrateSymbolProps, currentProps: CarbohydrateSymbolProps) => { + state.createGeometry = newProps.detail !== currentProps.detail } }) } diff --git a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts index 735499fd290cee6d58f5213079613c20aed9d75b..f36e157eb43682d86e44021bb2ac3d658db7056c 100644 --- a/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/cross-link-restraint-cylinder.ts @@ -5,10 +5,10 @@ */ import { Link, Structure, StructureElement } from 'mol-model/structure'; -import { ComplexVisual, MeshUpdateState } from '..'; +import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh } from './util/link'; -import { Mesh } from '../../../mesh/mesh'; +import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; @@ -65,8 +65,8 @@ export function CrossLinkRestraintVisual(): ComplexVisual<CrossLinkRestraintProp createLocationIterator: CrossLinkRestraintIterator, getLoci: getLinkLoci, mark: markLink, - setUpdateState: (state: MeshUpdateState, newProps: CrossLinkRestraintProps, currentProps: CrossLinkRestraintProps) => { - state.createMesh = newProps.radialSegments !== currentProps.radialSegments + setUpdateState: (state: VisualUpdateState, newProps: CrossLinkRestraintProps, currentProps: CrossLinkRestraintProps) => { + state.createGeometry = newProps.radialSegments !== currentProps.radialSegments } }) } diff --git a/src/mol-geo/representation/structure/visual/element-point.ts b/src/mol-geo/representation/structure/visual/element-point.ts index eac5fb80226aad8dc30f67570d11f9c7469cdfe2..f624d11f10d49c0d3ec3b3009b3e24f421882e12 100644 --- a/src/mol-geo/representation/structure/visual/element-point.ts +++ b/src/mol-geo/representation/structure/visual/element-point.ts @@ -2,169 +2,56 @@ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> - * @author David Sehnal <david.sehnal@gmail.com> */ -import { ValueCell } from 'mol-util/value-cell' -import { PointRenderObject } from 'mol-gl/render-object' import { Unit, Structure } from 'mol-model/structure'; import { RuntimeContext } from 'mol-task' -import { UnitsVisual, DefaultStructureProps } from '..'; +import { UnitsVisual, VisualUpdateState } from '..'; import { getElementLoci, StructureElementIterator, markElement } from './util/element'; -import { createColors, createSizes, createUnitsPointRenderObject } from './util/common'; -import { deepEqual, UUID } from 'mol-util'; -import { Interval } from 'mol-data/int'; -import { PickingId } from '../../../util/picking'; -import { Loci, EmptyLoci, isEveryLoci } from 'mol-model/loci'; -import { MarkerAction, createMarkers, applyMarkerAction } from '../../../util/marker-data'; import { Vec3 } from 'mol-math/linear-algebra'; -import { fillSerial } from 'mol-util/array'; import { SizeThemeProps } from 'mol-view/theme/size'; -import { LocationIterator } from '../../../util/location-iterator'; -import { createTransforms } from '../../../util/transform-data'; -import { StructureGroup } from '../units-visual'; -import { updateRenderableState, updateBaseValues } from '../../util'; +import { UnitsPointVisual, DefaultUnitsPointProps } from '../units-visual'; +import { Point } from '../../../geometry/point/point'; +import { PointBuilder } from '../../../geometry/point/point-builder'; export const DefaultElementPointProps = { - ...DefaultStructureProps, + ...DefaultUnitsPointProps, sizeTheme: { name: 'uniform', value: 0.2 } as SizeThemeProps, pointSizeAttenuation: true, } -export type ElementPointProps = Partial<typeof DefaultElementPointProps> +export type ElementPointProps = typeof DefaultElementPointProps -export async function createElementPointVertices(ctx: RuntimeContext, unit: Unit, vertices?: ValueCell<Float32Array>) { +// TODO size + +export async function createElementPoint(ctx: RuntimeContext, unit: Unit, structure: Structure, props: ElementPointProps, point: Point) { const elements = unit.elements - const n = elements.length * 3 - const array = vertices && vertices.ref.value.length >= n ? vertices.ref.value : new Float32Array(n) + const n = elements.length + const builder = PointBuilder.create(n, n / 10, point) const pos = unit.conformation.invariantPosition - const p = Vec3.zero() - for (let i = 0; i < n; i += 3) { - pos(elements[i / 3], p) - array[i] = p[0] - array[i + 1] = p[1] - array[i + 2] = p[2] + + for (let i = 0; i < n; ++i) { + pos(elements[i], p) + builder.add(p[0], p[1], p[2], i) if (i % 10000 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'Creating points', current: i / 3, max: elements.length }); + await ctx.update({ message: 'Creating points', current: i, max: n }); } - ++i } - return vertices ? ValueCell.update(vertices, array) : ValueCell.create(array) + return builder.getPoint() } export function ElementPointVisual(): UnitsVisual<ElementPointProps> { - let renderObject: PointRenderObject | undefined - let currentProps = DefaultElementPointProps - let currentGroup: Unit.SymmetryGroup - let currentStructure: Structure - let locationIt: LocationIterator - let vertices: ValueCell<Float32Array> - let currentConformationId: UUID - - return { - get renderObject () { return renderObject }, - async createOrUpdate(ctx: RuntimeContext, props: ElementPointProps = {}, structureGroup?: StructureGroup) { - if (structureGroup) currentStructure = structureGroup.structure - const group = structureGroup ? structureGroup.group : undefined - if (!group && !currentGroup) { - throw new Error('missing group') - } else if (group && !currentGroup) { - currentProps = Object.assign({}, DefaultElementPointProps, props) - currentProps.colorTheme.structure = currentStructure - currentGroup = group - locationIt = StructureElementIterator.fromGroup(group) - - const unit = group.units[0] - currentConformationId = Unit.conformationId(unit) - vertices = await createElementPointVertices(ctx, unit, vertices) - - renderObject = await createUnitsPointRenderObject(ctx, group, vertices, locationIt, currentProps) - } else if (renderObject) { - if (group) currentGroup = group - - const newProps = { ...currentProps, ...props } - const unit = currentGroup.units[0] - - let updateTransform = false - let createVertices = false - let updateColor = false - let updateSize = false - - const newConformationId = Unit.conformationId(unit) - if (newConformationId !== currentConformationId) { - currentConformationId = newConformationId - createVertices = true - } - - if (currentGroup.units.length !== locationIt.instanceCount) updateTransform = true + return UnitsPointVisual<ElementPointProps>({ + defaultProps: DefaultElementPointProps, + createPoint: createElementPoint, + createLocationIterator: StructureElementIterator.fromGroup, + getLoci: getElementLoci, + mark: markElement, + setUpdateState: (state: VisualUpdateState, newProps: ElementPointProps, currentProps: ElementPointProps) => { - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) createVertices = true - if (!deepEqual(newProps.colorTheme, currentProps.colorTheme)) updateColor = true - if (!deepEqual(newProps.sizeTheme, currentProps.sizeTheme)) updateSize = true - - if (updateTransform) { - locationIt = StructureElementIterator.fromGroup(currentGroup) - const { instanceCount, groupCount } = locationIt - createTransforms(currentGroup, renderObject.values) - createMarkers(instanceCount * groupCount, renderObject.values) - updateColor = true - updateSize = true - } - - if (createVertices) { - await createElementPointVertices(ctx, unit, vertices) - ValueCell.update(renderObject.values.aGroup, fillSerial(new Float32Array(locationIt.groupCount))) // TODO reuse array - ValueCell.update(renderObject.values.drawCount, locationIt.groupCount) - updateColor = true - updateSize = true - } - - if (updateColor) { - await createColors(ctx, locationIt, newProps.colorTheme, renderObject.values) - } - - if (updateSize) { - await createSizes(ctx, locationIt, newProps.sizeTheme, renderObject.values) - } - - updateBaseValues(renderObject.values, newProps) - updateRenderableState(renderObject.state, newProps) - - currentProps = newProps - } - }, - getLoci(pickingId: PickingId) { - return renderObject ? getElementLoci(pickingId, currentGroup, renderObject.id) : EmptyLoci - }, - mark(loci: Loci, action: MarkerAction) { - if (!renderObject) return false - const { tMarker } = renderObject.values - const { groupCount, instanceCount } = locationIt - - function apply(interval: Interval) { - const start = Interval.start(interval) - const end = Interval.end(interval) - return applyMarkerAction(tMarker.ref.value.array, start, end, action) - } - - let changed = false - if (isEveryLoci(loci)) { - apply(Interval.ofBounds(0, groupCount * instanceCount)) - changed = true - } else { - changed = markElement(loci, currentGroup, apply) - } - if (changed) { - ValueCell.update(tMarker, tMarker.ref.value) - } - return changed - }, - destroy() { - // TODO - renderObject = undefined } - } -} + }) +} \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/element-sphere.ts b/src/mol-geo/representation/structure/visual/element-sphere.ts index 523e19e1e3d62d8cc1a0c0ce6c3d1fdc4b699c14..62a59004bb7393a0220bfc8d46c1b5e2e213242f 100644 --- a/src/mol-geo/representation/structure/visual/element-sphere.ts +++ b/src/mol-geo/representation/structure/visual/element-sphere.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { UnitsVisual, MeshUpdateState } from '..'; +import { UnitsVisual, VisualUpdateState } from '..'; import { createElementSphereMesh, markElement, getElementLoci, StructureElementIterator } from './util/element'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; @@ -22,8 +22,8 @@ export function ElementSphereVisual(): UnitsVisual<ElementSphereProps> { createLocationIterator: StructureElementIterator.fromGroup, getLoci: getElementLoci, mark: markElement, - setUpdateState: (state: MeshUpdateState, newProps: ElementSphereProps, currentProps: ElementSphereProps) => { - state.createMesh = newProps.detail !== currentProps.detail + setUpdateState: (state: VisualUpdateState, newProps: ElementSphereProps, currentProps: ElementSphereProps) => { + state.createGeometry = newProps.detail !== currentProps.detail } }) } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/gaussian-density-point.ts b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts new file mode 100644 index 0000000000000000000000000000000000000000..7bc2d1c9d671bad4c69321708b4b25ea99af4621 --- /dev/null +++ b/src/mol-geo/representation/structure/visual/gaussian-density-point.ts @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Unit, Structure } from 'mol-model/structure'; +import { RuntimeContext } from 'mol-task' +import { UnitsVisual, VisualUpdateState } from '..'; +import { StructureElementIterator } from './util/element'; +import { EmptyLoci } from 'mol-model/loci'; +import { Vec3 } from 'mol-math/linear-algebra'; +import { SizeThemeProps } from 'mol-view/theme/size'; +import { UnitsPointVisual, DefaultUnitsPointProps } from '../units-visual'; +import { computeGaussianDensity } from './util/gaussian'; +import { Color } from 'mol-util/color'; +import { ColorThemeProps } from 'mol-view/theme/color'; +import { Point } from '../../../geometry/point/point'; +import { PointBuilder } from '../../../geometry/point/point-builder'; + +export const DefaultGaussianDensityPointProps = { + ...DefaultUnitsPointProps, + + sizeTheme: { name: 'uniform', value: 1.5 } as SizeThemeProps, + colorTheme: { name: 'uniform', value: Color(0xAAAAAA) } as ColorThemeProps, + pointSizeAttenuation: false, + + resolutionFactor: 7, + probeRadius: 0, + isoValue: 1.5, +} +export type GaussianDensityPointProps = typeof DefaultGaussianDensityPointProps + +export interface GaussianDensityProps { + sizeTheme: SizeThemeProps + + resolutionFactor: number + probeRadius: number + isoValue: number +} + +export async function createGaussianDensityPoint(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps, point?: Point) { + const { transform, field: { space, data } } = await computeGaussianDensity(unit, structure, props).runAsChild(ctx) + + const { dimensions, get } = space + const [ xn, yn, zn ] = dimensions + + const n = xn * yn * zn * 3 + const builder = PointBuilder.create(n, n / 10, point) + + const p = Vec3.zero() + let i = 0 + + for (let x = 0; x < xn; ++x) { + for (let y = 0; y < yn; ++y) { + for (let z = 0; z < zn; ++z) { + if (get(data, x, y, z) > 0.001) { + Vec3.set(p, x, y, z) + Vec3.transformMat4(p, p, transform) + builder.add(p[0], p[1], p[2], i) + } + if (i % 100000 === 0 && ctx.shouldUpdate) { + await ctx.update({ message: 'Creating density points', current: i, max: n }); + } + ++i + } + } + } + return builder.getPoint() +} + +export function GaussianDensityPointVisual(): UnitsVisual<GaussianDensityPointProps> { + return UnitsPointVisual<GaussianDensityPointProps>({ + defaultProps: DefaultGaussianDensityPointProps, + createPoint: createGaussianDensityPoint, + createLocationIterator: StructureElementIterator.fromGroup, + getLoci: () => EmptyLoci, + mark: () => false, + setUpdateState: (state: VisualUpdateState, newProps: GaussianDensityPointProps, currentProps: GaussianDensityPointProps) => { + + } + }) +} \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts index f966d5076ce7949b6309f33eea7095e8302b7da6..8966ca864a445e4ae546d338d66a73f151c231af 100644 --- a/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-geo/representation/structure/visual/gaussian-surface-mesh.ts @@ -4,17 +4,17 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Unit, Structure, StructureElement } from 'mol-model/structure'; -import { UnitsVisual, MeshUpdateState } from '..'; +import { Unit, Structure } from 'mol-model/structure'; +import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; +import { Mesh } from '../../../geometry/mesh/mesh'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; import { StructureElementIterator, getElementLoci, markElement } from './util/element'; import { computeMarchingCubes } from '../../../util/marching-cubes/algorithm'; -import { Tensor, Vec3, Mat4 } from 'mol-math/linear-algebra'; -import { Box3D } from 'mol-math/geometry'; -import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; +import { SizeThemeProps } from 'mol-view/theme/size'; import { Color } from 'mol-util/color'; +import { computeGaussianDensity } from './util/gaussian'; +import { ColorThemeProps } from 'mol-view/theme/color'; export interface GaussianSurfaceMeshProps { sizeTheme: SizeThemeProps @@ -24,116 +24,22 @@ export interface GaussianSurfaceMeshProps { isoValue: number } -function getDelta(box: Box3D, resolutionFactor: number) { - const extent = Vec3.sub(Vec3.zero(), box.max, box.min) - - const n = Math.pow(Math.pow(2, resolutionFactor), 3) - const f = (extent[0] * extent[1] * extent[2]) / n - const s = Math.pow(f, 1 / 3) - const size = Vec3.zero() - // Vec3.scale(size, extent, s) - Vec3.ceil(size, Vec3.scale(size, extent, s)) - const delta = Vec3.div(Vec3.zero(), extent, size) - return delta -} - async function createGaussianSurfaceMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianSurfaceMeshProps, mesh?: Mesh): Promise<Mesh> { - const { resolutionFactor, probeRadius, isoValue } = props - - const { elements } = unit; - const elementCount = elements.length; - const sizeTheme = SizeTheme(props.sizeTheme) - - const v = Vec3.zero() - const p = Vec3.zero() - const pos = unit.conformation.invariantPosition - const l = StructureElement.create() - l.unit = unit - - const pad = (probeRadius + 2) * 2 // TODO calculate max radius - const box = unit.lookup3d.boundary.box - const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad)); - const extent = Vec3.sub(Vec3.zero(), expandedBox.max, expandedBox.min) - const min = expandedBox.min - - // const n = Math.pow(128, 3) - // const f = (extent[0] * extent[1] * extent[2]) / n - // const s = Math.pow(f, 1 / 3) - // const size = Vec3.zero() - // // Vec3.scale(size, extent, s) - // Vec3.ceil(size, Vec3.scale(size, extent, s)) - // const delta = Vec3.div(Vec3.zero(), extent, size) - - // console.log('extent', extent) - // console.log('n', n) - // console.log('f', f) - // console.log('s', s) - // console.log('size', size) - // console.log('delta', delta) - const delta = getDelta(Box3D.expand(Box3D.empty(), structure.boundary.box, Vec3.create(pad, pad, pad)), resolutionFactor) - const dim = Vec3.zero() - Vec3.ceil(dim, Vec3.mul(dim, extent, delta)) - // console.log('dim', dim, dim[0] * dim[1] * dim[2]) - - const space = Tensor.Space(dim, [0, 1, 2], Float32Array) - const data = space.create() - const field = Tensor.create(space, data) - - const c = Vec3.zero() - - const radius2 = Vec3.scale(Vec3.zero(), delta, 2) - const alpha = 1.5 // smoothness + const { isoValue } = props console.time('surface density') - for (let i = 0; i < elementCount; i++) { - l.element = elements[i] - pos(elements[i], v) - - Vec3.sub(v, v, min) - Vec3.mul(c, v, delta) - - const radius = sizeTheme.size(l) // + probeRadius - - const minX = Math.floor(c[0] - radius2[0]) - 1 - const minY = Math.floor(c[1] - radius2[1]) - 1 - const minZ = Math.floor(c[2] - radius2[2]) - 1 - const maxX = Math.ceil(c[0] + radius2[0]) + 1 - const maxY = Math.ceil(c[1] + radius2[1]) + 1 - const maxZ = Math.ceil(c[2] + radius2[2]) + 1 - - for (let x = minX; x < maxX; ++x) { - for (let y = minY; y < maxY; ++y) { - for (let z = minZ; z < maxZ; ++z) { - Vec3.set(p, x, y, z) - Vec3.div(p, p, delta) - const dist = Vec3.distance(p, v) - const density = Math.exp(-alpha * Math.pow((dist) / radius, 2)) - space.set(data, x, y, z, space.get(data, x, y, z) + density) - } - } - } - - if (i % 100 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'Gaussian surface', current: i, max: elementCount }); - } - } + const { transform, field } = await computeGaussianDensity(unit, structure, props).runAsChild(ctx) console.timeEnd('surface density') - // console.log('data', data) - console.time('surface mc') const surface = await computeMarchingCubes({ - isoLevel: isoValue * Math.exp(-alpha), + isoLevel: Math.exp(-isoValue), scalarField: field, oldSurface: mesh }).runAsChild(ctx) console.timeEnd('surface mc') - const t = Mat4.identity() - Mat4.fromScaling(t, Vec3.inverse(Vec3.zero(), delta)) - Mat4.setTranslation(t, expandedBox.min) - - Mesh.transformImmediate(surface, t) + Mesh.transformImmediate(surface, transform) Mesh.computeNormalsImmediate(surface) return surface; @@ -149,11 +55,11 @@ export const DefaultGaussianSurfaceProps = { flipSided: true, // flatShaded: true, alpha: 0.7, - colorTheme: { name: 'uniform' as 'uniform', value: Color(0xDDDDDD) }, + colorTheme: { name: 'uniform' as 'uniform', value: Color(0xDDDDDD) } as ColorThemeProps, resolutionFactor: 7, - probeRadius: 1.4, - isoValue: 1, + probeRadius: 0, + isoValue: 1.5, } export type GaussianSurfaceProps = typeof DefaultGaussianSurfaceProps @@ -164,10 +70,10 @@ export function GaussianSurfaceVisual(): UnitsVisual<GaussianSurfaceProps> { createLocationIterator: StructureElementIterator.fromGroup, getLoci: getElementLoci, mark: markElement, - setUpdateState: (state: MeshUpdateState, newProps: GaussianSurfaceProps, currentProps: GaussianSurfaceProps) => { - if (newProps.resolutionFactor !== currentProps.resolutionFactor) state.createMesh = true - if (newProps.probeRadius !== currentProps.probeRadius) state.createMesh = true - if (newProps.isoValue !== currentProps.isoValue) state.createMesh = true + setUpdateState: (state: VisualUpdateState, newProps: GaussianSurfaceProps, currentProps: GaussianSurfaceProps) => { + if (newProps.resolutionFactor !== currentProps.resolutionFactor) state.createGeometry = true + if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true + if (newProps.isoValue !== currentProps.isoValue) state.createGeometry = true } }) } \ No newline at end of file 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 44469dacff2b8bc4587e8cdb89ce9da3a15b4bff..91fac0b244bbbe0d56cfe65f1abbb20deacd925d 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 @@ -5,10 +5,10 @@ */ import { Link, Structure, StructureElement } from 'mol-model/structure'; -import { ComplexVisual, MeshUpdateState } from '..'; +import { ComplexVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { LinkCylinderProps, DefaultLinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link'; -import { Mesh } from '../../../mesh/mesh'; +import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; @@ -63,8 +63,8 @@ export function InterUnitLinkVisual(): ComplexVisual<InterUnitLinkProps> { createLocationIterator: LinkIterator.fromStructure, getLoci: getLinkLoci, mark: markLink, - setUpdateState: (state: MeshUpdateState, newProps: InterUnitLinkProps, currentProps: InterUnitLinkProps) => { - state.createMesh = newProps.radialSegments !== currentProps.radialSegments + setUpdateState: (state: VisualUpdateState, newProps: InterUnitLinkProps, currentProps: InterUnitLinkProps) => { + state.createGeometry = newProps.radialSegments !== currentProps.radialSegments } }) } 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 a3d6dd8687bc1624fd75fb2b45c2a96e383af1c8..8ec45a83d67947576d6647137b871bcf71471d00 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 @@ -6,10 +6,10 @@ */ import { Unit, Link, StructureElement, Structure } from 'mol-model/structure'; -import { UnitsVisual, MeshUpdateState } from '..'; +import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' import { DefaultLinkCylinderProps, LinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link'; -import { Mesh } from '../../../mesh/mesh'; +import { Mesh } from '../../../geometry/mesh/mesh'; import { PickingId } from '../../../util/picking'; import { Vec3 } from 'mol-math/linear-algebra'; import { Loci, EmptyLoci } from 'mol-model/loci'; @@ -77,8 +77,8 @@ export function IntraUnitLinkVisual(): UnitsVisual<IntraUnitLinkProps> { createLocationIterator: LinkIterator.fromGroup, getLoci: getLinkLoci, mark: markLink, - setUpdateState: (state: MeshUpdateState, newProps: LinkCylinderProps, currentProps: LinkCylinderProps) => { - state.createMesh = newProps.radialSegments !== currentProps.radialSegments + setUpdateState: (state: VisualUpdateState, newProps: LinkCylinderProps, currentProps: LinkCylinderProps) => { + state.createGeometry = newProps.radialSegments !== currentProps.radialSegments } }) } diff --git a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts index 82387af83fe0a284eebadd7a38b129219606807e..48733329c73d40cc64bb6eb23416b73826b69375 100644 --- a/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-geo/representation/structure/visual/nucleotide-block-mesh.ts @@ -7,14 +7,14 @@ import { Unit, Structure } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; -import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { Mesh } from '../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { Segmentation } from 'mol-data/int'; import { MoleculeType, isNucleic, isPurinBase, isPyrimidineBase } from 'mol-model/structure/model/types'; import { getElementIndexForAtomId, getElementIndexForAtomRole } from 'mol-model/structure/util'; import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; -import { addCylinder } from '../../../mesh/builder/cylinder'; +import { addCylinder } from '../../../geometry/mesh/builder/cylinder'; import { Box } from '../../../primitive/box'; import { NucleotideLocationIterator, markNucleotideElement, getNucleotideElementLoci } from './util/nucleotide'; diff --git a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts index cd9ca682c0cab90544d44ab88e7958a4858ef956..db7428205695bdcc41335eb12be0c7123fe235d6 100644 --- a/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-backbone-cylinder.ts @@ -5,10 +5,10 @@ */ import { Unit, Structure } from 'mol-model/structure'; -import { UnitsVisual, MeshUpdateState } from '..'; +import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; -import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { Mesh } from '../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerBackboneIterator } from './util/polymer'; import { getElementLoci, markElement, StructureElementIterator } from './util/element'; import { Vec3 } from 'mol-math/linear-algebra'; @@ -16,7 +16,7 @@ import { DefaultUnitsMeshProps, UnitsMeshVisual } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { CylinderProps } from '../../../primitive/cylinder'; import { OrderedSet } from 'mol-data/int'; -import { addCylinder } from '../../../mesh/builder/cylinder'; +import { addCylinder } from '../../../geometry/mesh/builder/cylinder'; export interface PolymerBackboneCylinderProps { sizeTheme: SizeThemeProps @@ -77,8 +77,8 @@ export function PolymerBackboneVisual(): UnitsVisual<PolymerBackboneProps> { createLocationIterator: StructureElementIterator.fromGroup, getLoci: getElementLoci, mark: markElement, - setUpdateState: (state: MeshUpdateState, newProps: PolymerBackboneProps, currentProps: PolymerBackboneProps) => { - state.createMesh = newProps.radialSegments !== currentProps.radialSegments + setUpdateState: (state: VisualUpdateState, newProps: PolymerBackboneProps, currentProps: PolymerBackboneProps) => { + state.createGeometry = newProps.radialSegments !== currentProps.radialSegments } }) } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts index ddd31a67d6970f1b0e00416461a4a57fd7d79d40..0b6f96f8844ee94c01e37a7ab5efad3df5fbf4f0 100644 --- a/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts +++ b/src/mol-geo/representation/structure/visual/polymer-direction-wedge.ts @@ -7,8 +7,8 @@ import { Unit, Structure } from 'mol-model/structure'; import { UnitsVisual } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; -import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { Mesh } from '../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer'; import { Vec3, Mat4 } from 'mol-math/linear-algebra'; import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types'; diff --git a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts index 21ebafc2d3ffd91d4160defa3e9412568df14d86..cab4cd3940e72cad0ea9b5394c1c95435b47aad4 100644 --- a/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts +++ b/src/mol-geo/representation/structure/visual/polymer-gap-cylinder.ts @@ -5,17 +5,17 @@ */ import { Unit, Structure } from 'mol-model/structure'; -import { UnitsVisual, MeshUpdateState } from '..'; +import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; -import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { Mesh } from '../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerGapIterator, PolymerGapLocationIterator, markPolymerGapElement, getPolymerGapElementLoci } from './util/polymer'; import { Vec3 } from 'mol-math/linear-algebra'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { CylinderProps } from '../../../primitive/cylinder'; -import { addSphere } from '../../../mesh/builder/sphere'; -import { addFixedCountDashedCylinder } from '../../../mesh/builder/cylinder'; +import { addSphere } from '../../../geometry/mesh/builder/sphere'; +import { addFixedCountDashedCylinder } from '../../../geometry/mesh/builder/cylinder'; const segmentCount = 10 @@ -84,8 +84,8 @@ export function PolymerGapVisual(): UnitsVisual<PolymerGapProps> { createLocationIterator: PolymerGapLocationIterator.fromGroup, getLoci: getPolymerGapElementLoci, mark: markPolymerGapElement, - setUpdateState: (state: MeshUpdateState, newProps: PolymerGapProps, currentProps: PolymerGapProps) => { - state.createMesh = newProps.radialSegments !== currentProps.radialSegments + setUpdateState: (state: VisualUpdateState, newProps: PolymerGapProps, currentProps: PolymerGapProps) => { + state.createGeometry = newProps.radialSegments !== currentProps.radialSegments } }) } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts index 186f374e1ad71d661731431b3e9f100b6f690e63..6ecfa05d443b4bd7e725898ad697ca32b0f287be 100644 --- a/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-geo/representation/structure/visual/polymer-trace-mesh.ts @@ -5,16 +5,16 @@ */ import { Unit, Structure } from 'mol-model/structure'; -import { UnitsVisual, MeshUpdateState } from '..'; +import { UnitsVisual, VisualUpdateState } from '..'; import { RuntimeContext } from 'mol-task' -import { Mesh } from '../../../mesh/mesh'; -import { MeshBuilder } from '../../../mesh/mesh-builder'; +import { Mesh } from '../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../geometry/mesh/mesh-builder'; import { PolymerTraceIterator, createCurveSegmentState, interpolateCurveSegment, PolymerLocationIterator, getPolymerElementLoci, markPolymerElement } from './util/polymer'; import { SecondaryStructureType, isNucleic } from 'mol-model/structure/model/types'; import { UnitsMeshVisual, DefaultUnitsMeshProps } from '../units-visual'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; -import { addSheet } from '../../../mesh/builder/sheet'; -import { addTube } from '../../../mesh/builder/tube'; +import { addSheet } from '../../../geometry/mesh/builder/sheet'; +import { addTube } from '../../../geometry/mesh/builder/tube'; export interface PolymerTraceMeshProps { sizeTheme: SizeThemeProps @@ -97,8 +97,8 @@ export function PolymerTraceVisual(): UnitsVisual<PolymerTraceProps> { createLocationIterator: PolymerLocationIterator.fromGroup, getLoci: getPolymerElementLoci, mark: markPolymerElement, - setUpdateState: (state: MeshUpdateState, newProps: PolymerTraceProps, currentProps: PolymerTraceProps) => { - state.createMesh = ( + setUpdateState: (state: VisualUpdateState, newProps: PolymerTraceProps, currentProps: PolymerTraceProps) => { + state.createGeometry = ( newProps.linearSegments !== currentProps.linearSegments || newProps.radialSegments !== currentProps.radialSegments || newProps.aspectRatio !== currentProps.aspectRatio || diff --git a/src/mol-geo/representation/structure/visual/util/common.ts b/src/mol-geo/representation/structure/visual/util/common.ts index 0dfb1317bd369f48ba0ec9f8590f0811f3cdba6b..1377c9cd97ed38a41c676cf841cac568e5a36463 100644 --- a/src/mol-geo/representation/structure/visual/util/common.ts +++ b/src/mol-geo/representation/structure/visual/util/common.ts @@ -8,12 +8,10 @@ import { Unit, Structure } from 'mol-model/structure'; import { createUniformColor, ColorData, createGroupColor, createGroupInstanceColor, createInstanceColor, ColorType } from '../../../../util/color-data'; import { createUniformSize, SizeData, createGroupSize, createGroupInstanceSize, createInstanceSize, SizeType } from '../../../../util/size-data'; -import { ValueCell } from 'mol-util'; import { LocationIterator } from '../../../../util/location-iterator'; -import { Mesh } from '../../../../mesh/mesh'; +import { Mesh } from '../../../../geometry/mesh/mesh'; import { MeshValues, PointValues } from 'mol-gl/renderable'; import { getMeshData } from '../../../../util/mesh-data'; -import { MeshProps, createMeshValues, createRenderableState, createPointValues } from '../../../util'; import { StructureProps } from '../..'; import { createMarkers } from '../../../../util/marker-data'; import { createMeshRenderObject, createPointRenderObject } from 'mol-gl/render-object'; @@ -21,8 +19,10 @@ import { ColorThemeProps, ColorTheme } from 'mol-view/theme/color'; import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; import { RuntimeContext } from 'mol-task'; import { PointProps } from 'mol-geo/representation/structure/representation/point'; -import { fillSerial } from 'mol-util/array'; import { TransformData, createIdentityTransform, createTransforms } from '../../../../util/transform-data'; +import { Point } from '../../../../geometry/point/point'; +import { getPointData } from '../../../../util/point-data'; +import { MeshProps, createMeshValues, createRenderableState, createPointValues } from '../../../../geometry/geometry'; function getGranularity(locationIt: LocationIterator, granularity: ColorType | SizeType) { // Always use 'group' granularity for 'complex' location iterators, @@ -52,7 +52,7 @@ export async function createSizes(ctx: RuntimeContext, locationIt: LocationItera // mesh -type StructureMeshProps = Required<MeshProps & StructureProps> +type StructureMeshProps = MeshProps & StructureProps async function _createMeshValues(ctx: RuntimeContext, transforms: TransformData, mesh: Mesh, locationIt: LocationIterator, props: StructureMeshProps): Promise<MeshValues> { const { instanceCount, groupCount } = locationIt @@ -100,19 +100,18 @@ export async function updateComplexMeshRenderObject(ctx: RuntimeContext, structu // point -type StructurePointProps = Required<PointProps & StructureProps> +type StructurePointProps = PointProps & StructureProps -async function _createPointValues(ctx: RuntimeContext, transforms: TransformData, vertices: ValueCell<Float32Array>, locationIt: LocationIterator, props: StructurePointProps): Promise<PointValues> { +async function _createPointValues(ctx: RuntimeContext, transforms: TransformData, point: Point, locationIt: LocationIterator, props: StructurePointProps): Promise<PointValues> { const { instanceCount, groupCount } = locationIt const color = await createColors(ctx, locationIt, props.colorTheme) const size = await createSizes(ctx, locationIt, props.sizeTheme) const marker = createMarkers(instanceCount * groupCount) - const counts = { drawCount: groupCount, groupCount, instanceCount } + const counts = { drawCount: point.vertexCount, groupCount, instanceCount } return { - aPosition: vertices, - aGroup: ValueCell.create(fillSerial(new Float32Array(groupCount))), + ...getPointData(point), ...color, ...size, ...marker, @@ -121,13 +120,13 @@ async function _createPointValues(ctx: RuntimeContext, transforms: TransformData } } -export async function createUnitsPointValues(ctx: RuntimeContext, group: Unit.SymmetryGroup, vertices: ValueCell<Float32Array>, locationIt: LocationIterator, props: StructurePointProps): Promise<PointValues> { +export async function createUnitsPointValues(ctx: RuntimeContext, group: Unit.SymmetryGroup, point: Point, locationIt: LocationIterator, props: StructurePointProps): Promise<PointValues> { const transforms = createTransforms(group) - return _createPointValues(ctx, transforms, vertices, locationIt, props) + return _createPointValues(ctx, transforms, point, locationIt, props) } -export async function createUnitsPointRenderObject(ctx: RuntimeContext, group: Unit.SymmetryGroup, vertices: ValueCell<Float32Array>, locationIt: LocationIterator, props: StructurePointProps) { - const values = await createUnitsPointValues(ctx, group, vertices, locationIt, props) +export async function createUnitsPointRenderObject(ctx: RuntimeContext, group: Unit.SymmetryGroup, point: Point, locationIt: LocationIterator, props: StructurePointProps) { + const values = await createUnitsPointValues(ctx, group, point, locationIt, props) const state = createRenderableState(props) return createPointRenderObject(values, state) } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/util/element.ts b/src/mol-geo/representation/structure/visual/util/element.ts index 6887addab337f1956adcb4c1645e2586c9bbd4ab..28d4f1add33e11152269038cf6aedc4052ba5851 100644 --- a/src/mol-geo/representation/structure/visual/util/element.ts +++ b/src/mol-geo/representation/structure/visual/util/element.ts @@ -8,14 +8,14 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { Unit, StructureElement, Structure } from 'mol-model/structure'; import { RuntimeContext } from 'mol-task'; import { sphereVertexCount } from '../../../../primitive/sphere'; -import { Mesh } from '../../../../mesh/mesh'; -import { MeshBuilder } from '../../../../mesh/mesh-builder'; +import { Mesh } from '../../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../../geometry/mesh/mesh-builder'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { Interval, OrderedSet } from 'mol-data/int'; import { PickingId } from '../../../../util/picking'; import { SizeTheme, SizeThemeProps } from 'mol-view/theme/size'; import { LocationIterator } from '../../../../util/location-iterator'; -import { addSphere } from '../../../../mesh/builder/sphere'; +import { addSphere } from '../../../../geometry/mesh/builder/sphere'; export interface ElementSphereMeshProps { sizeTheme: SizeThemeProps, diff --git a/src/mol-geo/representation/structure/visual/util/gaussian.ts b/src/mol-geo/representation/structure/visual/util/gaussian.ts new file mode 100644 index 0000000000000000000000000000000000000000..1607bbb7fb3f71ce0a4e5d0998da9fa1c05289de --- /dev/null +++ b/src/mol-geo/representation/structure/visual/util/gaussian.ts @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Unit, Structure, StructureElement } from 'mol-model/structure'; +import { RuntimeContext, Task } from 'mol-task' +import { Tensor, Vec3, Mat4 } from 'mol-math/linear-algebra'; +import { Box3D } from 'mol-math/geometry'; +import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size'; + +export interface GaussianDensityProps { + sizeTheme: SizeThemeProps + + resolutionFactor: number + probeRadius: number + isoValue: number +} + +function getDelta(box: Box3D, resolutionFactor: number) { + const extent = Vec3.sub(Vec3.zero(), box.max, box.min) + + const n = Math.pow(Math.pow(2, resolutionFactor), 3) + const f = (extent[0] * extent[1] * extent[2]) / n + const s = Math.pow(f, 1 / 3) + const size = Vec3.zero() + // Vec3.scale(size, extent, s) + Vec3.ceil(size, Vec3.scale(size, extent, s)) + const delta = Vec3.div(Vec3.zero(), extent, size) + return delta +} + +type Density = { transform: Mat4, field: Tensor } + +export function computeGaussianDensity(unit: Unit, structure: Structure, props: GaussianDensityProps) { + return Task.create('Gaussian Density', async ctx => { + return await GaussianDensity(ctx, unit, structure, props); + }); +} + +export async function GaussianDensity(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianDensityProps): Promise<Density> { + const { resolutionFactor, probeRadius, isoValue } = props + + const { elements } = unit; + const elementCount = elements.length; + const sizeTheme = SizeTheme(props.sizeTheme) + + const v = Vec3.zero() + const p = Vec3.zero() + const pos = unit.conformation.invariantPosition + const l = StructureElement.create(unit) + + const pad = (probeRadius + 3) * 3 // TODO calculate max radius + const box = unit.lookup3d.boundary.box + const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(pad, pad, pad)); + const extent = Vec3.sub(Vec3.zero(), expandedBox.max, expandedBox.min) + const min = expandedBox.min + + const delta = getDelta(Box3D.expand(Box3D.empty(), structure.boundary.box, Vec3.create(pad, pad, pad)), resolutionFactor) + const dim = Vec3.zero() + Vec3.ceil(dim, Vec3.mul(dim, extent, delta)) + + const space = Tensor.Space(dim, [0, 1, 2], Float32Array) + const data = space.create() + const field = Tensor.create(space, data) + + const c = Vec3.zero() + + const alpha = isoValue // smoothness + + const _r2 = (probeRadius + 1.4 * 2) + const _radius2 = Vec3.create(_r2, _r2, _r2) + Vec3.mul(_radius2, _radius2, delta) + const updateChunk = Math.ceil(10000 / (_radius2[0] * _radius2[1] * _radius2[2])) + + const beg = Vec3.zero() + const end = Vec3.zero() + + for (let i = 0; i < elementCount; i++) { + l.element = elements[i] + pos(elements[i], v) + + Vec3.sub(v, v, min) + Vec3.mul(c, v, delta) + + const radius = sizeTheme.size(l) + probeRadius + const rSq = radius * radius + + const r2 = (probeRadius + radius * 2) + const radius2 = Vec3.create(r2, r2, r2) + Vec3.mul(radius2, radius2, delta) + const r2sq = r2 * r2 + + const [ begX, begY, begZ ] = Vec3.floor(beg, Vec3.sub(beg, c, radius2)) + const [ endX, endY, endZ ] = Vec3.ceil(end, Vec3.add(end, c, radius2)) + + for (let x = begX; x < endX; ++x) { + for (let y = begY; y < endY; ++y) { + for (let z = begZ; z < endZ; ++z) { + Vec3.set(p, x, y, z) + Vec3.div(p, p, delta) + const distSq = Vec3.squaredDistance(p, v) + if (distSq <= r2sq) { + space.add(data, x, y, z, Math.exp(-alpha * (distSq / rSq))) + } + } + } + } + + if (i % updateChunk === 0 && ctx.shouldUpdate) { + await ctx.update({ message: 'filling density grid', current: i, max: elementCount }); + } + } + + const t = Mat4.identity() + Mat4.fromScaling(t, Vec3.inverse(Vec3.zero(), delta)) + Mat4.setTranslation(t, expandedBox.min) + + return { + field, + transform: t + } +} \ No newline at end of file diff --git a/src/mol-geo/representation/structure/visual/util/link.ts b/src/mol-geo/representation/structure/visual/util/link.ts index ca73e55b9cb017173c7cb9af15701e7aff21a1fc..b218c9cf2420e8da986886068bb0bb6349e22d50 100644 --- a/src/mol-geo/representation/structure/visual/util/link.ts +++ b/src/mol-geo/representation/structure/visual/util/link.ts @@ -6,15 +6,15 @@ import { Vec3 } from 'mol-math/linear-algebra'; import { RuntimeContext } from 'mol-task'; -import { Mesh } from '../../../../mesh/mesh'; -import { MeshBuilder } from '../../../../mesh/mesh-builder'; +import { Mesh } from '../../../../geometry/mesh/mesh'; +import { MeshBuilder } from '../../../../geometry/mesh/mesh-builder'; import { LinkType } from 'mol-model/structure/model/types'; -import { DefaultMeshProps } from '../../../util'; import { SizeThemeProps } from 'mol-view/theme/size'; import { CylinderProps } from '../../../../primitive/cylinder'; import { LocationIterator } from '../../../../util/location-iterator'; import { Unit, StructureElement, Structure, Link } from 'mol-model/structure'; -import { addFixedCountDashedCylinder, addCylinder, addDoubleCylinder } from '../../../../mesh/builder/cylinder'; +import { addFixedCountDashedCylinder, addCylinder, addDoubleCylinder } from '../../../../geometry/mesh/builder/cylinder'; +import { DefaultMeshProps } from '../../../../geometry/geometry'; export const DefaultLinkCylinderProps = { ...DefaultMeshProps, diff --git a/src/mol-geo/representation/util.ts b/src/mol-geo/representation/util.ts index 48df84aa75bcdbd5b215c031c7144a7f7b4a330d..407ade0f2311b0472fd15688a57b63b555251444 100644 --- a/src/mol-geo/representation/util.ts +++ b/src/mol-geo/representation/util.ts @@ -4,97 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from 'mol-util/value-cell' -import { BaseValues } from 'mol-gl/renderable/schema'; -import { MeshValues, RenderableState } from 'mol-gl/renderable'; import { defaults } from 'mol-util'; import { Structure } from 'mol-model/structure'; - -export const DefaultBaseProps = { - alpha: 1, - visible: true, - depthMask: true, - useFog: false, - quality: 'auto' as VisualQuality -} -export type BaseProps = typeof DefaultBaseProps - -export const DefaultMeshProps = { - ...DefaultBaseProps, - doubleSided: false, - flipSided: false, - flatShaded: false, -} -export type MeshProps = typeof DefaultMeshProps - -export const DefaultPointProps = { - ...DefaultBaseProps, - pointSizeAttenuation: true -} -export type PointProps = typeof DefaultPointProps - -type Counts = { drawCount: number, groupCount: number, instanceCount: number } - -export function createBaseValues(props: Required<BaseProps>, counts: Counts) { - return { - uAlpha: ValueCell.create(props.alpha), - uGroupCount: ValueCell.create(counts.groupCount), - drawCount: ValueCell.create(counts.drawCount), - dUseFog: ValueCell.create(props.useFog), - } -} - -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), - } -} - -export function createPointValues(props: Required<PointProps>, counts: Counts) { - return { - ...createBaseValues(props, counts), - dPointSizeAttenuation: ValueCell.create(props.pointSizeAttenuation), - } -} - -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) - ValueCell.updateIfChanged(values.dUseFog, props.useFog) -} - -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) -} - -export function updateRenderableState(state: RenderableState, props: Required<BaseProps>) { - state.visible = props.visible - state.depthMask = props.depthMask -} - -export const VisualQualityInfo = { - 'custom': {}, - 'auto': {}, - 'highest': {}, - 'high': {}, - 'medium': {}, - 'low': {}, - 'lowest': {}, -} -export type VisualQuality = keyof typeof VisualQualityInfo -export const VisualQualityNames = Object.keys(VisualQualityInfo) +import { VisualQuality } from '../geometry/geometry'; export interface QualityProps { quality: VisualQuality diff --git a/src/mol-geo/representation/volume/index.ts b/src/mol-geo/representation/volume/index.ts index 9197885d3c9cebb758d2cd37218437ec3164f561..0ddad3eeaba9ca880578380152e0bf4126026687 100644 --- a/src/mol-geo/representation/volume/index.ts +++ b/src/mol-geo/representation/volume/index.ts @@ -11,7 +11,7 @@ import { VolumeData } from 'mol-model/volume'; import { PickingId } from '../../util/picking'; import { Loci, EmptyLoci } from 'mol-model/loci'; import { MarkerAction } from '../../util/marker-data'; -import { DefaultBaseProps } from '../util'; +import { DefaultBaseProps } from '../../geometry/geometry'; export interface VolumeVisual<P extends RepresentationProps = {}> extends Visual<VolumeData, P> { } diff --git a/src/mol-geo/representation/volume/surface.ts b/src/mol-geo/representation/volume/surface.ts index 46671107fcfff72a825598c02692718e6c1953b7..c621e43ebb6ea16b8a9260f8ac382bc7dfa1309a 100644 --- a/src/mol-geo/representation/volume/surface.ts +++ b/src/mol-geo/representation/volume/surface.ts @@ -8,7 +8,7 @@ import { VolumeData, VolumeIsoValue } from 'mol-model/volume' import { Task, RuntimeContext } from 'mol-task' import { computeMarchingCubes } from '../../util/marching-cubes/algorithm'; -import { Mesh } from '../../mesh/mesh'; +import { Mesh } from '../../geometry/mesh/mesh'; import { VolumeVisual } from '.'; import { createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'; import { ValueCell, defaults } from 'mol-util'; diff --git a/src/mol-geo/util/marching-cubes/algorithm.ts b/src/mol-geo/util/marching-cubes/algorithm.ts index 6ac77a8ffdb2e3411223ec1f4f0729bcb386547c..19393af7888be054c874c82d37949b5ecf24596e 100644 --- a/src/mol-geo/util/marching-cubes/algorithm.ts +++ b/src/mol-geo/util/marching-cubes/algorithm.ts @@ -7,7 +7,7 @@ import { Task, RuntimeContext } from 'mol-task' import { ChunkedArray } from 'mol-data/util' import { Tensor } from 'mol-math/linear-algebra' -import { Mesh } from '../../mesh/mesh' +import { Mesh } from '../../geometry/mesh/mesh' import { Index, EdgeIdInfo, CubeEdges, EdgeTable, TriTable } from './tables' import { ValueCell } from 'mol-util' @@ -76,6 +76,7 @@ class MarchingCubesComputation { const os = this.parameters.oldSurface return { + kind: 'mesh', vertexCount: this.state.vertexCount, triangleCount: this.state.triangleCount, vertexBuffer: os ? ValueCell.update(os.vertexBuffer, vb) : ValueCell.create(vb), diff --git a/src/mol-geo/util/mesh-data.ts b/src/mol-geo/util/mesh-data.ts index 0451ee98a8bfee2d7e2790c69a40a3144ca6ba69..37ed0291ce8843e72ac7068ddc8c4d23f6f7454d 100644 --- a/src/mol-geo/util/mesh-data.ts +++ b/src/mol-geo/util/mesh-data.ts @@ -5,7 +5,7 @@ */ import { ValueCell } from 'mol-util/value-cell' -import { Mesh } from '../mesh/mesh'; +import { Mesh } from '../geometry/mesh/mesh'; type MeshData = { aPosition: ValueCell<Float32Array>, diff --git a/src/mol-geo/util/point-data.ts b/src/mol-geo/util/point-data.ts new file mode 100644 index 0000000000000000000000000000000000000000..ce070cf7e9d34fb6bc418f3efa91b95af428d3e5 --- /dev/null +++ b/src/mol-geo/util/point-data.ts @@ -0,0 +1,20 @@ +/** + * 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 { Point } from '../geometry/point/point'; + +type PointData = { + aPosition: ValueCell<Float32Array>, + aGroup: ValueCell<Float32Array>, +} + +export function getPointData(point: Point): PointData { + return { + aPosition: point.vertexBuffer, + aGroup: point.groupBuffer, + } +} \ No newline at end of file diff --git a/src/mol-io/reader/obj/parser.ts b/src/mol-io/reader/obj/parser.ts index 46cd16ccb151b1fb0ab69afa873c83f33a09e0b8..046143b305b51530b1e8d0e1cad7f8cb097fa50c 100644 --- a/src/mol-io/reader/obj/parser.ts +++ b/src/mol-io/reader/obj/parser.ts @@ -6,7 +6,7 @@ import Result from '../result' import { Task, RuntimeContext } from 'mol-task' -import { Mesh } from 'mol-geo/mesh/mesh'; +import { Mesh } from 'mol-geo/geometry/mesh/mesh'; async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Mesh>> { // TODO diff --git a/src/mol-math/linear-algebra/tensor.ts b/src/mol-math/linear-algebra/tensor.ts index 4bcae46f7bd0db8987d0036ed8590ba804cd1d9c..0909730c58111245e1c2cf33ef46c49f648b31f7 100644 --- a/src/mol-math/linear-algebra/tensor.ts +++ b/src/mol-math/linear-algebra/tensor.ts @@ -20,6 +20,7 @@ export namespace Tensor { create(array?: ArrayCtor): Tensor.Data, get(data: Tensor.Data, ...coords: number[]): number set(data: Tensor.Data, ...coordsAndValue: number[]): number + add(data: Tensor.Data, ...coordsAndValue: number[]): number } interface Layout { @@ -45,8 +46,8 @@ export namespace Tensor { export function Space(dimensions: number[], axisOrderSlowToFast: number[], ctor?: ArrayCtor): Space { const layout = Layout(dimensions, axisOrderSlowToFast, ctor); - const { get, set } = accessors(layout); - return { rank: dimensions.length, dimensions, axisOrderSlowToFast, create: creator(layout), get, set }; + const { get, set, add } = accessors(layout); + return { rank: dimensions.length, dimensions, axisOrderSlowToFast, create: creator(layout), get, set, add }; } export function Data1(values: ArrayLike<number>): Data { return values as Data; } @@ -98,52 +99,89 @@ export namespace Tensor { return true; } - function accessors(layout: Layout): { get: Space['get'], set: Space['set'] } { + function accessors(layout: Layout): { get: Space['get'], set: Space['set'], add: Space['add'] } { const { dimensions, axisOrderFastToSlow: ao } = layout; switch (dimensions.length) { - case 1: return { get: (t, d) => t[d], set: (t, d, x) => t[d] = x }; + case 1: return { + get: (t, d) => t[d], + set: (t, d, x) => t[d] = x, + add: (t, d, x) => t[d] += x + }; case 2: { // column major if (ao[0] === 0 && ao[1] === 1) { const rows = dimensions[0]; - return { get: (t, i, j) => t[j * rows + i], set: (t, i, j, x) => t[j * rows + i] = x }; + return { + get: (t, i, j) => t[j * rows + i], + set: (t, i, j, x) => t[j * rows + i] = x, + add: (t, i, j, x) => t[j * rows + i] += x + }; } if (ao[0] === 1 && ao[1] === 0) { const cols = dimensions[1]; - return { get: (t, i, j) => t[i * cols + j], set: (t, i, j, x) => t[i * cols + j] = x }; + return { + get: (t, i, j) => t[i * cols + j], + set: (t, i, j, x) => t[i * cols + j] = x, + add: (t, i, j, x) => t[i * cols + j] += x + }; } throw new Error('bad axis order') } case 3: { if (ao[0] === 0 && ao[1] === 1 && ao[2] === 2) { // 012 ijk const u = dimensions[0], v = dimensions[1], uv = u * v; - return { get: (t, i, j, k) => t[i + j * u + k * uv], set: (t, i, j, k, x ) => t[i + j * u + k * uv] = x }; + return { + get: (t, i, j, k) => t[i + j * u + k * uv], + set: (t, i, j, k, x ) => t[i + j * u + k * uv] = x, + add: (t, i, j, k, x ) => t[i + j * u + k * uv] += x + }; } if (ao[0] === 0 && ao[1] === 2 && ao[2] === 1) { // 021 ikj const u = dimensions[0], v = dimensions[2], uv = u * v; - return { get: (t, i, j, k) => t[i + k * u + j * uv], set: (t, i, j, k, x ) => t[i + k * u + j * uv] = x }; + return { + get: (t, i, j, k) => t[i + k * u + j * uv], + set: (t, i, j, k, x ) => t[i + k * u + j * uv] = x, + add: (t, i, j, k, x ) => t[i + k * u + j * uv] += x + }; } if (ao[0] === 1 && ao[1] === 0 && ao[2] === 2) { // 102 jik const u = dimensions[1], v = dimensions[0], uv = u * v; - return { get: (t, i, j, k) => t[j + i * u + k * uv], set: (t, i, j, k, x ) => t[j + i * u + k * uv] = x }; + return { + get: (t, i, j, k) => t[j + i * u + k * uv], + set: (t, i, j, k, x ) => t[j + i * u + k * uv] = x, + add: (t, i, j, k, x ) => t[j + i * u + k * uv] += x + }; } if (ao[0] === 1 && ao[1] === 2 && ao[2] === 0) { // 120 jki const u = dimensions[1], v = dimensions[2], uv = u * v; - return { get: (t, i, j, k) => t[j + k * u + i * uv], set: (t, i, j, k, x ) => t[j + k * u + i * uv] = x }; + return { + get: (t, i, j, k) => t[j + k * u + i * uv], + set: (t, i, j, k, x ) => t[j + k * u + i * uv] = x, + add: (t, i, j, k, x ) => t[j + k * u + i * uv] += x + }; } if (ao[0] === 2 && ao[1] === 0 && ao[2] === 1) { // 201 kij const u = dimensions[2], v = dimensions[0], uv = u * v; - return { get: (t, i, j, k) => t[k + i * u + j * uv], set: (t, i, j, k, x ) => t[k + i * u + j * uv] = x }; + return { + get: (t, i, j, k) => t[k + i * u + j * uv], + set: (t, i, j, k, x ) => t[k + i * u + j * uv] = x, + add: (t, i, j, k, x ) => t[k + i * u + j * uv] += x + }; } if (ao[0] === 2 && ao[1] === 1 && ao[2] === 0) { // 210 kji const u = dimensions[2], v = dimensions[1], uv = u * v; - return { get: (t, i, j, k) => t[k + j * u + i * uv], set: (t, i, j, k, x ) => t[k + j * u + i * uv] = x }; + return { + get: (t, i, j, k) => t[k + j * u + i * uv], + set: (t, i, j, k, x ) => t[k + j * u + i * uv] = x, + add: (t, i, j, k, x ) => t[k + j * u + i * uv] += x + }; } throw new Error('bad axis order') } default: return { get: (t, ...c) => t[dataOffset(layout, c)], - set: (t, ...c) => t[dataOffset(layout, c)] = c[c.length - 1] + set: (t, ...c) => t[dataOffset(layout, c)] = c[c.length - 1], + add: (t, ...c) => t[dataOffset(layout, c)] += c[c.length - 1] }; } } diff --git a/src/mol-model/shape/shape.ts b/src/mol-model/shape/shape.ts index ffc602342db05a6419dd471d38b755ff41c51fa3..b911bd340fa8432444d4253b4fbcbed3608a592e 100644 --- a/src/mol-model/shape/shape.ts +++ b/src/mol-model/shape/shape.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Mesh } from 'mol-geo/mesh/mesh'; +import { Mesh } from 'mol-geo/geometry/mesh/mesh'; import { Color } from 'mol-util/color'; import { UUID, ValueCell } from 'mol-util'; import { OrderedSet } from 'mol-data/int';