diff --git a/src/apps/render-test/state.ts b/src/apps/render-test/state.ts index 0a65fce44326cfcb21b9668258b4d879e6fe219c..bfc4e2a2a2f2fb61a2b214224964869b0c176a06 100644 --- a/src/apps/render-test/state.ts +++ b/src/apps/render-test/state.ts @@ -7,16 +7,16 @@ import { ValueCell } from 'mol-util/value-cell' import { Vec3, Mat4 } from 'mol-math/linear-algebra' -import { createRenderer, createRenderObject, RenderObject } from 'mol-gl/renderer' +import { createRenderer, createRenderObject } from 'mol-gl/renderer' import { createColorTexture } from 'mol-gl/util'; -import Icosahedron from 'mol-geo/primitive/icosahedron' -import Box from 'mol-geo/primitive/box' +// import Icosahedron from 'mol-geo/primitive/icosahedron' +// import Box from 'mol-geo/primitive/box' import Spacefill from 'mol-geo/representation/structure/spacefill' import Point from 'mol-geo/representation/structure/point' import CIF from 'mol-io/reader/cif' import { Run, Progress } from 'mol-task' -import { Structure } from 'mol-model/structure' +import { Structure, Symmetry } from 'mol-model/structure' function log(progress: Progress) { const p = progress.root.progress @@ -38,6 +38,7 @@ async function getPdb(pdb: string) { } import mcubes from './mcubes' +import { StructureRepresentation } from 'mol-geo/representation/structure'; // import Cylinder from 'mol-geo/primitive/cylinder'; export default class State { @@ -123,16 +124,16 @@ export default class State { const mesh2 = makeCubesMesh(); renderer.add(mesh2) - const structures = await getPdb('4v99') - const { elements, units } = structures[0]; + const structures = await getPdb('1rb8') + const struct = Symmetry.buildAssembly(structures[0], '1') - // const spacefill = Spacefill() - // const spacefills = await Run(spacefill.create(units, elements), log, 100) - // spacefills.forEach(renderer.add) + const structPointRepr = StructureRepresentation(Point) + await Run(structPointRepr.create(struct)) + structPointRepr.renderObjects.forEach(renderer.add) - const point = Point() - const points = await Run(point.create(units, elements), log, 100) - points.forEach(renderer.add) + const structSpacefillRepr = StructureRepresentation(Spacefill) + await Run(structSpacefillRepr.create(struct)) + structSpacefillRepr.renderObjects.forEach(renderer.add) renderer.frame() } diff --git a/src/mol-geo/representation/structure/index.ts b/src/mol-geo/representation/structure/index.ts index a5d71c0b486098db914b7743bd4379df4ea11451..76210a764f667135c06c807bfa23d7c4c9b8d647 100644 --- a/src/mol-geo/representation/structure/index.ts +++ b/src/mol-geo/representation/structure/index.ts @@ -5,55 +5,85 @@ */ import { ElementGroup, ElementSet, Structure, Unit } from 'mol-model/structure'; -import { RenderObject } from 'mol-gl/renderer'; import { EquivalenceClasses } from 'mol-data/util'; import { OrderedSet } from 'mol-data/int' import { Task } from 'mol-task' +import { RenderObject } from 'mol-gl/renderer'; export interface RepresentationProps { } -export interface UnitRepresentation { - create: (units: ReadonlyArray<Unit>, elements: ElementSet, props?: Partial<RepresentationProps>) => Task<RenderObject[]>, +export interface UnitsRepresentation<Props> { + renderObjects: ReadonlyArray<RenderObject>, + create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: Props) => Task<void>, update: (props: RepresentationProps) => boolean, } -// export interface StructureRepresentation { -// create: (structure: Structure, props: RepresentationProps) => boolean, -// update: (props: RepresentationProps) => boolean -// } - -export class StructureRepresentation { - constructor(private repr: UnitRepresentation) { +export interface StructureRepresentation<Props> { + renderObjects: ReadonlyArray<RenderObject>, + create: (structure: Structure, props?: Props) => Task<void>, + update: (elements: ElementSet, props: Props) => boolean +} - } - create(structure: Structure) { - return Task.create('S. repr.', async ctx => { +export function StructureRepresentation<Props>(reprCtor: () => UnitsRepresentation<Props>): StructureRepresentation<Props> { + const renderObjects: RenderObject[] = [] + const unitReprs: UnitsRepresentation<Props>[] = [] - const { elements, units } = structure; - const uniqueGroups = EquivalenceClasses<number, ElementGroup>( - ElementGroup.hashCode, - (a, b) => units[a.id].model.id === units[b.id].model.id && OrderedSet.areEqual(a.elements, b.elements)); + return { + renderObjects, + create(structure: Structure, props: Props = {} as Props) { + return Task.create('StructureRepresentation', async ctx => { + const { elements, units } = structure; + const uniqueGroups = EquivalenceClasses<number, ElementGroup>( + ElementGroup.hashCode, + (a, b) => units[a.id].model.id === units[b.id].model.id && + OrderedSet.areEqual(a.elements, b.elements) + ); + // TODO + // const uniqueOperators = EquivalenceClasses<number, ElementGroup>( + // ElementGroup.hashCode, + // (a, b) => units[a.id].model.id === units[b.id].model.id && + // OrderedSet.areEqual(a.elements, b.elements) + // ); - for (let i = 0, _i = ElementSet.unitCount(elements); i < _i; i++) { - const group = ElementSet.unitGetByIndex(elements, i); - uniqueGroups.add(group.id, group); + for (let i = 0, _i = ElementSet.unitCount(elements); i < _i; i++) { + const group = ElementSet.unitGetByIndex(elements, i); + uniqueGroups.add(i, group); + // console.log(i, group) + } - } + for (let i = 0, _i = uniqueGroups.groups.length; i < _i; i++) { + const groupUnits: Unit[] = [] + const group = uniqueGroups.groups[i] + // console.log('group', i) + for (let j = 0, _j = group.length; j < _j; j++) { + groupUnits.push(units[group[j]]) + // console.log(units[group[j]].operator.matrix) + } + const elementGroup = ElementSet.unitGetByIndex(elements, group[0]) + const repr = reprCtor() + unitReprs.push(repr) + await ctx.update({ message: 'Building units...', current: i, max: _i }); + await ctx.runChild(repr.create(groupUnits, elementGroup, props)); + renderObjects.push(...repr.renderObjects) + } - const u = this.repr.create(units, 0 as any, 0 as any); - await ctx.update('Building units...'); - await ctx.runChild(u); + // console.log(ElementSet.unitCount(elements)) + // console.log(uniqueGroups) - //ctx.runChild(...) - //uniqueGroups.groups + // console.log({ elements, units }) - return true - }); - } - update(elements: ElementSet, props: RepresentationProps) { - // TODO check model.id, conformation.id, unit.id, elementGroup(.hashCode/.areEqual) - return false + // const repr = reprCtor() + // unitReprs.push(repr) + // await ctx.update('Building units...'); + // await ctx.runChild(repr.create(units, elements, props)); + // renderObjects.push(...repr.renderObjects) + }); + }, + update(elements: ElementSet, props: RepresentationProps) { + // TODO check model.id, conformation.id, unit.id, elementGroup(.hashCode/.areEqual) + return false + } } } \ No newline at end of file diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts index af7aaa05c90987bac5e874edfaf092a45a17c226..0e930adf7afc2576cb66813daa2526563b0d8fa4 100644 --- a/src/mol-geo/representation/structure/point.ts +++ b/src/mol-geo/representation/structure/point.ts @@ -11,43 +11,42 @@ import { createColorTexture } from 'mol-gl/util'; import { Mat4 } from 'mol-math/linear-algebra' import { OrderedSet } from 'mol-data/int' import { ChunkedArray } from 'mol-data/util'; -import { Element, Unit, ElementSet } from 'mol-model/structure'; -import P from 'mol-model/structure/query/properties'; -import { RepresentationProps, UnitRepresentation } from './index'; +import { Unit, ElementGroup } from 'mol-model/structure'; +import { RepresentationProps, UnitsRepresentation } from './index'; import { Task } from 'mol-task' +export const DefaultPointProps = { -export default function Point(): UnitRepresentation { +} +export type PointProps = Partial<typeof DefaultPointProps> + +export default function Point(): UnitsRepresentation<PointProps> { const renderObjects: RenderObject[] = [] const vertices = ChunkedArray.create(Float32Array, 3, 1024, 2048); return { - create: (units: ReadonlyArray<Unit>, elements: ElementSet, props: Partial<RepresentationProps> = {}) => Task.create('Spacefill', async ctx => { - const l = Element.Location(); - - const unitIds = ElementSet.unitIds(elements); - for (let i = 0, _i = unitIds.length; i < _i; i++) { - const unitId = unitIds[i]; - const unit = units[unitId]; - const elementGroup = ElementSet.unitGetByIndex(elements, i); - const elementCount = OrderedSet.size(elementGroup.elements) - l.unit = unit; + renderObjects, + create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: PointProps = {}) => Task.create('Spacefill', async ctx => { + // const l = Element.Location(); - for (let i = 0; i < elementCount; i++) { - l.element = OrderedSet.getAt(elementGroup.elements, i) - ChunkedArray.add3(vertices, P.atom.x(l), P.atom.y(l), P.atom.z(l)) - } + const { x, y, z } = units[0].model.conformation + const elementCount = OrderedSet.size(elementGroup.elements) + for (let i = 0; i < elementCount; i++) { + const e = OrderedSet.getAt(elementGroup.elements, i) + ChunkedArray.add3(vertices, x[e], y[e], z[e]) if (i % 10 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'Point', current: i, max: _i }); + await ctx.update({ message: 'Point', current: i, max: elementCount }); } } - const transformArray = new Float32Array(32) - const m4 = Mat4.identity() - Mat4.toArray(m4, transformArray, 0) + const unitsCount = units.length + const transformArray = new Float32Array(unitsCount * 16) + for (let i = 0; i < unitsCount; i++) { + Mat4.toArray(units[i].operator.matrix, transformArray, i * 16) + } - const color = ValueCell.create(createColorTexture(1)) + const color = ValueCell.create(createColorTexture(unitsCount)) color.ref.value.set([ 0, 0, 255 ]) const points = createRenderObject('point', { @@ -55,12 +54,10 @@ export default function Point(): UnitRepresentation { color, transform: ValueCell.create(transformArray), - instanceCount: transformArray.length / 16, + instanceCount: unitsCount, positionCount: vertices.elementCount }, {}) renderObjects.push(points) - - return renderObjects }), update: (props: RepresentationProps) => false } diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts index 0b055be5a747997ffac1e612cf5a45aab3091031..f87c59cc543ff1b5230e54198f831e47dcecbb50 100644 --- a/src/mol-geo/representation/structure/spacefill.ts +++ b/src/mol-geo/representation/structure/spacefill.ts @@ -10,62 +10,56 @@ import { createRenderObject, RenderObject } from 'mol-gl/renderer' import { createColorTexture } from 'mol-gl/util'; import { Vec3, Mat4 } from 'mol-math/linear-algebra' import { OrderedSet } from 'mol-data/int' -import { Element, Unit, ElementSet } from 'mol-model/structure'; -import P from 'mol-model/structure/query/properties'; -import { RepresentationProps, UnitRepresentation } from './index'; +import { Unit, ElementGroup } from 'mol-model/structure'; +import { RepresentationProps, UnitsRepresentation } from './index'; import { Task } from 'mol-task' import { MeshBuilder } from '../../shape/mesh-builder'; +import { VdwRadius } from 'mol-model/structure/model/properties/atomic'; -export default function Spacefill(): UnitRepresentation { - const renderObjects: RenderObject[] = [] +export const DefaultSpacefillProps = { + +} +export type SpacefillProps = Partial<typeof DefaultSpacefillProps> - // unit: Unit, atomGroup: AtomGroup +export default function Spacefill(): UnitsRepresentation<SpacefillProps> { + const renderObjects: RenderObject[] = [] return { - create: (units: ReadonlyArray<Unit>, elements: ElementSet, props: Partial<RepresentationProps> = {}) => Task.create('Spacefill', async ctx => { - const l = Element.Location(); + renderObjects, + create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: SpacefillProps = {}) => Task.create('Spacefill', async ctx => { const meshBuilder = MeshBuilder.create() - const unitIds = ElementSet.unitIds(elements); - for (let i = 0, _i = unitIds.length; i < _i; i++) { - const unitId = unitIds[i]; - const unit = units[unitId]; - const elementGroup = ElementSet.unitGetByIndex(elements, i); - - const elementCount = OrderedSet.size(elementGroup.elements) - - l.unit = unit; + const v = Vec3.zero() + const m = Mat4.identity() - const v = Vec3.zero() - const m = Mat4.identity() + const { x, y, z } = units[0].model.conformation + const { type_symbol } = units[0].model.hierarchy.atoms + const elementCount = OrderedSet.size(elementGroup.elements) + for (let i = 0; i < elementCount; i++) { + const e = OrderedSet.getAt(elementGroup.elements, i) + v[0] = x[e] + v[1] = y[e] + v[2] = z[e] + Mat4.setTranslation(m, v) - for (let i = 0; i < elementCount; i++) { - l.element = OrderedSet.getAt(elementGroup.elements, i) - - v[0] = P.atom.x(l) - v[1] = P.atom.y(l) - v[2] = P.atom.z(l) - Mat4.setTranslation(m, v) - - meshBuilder.addIcosahedron(m, { radius: P.atom.vdw(l), detail: 1 }) - } + meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), detail: 0 }) if (i % 10 === 0 && ctx.shouldUpdate) { - await ctx.update({ message: 'Spacefill', current: i, max: _i }); + await ctx.update({ message: 'Spacefill', current: i, max: elementCount }); } } - const transformArray = new Float32Array(32) - const m4 = Mat4.identity() - Mat4.toArray(m4, transformArray, 0) + const unitsCount = units.length + const transformArray = new Float32Array(unitsCount * 16) + for (let i = 0; i < unitsCount; i++) { + Mat4.toArray(units[i].operator.matrix, transformArray, i * 16) + } - const color = ValueCell.create(createColorTexture(1)) + const color = ValueCell.create(createColorTexture(unitsCount)) color.ref.value.set([ 0, 0, 255 ]) const mesh = meshBuilder.getMesh() - // console.log(mesh) - const spheres = createRenderObject('mesh', { position: mesh.vertexBuffer, normal: mesh.normalBuffer, @@ -73,13 +67,11 @@ export default function Spacefill(): UnitRepresentation { transform: ValueCell.create(transformArray), elements: mesh.indexBuffer, - instanceCount: transformArray.length / 16, + instanceCount: unitsCount, elementCount: mesh.triangleCount, positionCount: mesh.vertexCount }, {}) renderObjects.push(spheres) - - return renderObjects }), update: (props: RepresentationProps) => false } diff --git a/src/mol-gl/renderable/point.ts b/src/mol-gl/renderable/point.ts index 5bc8aed303ec225c9e2abb893285e045c9f74a98..99b31165599afc448cf0e5bb589a87387c49e2bf 100644 --- a/src/mol-gl/renderable/point.ts +++ b/src/mol-gl/renderable/point.ts @@ -24,6 +24,7 @@ namespace Point { } export function create(regl: REGL.Regl, data: Data): Renderable { + console.log(data) const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount))) const command = regl({ ...PointShaders, diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index 17c13e3f0ae50e46aec969ea6a5ce30d763db2b3..f4c25f0f64248e9b651e9496759106d08ec9113a 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -70,7 +70,9 @@ export function createRenderer(container: HTMLDivElement): Renderer { const camera = Camera.create(regl, container, { center: Vec3.create(0, 0, 0), near: 0.01, - far: 1000 + far: 10000, + minDistance: 0.01, + maxDistance: 10000 }) const baseContext = regl({ diff --git a/src/mol-gl/shader/point.vert b/src/mol-gl/shader/point.vert index f28cc6e9eca85124967ed30df9eac9e2f3feb4f5..86802b5376bf1291f03d411f39fbf5420a0c45bb 100644 --- a/src/mol-gl/shader/point.vert +++ b/src/mol-gl/shader/point.vert @@ -21,6 +21,6 @@ attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformCo void main(){ mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3); // vColor = color; - gl_PointSize = 5.0; + gl_PointSize = 1.0; gl_Position = projection * view * model * transform * vec4(position, 1.0); } \ No newline at end of file