From 2ad23d6c2929681497857567c3db4f659b594bc4 Mon Sep 17 00:00:00 2001
From: Alexander Rose <alexander.rose@weirdbyte.de>
Date: Sun, 3 Jun 2018 00:19:12 -0400
Subject: [PATCH] refactored spacefill creation a bit

---
 .../representation/structure/spacefill.ts     | 62 +++++--------------
 src/mol-geo/representation/structure/utils.ts | 43 ++++++++++++-
 src/mol-geo/shape/mesh.ts                     | 22 +++++++
 src/mol-geo/util/marching-cubes/algorithm.ts  |  1 +
 4 files changed, 77 insertions(+), 51 deletions(-)

diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts
index f2ace9de1..ebfbe71a1 100644
--- a/src/mol-geo/representation/structure/spacefill.ts
+++ b/src/mol-geo/representation/structure/spacefill.ts
@@ -8,15 +8,11 @@
 import { ValueCell } from 'mol-util/value-cell'
 
 import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'
-// import { createColorTexture } from 'mol-gl/util';
-import { Vec3, Mat4 } from 'mol-math/linear-algebra'
 import { Unit, Element, Queries } from 'mol-model/structure';
 import { UnitsRepresentation, DefaultStructureProps } from './index';
 import { Task } from 'mol-task'
-import { MeshBuilder } from '../../shape/mesh-builder';
-import { createTransforms, createColors, createFlags, createEmptyFlags } from './utils';
+import { createTransforms, createColors, createFlags, createEmptyFlags, createSphereMesh } from './utils';
 import VertexMap from '../../shape/vertex-map';
-import { icosahedronVertexCount } from '../../primitive/icosahedron';
 import { deepEqual, defaults } from 'mol-util';
 import { fillSerial } from 'mol-gl/renderable/util';
 import { RenderableState, MeshValues } from 'mol-gl/renderable';
@@ -24,6 +20,19 @@ import { getMeshData } from '../../util/mesh-data';
 import { Mesh } from '../../shape/mesh';
 import { PickingId } from '../../util/picking';
 
+function createSpacefillMesh(unit: Unit, detail: number, mesh?: Mesh) {
+    let radius: Element.Property<number>
+    if (Unit.isAtomic(unit)) {
+        radius = Queries.props.atom.vdw_radius
+    } else if (Unit.isSpheres(unit)) {
+        radius = Queries.props.coarse.sphere_radius
+    } else {
+        console.warn('Unsupported unit type')
+        return Task.constant('Empty mesh', Mesh.createEmpty(mesh))
+    }
+    return createSphereMesh(unit, radius, detail, mesh)
+}
+
 export const DefaultSpacefillProps = {
     ...DefaultStructureProps,
     flipSided: false,
@@ -32,49 +41,6 @@ export const DefaultSpacefillProps = {
 }
 export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
 
-function createSpacefillMesh(unit: Unit, detail: number, mesh?: Mesh) {
-    return Task.create('Sphere mesh', async ctx => {
-        const { elements } = unit;
-        const elementCount = elements.length;
-        const vertexCount = elementCount * icosahedronVertexCount(detail)
-        const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
-
-        let radius: Element.Property<number>
-        if (Unit.isAtomic(unit)) {
-            radius = Queries.props.atom.vdw_radius
-        } else if (Unit.isSpheres(unit)) {
-            radius = Queries.props.coarse.sphere_radius
-        } else {
-            console.warn('Unsupported unit type')
-            return meshBuilder.getMesh()
-        }
-
-        const v = Vec3.zero()
-        const m = Mat4.identity()
-
-        const { x, y, z } = unit.conformation
-        const l = Element.Location()
-        l.unit = unit
-
-        for (let i = 0; i < elementCount; i++) {
-            l.element = elements[i]
-            v[0] = x(l.element)
-            v[1] = y(l.element)
-            v[2] = z(l.element)
-            Mat4.setTranslation(m, v)
-
-            meshBuilder.setId(i)
-            meshBuilder.addIcosahedron(m, { radius: radius(l), detail })
-
-            if (i % 10000 === 0 && ctx.shouldUpdate) {
-                await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
-            }
-        }
-
-        return meshBuilder.getMesh()
-    })
-}
-
 export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
     const renderObjects: RenderObject[] = []
     let spheres: MeshRenderObject
diff --git a/src/mol-geo/representation/structure/utils.ts b/src/mol-geo/representation/structure/utils.ts
index cee35dd1e..5771c3f12 100644
--- a/src/mol-geo/representation/structure/utils.ts
+++ b/src/mol-geo/representation/structure/utils.ts
@@ -5,8 +5,8 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { Unit } from 'mol-model/structure';
-import { Mat4, Vec2 } from 'mol-math/linear-algebra'
+import { Unit, Element } from 'mol-model/structure';
+import { Mat4, Vec2, Vec3 } from 'mol-math/linear-algebra'
 
 import { createUniformColor, ColorData } from '../../util/color-data';
 import { createUniformSize } from '../../util/size-data';
@@ -16,6 +16,10 @@ import { ColorTheme, SizeTheme } from '../../theme';
 import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color';
 import { ValueCell } from 'mol-util';
 import { TextureImage, createTextureImage } from 'mol-gl/renderable/util';
+import { Mesh } from '../../shape/mesh';
+import { Task } from 'mol-task';
+import { icosahedronVertexCount } from '../../primitive/icosahedron';
+import { MeshBuilder } from '../../shape/mesh-builder';
 
 export function createTransforms({ units }: Unit.SymmetryGroup, transforms?: ValueCell<Float32Array>) {
     const unitCount = units.length
@@ -93,4 +97,37 @@ export function createEmptyFlags(flagData?: FlagData) {
             uFlagTexSize: ValueCell.create(Vec2.create(1, 1)),
         }
     }
-}
\ No newline at end of file
+}
+
+export function createSphereMesh(unit: Unit, radius: Element.Property<number>, detail: number, mesh?: Mesh) {
+    return Task.create('Sphere mesh', async ctx => {
+        const { elements } = unit;
+        const elementCount = elements.length;
+        const vertexCount = elementCount * icosahedronVertexCount(detail)
+        const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
+
+        const v = Vec3.zero()
+        const m = Mat4.identity()
+
+        const { x, y, z } = unit.conformation
+        const l = Element.Location()
+        l.unit = unit
+
+        for (let i = 0; i < elementCount; i++) {
+            l.element = elements[i]
+            v[0] = x(l.element)
+            v[1] = y(l.element)
+            v[2] = z(l.element)
+            Mat4.setTranslation(m, v)
+
+            meshBuilder.setId(i)
+            meshBuilder.addIcosahedron(m, { radius: radius(l), detail })
+
+            if (i % 10000 === 0 && ctx.shouldUpdate) {
+                await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
+            }
+        }
+
+        return meshBuilder.getMesh()
+    })
+}
diff --git a/src/mol-geo/shape/mesh.ts b/src/mol-geo/shape/mesh.ts
index 6d63fd851..9447404a3 100644
--- a/src/mol-geo/shape/mesh.ts
+++ b/src/mol-geo/shape/mesh.ts
@@ -15,6 +15,8 @@ export interface Mesh {
     vertexCount: number,
     /** Number of triangles in the mesh */
     triangleCount: number,
+    /** Number of offsets in the mesh */
+    offsetCount: number,
 
     /** Vertex buffer as array of xyz values wrapped in a value cell */
     vertexBuffer: ValueCell<Float32Array>,
@@ -37,6 +39,26 @@ export interface Mesh {
 }
 
 export namespace Mesh {
+    export function createEmpty(mesh?: Mesh): Mesh {
+        const vb = mesh ? mesh.vertexBuffer.ref.value : new Float32Array(0)
+        const ib = mesh ? mesh.indexBuffer.ref.value : new Uint32Array(0)
+        const nb = mesh ? mesh.normalBuffer.ref.value : new Float32Array(0)
+        const idb = mesh ? mesh.idBuffer.ref.value : new Float32Array(0)
+        const ob = mesh ? mesh.offsetBuffer.ref.value : new Uint32Array(0)
+        return {
+            vertexCount: 0,
+            triangleCount: 0,
+            offsetCount: 0,
+            vertexBuffer: mesh ? ValueCell.update(mesh.vertexBuffer, vb) : ValueCell.create(vb),
+            indexBuffer: mesh ? ValueCell.update(mesh.indexBuffer, ib) : ValueCell.create(ib),
+            normalBuffer: mesh ? ValueCell.update(mesh.normalBuffer, nb) : ValueCell.create(nb),
+            idBuffer: mesh ? ValueCell.update(mesh.idBuffer, idb) : ValueCell.create(idb),
+            offsetBuffer: mesh ? ValueCell.update(mesh.offsetBuffer, ob) : ValueCell.create(ob),
+            normalsComputed: true,
+            offsetsComputed: true,
+        }
+    }
+
     export function computeNormalsImmediate(surface: Mesh) {
         if (surface.normalsComputed) return;
 
diff --git a/src/mol-geo/util/marching-cubes/algorithm.ts b/src/mol-geo/util/marching-cubes/algorithm.ts
index 248f05397..4b2eaf964 100644
--- a/src/mol-geo/util/marching-cubes/algorithm.ts
+++ b/src/mol-geo/util/marching-cubes/algorithm.ts
@@ -76,6 +76,7 @@ class MarchingCubesComputation {
         const ret: Mesh = {
             vertexCount:  this.state.vertexCount,
             triangleCount: this.state.triangleCount,
+            offsetCount: 0,
             vertexBuffer: os ? ValueCell.update(os.vertexBuffer, vb) : ValueCell.create(vb),
             indexBuffer: os ? ValueCell.update(os.indexBuffer, ib) : ValueCell.create(ib),
             normalBuffer: os ? os.normalBuffer : ValueCell.create(new Float32Array(0)),
-- 
GitLab