-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshaderLib.mjs
128 lines (110 loc) · 3.04 KB
/
shaderLib.mjs
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const sumReducer = (sum, x) => sum + x;
const sin = Math.sin,
cos = Math.cos,
sqrt = Math.sqrt;
/**
* Cartesian distance between two points.
* @param point0 {number[]}
* @param point1 {number[]}
* @returns {number}
*/
export const distance = (point0, point1) => {
if (point0.length !== point1.length)
throw new Error("Dimensionality must match");
return sqrt(
point0
.map((dim0, index) => Math.pow(point1[index] - dim0, 2))
.reduce(sumReducer, 0)
);
};
/**
* Get the magnitude of a vector.
* @param vector {number[]}
* @returns {number}
*/
export const magnitude = (vector) => {
return sqrt(vector.map((dim) => dim * dim).reduce(sumReducer, 0));
};
/**
* Normalize a vector
* @param vector {number[]}
* @returns {number[]}
*/
export const normalize = (vector) => {
const mag = magnitude(vector);
return vector.map((dim) => dim / mag);
};
/**
* Apply a function to elements from both vectors.
* @param vector0 {number[]}
* @param vector1 {number[]}number}
* @param operation {(number, number) => number}
* @returns {number[]}
*/
const vectorApply = (vector0, vector1, operation) => {
return vector0.map((dim0, index) =>
operation(dim0, vector1 instanceof Array ? vector1[index] : vector1)
);
};
export const add = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => a + b);
export const sub = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => a - b);
export const div = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => a / b);
export const mul = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => a * b);
export const max = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => (a > b ? a : b));
export const min = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => (a < b ? a : b));
export const dot = (vector0, vector1) =>
vectorApply(vector0, vector1, (a, b) => a * b).reduce(sumReducer, 0);
export const abs = (vector) => {
return vector.map((dim) => Math.abs(dim));
};
export const pow = (vector, power) => {
return vector.map((dim) => Math.pow(dim, power));
};
/**
* Rotate a 3D vector around the X axis.
* @param param0 {[number, number, number]}
* @param theta {number}
* @returns {[number, number, number]}
*/
export const rotate3DX = ([x, y, z], theta) => {
// prettier-ignore
return [
x,
y * cos(theta) - z * sin(theta),
y * sin(theta) + z * cos(theta),
];
};
/**
* Rotate a 3D vector around the Y axis.
* @param param0 {[number, number, number]}
* @param theta {number}
* @returns {[number, number, number]}
*/
export const rotate3DY = ([x, y, z], theta) => {
// prettier-ignore
return [
x * cos(theta) + z * sin(theta),
y,
-x * sin(theta) + z * cos(theta),
];
};
/**
* Rotate a 3D vector around the Z axis.
* @param param0 {[number, number, number]}
* @param theta {number}
* @returns {[number, number, number]}
*/
export const rotate3DZ = ([x, y, z], theta) => {
// prettier-ignore
return [
x * cos(theta) - y * sin(theta),
x * sin(theta) + y * cos(theta),
z,
];
};