-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbigint-trackball.js
79 lines (79 loc) · 2.57 KB
/
bigint-trackball.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
function gcd(a, b) {
return BigInt(b ? gcd(b, a % b) : Math.abs(new Number(a)));
}
class Trackball {
simplify() {
let GCD = [ this.denominator, ...this.submatrix ].reduce(gcd);
this.submatrix = this.submatrix.map( x => x / GCD );
this.denominator /= GCD;
}
get matrix() {
let M = this.submatrix.map(
x => new Number(x)/new Number(this.denominator)
);
return [
M[0], M[1], M[2], 0,
M[3], M[4], M[5], 0,
M[6], M[7], M[8], 0,
0, 0, 0, 1
];
}
copy() {
this.simplify();
this.submatrix_copy = this.submatrix.slice();
this.denominator_copy = this.denominator;
}
constructor(canvas) {
this.drag = false;
this.canvas = canvas;
this.submatrix = [1n, 0n, 0n, 0n, 1n, 0n, 0n, 0n, 1n];
this.submatrix_copy = [1n, 0n, 0n, 0n, 1n, 0n, 0n, 0n, 1n];
this.denominator = 1n;
this.denominator_copy = 1n;
this.maxLength = Math.max(this.canvas.width, this.canvas.height);
canvas.addEventListener(
"mousedown", e => {
this.copy();
this.drag = true;
this.x = e.pageX;
this.y = e.pageY;
e.preventDefault();
return false;
}, false
);
document.addEventListener(
"mouseup", e => {
this.drag = false;
this.simplify();
}
);
document.addEventListener(
"mousemove", e => {
if (!this.drag) return false;
let X = -BigInt(e.pageX-this.x),
Y = BigInt(e.pageY-this.y),
Z = BigInt(this.maxLength),
X2 = X*X, Y2 = Y*Y, Z2 = Z*Z,
Z3 = Z2*Z,
A = Z2*(Z2-X2-Y2),
Q2 = Z2*(Z2+X2+Y2),
Q4 = Q2*Q2,
B = 2n*Z3*X,
C = 2n*Z3*Y,
A2 = A*A, B2 = B*B, C2 = C*C,
AB = A*B, BC = B*C, AC = A*C;
mat3.multiply(
this.submatrix,
[
A2-B2+C2, -2n*BC , 2n*AB,
-2n*BC , A2+B2-C2, 2n*AC,
-2n*AB , -2n*AC , A2-B2-C2
],
this.submatrix_copy
);
this.denominator = this.denominator_copy*Q4;
e.preventDefault();
}, false
);
}
}