clip.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Quat, Vec3 } from '../mol-math/linear-algebra';
  7. import { degToRad } from '../mol-math/misc';
  8. import { ParamDefinition as PD } from './param-definition';
  9. import { stringToWords } from './string';
  10. export interface Clip {
  11. variant: Clip.Variant,
  12. objects: Clip.Objects
  13. }
  14. export function Clip() {
  15. }
  16. export namespace Clip {
  17. /** Clip object types */
  18. export const Type = {
  19. none: 0, // to switch clipping off
  20. plane: 1,
  21. sphere: 2,
  22. cube: 3,
  23. cylinder: 4,
  24. infiniteCone: 5,
  25. };
  26. export type Variant = 'instance' | 'pixel'
  27. export type Objects = {
  28. count: number
  29. type: number[]
  30. invert: boolean[]
  31. position: number[]
  32. rotation: number[]
  33. scale: number[]
  34. }
  35. export const Params = {
  36. variant: PD.Select('pixel', PD.arrayToOptions<Variant>(['instance', 'pixel'])),
  37. objects: PD.ObjectList({
  38. type: PD.Select('plane', PD.objectToOptions(Type, t => stringToWords(t))),
  39. invert: PD.Boolean(false),
  40. position: PD.Vec3(Vec3()),
  41. rotation: PD.Group({
  42. axis: PD.Vec3(Vec3.create(1, 0, 0)),
  43. angle: PD.Numeric(0, { min: -180, max: 180, step: 1 }, { description: 'Angle in Degrees' }),
  44. }, { isExpanded: true }),
  45. scale: PD.Vec3(Vec3.create(1, 1, 1)),
  46. }, o => stringToWords(o.type))
  47. };
  48. export type Params = typeof Params
  49. export type Props = PD.Values<Params>
  50. function createClipObjects() {
  51. return {
  52. count: 0,
  53. type: (new Array(5)).fill(1),
  54. invert: (new Array(5)).fill(false),
  55. position: (new Array(5 * 3)).fill(0),
  56. rotation: (new Array(5 * 4)).fill(0),
  57. scale: (new Array(5 * 3)).fill(1),
  58. };
  59. }
  60. const qA = Quat();
  61. const qB = Quat();
  62. const vA = Vec3();
  63. const vB = Vec3();
  64. export function getClip(props: Props, clip?: Clip): Clip {
  65. const { type, invert, position, rotation, scale } = clip?.objects || createClipObjects();
  66. for (let i = 0, il = props.objects.length; i < il; ++i) {
  67. const p = props.objects[i];
  68. type[i] = Type[p.type];
  69. invert[i] = p.invert;
  70. Vec3.toArray(p.position, position, i * 3);
  71. Quat.toArray(Quat.setAxisAngle(qA, p.rotation.axis, degToRad(p.rotation.angle)), rotation, i * 4);
  72. Vec3.toArray(p.scale, scale, i * 3);
  73. }
  74. return {
  75. variant: props.variant,
  76. objects: { count: props.objects.length, type, invert, position, rotation, scale }
  77. };
  78. }
  79. export function areEqual(cA: Clip, cB: Clip) {
  80. if (cA.variant !== cB.variant) return false;
  81. if (cA.objects.count !== cB.objects.count) return false;
  82. const oA = cA.objects, oB = cB.objects;
  83. for (let i = 0, il = oA.count; i < il; ++i) {
  84. if (oA.invert[i] !== oB.invert[i]) return false;
  85. if (oA.type[i] !== oB.type[i]) return false;
  86. Vec3.fromArray(vA, oA.position, i * 3);
  87. Vec3.fromArray(vB, oB.position, i * 3);
  88. if (!Vec3.equals(vA, vB)) return false;
  89. Vec3.fromArray(vA, oA.scale, i * 3);
  90. Vec3.fromArray(vB, oB.scale, i * 3);
  91. if (!Vec3.equals(vA, vB)) return false;
  92. Quat.fromArray(qA, oA.rotation, i * 4);
  93. Quat.fromArray(qB, oB.rotation, i * 4);
  94. if (!Quat.equals(qA, qB)) return false;
  95. }
  96. return true;
  97. }
  98. }