// Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 import Matrix from './Matrix'; const ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; const uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1]; const vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1]; const vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1]; const tempMatrices = []; const mul = []; function signum(x) { if (x < 0) { return -1; } if (x > 0) { return 1; } return 0; } function init() { for (let i = 0; i < 16; i++) { const row = []; mul.push(row); for (let j = 0; j < 16; j++) { const _ux = signum((ux[i] * ux[j]) + (vx[i] * uy[j])); const _uy = signum((uy[i] * ux[j]) + (vy[i] * uy[j])); const _vx = signum((ux[i] * vx[j]) + (vx[i] * vy[j])); const _vy = signum((uy[i] * vx[j]) + (vy[i] * vy[j])); for (let k = 0; k < 16; k++) { if (ux[k] === _ux && uy[k] === _uy && vx[k] === _vx && vy[k] === _vy) { row.push(k); break; } } } } for (let i = 0; i < 16; i++) { const mat = new Matrix(); mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0); tempMatrices.push(mat); } } init(); /** * Implements Dihedral Group D_8, see [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html}, * D8 is the same but with diagonals. Used for texture rotations. * * Vector xX(i), xY(i) is U-axis of sprite with rotation i * Vector yY(i), yY(i) is V-axis of sprite with rotation i * Rotations: 0 grad (0), 90 grad (2), 180 grad (4), 270 grad (6) * Mirrors: vertical (8), main diagonal (10), horizontal (12), reverse diagonal (14) * This is the small part of gameofbombs.com portal system. It works. * * @author Ivan @ivanpopelyshev * @class * @memberof PIXI */ const GroupD8 = { E: 0, SE: 1, S: 2, SW: 3, W: 4, NW: 5, N: 6, NE: 7, MIRROR_VERTICAL: 8, MIRROR_HORIZONTAL: 12, uX: (ind) => ux[ind], uY: (ind) => uy[ind], vX: (ind) => vx[ind], vY: (ind) => vy[ind], inv: (rotation) => { if (rotation & 8) { return rotation & 15; } return (-rotation) & 7; }, add: (rotationSecond, rotationFirst) => mul[rotationSecond][rotationFirst], sub: (rotationSecond, rotationFirst) => mul[rotationSecond][GroupD8.inv(rotationFirst)], /** * Adds 180 degrees to rotation. Commutative operation. * * @memberof PIXI.GroupD8 * @param {number} rotation - The number to rotate. * @returns {number} rotated number */ rotate180: (rotation) => rotation ^ 4, /** * Direction of main vector can be horizontal, vertical or diagonal. * Some objects work with vertical directions different. * * @memberof PIXI.GroupD8 * @param {number} rotation - The number to check. * @returns {boolean} Whether or not the direction is vertical */ isVertical: (rotation) => (rotation & 3) === 2, /** * @memberof PIXI.GroupD8 * @param {number} dx - TODO * @param {number} dy - TODO * * @return {number} TODO */ byDirection: (dx, dy) => { if (Math.abs(dx) * 2 <= Math.abs(dy)) { if (dy >= 0) { return GroupD8.S; } return GroupD8.N; } else if (Math.abs(dy) * 2 <= Math.abs(dx)) { if (dx > 0) { return GroupD8.E; } return GroupD8.W; } else if (dy > 0) { if (dx > 0) { return GroupD8.SE; } return GroupD8.SW; } else if (dx > 0) { return GroupD8.NE; } return GroupD8.NW; }, /** * Helps sprite to compensate texture packer rotation. * * @memberof PIXI.GroupD8 * @param {PIXI.Matrix} matrix - sprite world matrix * @param {number} rotation - The rotation factor to use. * @param {number} tx - sprite anchoring * @param {number} ty - sprite anchoring */ matrixAppendRotationInv: (matrix, rotation, tx = 0, ty = 0) => { // Packer used "rotation", we use "inv(rotation)" const mat = tempMatrices[GroupD8.inv(rotation)]; mat.tx = tx; mat.ty = ty; matrix.append(mat); }, }; export default GroupD8;