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 @@
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()
}
......
......@@ -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>[] = []
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));
(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);
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
// 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
......@@ -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();
renderObjects,
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 { x, y, z } = units[0].model.conformation
const elementCount = OrderedSet.size(elementGroup.elements)
l.unit = unit;
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 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
}
......
......@@ -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 { 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++) {
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)
const e = OrderedSet.getAt(elementGroup.elements, i)
v[0] = x[e]
v[1] = y[e]
v[2] = z[e]
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
}
......
......@@ -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,
......
......@@ -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({
......
......@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment