clip.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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(count: number) {
  51. return {
  52. count: 0,
  53. type: (new Array(count)).fill(1),
  54. invert: (new Array(count)).fill(false),
  55. position: (new Array(count * 3)).fill(0),
  56. rotation: (new Array(count * 4)).fill(0),
  57. scale: (new Array(count * 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 count = props.objects.length;
  66. const { type, invert, position, rotation, scale } = clip?.objects || createClipObjects(count);
  67. for (let i = 0; i < count; ++i) {
  68. const p = props.objects[i];
  69. type[i] = Type[p.type];
  70. invert[i] = p.invert;
  71. Vec3.toArray(p.position, position, i * 3);
  72. Quat.toArray(Quat.setAxisAngle(qA, p.rotation.axis, degToRad(p.rotation.angle)), rotation, i * 4);
  73. Vec3.toArray(p.scale, scale, i * 3);
  74. }
  75. return {
  76. variant: props.variant,
  77. objects: { count, type, invert, position, rotation, scale }
  78. };
  79. }
  80. export function areEqual(cA: Clip, cB: Clip) {
  81. if (cA.variant !== cB.variant) return false;
  82. if (cA.objects.count !== cB.objects.count) return false;
  83. const oA = cA.objects, oB = cB.objects;
  84. for (let i = 0, il = oA.count; i < il; ++i) {
  85. if (oA.invert[i] !== oB.invert[i]) return false;
  86. if (oA.type[i] !== oB.type[i]) return false;
  87. Vec3.fromArray(vA, oA.position, i * 3);
  88. Vec3.fromArray(vB, oB.position, i * 3);
  89. if (!Vec3.equals(vA, vB)) return false;
  90. Vec3.fromArray(vA, oA.scale, i * 3);
  91. Vec3.fromArray(vB, oB.scale, i * 3);
  92. if (!Vec3.equals(vA, vB)) return false;
  93. Quat.fromArray(qA, oA.rotation, i * 4);
  94. Quat.fromArray(qB, oB.rotation, i * 4);
  95. if (!Quat.equals(qA, qB)) return false;
  96. }
  97. return true;
  98. }
  99. }