Source: core/math/GroupD8.js

core/math/GroupD8.js

  1. // Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16
  2. import Matrix from './Matrix';
  3. const ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1];
  4. const uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1];
  5. const vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1];
  6. const vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1];
  7. const tempMatrices = [];
  8. const mul = [];
  9. function signum(x)
  10. {
  11. if (x < 0)
  12. {
  13. return -1;
  14. }
  15. if (x > 0)
  16. {
  17. return 1;
  18. }
  19. return 0;
  20. }
  21. function init()
  22. {
  23. for (let i = 0; i < 16; i++)
  24. {
  25. const row = [];
  26. mul.push(row);
  27. for (let j = 0; j < 16; j++)
  28. {
  29. const _ux = signum((ux[i] * ux[j]) + (vx[i] * uy[j]));
  30. const _uy = signum((uy[i] * ux[j]) + (vy[i] * uy[j]));
  31. const _vx = signum((ux[i] * vx[j]) + (vx[i] * vy[j]));
  32. const _vy = signum((uy[i] * vx[j]) + (vy[i] * vy[j]));
  33. for (let k = 0; k < 16; k++)
  34. {
  35. if (ux[k] === _ux && uy[k] === _uy && vx[k] === _vx && vy[k] === _vy)
  36. {
  37. row.push(k);
  38. break;
  39. }
  40. }
  41. }
  42. }
  43. for (let i = 0; i < 16; i++)
  44. {
  45. const mat = new Matrix();
  46. mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0);
  47. tempMatrices.push(mat);
  48. }
  49. }
  50. init();
  51. /**
  52. * Implements Dihedral Group D_8, see [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html},
  53. * D8 is the same but with diagonals. Used for texture rotations.
  54. *
  55. * Vector xX(i), xY(i) is U-axis of sprite with rotation i
  56. * Vector yY(i), yY(i) is V-axis of sprite with rotation i
  57. * Rotations: 0 grad (0), 90 grad (2), 180 grad (4), 270 grad (6)
  58. * Mirrors: vertical (8), main diagonal (10), horizontal (12), reverse diagonal (14)
  59. * This is the small part of gameofbombs.com portal system. It works.
  60. *
  61. * @author Ivan @ivanpopelyshev
  62. * @class
  63. * @memberof PIXI
  64. */
  65. const GroupD8 = {
  66. E: 0,
  67. SE: 1,
  68. S: 2,
  69. SW: 3,
  70. W: 4,
  71. NW: 5,
  72. N: 6,
  73. NE: 7,
  74. MIRROR_VERTICAL: 8,
  75. MIRROR_HORIZONTAL: 12,
  76. uX: (ind) => ux[ind],
  77. uY: (ind) => uy[ind],
  78. vX: (ind) => vx[ind],
  79. vY: (ind) => vy[ind],
  80. inv: (rotation) =>
  81. {
  82. if (rotation & 8)
  83. {
  84. return rotation & 15;
  85. }
  86. return (-rotation) & 7;
  87. },
  88. add: (rotationSecond, rotationFirst) => mul[rotationSecond][rotationFirst],
  89. sub: (rotationSecond, rotationFirst) => mul[rotationSecond][GroupD8.inv(rotationFirst)],
  90. /**
  91. * Adds 180 degrees to rotation. Commutative operation.
  92. *
  93. * @memberof PIXI.GroupD8
  94. * @param {number} rotation - The number to rotate.
  95. * @returns {number} rotated number
  96. */
  97. rotate180: (rotation) => rotation ^ 4,
  98. /**
  99. * Direction of main vector can be horizontal, vertical or diagonal.
  100. * Some objects work with vertical directions different.
  101. *
  102. * @memberof PIXI.GroupD8
  103. * @param {number} rotation - The number to check.
  104. * @returns {boolean} Whether or not the direction is vertical
  105. */
  106. isVertical: (rotation) => (rotation & 3) === 2,
  107. /**
  108. * @memberof PIXI.GroupD8
  109. * @param {number} dx - TODO
  110. * @param {number} dy - TODO
  111. *
  112. * @return {number} TODO
  113. */
  114. byDirection: (dx, dy) =>
  115. {
  116. if (Math.abs(dx) * 2 <= Math.abs(dy))
  117. {
  118. if (dy >= 0)
  119. {
  120. return GroupD8.S;
  121. }
  122. return GroupD8.N;
  123. }
  124. else if (Math.abs(dy) * 2 <= Math.abs(dx))
  125. {
  126. if (dx > 0)
  127. {
  128. return GroupD8.E;
  129. }
  130. return GroupD8.W;
  131. }
  132. else if (dy > 0)
  133. {
  134. if (dx > 0)
  135. {
  136. return GroupD8.SE;
  137. }
  138. return GroupD8.SW;
  139. }
  140. else if (dx > 0)
  141. {
  142. return GroupD8.NE;
  143. }
  144. return GroupD8.NW;
  145. },
  146. /**
  147. * Helps sprite to compensate texture packer rotation.
  148. *
  149. * @memberof PIXI.GroupD8
  150. * @param {PIXI.Matrix} matrix - sprite world matrix
  151. * @param {number} rotation - The rotation factor to use.
  152. * @param {number} tx - sprite anchoring
  153. * @param {number} ty - sprite anchoring
  154. */
  155. matrixAppendRotationInv: (matrix, rotation, tx = 0, ty = 0) =>
  156. {
  157. // Packer used "rotation", we use "inv(rotation)"
  158. const mat = tempMatrices[GroupD8.inv(rotation)];
  159. mat.tx = tx;
  160. mat.ty = ty;
  161. matrix.append(mat);
  162. },
  163. };
  164. export default GroupD8;