Skip to content
Snippets Groups Projects
Commit 84e6ebf5 authored by Alexander Rose's avatar Alexander Rose
Browse files

wip, gaussian surface

parent 92c05b42
No related branches found
No related tags found
No related merge requests found
Showing
with 220 additions and 17 deletions
......@@ -24,6 +24,7 @@ import { StructureRepresentation } from 'mol-geo/representation/structure';
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';
export interface StructureView {
readonly viewer: Viewer
......@@ -66,6 +67,7 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
const active: { [k: string]: boolean } = {
cartoon: true,
point: false,
surface: true,
ballAndStick: false,
carbohydrate: false,
spacefill: false,
......@@ -76,6 +78,7 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>
const structureRepresentations: { [k: string]: StructureRepresentation<any> } = {
cartoon: CartoonRepresentation(),
surface: SurfaceRepresentation(),
point: PointRepresentation(),
ballAndStick: BallAndStickRepresentation(),
carbohydrate: CarbohydrateRepresentation(),
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { UnitsRepresentation } from '..';
import { GaussianSurfaceVisual, DefaultGaussianSurfaceProps } from '../visual/gaussian-surface-mesh';
import { StructureRepresentation } from '../units-representation';
import { Structure } from 'mol-model/structure';
import { MarkerAction } from '../../../util/marker-data';
import { Loci } from 'mol-model/loci';
import { PickingId } from '../../../util/picking';
export const DefaultSurfaceProps = {
...DefaultGaussianSurfaceProps,
}
export type SurfaceProps = typeof DefaultSurfaceProps
export type SurfaceRepresentation = StructureRepresentation<SurfaceProps>
export function SurfaceRepresentation(): SurfaceRepresentation {
let currentProps: SurfaceProps
const gaussianRepr = UnitsRepresentation('Gaussian surface', GaussianSurfaceVisual)
return {
label: 'Surface',
get renderObjects() {
return [ ...gaussianRepr.renderObjects ]
},
get props() {
return { ...gaussianRepr.props }
},
createOrUpdate: (props: Partial<SurfaceProps> = {}, structure?: Structure) => {
currentProps = Object.assign({}, DefaultSurfaceProps, currentProps, props)
return gaussianRepr.createOrUpdate(currentProps, structure)
},
getLoci: (pickingId: PickingId) => {
return gaussianRepr.getLoci(pickingId)
},
mark: (loci: Loci, action: MarkerAction) => {
return gaussianRepr.mark(loci, action)
},
destroy() {
gaussianRepr.destroy()
}
}
}
\ No newline at end of file
......@@ -32,7 +32,7 @@ export type UnitsMeshProps = typeof DefaultUnitsMeshProps
export interface UnitsMeshVisualBuilder<P extends UnitsMeshProps> {
defaultProps: P
createMesh(ctx: RuntimeContext, unit: Unit, props: P, mesh?: Mesh): Promise<Mesh>
createMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: P, mesh?: Mesh): Promise<Mesh>
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
......@@ -59,7 +59,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu
const unit = group.units[0]
currentConformationId = Unit.conformationId(unit)
mesh = currentProps.unitKinds.includes(unit.kind)
? await createMesh(ctx, unit, currentProps, mesh)
? await createMesh(ctx, unit, currentStructure, currentProps, mesh)
: Mesh.createEmpty(mesh)
// TODO create empty location iterator when not in unitKinds
......@@ -102,7 +102,7 @@ export function UnitsMeshVisual<P extends UnitsMeshProps>(builder: UnitsMeshVisu
if (updateState.createMesh) {
mesh = newProps.unitKinds.includes(unit.kind)
? await createMesh(ctx, unit, newProps, mesh)
? await createMesh(ctx, unit, currentStructure, newProps, mesh)
: Mesh.createEmpty(mesh)
ValueCell.update(renderObject.values.drawCount, mesh.triangleCount * 3)
updateState.updateColor = true
......
/**
* 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 { UnitsVisual, MeshUpdateState } from '..';
import { RuntimeContext } from 'mol-task'
import { Mesh } from '../../../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 { ValueCell } from 'mol-util';
import { smoothstep } from 'mol-math/interpolate';
export interface GaussianSurfaceMeshProps {
}
function getDelta(box: Box3D) {
const extent = Vec3.sub(Vec3.zero(), box.max, box.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)
return delta
}
async function createGaussianSurfaceMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: GaussianSurfaceMeshProps, mesh?: Mesh): Promise<Mesh> {
const { elements } = unit;
const elementCount = elements.length;
const r = 2.5;
const v = Vec3.zero()
const p = Vec3.zero()
const pos = unit.conformation.invariantPosition
const box = unit.lookup3d.boundary.box
const expandedBox = Box3D.expand(Box3D.empty(), box, Vec3.create(r*3, r*3, r*3));
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(r*3, r*3, r*3)))
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)
for (let i = 0; i < elementCount; i++) {
pos(elements[i], v)
Vec3.mul(v, Vec3.sub(v, v, min), delta)
const size = r
const radius = size * delta[0]
const minX = Math.floor(v[0] - radius)
const minY = Math.floor(v[1] - radius)
const minZ = Math.floor(v[2] - radius)
const maxX = Math.floor(v[0] + radius)
const maxY = Math.floor(v[1] + radius)
const maxZ = Math.floor(v[2] + radius)
for (let x = minX; x <= maxX; ++x) {
for (let y = minY; y <= maxY; ++y) {
for (let z = minZ; z <= maxZ; ++z) {
const dist = Vec3.distance(Vec3.set(p, x, y, z), v)
if (dist <= radius) {
const density = 1.0 - smoothstep(0.0, radius * 1.0, dist)
space.set(data, x, y, z, space.get(data, x, y, z) + density)
}
}
}
}
if (i % 10000 === 0 && ctx.shouldUpdate) {
await ctx.update({ message: 'Gaussian surface', current: i, max: elementCount });
}
}
// console.log('data', data)
const surface = await computeMarchingCubes({
isoLevel: 0.1,
scalarField: field,
oldSurface: mesh
}).runAsChild(ctx);
const t = Mat4.identity()
Mat4.fromUniformScaling(t, 1 / delta[0])
Mat4.setTranslation(t, expandedBox.min)
ValueCell.update(surface.groupBuffer, new Float32Array(surface.vertexCount))
Mesh.transformImmediate(surface, t)
await Mesh.computeNormals(surface).runAsChild(ctx)
// console.log('surface', surface)
// const transform = VolumeData.getGridToCartesianTransform(volume);
// ctx.update({ message: 'Transforming mesh...' });
// Mesh.transformImmediate(surface, transform);
return surface;
}
export const DefaultGaussianSurfaceProps = {
...DefaultUnitsMeshProps,
linearSegments: 8,
radialSegments: 12,
aspectRatio: 5,
arrowFactor: 1.5,
flipSided: true,
// flatShaded: true,
}
export type GaussianSurfaceProps = typeof DefaultGaussianSurfaceProps
export function GaussianSurfaceVisual(): UnitsVisual<GaussianSurfaceProps> {
return UnitsMeshVisual<GaussianSurfaceProps>({
defaultProps: DefaultGaussianSurfaceProps,
createMesh: createGaussianSurfaceMesh,
createLocationIterator: StructureElementIterator.fromGroup,
getLoci: getElementLoci,
mark: markElement,
setUpdateState: (state: MeshUpdateState, newProps: GaussianSurfaceProps, currentProps: GaussianSurfaceProps) => {}
})
}
\ No newline at end of file
......@@ -5,7 +5,7 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { Unit, Link, StructureElement } from 'mol-model/structure';
import { Unit, Link, StructureElement, Structure } from 'mol-model/structure';
import { UnitsVisual, MeshUpdateState } from '..';
import { RuntimeContext } from 'mol-task'
import { DefaultLinkCylinderProps, LinkCylinderProps, createLinkCylinderMesh, LinkIterator } from './util/link';
......@@ -18,7 +18,7 @@ import { Interval } from 'mol-data/int';
import { SizeThemeProps, SizeTheme } from 'mol-view/theme/size';
import { BitFlags } from 'mol-util';
async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit, props: LinkCylinderProps, mesh?: Mesh) {
async function createIntraUnitLinkCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: LinkCylinderProps, mesh?: Mesh) {
if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
const sizeTheme = SizeTheme(props.sizeTheme)
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit } from 'mol-model/structure';
import { Unit, Structure } from 'mol-model/structure';
import { UnitsVisual } from '..';
import { RuntimeContext } from 'mol-task'
import { Mesh } from '../../../mesh/mesh';
......@@ -33,7 +33,7 @@ const sVec = Vec3.zero()
const box = Box()
// TODO define props, should be scalable
async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, props: {}, mesh?: Mesh) {
async function createNucleotideBlockMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: {}, mesh?: Mesh) {
if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
// TODO better vertex count estimate
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit } from 'mol-model/structure';
import { Unit, Structure } from 'mol-model/structure';
import { UnitsVisual, MeshUpdateState } from '..';
import { RuntimeContext } from 'mol-task'
import { Mesh } from '../../../mesh/mesh';
......@@ -23,7 +23,7 @@ export interface PolymerBackboneCylinderProps {
radialSegments: number
}
async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit, props: PolymerBackboneCylinderProps, mesh?: Mesh) {
async function createPolymerBackboneCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerBackboneCylinderProps, mesh?: Mesh) {
const polymerElementCount = unit.polymerElements.length
if (!polymerElementCount) return Mesh.createEmpty(mesh)
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit } from 'mol-model/structure';
import { Unit, Structure } from 'mol-model/structure';
import { UnitsVisual } from '..';
import { RuntimeContext } from 'mol-task'
import { Mesh } from '../../../mesh/mesh';
......@@ -32,7 +32,7 @@ export interface PolymerDirectionWedgeProps {
sizeTheme: SizeThemeProps
}
async function createPolymerDirectionWedgeMesh(ctx: RuntimeContext, unit: Unit, props: PolymerDirectionWedgeProps, mesh?: Mesh) {
async function createPolymerDirectionWedgeMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerDirectionWedgeProps, mesh?: Mesh) {
const polymerElementCount = unit.polymerElements.length
if (!polymerElementCount) return Mesh.createEmpty(mesh)
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit } from 'mol-model/structure';
import { Unit, Structure } from 'mol-model/structure';
import { UnitsVisual, MeshUpdateState } from '..';
import { RuntimeContext } from 'mol-task'
import { Mesh } from '../../../mesh/mesh';
......@@ -24,7 +24,7 @@ export interface PolymerGapCylinderProps {
radialSegments: number
}
async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, props: PolymerGapCylinderProps, mesh?: Mesh) {
async function createPolymerGapCylinderMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerGapCylinderProps, mesh?: Mesh) {
const polymerGapCount = unit.gapElements.length
if (!polymerGapCount) return Mesh.createEmpty(mesh)
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Unit } from 'mol-model/structure';
import { Unit, Structure } from 'mol-model/structure';
import { UnitsVisual, MeshUpdateState } from '..';
import { RuntimeContext } from 'mol-task'
import { Mesh } from '../../../mesh/mesh';
......@@ -26,7 +26,7 @@ export interface PolymerTraceMeshProps {
// TODO handle polymer ends properly
async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, props: PolymerTraceMeshProps, mesh?: Mesh) {
async function createPolymerTraceMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: PolymerTraceMeshProps, mesh?: Mesh) {
const polymerElementCount = unit.polymerElements.length
if (!polymerElementCount) return Mesh.createEmpty(mesh)
......
......@@ -5,7 +5,7 @@
*/
import { Vec3 } from 'mol-math/linear-algebra';
import { Unit, StructureElement } from 'mol-model/structure';
import { Unit, StructureElement, Structure } from 'mol-model/structure';
import { RuntimeContext } from 'mol-task';
import { sphereVertexCount } from '../../../../primitive/sphere';
import { Mesh } from '../../../../mesh/mesh';
......@@ -22,7 +22,7 @@ export interface ElementSphereMeshProps {
detail: number,
}
export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, props: ElementSphereMeshProps, mesh?: Mesh) {
export async function createElementSphereMesh(ctx: RuntimeContext, unit: Unit, structure: Structure, props: ElementSphereMeshProps, mesh?: Mesh) {
const { detail } = props
const { elements } = unit;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment