Newer
Older
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import './index.html'
import { Canvas3D } from 'mol-canvas3d/canvas3d';
import { MeshBuilder } from 'mol-geo/geometry/mesh/mesh-builder';
import { Sphere } from 'mol-geo/primitive/sphere';
import { Mat4, Vec3 } from 'mol-math/linear-algebra';
import { Shape } from 'mol-model/shape';
import { ShapeRepresentation } from 'mol-repr/shape/representation';
import { ColorNames } from 'mol-util/color/tables';
import { Mesh } from 'mol-geo/geometry/mesh/mesh';
import { labelFirst } from 'mol-theme/label';
import { RuntimeContext, Progress } from 'mol-task';
import { Representation } from 'mol-repr/representation';
import { MarkerAction } from 'mol-geo/geometry/marker-data';
import { EveryLoci } from 'mol-model/loci';
const parent = document.getElementById('app')!
parent.style.width = '100%'
parent.style.height = '100%'
const canvas = document.createElement('canvas')
canvas.style.width = '100%'
canvas.style.height = '100%'
parent.appendChild(canvas)
const info = document.createElement('div')
info.style.position = 'absolute'
info.style.fontFamily = 'sans-serif'
info.style.fontSize = '24pt'
info.style.bottom = '20px'
info.style.right = '20px'
info.style.color = 'white'
parent.appendChild(info)
const canvas3d = Canvas3D.create(canvas)
canvas3d.input.move.subscribe(({x, y}) => {
const pickingId = canvas3d.identify(x, y)
const reprLoci = canvas3d.getLoci(pickingId)
label = labelFirst(reprLoci.loci)
if (!Representation.Loci.areEqual(prevReprLoci, reprLoci)) {
canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight)
canvas3d.mark(reprLoci, MarkerAction.Highlight)
prevReprLoci = reprLoci
}
} else {
canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight)
prevReprLoci = Representation.Loci.Empty
}
info.innerText = label
})
/**
* Create a mesh of spheres at given centers
* - asynchronous (using async/await)
* - progress tracking (via `ctx.update`)
* - re-use storage from an existing mesh if given
*/
async function getSphereMesh(ctx: RuntimeContext, centers: number[], mesh?: Mesh) {
const builderState = MeshBuilder.createState(centers.length * 128, centers.length * 128 / 2, mesh)
const t = Mat4.identity()
const v = Vec3.zero()
builderState.currentGroup = 0
for (let i = 0, il = centers.length / 3; i < il; ++i) {
// for production, calls to update should be guarded by `if (ctx.shouldUpdate)`
await ctx.update({ current: i, max: il, message: `adding sphere ${i}` })
builderState.currentGroup = i
Mat4.setTranslation(t, Vec3.fromArray(v, centers, i * 3))
MeshBuilder.addPrimitive(builderState, t, sphere)
}
return MeshBuilder.getMesh(builderState)
}
MarcoSchaeferT
committed
centers: [0, 0, 0, 0, 3, 0, 1, 0 , 4],
colors: [ColorNames.tomato, ColorNames.springgreen, ColorNames.springgreen],
labels: ['Sphere 0, Instance A', 'Sphere 1, Instance A', 'Sphere 0, Instance B', 'Sphere 1, Instance B'],
transforms: [Mat4.identity(), Mat4.fromTranslation(Mat4.zero(), Vec3.create(3, 0, 0))]
}
/**
* Get shape from `MyData` object
*/
async function getShape(ctx: RuntimeContext, data: MyData, props: {}, shape?: Shape<Mesh>) {
await ctx.update('async creation of shape from myData')
const { centers, colors, labels, transforms } = data
const mesh = await getSphereMesh(ctx, centers, shape && shape.geometry)
const groupCount = centers.length / 3
(groupId: number) => colors[groupId], // color: per group, same for instances
() => 1, // size: constant
(groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId], // label: per group and instance
const repr = ShapeRepresentation(getShape, Mesh.Utils)
MarcoSchaeferT
committed
export async function init() {
// Create shape from myData and add to canvas3d
await repr.createOrUpdate({}, myData).run((p: Progress) => console.log(Progress.format(p)))
canvas3d.add(repr)
canvas3d.resetCamera()
// Change color after 1s
setTimeout(async () => {
myData.colors[0] = ColorNames.darkmagenta
// Calling `createOrUpdate` with `data` will trigger color and transform update
await repr.createOrUpdate({}, myData).run()
}, 1000)
}