Bladeren bron

added GroupMapping to mesh, lines, spheres geometries

Alexander Rose 5 jaren geleden
bovenliggende
commit
872130d65c

+ 16 - 2
src/mol-geo/geometry/lines/lines.ts

@@ -6,7 +6,9 @@
 
 import { ValueCell } from '../../../mol-util'
 import { Mat4 } from '../../../mol-math/linear-algebra'
-import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../../util';
+import { transformPositionArray,/* , transformDirectionArray, getNormalMatrix */
+GroupMapping,
+createGroupMapping} from '../../util';
 import { GeometryUtils } from '../geometry';
 import { createColors } from '../color-data';
 import { createMarkers } from '../marker-data';
@@ -46,6 +48,8 @@ export interface Lines {
 
     /** Bounding sphere of the lines */
     readonly boundingSphere: Sphere3D
+    /** Maps group ids to line indices */
+    readonly groupMapping: GroupMapping
 }
 
 export namespace Lines {
@@ -95,7 +99,10 @@ export namespace Lines {
     function fromArrays(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number): Lines {
 
         const boundingSphere = Sphere3D()
+        let groupMapping: GroupMapping
+
         let currentHash = -1
+        let currentGroup = -1
 
         const lines = {
             kind: 'lines' as const,
@@ -111,11 +118,18 @@ export namespace Lines {
                     const s = calculateInvariantBoundingSphere(lines.startBuffer.ref.value, lines.lineCount * 4, 4)
                     const e = calculateInvariantBoundingSphere(lines.endBuffer.ref.value, lines.lineCount * 4, 4)
 
-                    Sphere3D.copy(boundingSphere, Sphere3D.expandBySphere(s, e))
+                    Sphere3D.expandBySphere(boundingSphere, s, e)
                     currentHash = newHash
                 }
                 return boundingSphere
             },
+            get groupMapping() {
+                if (lines.groupBuffer.ref.version !== currentGroup) {
+                    groupMapping = createGroupMapping(lines.groupBuffer.ref.value, lines.lineCount, 4)
+                    currentGroup = lines.groupBuffer.ref.version
+                }
+                return groupMapping
+            }
         }
         return lines
     }

+ 13 - 1
src/mol-geo/geometry/mesh/mesh.ts

@@ -8,7 +8,7 @@
 import { ValueCell } from '../../../mol-util'
 import { Vec3, Mat4, Mat3 } from '../../../mol-math/linear-algebra'
 import { Sphere3D } from '../../../mol-math/geometry'
-import { transformPositionArray, transformDirectionArray, computeIndexedVertexNormals} from '../../util';
+import { transformPositionArray, transformDirectionArray, computeIndexedVertexNormals, GroupMapping, createGroupMapping} from '../../util';
 import { GeometryUtils } from '../geometry';
 import { createMarkers } from '../marker-data';
 import { TransformData } from '../transform-data';
@@ -43,6 +43,8 @@ export interface Mesh {
 
     /** Bounding sphere of the mesh */
     readonly boundingSphere: Sphere3D
+    /** Maps group ids to vertex indices */
+    readonly groupMapping: GroupMapping
 }
 
 export namespace Mesh {
@@ -71,7 +73,10 @@ export namespace Mesh {
     function fromArrays(vertices: Float32Array, indices: Uint32Array, normals: Float32Array, groups: Float32Array, vertexCount: number, triangleCount: number): Mesh {
 
         const boundingSphere = Sphere3D()
+        let groupMapping: GroupMapping
+
         let currentHash = -1
+        let currentGroup = -1
 
         const mesh = {
             kind: 'mesh' as const,
@@ -90,6 +95,13 @@ export namespace Mesh {
                 }
                 return boundingSphere
             },
+            get groupMapping() {
+                if (mesh.groupBuffer.ref.version !== currentGroup) {
+                    groupMapping = createGroupMapping(mesh.groupBuffer.ref.value, mesh.vertexCount)
+                    currentGroup = mesh.groupBuffer.ref.version
+                }
+                return groupMapping
+            }
         }
         return mesh
     }

+ 13 - 0
src/mol-geo/geometry/spheres/spheres.ts

@@ -21,6 +21,7 @@ import { BaseGeometry } from '../base';
 import { createEmptyOverpaint } from '../overpaint-data';
 import { createEmptyTransparency } from '../transparency-data';
 import { hashFnv32a } from '../../../mol-data/util';
+import { GroupMapping, createGroupMapping } from '../../util';
 
 export interface Spheres {
     readonly kind: 'spheres',
@@ -39,6 +40,8 @@ export interface Spheres {
 
     /** Bounding sphere of the spheres */
     readonly boundingSphere: Sphere3D
+    /** Maps group ids to sphere indices */
+    readonly groupMapping: GroupMapping
 }
 
 export namespace Spheres {
@@ -67,7 +70,10 @@ export namespace Spheres {
     function fromArrays(centers: Float32Array, mappings: Float32Array, indices: Uint32Array, groups: Float32Array, sphereCount: number): Spheres {
 
         const boundingSphere = Sphere3D()
+        let groupMapping: GroupMapping
+
         let currentHash = -1
+        let currentGroup = -1
 
         const spheres = {
             kind: 'spheres' as const,
@@ -85,6 +91,13 @@ export namespace Spheres {
                 }
                 return boundingSphere
             },
+            get groupMapping() {
+                if (spheres.groupBuffer.ref.version !== currentGroup) {
+                    groupMapping = createGroupMapping(spheres.groupBuffer.ref.value, spheres.sphereCount, 4)
+                    currentGroup = spheres.groupBuffer.ref.version
+                }
+                return groupMapping
+            }
         }
         return spheres
     }

+ 42 - 1
src/mol-geo/util.ts

@@ -6,6 +6,7 @@
 
 import { Vec3, Mat4, Mat3 } from '../mol-math/linear-algebra'
 import { NumberArray } from '../mol-util/type-helpers';
+import { arrayMax } from '../mol-util/array';
 
 export function normalizeVec3Array<T extends NumberArray> (a: T, count: number) {
     for (let i = 0, il = count * 3; i < il; i += 3) {
@@ -118,4 +119,44 @@ export function computeVertexNormals<T extends NumberArray> (vertices: NumberArr
     }
 
     return normalizeVec3Array(normals, vertexCount)
-}
+}
+
+/**
+ * Maps groups to data, range for group i is offsets[i] to offsets[i + 1]
+ */
+export type GroupMapping = {
+    /** data indices */
+    readonly indices: ArrayLike<number>
+    /** range for group i is offsets[i] to offsets[i + 1] */
+    readonly offsets: ArrayLike<number>
+}
+
+/**
+ * The `step` parameter allows to skip over repeated values in `groups`
+ */
+export function createGroupMapping(groups: ArrayLike<number>, dataCount: number, step = 1): GroupMapping {
+    const maxId = arrayMax(groups)
+
+    const offsets = new Int32Array(maxId + 2)
+    const bucketFill = new Int32Array(dataCount)
+    const bucketSizes = new Int32Array(dataCount)
+
+    for (let i = 0, il = dataCount * step; i < il; i += step) ++bucketSizes[groups[i]]
+
+    let offset = 0
+    for (let i = 0; i < dataCount; i++) {
+        offsets[i] = offset
+        offset += bucketSizes[i]
+    }
+    offsets[dataCount] = offset
+
+    const indices = new Int32Array(offset)
+    for (let i = 0, il = dataCount * step; i < il; i += step) {
+        const g = groups[i]
+        const og = offsets[g] + bucketFill[g]
+        indices[og] = i
+        ++bucketFill[g]
+    }
+
+    return { indices, offsets }
+}