@block_factory/lib 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esbuild.config.mjs +18 -0
- package/index.d.ts +16 -0
- package/index.js +526 -0
- package/index.ts +16 -0
- package/package.json +32 -0
- package/tsconfig.json +27 -0
- package/util/Command.d.ts +23 -0
- package/util/Command.ts +124 -0
- package/util/Form.d.ts +75 -0
- package/util/Form.ts +246 -0
- package/util/Math.d.ts +14 -0
- package/util/Math.ts +68 -0
- package/util/RawText.d.ts +33 -0
- package/util/RawText.ts +76 -0
- package/util/Signal.d.ts +9 -0
- package/util/Signal.ts +73 -0
- package/util/Vector.d.ts +60 -0
- package/util/Vector.ts +388 -0
package/util/Signal.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export type Callback<T = void> = (data: T) => void;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Signal class for event handling.
|
|
5
|
+
* Allows connecting, disconnecting, and emitting events to listeners.
|
|
6
|
+
*
|
|
7
|
+
* @template T - Type of data passed to listeners.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { Signal } from "./_lib/signal";
|
|
12
|
+
*
|
|
13
|
+
* interface ExampleEvent {
|
|
14
|
+
* n: number;
|
|
15
|
+
* s: string;
|
|
16
|
+
* b: boolean;
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* class TestObject {
|
|
20
|
+
* example = new Signal<ExampleEvent>();
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* const tstObject = new TestObject();
|
|
24
|
+
* tstObject.example.connect(({n, s, b}) => console.warn(`n: ${n}, s: ${s}, b: ${b}`));
|
|
25
|
+
*
|
|
26
|
+
* for (let i = 0; i < 4; i++) {
|
|
27
|
+
* let n: number = 1;
|
|
28
|
+
* let s: string = "example";
|
|
29
|
+
* let b: boolean = true;
|
|
30
|
+
* tstObject.example.emit({n, s, b});
|
|
31
|
+
* if (i === 3) { // Disconnect after 4th emit
|
|
32
|
+
* tstObject.example.disconnect();
|
|
33
|
+
* tstObject.example.emit({n, s, b});
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
export class Signal<T = void> {
|
|
40
|
+
private listeners: Set<Callback<T>> = new Set();
|
|
41
|
+
|
|
42
|
+
/** Connect a listener */
|
|
43
|
+
public connect(callback: Callback<T>): void {
|
|
44
|
+
this.listeners.add(callback);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Disconnect a listener */
|
|
48
|
+
public disconnect(callback?: Callback<T>): boolean {
|
|
49
|
+
if (callback) {
|
|
50
|
+
this.listeners.delete(callback);
|
|
51
|
+
return true;
|
|
52
|
+
} else {
|
|
53
|
+
this.listeners.clear();
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Connect a listener that runs only once */
|
|
59
|
+
public once(callback: Callback<T>) {
|
|
60
|
+
const wrapper: Callback<T> = (data) => {
|
|
61
|
+
this.disconnect(wrapper);
|
|
62
|
+
callback(data);
|
|
63
|
+
};
|
|
64
|
+
this.connect(wrapper);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Emit signal to all listeners */
|
|
68
|
+
public emit(data: T) {
|
|
69
|
+
for (const cb of [...this.listeners]) {
|
|
70
|
+
cb(data);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
package/util/Vector.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare class Vec2 {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
static ZERO: Vec2;
|
|
5
|
+
static UP: Vec2;
|
|
6
|
+
static DOWN: Vec2;
|
|
7
|
+
static LEFT: Vec2;
|
|
8
|
+
static RIGHT: Vec2;
|
|
9
|
+
constructor(x: number, y: number);
|
|
10
|
+
static add(a: Vec2, b: Vec2 | number): Vec2;
|
|
11
|
+
static subtract(a: Vec2, b: Vec2 | number): Vec2;
|
|
12
|
+
static multiply(a: Vec2, b: Vec2 | number): Vec2;
|
|
13
|
+
static divide(a: Vec2, b: Vec2 | number): Vec2;
|
|
14
|
+
static lerp(a: Vec2, b: Vec2, t: number): Vec2;
|
|
15
|
+
static clamp(v: Vec2, min: Vec2, max: Vec2): Vec2;
|
|
16
|
+
static dot(a: Vec2, b: Vec2): number;
|
|
17
|
+
static magnitude(a: Vec2): number;
|
|
18
|
+
static normalize(a: Vec2): Vec2;
|
|
19
|
+
static distance(a: Vec2, b: Vec2): number;
|
|
20
|
+
static negate(a: Vec2): Vec2;
|
|
21
|
+
static equals(a: Vec2, b: Vec2): boolean;
|
|
22
|
+
static approxEquals(a: Vec2, b: Vec2, epsilon?: number): boolean;
|
|
23
|
+
static angle(a: Vec2, b: Vec2): number;
|
|
24
|
+
static perpendicular(a: Vec2): Vec2;
|
|
25
|
+
}
|
|
26
|
+
export declare class Vec3 {
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
z: number;
|
|
30
|
+
static ZERO: Vec3;
|
|
31
|
+
static UP: Vec3;
|
|
32
|
+
static DOWN: Vec3;
|
|
33
|
+
static LEFT: Vec3;
|
|
34
|
+
static RIGHT: Vec3;
|
|
35
|
+
static FORWARD: Vec3;
|
|
36
|
+
static BACK: Vec3;
|
|
37
|
+
static WEST: Vec3;
|
|
38
|
+
static EAST: Vec3;
|
|
39
|
+
static NORTH: Vec3;
|
|
40
|
+
static SOUTH: Vec3;
|
|
41
|
+
constructor(x: number, y: number, z: number);
|
|
42
|
+
static add(a: Vec3, b: Vec3 | number): Vec3;
|
|
43
|
+
static subtract(a: Vec3, b: Vec3 | number): Vec3;
|
|
44
|
+
static multiply(a: Vec3, b: Vec3 | number): Vec3;
|
|
45
|
+
static divide(a: Vec3, b: Vec3 | number): Vec3;
|
|
46
|
+
static lerp(a: Vec3, b: Vec3, t: number): Vec3;
|
|
47
|
+
static clamp(v: Vec3, min: Vec3, max: Vec3): Vec3;
|
|
48
|
+
static dot(a: Vec3, b: Vec3): number;
|
|
49
|
+
static cross(a: Vec3, b: Vec3): Vec3;
|
|
50
|
+
static magnitude(a: Vec3): number;
|
|
51
|
+
static normalize(a: Vec3): Vec3;
|
|
52
|
+
static distance(a: Vec3, b: Vec3): number;
|
|
53
|
+
static negate(a: Vec3): Vec3;
|
|
54
|
+
static equals(a: Vec3, b: Vec3): boolean;
|
|
55
|
+
static approxEquals(a: Vec3, b: Vec3, epsilon?: number): boolean;
|
|
56
|
+
static angle(a: Vec3, b: Vec3): number;
|
|
57
|
+
static project(a: Vec3, onto: Vec3): Vec3;
|
|
58
|
+
static cartesian(radius: number, theta: number, phi: number): Vec3;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=Vector.d.ts.map
|
package/util/Vector.ts
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/*
|
|
2
|
+
**************************************************
|
|
3
|
+
Copyright (c) Block Factory - All rights reserved.
|
|
4
|
+
**************************************************
|
|
5
|
+
Author: Donthedev <https://github.com/voxeldon>
|
|
6
|
+
**************************************************
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 2D vector utility class.
|
|
11
|
+
* Provides common vector math operations for 2D space.
|
|
12
|
+
*/
|
|
13
|
+
export class Vec2 {
|
|
14
|
+
|
|
15
|
+
/** Constant zero vector (0, 0) */
|
|
16
|
+
static ZERO: Vec2 = new Vec2(0, 0);
|
|
17
|
+
|
|
18
|
+
/** Up direction (0, 1) */
|
|
19
|
+
static UP: Vec2 = new Vec2(0, 1);
|
|
20
|
+
|
|
21
|
+
/** Down direction (0, -1) */
|
|
22
|
+
static DOWN: Vec2 = new Vec2(0, -1);
|
|
23
|
+
|
|
24
|
+
/** Left direction (-1, 0) */
|
|
25
|
+
static LEFT: Vec2 = new Vec2(-1, 0);
|
|
26
|
+
|
|
27
|
+
/** Right direction (1, 0) */
|
|
28
|
+
static RIGHT: Vec2 = new Vec2(1, 0);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new Vec2.
|
|
32
|
+
* @param x X component
|
|
33
|
+
* @param y Y component
|
|
34
|
+
*/
|
|
35
|
+
constructor(public x: number, public y: number) { }
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Adds a vector or scalar to a vector.
|
|
39
|
+
* @param a Base vector
|
|
40
|
+
* @param b Vector or scalar to add
|
|
41
|
+
*/
|
|
42
|
+
static add(a: Vec2, b: Vec2 | number): Vec2 {
|
|
43
|
+
if (typeof b === 'number') return new Vec2(a.x + b, a.y + b);
|
|
44
|
+
else return new Vec2(a.x + b.x, a.y + b.y);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Subtracts a vector or scalar from a vector.
|
|
49
|
+
* @param a Base vector
|
|
50
|
+
* @param b Vector or scalar to subtract
|
|
51
|
+
*/
|
|
52
|
+
static subtract(a: Vec2, b: Vec2 | number): Vec2 {
|
|
53
|
+
if (typeof b === 'number') return new Vec2(a.x - b, a.y - b);
|
|
54
|
+
else return new Vec2(a.x - b.x, a.y - b.y);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Multiplies a vector by another vector (component-wise) or scalar.
|
|
59
|
+
*/
|
|
60
|
+
static multiply(a: Vec2, b: Vec2 | number): Vec2 {
|
|
61
|
+
if (typeof b === 'number') return new Vec2(a.x * b, a.y * b);
|
|
62
|
+
else return new Vec2(a.x * b.x, a.y * b.y);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Divides a vector by another vector (component-wise) or scalar.
|
|
67
|
+
*/
|
|
68
|
+
static divide(a: Vec2, b: Vec2 | number): Vec2 {
|
|
69
|
+
if (typeof b === 'number') return new Vec2(a.x / b, a.y / b);
|
|
70
|
+
else return new Vec2(a.x / b.x, a.y / b.y);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Linearly interpolates between two vectors.
|
|
75
|
+
* @param t Interpolation factor (0–1)
|
|
76
|
+
*/
|
|
77
|
+
static lerp(a: Vec2, b: Vec2, t: number): Vec2 {
|
|
78
|
+
return new Vec2(
|
|
79
|
+
a.x + (b.x - a.x) * t,
|
|
80
|
+
a.y + (b.y - a.y) * t
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Clamps a vector between a minimum and maximum vector.
|
|
86
|
+
*/
|
|
87
|
+
static clamp(v: Vec2, min: Vec2, max: Vec2): Vec2 {
|
|
88
|
+
return new Vec2(
|
|
89
|
+
Math.min(Math.max(v.x, min.x), max.x),
|
|
90
|
+
Math.min(Math.max(v.y, min.y), max.y)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Dot product of two vectors.
|
|
96
|
+
*/
|
|
97
|
+
static dot(a: Vec2, b: Vec2): number {
|
|
98
|
+
return a.x * b.x + a.y * b.y;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Length (magnitude) of a vector.
|
|
103
|
+
*/
|
|
104
|
+
static magnitude(a: Vec2): number {
|
|
105
|
+
return Math.sqrt(a.x * a.x + a.y * a.y);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Returns a normalized (unit length) vector.
|
|
110
|
+
* If magnitude is zero, returns (0, 0).
|
|
111
|
+
*/
|
|
112
|
+
static normalize(a: Vec2): Vec2 {
|
|
113
|
+
const mag = Vec2.magnitude(a);
|
|
114
|
+
return mag === 0 ? new Vec2(0, 0) : new Vec2(a.x / mag, a.y / mag);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Distance between two vectors.
|
|
119
|
+
*/
|
|
120
|
+
static distance(a: Vec2, b: Vec2): number {
|
|
121
|
+
return Vec2.magnitude(Vec2.subtract(a, b));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns the negated vector.
|
|
126
|
+
*/
|
|
127
|
+
static negate(a: Vec2): Vec2 {
|
|
128
|
+
return new Vec2(-a.x, -a.y);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Checks exact equality between two vectors.
|
|
133
|
+
*/
|
|
134
|
+
static equals(a: Vec2, b: Vec2): boolean {
|
|
135
|
+
return a.x === b.x && a.y === b.y;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Checks approximate equality between two vectors.
|
|
140
|
+
* @param epsilon Allowed difference threshold
|
|
141
|
+
*/
|
|
142
|
+
static approxEquals(a: Vec2, b: Vec2, epsilon = 0.0001): boolean {
|
|
143
|
+
return (
|
|
144
|
+
Math.abs(a.x - b.x) < epsilon &&
|
|
145
|
+
Math.abs(a.y - b.y) < epsilon
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns the angle (in radians) between two vectors.
|
|
151
|
+
* Returns 0 if either vector has zero length.
|
|
152
|
+
*/
|
|
153
|
+
static angle(a: Vec2, b: Vec2): number {
|
|
154
|
+
const magA = Vec2.magnitude(a);
|
|
155
|
+
const magB = Vec2.magnitude(b);
|
|
156
|
+
const denom = magA * magB;
|
|
157
|
+
if (denom === 0) return 0;
|
|
158
|
+
|
|
159
|
+
let c = Vec2.dot(a, b) / denom;
|
|
160
|
+
c = Math.max(-1, Math.min(1, c));
|
|
161
|
+
return Math.acos(c);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Returns a perpendicular vector (-y, x).
|
|
166
|
+
*/
|
|
167
|
+
static perpendicular(a: Vec2): Vec2 {
|
|
168
|
+
return new Vec2(-a.y, a.x);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 3D vector utility class.
|
|
174
|
+
* Provides common vector math operations for 3D space.
|
|
175
|
+
*/
|
|
176
|
+
export class Vec3 {
|
|
177
|
+
|
|
178
|
+
/** Constant zero vector (0, 0, 0) */
|
|
179
|
+
static ZERO: Vec3 = new Vec3(0, 0, 0);
|
|
180
|
+
|
|
181
|
+
/** Up direction (0, 1, 0) */
|
|
182
|
+
static UP: Vec3 = new Vec3(0, 1, 0);
|
|
183
|
+
|
|
184
|
+
/** Down direction (0, -1, 0) */
|
|
185
|
+
static DOWN: Vec3 = new Vec3(0, -1, 0);
|
|
186
|
+
|
|
187
|
+
/** Left direction (-1, 0, 0) */
|
|
188
|
+
static LEFT: Vec3 = new Vec3(-1, 0, 0);
|
|
189
|
+
|
|
190
|
+
/** Right direction (1, 0, 0) */
|
|
191
|
+
static RIGHT: Vec3 = new Vec3(1, 0, 0);
|
|
192
|
+
|
|
193
|
+
/** Forward direction (0, 0, 1) */
|
|
194
|
+
static FORWARD: Vec3 = new Vec3(0, 0, 1);
|
|
195
|
+
|
|
196
|
+
/** Backward direction (0, 0, -1) */
|
|
197
|
+
static BACK: Vec3 = new Vec3(0, 0, -1);
|
|
198
|
+
|
|
199
|
+
/** West direction (-1, 0, 0) */
|
|
200
|
+
static WEST: Vec3 = new Vec3(-1, 0, 0);
|
|
201
|
+
|
|
202
|
+
/** East direction (1, 0, 0) */
|
|
203
|
+
static EAST: Vec3 = new Vec3(1, 0, 0);
|
|
204
|
+
|
|
205
|
+
/** North direction (0, 0, 1) */
|
|
206
|
+
static NORTH: Vec3 = new Vec3(0, 0, 1);
|
|
207
|
+
|
|
208
|
+
/** South direction (0, 0, -1) */
|
|
209
|
+
static SOUTH: Vec3 = new Vec3(0, 0, -1);
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Creates a new Vec3.
|
|
213
|
+
* @param x X component
|
|
214
|
+
* @param y Y component
|
|
215
|
+
* @param z Z component
|
|
216
|
+
*/
|
|
217
|
+
constructor(public x: number, public y: number, public z: number) { }
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Adds a vector or scalar to a vector.
|
|
221
|
+
* @param a Base vector
|
|
222
|
+
* @param b Vector or scalar to add
|
|
223
|
+
*/
|
|
224
|
+
static add(a: Vec3, b: Vec3 | number): Vec3 {
|
|
225
|
+
if (typeof b === 'number') return new Vec3(a.x + b, a.y + b, a.z + b);
|
|
226
|
+
else return new Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Subtracts a vector or scalar from a vector.
|
|
231
|
+
* @param a Base vector
|
|
232
|
+
* @param b Vector or scalar to subtract
|
|
233
|
+
*/
|
|
234
|
+
static subtract(a: Vec3, b: Vec3 | number): Vec3 {
|
|
235
|
+
if (typeof b === 'number') return new Vec3(a.x - b, a.y - b, a.z - b);
|
|
236
|
+
else return new Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Multiplies a vector by another vector (component-wise) or scalar.
|
|
241
|
+
*/
|
|
242
|
+
static multiply(a: Vec3, b: Vec3 | number): Vec3 {
|
|
243
|
+
if (typeof b === 'number') return new Vec3(a.x * b, a.y * b, a.z * b);
|
|
244
|
+
else return new Vec3(a.x * b.x, a.y * b.y, a.z * b.z);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Divides a vector by another vector (component-wise) or scalar.
|
|
249
|
+
*/
|
|
250
|
+
static divide(a: Vec3, b: Vec3 | number): Vec3 {
|
|
251
|
+
if (typeof b === 'number') return new Vec3(a.x / b, a.y / b, a.z / b);
|
|
252
|
+
else return new Vec3(a.x / b.x, a.y / b.y, a.z / b.z);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Linearly interpolates between two vectors.
|
|
257
|
+
* @param t Interpolation factor (0–1)
|
|
258
|
+
*/
|
|
259
|
+
static lerp(a: Vec3, b: Vec3, t: number): Vec3 {
|
|
260
|
+
return new Vec3(
|
|
261
|
+
a.x + (b.x - a.x) * t,
|
|
262
|
+
a.y + (b.y - a.y) * t,
|
|
263
|
+
a.z + (b.z - a.z) * t
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Clamps a vector between a minimum and maximum vector.
|
|
269
|
+
*/
|
|
270
|
+
static clamp(v: Vec3, min: Vec3, max: Vec3): Vec3 {
|
|
271
|
+
return new Vec3(
|
|
272
|
+
Math.min(Math.max(v.x, min.x), max.x),
|
|
273
|
+
Math.min(Math.max(v.y, min.y), max.y),
|
|
274
|
+
Math.min(Math.max(v.z, min.z), max.z)
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Dot product of two vectors.
|
|
280
|
+
*/
|
|
281
|
+
static dot(a: Vec3, b: Vec3): number {
|
|
282
|
+
return a.x * b.x + a.y * b.y + a.z * b.z;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Cross product of two vectors.
|
|
287
|
+
* Returns a vector perpendicular to both inputs.
|
|
288
|
+
*/
|
|
289
|
+
static cross(a: Vec3, b: Vec3): Vec3 {
|
|
290
|
+
return new Vec3(
|
|
291
|
+
a.y * b.z - a.z * b.y,
|
|
292
|
+
a.z * b.x - a.x * b.z,
|
|
293
|
+
a.x * b.y - a.y * b.x
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Length (magnitude) of a vector.
|
|
299
|
+
*/
|
|
300
|
+
static magnitude(a: Vec3): number {
|
|
301
|
+
return Math.sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Returns a normalized (unit length) vector.
|
|
306
|
+
* If magnitude is zero, returns (0, 0, 0).
|
|
307
|
+
*/
|
|
308
|
+
static normalize(a: Vec3): Vec3 {
|
|
309
|
+
const mag = Vec3.magnitude(a);
|
|
310
|
+
return mag === 0
|
|
311
|
+
? new Vec3(0, 0, 0)
|
|
312
|
+
: new Vec3(a.x / mag, a.y / mag, a.z / mag);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Distance between two vectors.
|
|
317
|
+
*/
|
|
318
|
+
static distance(a: Vec3, b: Vec3): number {
|
|
319
|
+
return Vec3.magnitude(Vec3.subtract(a, b));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Returns the negated vector.
|
|
324
|
+
*/
|
|
325
|
+
static negate(a: Vec3): Vec3 {
|
|
326
|
+
return new Vec3(-a.x, -a.y, -a.z);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Checks exact equality between two vectors.
|
|
331
|
+
*/
|
|
332
|
+
static equals(a: Vec3, b: Vec3): boolean {
|
|
333
|
+
return a.x === b.x && a.y === b.y && a.z === b.z;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Checks approximate equality between two vectors.
|
|
338
|
+
* @param epsilon Allowed difference threshold
|
|
339
|
+
*/
|
|
340
|
+
static approxEquals(a: Vec3, b: Vec3, epsilon = 0.0001): boolean {
|
|
341
|
+
return (
|
|
342
|
+
Math.abs(a.x - b.x) < epsilon &&
|
|
343
|
+
Math.abs(a.y - b.y) < epsilon &&
|
|
344
|
+
Math.abs(a.z - b.z) < epsilon
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Returns the angle (in radians) between two vectors.
|
|
350
|
+
* Returns 0 if either vector has zero length.
|
|
351
|
+
*/
|
|
352
|
+
static angle(a: Vec3, b: Vec3): number {
|
|
353
|
+
const magA = Vec3.magnitude(a);
|
|
354
|
+
const magB = Vec3.magnitude(b);
|
|
355
|
+
const denom = magA * magB;
|
|
356
|
+
if (denom === 0) return 0;
|
|
357
|
+
|
|
358
|
+
let c = Vec3.dot(a, b) / denom;
|
|
359
|
+
c = Math.max(-1, Math.min(1, c));
|
|
360
|
+
return Math.acos(c);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Projects vector `a` onto vector `onto`.
|
|
365
|
+
* If `onto` has zero length, returns (0, 0, 0).
|
|
366
|
+
*/
|
|
367
|
+
static project(a: Vec3, onto: Vec3): Vec3 {
|
|
368
|
+
const denom = Vec3.dot(onto, onto);
|
|
369
|
+
if (denom === 0) return new Vec3(0, 0, 0);
|
|
370
|
+
|
|
371
|
+
const scale = Vec3.dot(a, onto) / denom;
|
|
372
|
+
return Vec3.multiply(onto, scale);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Converts spherical coordinates to cartesian coordinates.
|
|
377
|
+
* @param radius Distance from origin
|
|
378
|
+
* @param theta Azimuth angle (radians)
|
|
379
|
+
* @param phi Polar angle (radians)
|
|
380
|
+
*/
|
|
381
|
+
static cartesian(radius: number, theta: number, phi: number): Vec3 {
|
|
382
|
+
return new Vec3(
|
|
383
|
+
radius * Math.sin(phi) * Math.cos(theta),
|
|
384
|
+
radius * Math.sin(phi) * Math.sin(theta),
|
|
385
|
+
radius * Math.cos(phi)
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
}
|