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

wip, structure animation

parent 9d730e95
No related branches found
No related tags found
No related merge requests found
...@@ -15,7 +15,9 @@ import { StateObjectCell, State } from 'mol-state'; ...@@ -15,7 +15,9 @@ import { StateObjectCell, State } from 'mol-state';
const StructureAnimationParams = { const StructureAnimationParams = {
rotate: PD.Boolean(false), 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> type StructureAnimationProps = PD.Values<typeof StructureAnimationParams>
...@@ -38,7 +40,11 @@ function getRootStructure(root: StateObjectCell, state: State) { ...@@ -38,7 +40,11 @@ function getRootStructure(root: StateObjectCell, state: State) {
return parent && parent.obj ? parent.obj as PluginStateObject.Molecule.Structure : undefined 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>({ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>({
name: 'structure-animation', name: 'structure-animation',
display: { name: 'Structure Animation', group: 'Animation' }, display: { name: 'Structure Animation', group: 'Animation' },
...@@ -58,62 +64,68 @@ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps> ...@@ -58,62 +64,68 @@ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>
this.update(params) 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) { if (play) {
const state = this.ctx.state.dataState const animateRotate = (t: number) => {
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D)); this.rotate(degToRad((t / 10) % 360))
const rotate = (t: number) => { this.rotateAnimHandle = requestAnimationFrame(animateRotate)
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)
} }
this.rotateAnimHandle = requestAnimationFrame(rotate) this.rotateAnimHandle = requestAnimationFrame(animateRotate)
} else { } else {
cancelAnimationFrame(this.rotateAnimHandle) 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) { if (play) {
const state = this.ctx.state.dataState const animateExplode = (t: number) => {
const reprs = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Representation3D)); this.explode((Math.sin(t * 0.001) + 1) * 5)
const explode = (t: number) => { this.explodeAnimHandle = requestAnimationFrame(animateExplode)
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)
} }
this.explodeAnimHandle = requestAnimationFrame(explode) this.explodeAnimHandle = requestAnimationFrame(animateExplode)
} else { } else {
cancelAnimationFrame(this.explodeAnimHandle) cancelAnimationFrame(this.explodeAnimHandle)
} }
...@@ -125,11 +137,19 @@ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps> ...@@ -125,11 +137,19 @@ export const StructureAnimation = PluginBehavior.create<StructureAnimationProps>
let updated = PD.areEqual(StructureAnimationParams, this.params, p) let updated = PD.areEqual(StructureAnimationParams, this.params, p)
if (this.params.rotate !== p.rotate) { if (this.params.rotate !== p.rotate) {
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) { if (this.params.explode !== p.explode) {
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; return updated;
} }
......
...@@ -37,7 +37,7 @@ const DefaultSpec: PluginSpec = { ...@@ -37,7 +37,7 @@ const DefaultSpec: PluginSpec = {
PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci), PluginSpec.Behavior(PluginBehaviors.Representation.SelectLoci),
PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider), PluginSpec.Behavior(PluginBehaviors.Representation.DefaultLociLabelProvider),
PluginSpec.Behavior(PluginBehaviors.Camera.FocusLociOnSelect, { minRadius: 20, extraRadius: 4 }), 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.PDBeStructureQualityReport, { autoAttach: true }),
PluginSpec.Behavior(PluginBehaviors.CustomProps.RCSBAssemblySymmetry, { 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.
Finish editing this message first!
Please register or to comment