From 7f0fae3916a94f17d8d11badc9166488f8edab52 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Fri, 1 Feb 2019 16:20:30 -0800 Subject: [PATCH] added StructureUnitTransforms, added unitTransforms to StructureRepresentationState --- src/mol-geo/geometry/transform-data.ts | 4 +- .../structure/util/unit-transforms.ts | 46 +++++++++++++++++++ src/mol-repr/shape/representation.ts | 4 +- .../structure/complex-representation.ts | 16 +++++-- src/mol-repr/structure/complex-visual.ts | 2 +- .../structure/units-representation.ts | 18 ++++++-- src/mol-repr/structure/units-visual.ts | 2 +- src/mol-repr/visual.ts | 9 ++-- 8 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 src/mol-model/structure/structure/util/unit-transforms.ts diff --git a/src/mol-geo/geometry/transform-data.ts b/src/mol-geo/geometry/transform-data.ts index 87f0b7ac9..de4b2b797 100644 --- a/src/mol-geo/geometry/transform-data.ts +++ b/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) } \ No newline at end of file diff --git a/src/mol-model/structure/structure/util/unit-transforms.ts b/src/mol-model/structure/structure/util/unit-transforms.ts new file mode 100644 index 000000000..84f2c5d6b --- /dev/null +++ b/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)] + } +} \ No newline at end of file diff --git a/src/mol-repr/shape/representation.ts b/src/mol-repr/shape/representation.ts index 96faec9f8..d0cec8c69 100644 --- a/src/mol-repr/shape/representation.ts +++ b/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) diff --git a/src/mol-repr/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts index ba7be4eec..b3ca4d235 100644 --- a/src/mol-repr/structure/complex-representation.ts +++ b/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) { diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts index e32467d1a..833e2126c 100644 --- a/src/mol-repr/structure/complex-visual.ts +++ b/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() { diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts index 5f3484040..ccf0e37f3 100644 --- a/src/mol-repr/structure/units-representation.ts +++ b/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) { diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index 0d16a1029..f7ed2da1b 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/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() { diff --git a/src/mol-repr/visual.ts b/src/mol-repr/visual.ts index e72cf38f2..7c24baaa9 100644 --- a/src/mol-repr/visual.ts +++ b/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) -- GitLab