camera-spin.ts 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { Camera } from '../../../mol-canvas3d/camera';
  7. import { clamp } from '../../../mol-math/interpolate';
  8. import { Quat, Vec3 } from '../../../mol-math/linear-algebra/3d';
  9. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  10. import { PluginStateAnimation } from '../model';
  11. const _dir = Vec3(), _axis = Vec3(), _rot = Quat();
  12. type State = { snapshot: Camera.Snapshot };
  13. export const AnimateCameraSpin = PluginStateAnimation.create({
  14. name: 'built-in.animate-camera-spin',
  15. display: { name: 'Camera Spin' },
  16. params: () => ({
  17. durationInMs: PD.Numeric(4000, { min: 100, max: 20000, step: 100 }),
  18. speed: PD.Numeric(1, { min: 1, max: 10, step: 1 }, { description: 'How many times to spin in the specified dutation.' }),
  19. direction: PD.Select<'cw' | 'ccw'>('cw', [['cw', 'Clockwise'], ['ccw', 'Counter Clockwise']], { cycle: true })
  20. }),
  21. initialState: (_, ctx) => ({ snapshot: ctx.canvas3d?.camera.getSnapshot()! }) as State,
  22. getDuration: p => ({ kind: 'fixed', durationMs: p.durationInMs }),
  23. teardown: (_, state: State, ctx) => {
  24. ctx.canvas3d?.requestCameraReset({ snapshot: state.snapshot, durationMs: 0 });
  25. },
  26. async apply(animState: State, t, ctx) {
  27. if (t.current === 0) {
  28. return { kind: 'next', state: animState };
  29. }
  30. const snapshot = animState.snapshot;
  31. if (snapshot.radiusMax < 0.0001) {
  32. return { kind: 'finished' };
  33. }
  34. const phase = clamp(t.current / ctx.params.durationInMs, 0, 1);
  35. if (phase >= 0.99999) {
  36. ctx.plugin.canvas3d?.requestCameraReset({ snapshot, durationMs: 0 });
  37. return { kind: 'finished' };
  38. }
  39. const angle = 2 * Math.PI * phase * ctx.params.speed * (ctx.params.direction === 'ccw' ? -1 : 1);
  40. Vec3.sub(_dir, snapshot.position, snapshot.target);
  41. Vec3.normalize(_axis, snapshot.up);
  42. Quat.setAxisAngle(_rot, _axis, angle);
  43. Vec3.transformQuat(_dir, _dir, _rot);
  44. const position = Vec3.add(Vec3(), snapshot.target, _dir);
  45. ctx.plugin.canvas3d?.requestCameraReset({ snapshot: { ...snapshot, position }, durationMs: 0 });
  46. return { kind: 'next', state: animState };
  47. }
  48. });