Skip to content
Snippets Groups Projects
Commit f1bbacbd authored by Alexander Rose's avatar Alexander Rose
Browse files

wip, structure animation

parent 9d730e95
Branches
Tags
No related merge requests found
......@@ -15,7 +15,9 @@ import { StateObjectCell, State } from 'mol-state';
const StructureAnimationParams = {
rotate: PD.Boolean(false),
explode: PD.Boolean(false)
rotateValue: PD.Numeric(0, { min: 0, max: 360, step: 0.1 }),
explode: PD.Boolean(false),
explodeValue: PD.Numeric(0, { min: 0, max: 100, step: 0.1 }),
}
type StructureAnimationProps = PD.Values<typeof StructureAnimationParams>
......@@ -38,7 +40,11 @@ function getRootStructure(root: StateObjectCell, state: State) {
return parent && parent.obj ? parent.obj as PluginStateObject.Molecule.Structure : undefined
}
// TODO this is just for testing purposes
/**
* TODO
* - animation class is just for testing purposes, needs better API
* - allow per-unit transform `unitTransform: { [unitId: number]: Mat4 }`
*/
export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>({
name: 'structure-animation',
display: { name: 'Structure Animation', group: 'Animation' },
......@@ -58,62 +64,68 @@ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>
this.update(params)
}
rotate(play: boolean) {
rotate(rad: number) {
const state = this.ctx.state.dataState
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D));
Mat4.rotate(this.rotMat, this.tmpMat, rad, this.rotVec)
for (const r of reprs) {
if (!SO.isRepresentation3D(r.obj)) return
const structure = getRootStructure(r, state)
if (!structure) continue
Vec3.negate(this.transVec, Vec3.copy(this.transVec, structure.data.boundary.sphere.center))
Mat4.fromTranslation(this.transMat, this.transVec)
Mat4.mul(this.animMat, this.rotMat, this.transMat)
Vec3.copy(this.transVec, structure.data.boundary.sphere.center)
Mat4.fromTranslation(this.transMat, this.transVec)
Mat4.mul(this.animMat, this.transMat, this.animMat)
r.obj.data.setState({ transform: this.animMat })
this.ctx.canvas3d.add(r.obj.data)
this.ctx.canvas3d.requestDraw(true)
}
}
animateRotate(play: boolean) {
if (play) {
const state = this.ctx.state.dataState
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D));
const rotate = (t: number) => {
const rad = degToRad((t / 10) % 360)
Mat4.rotate(this.rotMat, this.tmpMat, rad, this.rotVec)
for (const r of reprs) {
if (!SO.isRepresentation3D(r.obj)) return
const structure = getRootStructure(r, state)
if (!structure) continue
Vec3.negate(this.transVec, Vec3.copy(this.transVec, structure.data.boundary.sphere.center))
Mat4.fromTranslation(this.transMat, this.transVec)
Mat4.mul(this.animMat, this.rotMat, this.transMat)
Vec3.copy(this.transVec, structure.data.boundary.sphere.center)
Mat4.fromTranslation(this.transMat, this.transVec)
Mat4.mul(this.animMat, this.transMat, this.animMat)
r.obj.data.setState({ transform: this.animMat })
this.ctx.canvas3d.add(r.obj.data)
this.ctx.canvas3d.requestDraw(true)
}
this.rotateAnimHandle = requestAnimationFrame(rotate)
const animateRotate = (t: number) => {
this.rotate(degToRad((t / 10) % 360))
this.rotateAnimHandle = requestAnimationFrame(animateRotate)
}
this.rotateAnimHandle = requestAnimationFrame(rotate)
this.rotateAnimHandle = requestAnimationFrame(animateRotate)
} else {
cancelAnimationFrame(this.rotateAnimHandle)
}
}
explode(play: boolean) {
explode(d: number) {
const state = this.ctx.state.dataState
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D));
for (const r of reprs) {
if (!SO.isRepresentation3D(r.obj)) return
const structure = getStructure(r, state)
if (!structure) continue
const rootStructure = getRootStructure(r, state)
if (!rootStructure) continue
Vec3.sub(this.transVec, structure.data.boundary.sphere.center, rootStructure.data.boundary.sphere.center)
Vec3.setMagnitude(this.transVec, this.transVec, d)
Mat4.fromTranslation(this.animMat, this.transVec)
r.obj.data.setState({ transform: this.animMat })
this.ctx.canvas3d.add(r.obj.data)
this.ctx.canvas3d.requestDraw(true)
}
}
animateExplode(play: boolean) {
if (play) {
const state = this.ctx.state.dataState
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D));
const explode = (t: number) => {
const d = (Math.sin(t * 0.001) + 1) * 5
for (const r of reprs) {
if (!SO.isRepresentation3D(r.obj)) return
const structure = getStructure(r, state)
if (!structure) continue
const rootStructure = getRootStructure(r, state)
if (!rootStructure) continue
Vec3.sub(this.transVec, structure.data.boundary.sphere.center, rootStructure.data.boundary.sphere.center)
Vec3.setMagnitude(this.transVec, this.transVec, d)
Mat4.fromTranslation(this.animMat, this.transVec)
r.obj.data.setState({ transform: this.animMat })
this.ctx.canvas3d.add(r.obj.data)
this.ctx.canvas3d.requestDraw(true)
}
this.explodeAnimHandle = requestAnimationFrame(explode)
const animateExplode = (t: number) => {
this.explode((Math.sin(t * 0.001) + 1) * 5)
this.explodeAnimHandle = requestAnimationFrame(animateExplode)
}
this.explodeAnimHandle = requestAnimationFrame(explode)
this.explodeAnimHandle = requestAnimationFrame(animateExplode)
} else {
cancelAnimationFrame(this.explodeAnimHandle)
}
......@@ -125,11 +137,19 @@ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>
let updated = PD.areEqual(StructureAnimationParams, this.params, p)
if (this.params.rotate !== p.rotate) {
this.params.rotate = p.rotate
this.rotate(this.params.rotate)
this.animateRotate(this.params.rotate)
}
if (this.params.explode !== p.explode) {
this.params.explode = p.explode
this.explode(this.params.explode)
this.animateExplode(this.params.explode)
}
if (this.params.rotateValue !== p.rotateValue) {
this.params.rotateValue = p.rotateValue
this.rotate(degToRad(this.params.rotateValue))
}
if (this.params.explodeValue !== p.explodeValue) {
this.params.explodeValue = p.explodeValue
this.explode(this.params.explodeValue)
}
return updated;
}
......
......@@ -37,7 +37,7 @@ const DefaultSpec: PluginSpec = {
PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
PluginSpec.Behavior(PluginBehaviors.Camera.FocusLociOnSelect, { minRadius: 20, extraRadius: 4 }),
PluginSpec.Behavior(PluginBehaviors.Animation.StructureAnimation, { rotate: false, explode: false }),
PluginSpec.Behavior(PluginBehaviors.Animation.StructureAnimation, { rotate: false, rotateValue: 0, explode: false, explodeValue: 0 }),
PluginSpec.Behavior(PluginBehaviors.CustomProps.PDBeStructureQualityReport, { autoAttach: true }),
PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBAssemblySymmetry, { autoAttach: true }),
]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment