Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sisilicon
GitHub Repository: sisilicon/worldedit-be
Path: blob/master/src/library/utils/matrix.ts
1784 views
1
import { Vector3 } from "@minecraft/server";
2
import { axis } from "./vector";
3
4
type matrixElements = [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];
5
6
export class Matrix {
7
public readonly vals: matrixElements = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
8
9
static fromTranslation(vec: Vector3) {
10
return new Matrix([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, vec.x, vec.y, vec.z, 1]);
11
}
12
13
static fromRotation(degrees: number, axis: axis | Vector3) {
14
// Based on http://www.gamedev.net/reference/articles/article1199.asp
15
const wrapped = ((degrees % 360) + 360) % 360;
16
const radians = (wrapped > 180 ? wrapped - 360 : wrapped) * (Math.PI / 180);
17
const c = Math.floor(10_000 * Math.cos(radians)) / 10_000;
18
const s = Math.floor(10_000 * Math.sin(radians)) / 10_000;
19
const t = 1 - c;
20
const { x, y, z } = typeof axis === "string" ? { x: Number(axis === "x"), y: Number(axis === "y"), z: Number(axis === "z") } : axis;
21
const tx = t * x;
22
const ty = t * y;
23
24
return new Matrix([tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1]);
25
}
26
27
static fromScale(vec: Vector3) {
28
return new Matrix([vec.x, 0, 0, 0, 0, vec.y, 0, 0, 0, 0, vec.z, 0, 0, 0, 0, 1]);
29
}
30
31
static fromRotationFlipOffset(rotation: Vector3, flip: Vector3, origin?: Vector3) {
32
const matrix = new Matrix().rotate(rotation.y, "y").rotate(rotation.x, "x").rotate(rotation.z, "z").scale(flip);
33
if (!origin) return matrix;
34
const translate = Matrix.fromTranslation(origin);
35
return translate.multiply(matrix).multiply(translate.invert());
36
}
37
38
constructor(values?: matrixElements) {
39
if (values) this.vals = [...values];
40
}
41
42
clone() {
43
return new Matrix(this.vals);
44
}
45
46
rotate(degrees: number, axis: axis) {
47
return Matrix.fromRotation(degrees, axis).multiply(this);
48
}
49
50
translate(vec: Vector3) {
51
return Matrix.fromTranslation(vec).multiply(this);
52
}
53
54
scale(vec: Vector3) {
55
return Matrix.fromScale(vec).multiply(this);
56
}
57
58
transpose() {
59
const vals = <matrixElements>[...this.vals];
60
vals[1] = this.vals[4];
61
vals[4] = this.vals[1];
62
vals[2] = this.vals[8];
63
vals[8] = this.vals[2];
64
vals[6] = this.vals[9];
65
vals[9] = this.vals[6];
66
vals[3] = this.vals[12];
67
vals[12] = this.vals[3];
68
vals[7] = this.vals[13];
69
vals[13] = this.vals[7];
70
vals[11] = this.vals[14];
71
vals[14] = this.vals[11];
72
return new Matrix(vals);
73
}
74
75
invert() {
76
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
77
const vals = <matrixElements>[...this.vals],
78
n11 = vals[0],
79
n21 = vals[1],
80
n31 = vals[2],
81
n41 = vals[3],
82
n12 = vals[4],
83
n22 = vals[5],
84
n32 = vals[6],
85
n42 = vals[7],
86
n13 = vals[8],
87
n23 = vals[9],
88
n33 = vals[10],
89
n43 = vals[11],
90
n14 = vals[12],
91
n24 = vals[13],
92
n34 = vals[14],
93
n44 = vals[15],
94
t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
95
t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
96
t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
97
t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
98
99
const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
100
101
if (det === 0) return new Matrix([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
102
103
const detInv = 1 / det;
104
105
vals[0] = t11 * detInv;
106
vals[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
107
vals[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
108
vals[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
109
110
vals[4] = t12 * detInv;
111
vals[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
112
vals[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
113
vals[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
114
115
vals[8] = t13 * detInv;
116
vals[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
117
vals[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
118
vals[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
119
120
vals[12] = t14 * detInv;
121
vals[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
122
vals[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
123
vals[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
124
125
return new Matrix(vals);
126
}
127
128
multiply(mat: Matrix) {
129
const result = new Matrix();
130
const vals = result.vals;
131
132
const a11 = this.vals[0],
133
a12 = this.vals[4],
134
a13 = this.vals[8],
135
a14 = this.vals[12];
136
const a21 = this.vals[1],
137
a22 = this.vals[5],
138
a23 = this.vals[9],
139
a24 = this.vals[13];
140
const a31 = this.vals[2],
141
a32 = this.vals[6],
142
a33 = this.vals[10],
143
a34 = this.vals[14];
144
const a41 = this.vals[3],
145
a42 = this.vals[7],
146
a43 = this.vals[11],
147
a44 = this.vals[15];
148
149
const b11 = mat.vals[0],
150
b12 = mat.vals[4],
151
b13 = mat.vals[8],
152
b14 = mat.vals[12];
153
const b21 = mat.vals[1],
154
b22 = mat.vals[5],
155
b23 = mat.vals[9],
156
b24 = mat.vals[13];
157
const b31 = mat.vals[2],
158
b32 = mat.vals[6],
159
b33 = mat.vals[10],
160
b34 = mat.vals[14];
161
const b41 = mat.vals[3],
162
b42 = mat.vals[7],
163
b43 = mat.vals[11],
164
b44 = mat.vals[15];
165
166
vals[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
167
vals[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
168
vals[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
169
vals[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
170
171
vals[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
172
vals[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
173
vals[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
174
vals[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
175
176
vals[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
177
vals[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
178
vals[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
179
vals[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
180
181
vals[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
182
vals[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
183
vals[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
184
vals[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
185
186
return result;
187
}
188
}
189
190