Browse Source

added StructureUnitTransforms, added unitTransforms to StructureRepresentationState

Alexander Rose 6 years ago
parent
commit
7f0fae3916

+ 2 - 2
src/mol-geo/geometry/transform-data.ts

@@ -85,8 +85,8 @@ export function updateTransformData(transformData: TransformData) {
     const extraTransform = transformData.extraTransform.ref.value
     for (let i = 0; i < instanceCount; i++) {
         const i16 = i * 16
-        Mat4.mulOffset(aTransform, transform, extraTransform, i16, i16, i16)
-        Mat4.mulOffset(aTransform, aTransform, matrix, i16, i16, 0)
+        Mat4.mulOffset(aTransform, extraTransform, transform, i16, i16, i16)
+        Mat4.mulOffset(aTransform, matrix, aTransform, i16, 0, i16)
     }
     ValueCell.update(transformData.aTransform, aTransform)
 }

+ 46 - 0
src/mol-model/structure/structure/util/unit-transforms.ts

@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Structure, Unit } from 'mol-model/structure';
+import { Mat4 } from 'mol-math/linear-algebra';
+import { IntMap } from 'mol-data/int';
+import { fillIdentityTransform } from 'mol-geo/geometry/transform-data';
+
+export class StructureUnitTransforms {
+    private unitTransforms: Float32Array
+    private groupUnitTransforms: Float32Array[] = []
+    /** maps unit.id to offset of transform in unitTransforms */
+    private unitOffsetMap = IntMap.Mutable<number>();
+    private groupIndexMap = IntMap.Mutable<number>();
+
+    constructor(readonly structure: Structure) {
+        this.unitTransforms = new Float32Array(structure.units.length * 16)
+        fillIdentityTransform(this.unitTransforms, structure.units.length)
+        let groupOffset = 0
+        for (let i = 0, il = structure.unitSymmetryGroups.length; i <il; ++i) {
+            const g = structure.unitSymmetryGroups[i]
+            this.groupIndexMap.set(g.hashCode, i)
+            const groupTransforms = this.unitTransforms.subarray(groupOffset, groupOffset + g.units.length * 16)
+            this.groupUnitTransforms.push(groupTransforms)
+            for (let j = 0, jl = g.units.length; j < jl; ++j) {
+                this.unitOffsetMap.set(g.units[j].id, groupOffset + j * 16)
+            }
+            groupOffset += g.units.length * 16
+        }
+    }
+
+    setTransform(matrix: Mat4, unit: Unit) {
+        Mat4.toArray(matrix, this.unitTransforms, this.unitOffsetMap.get(unit.id))
+    }
+
+    getTransform(out: Mat4, unit: Unit) {
+        return Mat4.fromArray(out, this.unitTransforms, this.unitOffsetMap.get(unit.id))
+    }
+
+    getSymmetryGroupTransforms(group: Unit.SymmetryGroup): Float32Array {
+        return this.groupUnitTransforms[this.groupIndexMap.get(group.hashCode)]
+    }
+}

+ 1 - 3
src/mol-repr/shape/representation.ts

@@ -196,9 +196,7 @@ export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Pa
             if (_renderObject) {
                 if (state.visible !== undefined) Visual.setVisibility(_renderObject, state.visible)
                 if (state.pickable !== undefined) Visual.setPickable(_renderObject, state.pickable)
-                if (state.transform !== undefined || state.instanceTransforms !== undefined) {
-                    Visual.setTransform(_renderObject, state.transform, state.instanceTransforms)
-                }
+                if (state.transform !== undefined) Visual.setTransform(_renderObject, state.transform)
             }
 
             Representation.updateState(_state, state)

+ 12 - 4
src/mol-repr/structure/complex-representation.ts

@@ -52,12 +52,20 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
         return visual ? visual.mark(loci, action) : false
     }
 
-    function setState(state: Partial<Representation.State>) {
-        if (state.visible !== undefined && visual) visual.setVisibility(state.visible)
+    function setState(state: Partial<StructureRepresentationState>) {
+        StructureRepresentationStateBuilder.update(_state, state)
+
+        if (state.visible !== undefined && visual) {
+            // hide visual when _unitTransforms is set
+            visual.setVisibility(state.visible && _state.unitTransforms === null)
+        }
         if (state.pickable !== undefined && visual) visual.setPickable(state.pickable)
         if (state.transform !== undefined && visual) visual.setTransform(state.transform)
-
-        Representation.updateState(_state, state)
+        if (state.unitTransforms !== undefined && visual) {
+            // Since ComplexVisuals always renders geometries between units the application of `unitTransforms`
+            // does not make sense. When given it is ignored here and sets the visual's visibility to `false`.
+            visual.setVisibility(_state.visible && state.unitTransforms === null)
+        }
     }
 
     function setTheme(theme: Theme) {

+ 1 - 1
src/mol-repr/structure/complex-visual.ts

@@ -200,7 +200,7 @@ export function ComplexVisual<G extends Geometry, P extends ComplexParams & Geom
         setPickable(pickable: boolean) {
             Visual.setPickable(renderObject, pickable)
         },
-        setTransform(matrix?: Mat4, instanceMatrices?: Float32Array) {
+        setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
             Visual.setTransform(renderObject, matrix, instanceMatrices)
         },
         destroy() {

+ 13 - 5
src/mol-repr/structure/units-representation.ts

@@ -162,15 +162,23 @@ export function UnitsRepresentation<P extends UnitsParams>(label: string, ctx: R
         return changed
     }
 
-    function setState(state: Partial<Representation.State>) {
-        const { visible, pickable, transform, instanceTransforms } = state
+    function setState(state: Partial<StructureRepresentationState>) {
+        const { visible, pickable, transform, unitTransforms } = state
         if (visible !== undefined) visuals.forEach(({ visual }) => visual.setVisibility(visible))
         if (pickable !== undefined) visuals.forEach(({ visual }) => visual.setPickable(pickable))
-        if (transform !== undefined || instanceTransforms !== undefined) {
-            visuals.forEach(({ visual }) => visual.setTransform(transform, instanceTransforms))
+        if (transform !== undefined) visuals.forEach(({ visual }) => visual.setTransform(transform))
+        if (unitTransforms !== undefined) {
+            visuals.forEach(({ visual, group }) => {
+                if (unitTransforms) {
+                    // console.log(group.hashCode, unitTransforms.getSymmetryGroupTransforms(group))
+                    visual.setTransform(undefined, unitTransforms.getSymmetryGroupTransforms(group))
+                } else {
+                    visual.setTransform(undefined, null)
+                }
+            })
         }
 
-        Representation.updateState(_state, state)
+        StructureRepresentationStateBuilder.update(_state, state)
     }
 
     function setTheme(theme: Theme) {

+ 1 - 1
src/mol-repr/structure/units-visual.ts

@@ -246,7 +246,7 @@ export function UnitsVisual<G extends Geometry, P extends UnitsParams & Geometry
         setPickable(pickable: boolean) {
             Visual.setPickable(renderObject, pickable)
         },
-        setTransform(matrix?: Mat4, instanceMatrices?: Float32Array) {
+        setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) {
             Visual.setTransform(renderObject, matrix, instanceMatrices)
         },
         destroy() {

+ 6 - 3
src/mol-repr/visual.ts

@@ -13,7 +13,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
 import { WebGLContext } from 'mol-gl/webgl/context';
 import { Theme } from 'mol-theme/theme';
 import { Mat4 } from 'mol-math/linear-algebra';
-import { updateTransformData } from 'mol-geo/geometry/transform-data';
+import { updateTransformData, fillIdentityTransform } from 'mol-geo/geometry/transform-data';
 import { calculateTransformBoundingSphere } from 'mol-gl/renderable/util';
 import { ValueCell } from 'mol-util';
 
@@ -33,7 +33,7 @@ interface Visual<D, P extends PD.Params> {
     mark: (loci: Loci, action: MarkerAction) => boolean
     setVisibility: (visible: boolean) => void
     setPickable: (pickable: boolean) => void
-    setTransform: (matrix?: Mat4, instanceMatrices?: Float32Array) => void
+    setTransform: (matrix?: Mat4, instanceMatrices?: Float32Array | null) => void
     destroy: () => void
 }
 namespace Visual {
@@ -45,7 +45,7 @@ namespace Visual {
         if (renderObject) renderObject.state.pickable = pickable
     }
 
-    export function setTransform(renderObject: GraphicsRenderObject | undefined, transform?: Mat4, instanceTransforms?: Float32Array) {
+    export function setTransform(renderObject: GraphicsRenderObject | undefined, transform?: Mat4, instanceTransforms?: Float32Array | null) {
         if (renderObject && (transform || instanceTransforms)) {
             const { values } = renderObject
             if (transform) {
@@ -55,6 +55,9 @@ namespace Visual {
             if (instanceTransforms) {
                 values.extraTransform.ref.value.set(instanceTransforms)
                 ValueCell.update(values.extraTransform, values.extraTransform.ref.value)
+            } else if (instanceTransforms === null) {
+                fillIdentityTransform(values.extraTransform.ref.value, values.instanceCount.ref.value)
+                ValueCell.update(values.extraTransform, values.extraTransform.ref.value)
             }
             updateTransformData(values)
             const boundingSphere = calculateTransformBoundingSphere(values.invariantBoundingSphere.ref.value, values.aTransform.ref.value, values.instanceCount.ref.value)