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';
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.
Finish editing this message first!
Please register or to comment