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

wip, repr instancing support

parent eea59e9e
No related branches found
No related tags found
No related merge requests found
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
import { ValueCell } from 'mol-util/value-cell' import { ValueCell } from 'mol-util/value-cell'
import { Vec3, Mat4 } from 'mol-math/linear-algebra' 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 { createColorTexture } from 'mol-gl/util';
import Icosahedron from 'mol-geo/primitive/icosahedron' // import Icosahedron from 'mol-geo/primitive/icosahedron'
import Box from 'mol-geo/primitive/box' // import Box from 'mol-geo/primitive/box'
import Spacefill from 'mol-geo/representation/structure/spacefill' import Spacefill from 'mol-geo/representation/structure/spacefill'
import Point from 'mol-geo/representation/structure/point' import Point from 'mol-geo/representation/structure/point'
import CIF from 'mol-io/reader/cif' import CIF from 'mol-io/reader/cif'
import { Run, Progress } from 'mol-task' import { Run, Progress } from 'mol-task'
import { Structure } from 'mol-model/structure' import { Structure, Symmetry } from 'mol-model/structure'
function log(progress: Progress) { function log(progress: Progress) {
const p = progress.root.progress const p = progress.root.progress
...@@ -38,6 +38,7 @@ async function getPdb(pdb: string) { ...@@ -38,6 +38,7 @@ async function getPdb(pdb: string) {
} }
import mcubes from './mcubes' import mcubes from './mcubes'
import { StructureRepresentation } from 'mol-geo/representation/structure';
// import Cylinder from 'mol-geo/primitive/cylinder'; // import Cylinder from 'mol-geo/primitive/cylinder';
export default class State { export default class State {
...@@ -123,16 +124,16 @@ export default class State { ...@@ -123,16 +124,16 @@ export default class State {
const mesh2 = makeCubesMesh(); const mesh2 = makeCubesMesh();
renderer.add(mesh2) renderer.add(mesh2)
const structures = await getPdb('4v99') const structures = await getPdb('1rb8')
const { elements, units } = structures[0]; const struct = Symmetry.buildAssembly(structures[0], '1')
// const spacefill = Spacefill() const structPointRepr = StructureRepresentation(Point)
// const spacefills = await Run(spacefill.create(units, elements), log, 100) await Run(structPointRepr.create(struct))
// spacefills.forEach(renderer.add) structPointRepr.renderObjects.forEach(renderer.add)
const point = Point() const structSpacefillRepr = StructureRepresentation(Spacefill)
const points = await Run(point.create(units, elements), log, 100) await Run(structSpacefillRepr.create(struct))
points.forEach(renderer.add) structSpacefillRepr.renderObjects.forEach(renderer.add)
renderer.frame() renderer.frame()
} }
......
...@@ -5,55 +5,85 @@ ...@@ -5,55 +5,85 @@
*/ */
import { ElementGroup, ElementSet, Structure, Unit } from 'mol-model/structure'; import { ElementGroup, ElementSet, Structure, Unit } from 'mol-model/structure';
import { RenderObject } from 'mol-gl/renderer';
import { EquivalenceClasses } from 'mol-data/util'; import { EquivalenceClasses } from 'mol-data/util';
import { OrderedSet } from 'mol-data/int' import { OrderedSet } from 'mol-data/int'
import { Task } from 'mol-task' import { Task } from 'mol-task'
import { RenderObject } from 'mol-gl/renderer';
export interface RepresentationProps { export interface RepresentationProps {
} }
export interface UnitRepresentation { export interface UnitsRepresentation<Props> {
create: (units: ReadonlyArray<Unit>, elements: ElementSet, props?: Partial<RepresentationProps>) => Task<RenderObject[]>, renderObjects: ReadonlyArray<RenderObject>,
create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: Props) => Task<void>,
update: (props: RepresentationProps) => boolean, update: (props: RepresentationProps) => boolean,
} }
// export interface StructureRepresentation { export interface StructureRepresentation<Props> {
// create: (structure: Structure, props: RepresentationProps) => boolean, renderObjects: ReadonlyArray<RenderObject>,
// update: (props: RepresentationProps) => boolean create: (structure: Structure, props?: Props) => Task<void>,
// } update: (elements: ElementSet, props: Props) => boolean
}
export class StructureRepresentation {
constructor(private repr: UnitRepresentation) {
} export function StructureRepresentation<Props>(reprCtor: () => UnitsRepresentation<Props>): StructureRepresentation<Props> {
create(structure: Structure) { const renderObjects: RenderObject[] = []
return Task.create('S. repr.', async ctx => { const unitReprs: UnitsRepresentation<Props>[] = []
const { elements, units } = structure; return {
const uniqueGroups = EquivalenceClasses<number, ElementGroup>( renderObjects,
ElementGroup.hashCode, create(structure: Structure, props: Props = {} as Props) {
(a, b) => units[a.id].model.id === units[b.id].model.id && OrderedSet.areEqual(a.elements, b.elements)); 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++) { for (let i = 0, _i = ElementSet.unitCount(elements); i < _i; i++) {
const group = ElementSet.unitGetByIndex(elements, i); const group = ElementSet.unitGetByIndex(elements, i);
uniqueGroups.add(group.id, group); 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); // console.log(ElementSet.unitCount(elements))
await ctx.update('Building units...'); // console.log(uniqueGroups)
await ctx.runChild(u);
//ctx.runChild(...) // console.log({ elements, units })
//uniqueGroups.groups
return true // const repr = reprCtor()
}); // unitReprs.push(repr)
} // await ctx.update('Building units...');
update(elements: ElementSet, props: RepresentationProps) { // await ctx.runChild(repr.create(units, elements, props));
// TODO check model.id, conformation.id, unit.id, elementGroup(.hashCode/.areEqual) // renderObjects.push(...repr.renderObjects)
return false });
},
update(elements: ElementSet, props: RepresentationProps) {
// TODO check model.id, conformation.id, unit.id, elementGroup(.hashCode/.areEqual)
return false
}
} }
} }
\ No newline at end of file
...@@ -11,43 +11,42 @@ import { createColorTexture } from 'mol-gl/util'; ...@@ -11,43 +11,42 @@ import { createColorTexture } from 'mol-gl/util';
import { Mat4 } from 'mol-math/linear-algebra' import { Mat4 } from 'mol-math/linear-algebra'
import { OrderedSet } from 'mol-data/int' import { OrderedSet } from 'mol-data/int'
import { ChunkedArray } from 'mol-data/util'; import { ChunkedArray } from 'mol-data/util';
import { Element, Unit, ElementSet } from 'mol-model/structure'; import { Unit, ElementGroup } from 'mol-model/structure';
import P from 'mol-model/structure/query/properties'; import { RepresentationProps, UnitsRepresentation } from './index';
import { RepresentationProps, UnitRepresentation } from './index';
import { Task } from 'mol-task' 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 renderObjects: RenderObject[] = []
const vertices = ChunkedArray.create(Float32Array, 3, 1024, 2048); const vertices = ChunkedArray.create(Float32Array, 3, 1024, 2048);
return { return {
create: (units: ReadonlyArray<Unit>, elements: ElementSet, props: Partial<RepresentationProps> = {}) => Task.create('Spacefill', async ctx => { renderObjects,
const l = Element.Location(); create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: PointProps = {}) => 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;
for (let i = 0; i < elementCount; i++) { const { x, y, z } = units[0].model.conformation
l.element = OrderedSet.getAt(elementGroup.elements, i) const elementCount = OrderedSet.size(elementGroup.elements)
ChunkedArray.add3(vertices, P.atom.x(l), P.atom.y(l), P.atom.z(l)) 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) { 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 unitsCount = units.length
const m4 = Mat4.identity() const transformArray = new Float32Array(unitsCount * 16)
Mat4.toArray(m4, transformArray, 0) 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 ]) color.ref.value.set([ 0, 0, 255 ])
const points = createRenderObject('point', { const points = createRenderObject('point', {
...@@ -55,12 +54,10 @@ export default function Point(): UnitRepresentation { ...@@ -55,12 +54,10 @@ export default function Point(): UnitRepresentation {
color, color,
transform: ValueCell.create(transformArray), transform: ValueCell.create(transformArray),
instanceCount: transformArray.length / 16, instanceCount: unitsCount,
positionCount: vertices.elementCount positionCount: vertices.elementCount
}, {}) }, {})
renderObjects.push(points) renderObjects.push(points)
return renderObjects
}), }),
update: (props: RepresentationProps) => false update: (props: RepresentationProps) => false
} }
......
...@@ -10,62 +10,56 @@ import { createRenderObject, RenderObject } from 'mol-gl/renderer' ...@@ -10,62 +10,56 @@ import { createRenderObject, RenderObject } from 'mol-gl/renderer'
import { createColorTexture } from 'mol-gl/util'; import { createColorTexture } from 'mol-gl/util';
import { Vec3, Mat4 } from 'mol-math/linear-algebra' import { Vec3, Mat4 } from 'mol-math/linear-algebra'
import { OrderedSet } from 'mol-data/int' import { OrderedSet } from 'mol-data/int'
import { Element, Unit, ElementSet } from 'mol-model/structure'; import { Unit, ElementGroup } from 'mol-model/structure';
import P from 'mol-model/structure/query/properties'; import { RepresentationProps, UnitsRepresentation } from './index';
import { RepresentationProps, UnitRepresentation } from './index';
import { Task } from 'mol-task' import { Task } from 'mol-task'
import { MeshBuilder } from '../../shape/mesh-builder'; import { MeshBuilder } from '../../shape/mesh-builder';
import { VdwRadius } from 'mol-model/structure/model/properties/atomic';
export default function Spacefill(): UnitRepresentation { export const DefaultSpacefillProps = {
const renderObjects: RenderObject[] = []
}
export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
// unit: Unit, atomGroup: AtomGroup export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
const renderObjects: RenderObject[] = []
return { return {
create: (units: ReadonlyArray<Unit>, elements: ElementSet, props: Partial<RepresentationProps> = {}) => Task.create('Spacefill', async ctx => { renderObjects,
const l = Element.Location(); create: (units: ReadonlyArray<Unit>, elementGroup: ElementGroup, props: SpacefillProps = {}) => Task.create('Spacefill', async ctx => {
const meshBuilder = MeshBuilder.create() const meshBuilder = MeshBuilder.create()
const unitIds = ElementSet.unitIds(elements); const v = Vec3.zero()
for (let i = 0, _i = unitIds.length; i < _i; i++) { const m = Mat4.identity()
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 { x, y, z } = units[0].model.conformation
const m = Mat4.identity() 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++) { meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), detail: 0 })
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 })
}
if (i % 10 === 0 && ctx.shouldUpdate) { 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 unitsCount = units.length
const m4 = Mat4.identity() const transformArray = new Float32Array(unitsCount * 16)
Mat4.toArray(m4, transformArray, 0) 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 ]) color.ref.value.set([ 0, 0, 255 ])
const mesh = meshBuilder.getMesh() const mesh = meshBuilder.getMesh()
// console.log(mesh)
const spheres = createRenderObject('mesh', { const spheres = createRenderObject('mesh', {
position: mesh.vertexBuffer, position: mesh.vertexBuffer,
normal: mesh.normalBuffer, normal: mesh.normalBuffer,
...@@ -73,13 +67,11 @@ export default function Spacefill(): UnitRepresentation { ...@@ -73,13 +67,11 @@ export default function Spacefill(): UnitRepresentation {
transform: ValueCell.create(transformArray), transform: ValueCell.create(transformArray),
elements: mesh.indexBuffer, elements: mesh.indexBuffer,
instanceCount: transformArray.length / 16, instanceCount: unitsCount,
elementCount: mesh.triangleCount, elementCount: mesh.triangleCount,
positionCount: mesh.vertexCount positionCount: mesh.vertexCount
}, {}) }, {})
renderObjects.push(spheres) renderObjects.push(spheres)
return renderObjects
}), }),
update: (props: RepresentationProps) => false update: (props: RepresentationProps) => false
} }
......
...@@ -24,6 +24,7 @@ namespace Point { ...@@ -24,6 +24,7 @@ namespace Point {
} }
export function create(regl: REGL.Regl, data: Data): Renderable { export function create(regl: REGL.Regl, data: Data): Renderable {
console.log(data)
const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount))) const instanceId = ValueCell.create(fillSerial(new Float32Array(data.instanceCount)))
const command = regl({ const command = regl({
...PointShaders, ...PointShaders,
......
...@@ -70,7 +70,9 @@ export function createRenderer(container: HTMLDivElement): Renderer { ...@@ -70,7 +70,9 @@ export function createRenderer(container: HTMLDivElement): Renderer {
const camera = Camera.create(regl, container, { const camera = Camera.create(regl, container, {
center: Vec3.create(0, 0, 0), center: Vec3.create(0, 0, 0),
near: 0.01, near: 0.01,
far: 1000 far: 10000,
minDistance: 0.01,
maxDistance: 10000
}) })
const baseContext = regl({ const baseContext = regl({
......
...@@ -21,6 +21,6 @@ attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformCo ...@@ -21,6 +21,6 @@ attribute vec4 transformColumn0, transformColumn1, transformColumn2, transformCo
void main(){ void main(){
mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3); mat4 transform = mat4(transformColumn0, transformColumn1, transformColumn2, transformColumn3);
// vColor = color; // vColor = color;
gl_PointSize = 5.0; gl_PointSize = 1.0;
gl_Position = projection * view * model * transform * vec4(position, 1.0); gl_Position = projection * view * model * transform * vec4(position, 1.0);
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment