diff --git a/src/mol-canvas3d/helper/bounding-sphere-helper.ts b/src/mol-canvas3d/helper/bounding-sphere-helper.ts index cb2c3d85ebccb3c690059f34107ac106869c2c63..78dcca7ba9e5ff5c4f5ab28ca30b21431adc4a6e 100644 --- a/src/mol-canvas3d/helper/bounding-sphere-helper.ts +++ b/src/mol-canvas3d/helper/bounding-sphere-helper.ts @@ -56,6 +56,7 @@ export class BoundingSphereHelper { const instanceData = this.instancesData.get(ro) const newInstanceData = updateBoundingSphereData(this.scene, r.invariantBoundingSphere, instanceData, ColorNames.skyblue, { aTransform: ro.values.aTransform, + transform: ro.values.transform, uInstanceCount: ro.values.uInstanceCount, instanceCount: ro.values.instanceCount, aInstance: ro.values.aInstance, diff --git a/src/mol-geo/geometry/transform-data.ts b/src/mol-geo/geometry/transform-data.ts index 2c1fd8690a6cb33b37faf6a31b7ba6d2f559de35..9c4b093c359ab71a6e1eb72e6155145ea27b0500 100644 --- a/src/mol-geo/geometry/transform-data.ts +++ b/src/mol-geo/geometry/transform-data.ts @@ -10,6 +10,7 @@ import { fillSerial } from 'mol-util/array'; export type TransformData = { aTransform: ValueCell<Float32Array>, + transform: ValueCell<Float32Array>, uInstanceCount: ValueCell<number>, instanceCount: ValueCell<number>, aInstance: ValueCell<Float32Array>, @@ -26,6 +27,7 @@ export function createTransform(transformArray: Float32Array, instanceCount: num } else { return { aTransform: ValueCell.create(transformArray), + transform: ValueCell.create(new Float32Array(transformArray)), uInstanceCount: ValueCell.create(instanceCount), instanceCount: ValueCell.create(instanceCount), aInstance: ValueCell.create(fillSerial(new Float32Array(instanceCount))) @@ -37,4 +39,17 @@ const identityTransform = new Float32Array(16) Mat4.toArray(Mat4.identity(), identityTransform, 0) export function createIdentityTransform(transformData?: TransformData): TransformData { return createTransform(identityTransform, 1, transformData) +} + +const tmpTransformMat4 = Mat4.identity() +export function setTransform(matrix: Mat4, transformData: TransformData) { + const instanceCount = transformData.instanceCount.ref.value + const transform = transformData.transform.ref.value + const aTransform = transformData.aTransform.ref.value + for (let i = 0; i < instanceCount; i++) { + Mat4.fromArray(tmpTransformMat4, transform, i * 16) + Mat4.mul(tmpTransformMat4, tmpTransformMat4, matrix) + Mat4.toArray(tmpTransformMat4, aTransform, i * 16) + } + ValueCell.update(transformData.aTransform, aTransform) } \ No newline at end of file diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts index 64a859e14cd5a44824cad68fd517bc284ecb5ffe..1f580b19975f0be7d9698ea336814bbfe0b9ed38 100644 --- a/src/mol-gl/_spec/renderer.spec.ts +++ b/src/mol-gl/_spec/renderer.spec.ts @@ -56,6 +56,7 @@ function createPoints() { const aTransform = ValueCell.create(new Float32Array(16)) const m4 = Mat4.identity() Mat4.toArray(m4, aTransform.ref.value, 0) + const transform = ValueCell.create(new Float32Array(aTransform.ref.value)) const boundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2)) const invariantBoundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2)) @@ -77,6 +78,7 @@ function createPoints() { drawCount: ValueCell.create(3), instanceCount: ValueCell.create(1), + transform, boundingSphere, invariantBoundingSphere, diff --git a/src/mol-gl/renderable/direct-volume.ts b/src/mol-gl/renderable/direct-volume.ts index 228cdec89e6fb0f5111b0c4e41d7d12d527ef7b9..b704e81ab874546491b4ffff9c76cf2ccf80b893 100644 --- a/src/mol-gl/renderable/direct-volume.ts +++ b/src/mol-gl/renderable/direct-volume.ts @@ -28,6 +28,7 @@ export const DirectVolumeSchema = { drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), + transform: AttributeSpec('float32', 16, 1), boundingSphere: ValueSpec('sphere'), invariantBoundingSphere: ValueSpec('sphere'), diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index 3bfac0c71e543d278ab36709b3210c8241a10f63..35a90f85d71e19442f9af5826713bb8b90eb9969 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -198,6 +198,7 @@ export const BaseSchema = { drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), + transform: AttributeSpec('float32', 16, 1), boundingSphere: ValueSpec('sphere'), invariantBoundingSphere: ValueSpec('sphere'), diff --git a/src/mol-repr/representation.ts b/src/mol-repr/representation.ts index 4f81047880b6e59fbb0b50ba3eaa5bac82d275af..3c7b2e95d862c9446b4b70b7dc6b18191191cddc 100644 --- a/src/mol-repr/representation.ts +++ b/src/mol-repr/representation.ts @@ -106,9 +106,13 @@ interface Representation<D, P extends PD.Params = {}> { } namespace Representation { export interface State { + /** Controls if the representation's renderobjects are rendered or not */ visible: boolean + /** Controls if the representation's renderobjects are pickable or not */ pickable: boolean + /** Controls if the representation's renderobjects are synced automatically with GPU or not */ syncManually: boolean + /** A transformation applied to the representation's renderobjects */ transform: Mat4 } export function createState() { @@ -255,5 +259,6 @@ export interface Visual<D, P extends PD.Params> { mark: (loci: Loci, action: MarkerAction) => boolean setVisibility: (value: boolean) => void setPickable: (value: boolean) => void + setTransform: (value: Mat4) => void destroy: () => void } \ No newline at end of file diff --git a/src/mol-repr/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts index 0ff4e4561a157970caa03ea963d3bab98ad1f82e..187f8608d23642d29bff26e0871a600f7be124e1 100644 --- a/src/mol-repr/structure/complex-representation.ts +++ b/src/mol-repr/structure/complex-representation.ts @@ -55,6 +55,7 @@ export function ComplexRepresentation<P extends StructureParams>(label: string, function setState(state: Partial<Representation.State>) { if (state.visible !== undefined && visual) visual.setVisibility(state.visible) if (state.pickable !== undefined && visual) visual.setPickable(state.pickable) + if (state.transform !== undefined && visual) visual.setTransform(state.transform) Representation.updateState(_state, state) } diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts index 30801c4e8eb1ada58c38e5367c10bb6dfe262111..f5217b91a9d6024fff8b66267c1d1d0dd1ac9a69 100644 --- a/src/mol-repr/structure/complex-visual.ts +++ b/src/mol-repr/structure/complex-visual.ts @@ -28,6 +28,8 @@ import { SizeTheme } from 'mol-theme/size'; import { RenderableState } from 'mol-gl/renderable'; import { UnitsParams } from './units-representation'; import { DirectVolume } from 'mol-geo/geometry/direct-volume/direct-volume'; +import { Mat4 } from 'mol-math/linear-algebra'; +import { setTransform } from 'mol-geo/geometry/transform-data'; export interface ComplexVisual<P extends StructureParams> extends Visual<Structure, P> { } @@ -198,6 +200,9 @@ export function ComplexVisual<P extends ComplexParams>(builder: ComplexVisualGeo setPickable(value: boolean) { if (renderObject) renderObject.state.pickable = value }, + setTransform(value: Mat4) { + if (renderObject) setTransform(value, renderObject.values) + }, destroy() { // TODO renderObject = undefined diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts index 4d7f31f02ebb3b3fc1854b95a7ecbbf5cc42653c..5a0b0484b44bbebf3c786d1a4f2a397ea230f6dd 100644 --- a/src/mol-repr/structure/units-representation.ts +++ b/src/mol-repr/structure/units-representation.ts @@ -164,6 +164,7 @@ export function UnitsRepresentation<P extends UnitsParams>(label: string, ctx: R function setState(state: Partial<Representation.State>) { if (state.visible !== undefined) visuals.forEach(({ visual }) => visual.setVisibility(state.visible!)) if (state.pickable !== undefined) visuals.forEach(({ visual }) => visual.setPickable(state.pickable!)) + if (state.transform !== undefined) visuals.forEach(({ visual }) => visual.setTransform(state.transform!)) Representation.updateState(_state, state) } diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index d915e952184e32d04aeafdc976de840570a9e04c..0aafc91dd1275e7715236ee6210f4b4c3a608c30 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/src/mol-repr/structure/units-visual.ts @@ -30,6 +30,8 @@ import { ColorTheme } from 'mol-theme/color'; import { SizeTheme } from 'mol-theme/size'; import { UnitsParams } from './units-representation'; import { RenderableState } from 'mol-gl/renderable'; +import { Mat4 } from 'mol-math/linear-algebra'; +import { setTransform } from 'mol-geo/geometry/transform-data'; export type StructureGroup = { structure: Structure, group: Unit.SymmetryGroup } @@ -242,6 +244,9 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB setPickable(value: boolean) { if (renderObject) renderObject.state.pickable = value }, + setTransform(value: Mat4) { + if (renderObject) setTransform(value, renderObject.values) + }, destroy() { // TODO renderObject = undefined diff --git a/src/mol-repr/volume/representation.ts b/src/mol-repr/volume/representation.ts index c80d70ecfae307c10cd653507b30d99c51da9525..a361ad32d738a75c4908f4216db70dc54066d613 100644 --- a/src/mol-repr/volume/representation.ts +++ b/src/mol-repr/volume/representation.ts @@ -22,6 +22,8 @@ import { ValueCell } from 'mol-util'; import { Theme, createEmptyTheme } from 'mol-theme/theme'; import { Subject } from 'rxjs'; import { RenderableState } from 'mol-gl/renderable'; +import { Mat4 } from 'mol-math/linear-algebra'; +import { setTransform } from 'mol-geo/geometry/transform-data'; export interface VolumeVisual<P extends VolumeParams> extends Visual<VolumeData, P> { } @@ -128,6 +130,9 @@ export function VolumeVisual<P extends VolumeParams>(builder: VolumeVisualGeomet setPickable(value: boolean) { if (renderObject) renderObject.state.pickable = value }, + setTransform(value: Mat4) { + if (renderObject) setTransform(value, renderObject.values) + }, destroy() { // TODO renderObject = undefined