|
@@ -14,6 +14,7 @@ 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';
|
|
|
|
|
|
const parent = document.getElementById('app')!
|
|
|
parent.style.width = '100%'
|
|
@@ -45,42 +46,67 @@ canvas3d.input.move.subscribe(async ({x, y}) => {
|
|
|
info.innerText = label
|
|
|
})
|
|
|
|
|
|
-const builderState = MeshBuilder.createState()
|
|
|
-const t = Mat4.identity()
|
|
|
-const sphere = Sphere(2)
|
|
|
-builderState.currentGroup = 0
|
|
|
-MeshBuilder.addPrimitive(builderState, t, sphere)
|
|
|
-const mesh = MeshBuilder.getMesh(builderState)
|
|
|
+/**
|
|
|
+ * 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()
|
|
|
+ const sphere = Sphere(2)
|
|
|
+ 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)
|
|
|
+}
|
|
|
|
|
|
const myData = {
|
|
|
- mesh,
|
|
|
- groupCount: 1,
|
|
|
+ centers: [0, 0, 0, 0, 3, 0],
|
|
|
colors: [ColorNames.tomato, ColorNames.springgreen],
|
|
|
- labels: ['FooBaz0', 'FooBaz1'],
|
|
|
+ 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))]
|
|
|
}
|
|
|
type MyData = typeof myData
|
|
|
-function getShape(data: MyData, props: {}, shape?: Shape<Mesh>) {
|
|
|
- const { mesh, colors, labels, transforms, groupCount } = data
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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
|
|
|
return shape || Shape.create(
|
|
|
'test', mesh,
|
|
|
- (groupId: number, instanceId: number) => colors[instanceId * groupCount + groupId],
|
|
|
- (groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId],
|
|
|
+ (groupId: number) => colors[groupId], // per group, same for instances
|
|
|
+ (groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId], // per group and instance
|
|
|
transforms
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+// Init ShapeRepresentation container
|
|
|
const repr = ShapeRepresentation(getShape, Mesh.Utils)
|
|
|
|
|
|
-async function add() {
|
|
|
- await repr.createOrUpdate({}, myData).run()
|
|
|
+async function init() {
|
|
|
+ // Create shape from myData and add to canvas3d
|
|
|
+ await repr.createOrUpdate({}, myData).run((p: Progress) => console.log(Progress.format(p)))
|
|
|
console.log(repr)
|
|
|
canvas3d.add(repr)
|
|
|
canvas3d.resetCamera()
|
|
|
-}
|
|
|
-add()
|
|
|
|
|
|
-setTimeout(async () => {
|
|
|
- myData.colors[0] = ColorNames.darkmagenta
|
|
|
- await repr.createOrUpdate({}, myData).run()
|
|
|
-}, 1000)
|
|
|
+ // 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)
|
|
|
+}
|
|
|
+init()
|