@woosh/meep-engine 2.60.0 → 2.61.0
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/build/meep.cjs +20211 -20240
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +20211 -20240
- package/package.json +1 -1
- package/src/core/binary/BitSet.js +1 -1
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +30 -182
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.spec.js +27 -1
- package/src/core/geom/ConicRay.js +16 -21
- package/src/core/geom/ConicRay.spec.js +24 -0
- package/src/core/geom/packing/miniball/Miniball.js +68 -117
- package/src/core/geom/packing/miniball/Miniball.spec.js +3 -3
- package/src/core/geom/packing/miniball/Subspan.js +47 -34
- package/src/core/geom/packing/miniball/miniball_compute_quality.js +64 -0
- package/src/core/math/bessel_3.js +1 -0
- package/src/core/math/random/randomBytes.js +2 -2
- package/src/core/math/sqr.js +8 -0
- package/src/core/model/node-graph/Connection.js +21 -23
- package/src/core/model/node-graph/DataType.js +16 -17
- package/src/core/model/node-graph/NodeGraph.js +49 -50
- package/src/core/model/node-graph/node/NodeDescription.js +42 -44
- package/src/core/model/node-graph/node/NodeInstance.js +59 -60
- package/src/core/model/node-graph/node/NodeInstancePortReference.js +27 -29
- package/src/core/model/node-graph/node/NodeRegistry.js +16 -18
- package/src/core/model/node-graph/node/Port.js +35 -37
- package/src/core/model/node-graph/node/parameter/NodeParameterDescription.js +27 -13
- package/src/core/path/computePathDirectory.spec.js +8 -0
- package/src/core/process/BaseProcess.d.ts +5 -0
- package/src/core/process/WatchDog.js +76 -75
- package/src/core/process/action/AsynchronousAction.js +24 -22
- package/src/core/process/executor/profile/Profile.js +34 -24
- package/src/core/process/executor/profile/TraceEvent.js +75 -75
- package/src/core/process/worker/OnDemandWorkerManager.js +27 -30
- package/src/core/process/worker/WorkerBuilder.js +149 -149
- package/src/core/process/worker/WorkerProxy.js +25 -21
- package/src/core/process/worker/extractTransferables.js +2 -2
- package/src/engine/Engine.js +58 -53
- package/src/engine/EngineConfiguration.d.ts +4 -4
- package/src/engine/ecs/EntityManager.js +517 -614
- package/src/engine/ecs/System.js +2 -2
- package/src/engine/ecs/transform/Transform.d.ts +7 -5
- package/src/engine/ecs/transform/Transform.js +30 -16
- package/src/engine/ecs/validateSystem.js +89 -0
- package/src/engine/graphics/GraphicsEngine.js +433 -483
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +46 -48
- package/src/engine/graphics/ecs/camera/Camera.js +11 -11
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +2 -2
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +60 -62
- package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +20 -22
- package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +15 -4
- package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +156 -180
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +69 -71
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +51 -53
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +67 -69
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +56 -58
- package/src/engine/graphics/shadows/testShadowMapRendering.js +30 -34
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js +22 -20
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.js +10 -13
- package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +1 -1
- package/src/engine/plugin/EnginePluginManager.d.ts +6 -1
- package/src/engine/ecs/components/ClingToHeightMap.js +0 -19
- package/src/engine/ecs/components/SynchronizePosition.js +0 -15
- package/src/engine/ecs/systems/ClingToHeightMapSystem.js +0 -170
- package/src/engine/ecs/systems/SynchronizePositionSystem.js +0 -43
package/package.json
CHANGED
|
@@ -457,7 +457,7 @@ BitSet.prototype.get = function (bitIndex) {
|
|
|
457
457
|
assert.isNonNegativeInteger(bitIndex, "bitIndex");
|
|
458
458
|
|
|
459
459
|
if (bitIndex >= this.__length) {
|
|
460
|
-
//bit is outside
|
|
460
|
+
//bit is outside the recorded region
|
|
461
461
|
return false;
|
|
462
462
|
}
|
|
463
463
|
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { assert } from "../../../../assert.js";
|
|
1
|
+
import {mat3, vec3} from "gl-matrix";
|
|
2
|
+
import {assert} from "../../../../assert.js";
|
|
3
|
+
import {array_copy} from "../../../../collection/array/array_copy.js";
|
|
4
|
+
import {min2} from "../../../../math/min2.js";
|
|
6
5
|
|
|
7
6
|
/*
|
|
8
7
|
@see https://github.com/Bestmaker602/olacziy/blob/212b64ea5f1856b390cdf7629801243f76a4466d/libs/ibl/src/CubemapSH.cpp
|
|
9
8
|
*/
|
|
10
9
|
|
|
10
|
+
|
|
11
|
+
const F_PI = 3.14159265358979323846264338327950288;
|
|
12
|
+
const F_SQRT1_2 = 0.707106781186547524400844362104849039;
|
|
13
|
+
const M_SQRT_3 = 1.7320508076;
|
|
14
|
+
|
|
15
|
+
const M_SQRT_PI = 1.7724538509;
|
|
16
|
+
const M_SQRT_5 = 2.2360679775;
|
|
17
|
+
const M_SQRT_15 = 3.8729833462;
|
|
18
|
+
|
|
11
19
|
/**
|
|
12
20
|
*
|
|
13
21
|
* @param {number[]} M 5x5 matrix
|
|
14
22
|
* @param {number[]} x vec5
|
|
15
|
-
* @return {number[]}
|
|
23
|
+
* @return {number[]} vec5
|
|
16
24
|
*/
|
|
17
25
|
function multiply_5d(M, x) {
|
|
18
26
|
return [
|
|
@@ -24,51 +32,6 @@ function multiply_5d(M, x) {
|
|
|
24
32
|
];
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* returns n! / d!
|
|
30
|
-
* @param {number} n
|
|
31
|
-
* @param {number} d
|
|
32
|
-
* @return {number}
|
|
33
|
-
*/
|
|
34
|
-
function factorial(n, d = 1) {
|
|
35
|
-
let _d = max2(1, d);
|
|
36
|
-
let _n = max2(1, n);
|
|
37
|
-
|
|
38
|
-
let r = 1.0;
|
|
39
|
-
|
|
40
|
-
if (_n === _d) {
|
|
41
|
-
// intentionally left blank
|
|
42
|
-
} else if (_n > _d) {
|
|
43
|
-
for (; _n > _d; _n--) {
|
|
44
|
-
r *= _n;
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
for (; _d > _n; _d--) {
|
|
48
|
-
r *= _d;
|
|
49
|
-
}
|
|
50
|
-
r = 1.0 / r;
|
|
51
|
-
}
|
|
52
|
-
return r;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const F_PI = 3.14159265358979323846264338327950288;
|
|
56
|
-
const F_2_PI = 0.636619772367581343075535053490057448;
|
|
57
|
-
const F_2_SQRTPI = 1.12837916709551257389615890312154517;
|
|
58
|
-
const F_SQRT2 = 1.41421356237309504880168872420969808;
|
|
59
|
-
const F_SQRT1_2 = 0.707106781186547524400844362104849039;
|
|
60
|
-
const M_SQRT_3 = 1.7320508076;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* SH scaling factors:
|
|
64
|
-
* returns sqrt((2*l + 1) / 4*pi) * sqrt( (l-|m|)! / (l+|m|)! )
|
|
65
|
-
*/
|
|
66
|
-
function Kml(m, l) {
|
|
67
|
-
m = m < 0 ? -m : m; // abs() is not constexpr
|
|
68
|
-
const K = (2 * l + 1) * factorial((l - m), (l + m));
|
|
69
|
-
return Math.sqrt(K) * (F_2_SQRTPI * 0.25);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
35
|
/**
|
|
73
36
|
* compute Index of spherical harmonics coefficient
|
|
74
37
|
* @param {number} m signed offset from zonal harmonic
|
|
@@ -79,127 +42,6 @@ function SHindex(m, l) {
|
|
|
79
42
|
return l * (l + 1) + m;
|
|
80
43
|
}
|
|
81
44
|
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
* @param {number[]} result
|
|
85
|
-
* @param {number} result_offset
|
|
86
|
-
* @param {number} numBands
|
|
87
|
-
*/
|
|
88
|
-
function Ki(result, result_offset, numBands) {
|
|
89
|
-
for (let l = 0; l < numBands; l++) {
|
|
90
|
-
result[SHindex(0, l) + result_offset] = Kml(0, l);
|
|
91
|
-
for (let m = 1; m <= l; m++) {
|
|
92
|
-
result[SHindex(m, l) + result_offset] =
|
|
93
|
-
result[SHindex(-m, l) + result_offset] = F_SQRT2 * Kml(m, l);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* < cos(theta) > SH coefficients pre-multiplied by 1 / K(0,l)
|
|
100
|
-
* @param {number} l
|
|
101
|
-
* @returns {number}
|
|
102
|
-
*/
|
|
103
|
-
function computeTruncatedCosSh(l) {
|
|
104
|
-
if (l === 0) {
|
|
105
|
-
return F_PI;
|
|
106
|
-
} else if (l === 1) {
|
|
107
|
-
return 2 * F_PI / 3;
|
|
108
|
-
} else if ((l & 1) !== 0) {
|
|
109
|
-
return 0;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const l_2 = l / 2;
|
|
113
|
-
const A0 = ((l_2 & 1) ? 1.0 : -1.0) / ((l + 2) * (l - 1));
|
|
114
|
-
const A1 = factorial(l, l_2) / (factorial(l_2) * (1 << l));
|
|
115
|
-
return 2 * F_PI * A0 * A1;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/*
|
|
119
|
-
* Calculates non-normalized SH bases, i.e.:
|
|
120
|
-
* m > 0, cos(m*phi) * P(m,l)
|
|
121
|
-
* m < 0, sin(|m|*phi) * P(|m|,l)
|
|
122
|
-
* m = 0, P(0,l)
|
|
123
|
-
*/
|
|
124
|
-
function computeShBasis(SHb, result_offset, numBands, sx, sy, sz) {
|
|
125
|
-
|
|
126
|
-
/*
|
|
127
|
-
* TODO: all the Legendre computation below is identical for all faces, so it
|
|
128
|
-
* might make sense to pre-compute it once. Also note that there is
|
|
129
|
-
* a fair amount of symmetry within a face (which we could take advantage of
|
|
130
|
-
* to reduce the pre-compute table).
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
/*
|
|
134
|
-
* Below, we compute the associated Legendre polynomials using recursion.
|
|
135
|
-
* see: http://mathworld.wolfram.com/AssociatedLegendrePolynomial.html
|
|
136
|
-
*
|
|
137
|
-
* Note [0]: sz == cos(theta) ==> we only need to compute P(sz)
|
|
138
|
-
*
|
|
139
|
-
* Note [1]: We in fact compute P(sz) / sin(theta)^|m|, by removing
|
|
140
|
-
* the "sqrt(1 - sz*sz)" [i.e.: sin(theta)] factor from the recursion.
|
|
141
|
-
* This is later corrected in the ( cos(m*phi), sin(m*phi) ) recursion.
|
|
142
|
-
*/
|
|
143
|
-
|
|
144
|
-
// s = (x, y, z) = (sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta))
|
|
145
|
-
|
|
146
|
-
// handle m=0 separately, since it produces only one coefficient
|
|
147
|
-
let Pml_2 = 0;
|
|
148
|
-
let Pml_1 = 1;
|
|
149
|
-
SHb[result_offset + 0] = Pml_1;
|
|
150
|
-
for (let l = 1; l < numBands; l++) {
|
|
151
|
-
const Pml = ((2 * l - 1.0) * Pml_1 * sz - (l - 1.0) * Pml_2) / l;
|
|
152
|
-
Pml_2 = Pml_1;
|
|
153
|
-
Pml_1 = Pml;
|
|
154
|
-
SHb[result_offset + SHindex(0, l)] = Pml;
|
|
155
|
-
}
|
|
156
|
-
let Pmm = 1;
|
|
157
|
-
for (let m = 1; m < numBands; m++) {
|
|
158
|
-
Pmm = (1.0 - 2 * m) * Pmm; // See [1], divide by sqrt(1 - sz*sz);
|
|
159
|
-
Pml_2 = Pmm;
|
|
160
|
-
Pml_1 = (2 * m + 1.0) * Pmm * sz;
|
|
161
|
-
// l == m
|
|
162
|
-
SHb[result_offset + SHindex(-m, m)] = Pml_2;
|
|
163
|
-
SHb[result_offset + SHindex(m, m)] = Pml_2;
|
|
164
|
-
if (m + 1 < numBands) {
|
|
165
|
-
// l == m+1
|
|
166
|
-
SHb[result_offset + SHindex(-m, m + 1)] = Pml_1;
|
|
167
|
-
SHb[result_offset + SHindex(m, m + 1)] = Pml_1;
|
|
168
|
-
for (let l = m + 2; l < numBands; l++) {
|
|
169
|
-
const Pml = ((2 * l - 1.0) * Pml_1 * sz - (l + m - 1.0) * Pml_2) / (l - m);
|
|
170
|
-
Pml_2 = Pml_1;
|
|
171
|
-
Pml_1 = Pml;
|
|
172
|
-
SHb[result_offset + SHindex(-m, l)] = Pml;
|
|
173
|
-
SHb[result_offset + SHindex(m, l)] = Pml;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// At this point, SHb contains the associated Legendre polynomials divided
|
|
179
|
-
// by sin(theta)^|m|. Below we compute the SH basis.
|
|
180
|
-
//
|
|
181
|
-
// ( cos(m*phi), sin(m*phi) ) recursion:
|
|
182
|
-
// cos(m*phi + phi) == cos(m*phi)*cos(phi) - sin(m*phi)*sin(phi)
|
|
183
|
-
// sin(m*phi + phi) == sin(m*phi)*cos(phi) + cos(m*phi)*sin(phi)
|
|
184
|
-
// cos[m+1] == cos[m]*sx - sin[m]*sy
|
|
185
|
-
// sin[m+1] == sin[m]*sx + cos[m]*sy
|
|
186
|
-
//
|
|
187
|
-
// Note that (d.x, d.y) == (cos(phi), sin(phi)) * sin(theta), so the
|
|
188
|
-
// code below actually evaluates:
|
|
189
|
-
// (cos((m*phi), sin(m*phi)) * sin(theta)^|m|
|
|
190
|
-
let Cm = sx;
|
|
191
|
-
let Sm = sy;
|
|
192
|
-
for (let m = 1; m <= numBands; m++) {
|
|
193
|
-
for (let l = m; l < numBands; l++) {
|
|
194
|
-
SHb[result_offset + SHindex(-m, l)] *= Sm;
|
|
195
|
-
SHb[result_offset + SHindex(m, l)] *= Cm;
|
|
196
|
-
}
|
|
197
|
-
const Cm1 = Cm * sx - Sm * sy;
|
|
198
|
-
const Sm1 = Sm * sx + Cm * sy;
|
|
199
|
-
Cm = Cm1;
|
|
200
|
-
Sm = Sm1;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
45
|
|
|
204
46
|
/*
|
|
205
47
|
* utilities to rotate very low order spherical harmonics (up to 3rd band)
|
|
@@ -247,10 +89,10 @@ function rotateShericalHarmonicBand1(band1, M) {
|
|
|
247
89
|
/**
|
|
248
90
|
* This projects a vec3 to SH2/k space (i.e. we premultiply by 1/k)
|
|
249
91
|
* below can't be constexpr
|
|
250
|
-
* @return {number[]} vec5
|
|
251
92
|
* @param {number} x
|
|
252
93
|
* @param {number} y
|
|
253
94
|
* @param {number} z
|
|
95
|
+
* @return {number[]} vec5
|
|
254
96
|
*/
|
|
255
97
|
function project_v3_to_sh(x, y, z) {
|
|
256
98
|
return [
|
|
@@ -266,7 +108,7 @@ function project_v3_to_sh(x, y, z) {
|
|
|
266
108
|
*
|
|
267
109
|
* @param {number[]} band2 vec5
|
|
268
110
|
* @param {number[]} M mat3
|
|
269
|
-
* @return {
|
|
111
|
+
* @return {number[]} vec5
|
|
270
112
|
*/
|
|
271
113
|
function rotateShericalHarmonicBand2(band2, M) {
|
|
272
114
|
const n = F_SQRT1_2;
|
|
@@ -310,7 +152,7 @@ function rotateShericalHarmonicBand2(band2, M) {
|
|
|
310
152
|
return result;
|
|
311
153
|
}
|
|
312
154
|
|
|
313
|
-
|
|
155
|
+
/**
|
|
314
156
|
* SH from environment with high dynamic range (or high frequencies -- high dynamic range creates
|
|
315
157
|
* high frequencies) exhibit "ringing" and negative values when reconstructed.
|
|
316
158
|
* To mitigate this, we need to low-pass the input image -- or equivalently window the SH by
|
|
@@ -321,7 +163,9 @@ function rotateShericalHarmonicBand2(band2, M) {
|
|
|
321
163
|
* Deringing Spherical Harmonics
|
|
322
164
|
* by Peter-Pike Sloan
|
|
323
165
|
* https://www.ppsloan.org/publications/shdering.pdf
|
|
324
|
-
*
|
|
166
|
+
* @param {number} w
|
|
167
|
+
* @param {number} l
|
|
168
|
+
* @returns {number}
|
|
325
169
|
*/
|
|
326
170
|
function sincWindow(l, w) {
|
|
327
171
|
if (l === 0) {
|
|
@@ -379,10 +223,6 @@ function shmin(input_sh3) {
|
|
|
379
223
|
// See "Deringing Spherical Harmonics" by Peter-Pike Sloan
|
|
380
224
|
// https://www.ppsloan.org/publications/shdering.pdf
|
|
381
225
|
|
|
382
|
-
const M_SQRT_PI = 1.7724538509;
|
|
383
|
-
const M_SQRT_3 = 1.7320508076;
|
|
384
|
-
const M_SQRT_5 = 2.2360679775;
|
|
385
|
-
const M_SQRT_15 = 3.8729833462;
|
|
386
226
|
const A = [
|
|
387
227
|
1.0 / (2.0 * M_SQRT_PI), // 0: 0 0
|
|
388
228
|
-M_SQRT_3 / (2.0 * M_SQRT_PI), // 1: 1 -1
|
|
@@ -545,9 +385,13 @@ function windowing(f, cutoff, numBands) {
|
|
|
545
385
|
* @param {number} input_offset
|
|
546
386
|
* @param {number} numBands
|
|
547
387
|
* @param {number} channel_count
|
|
548
|
-
* @param {number} cutoff
|
|
388
|
+
* @param {number} [cutoff]
|
|
549
389
|
*/
|
|
550
|
-
function windowSH(
|
|
390
|
+
function windowSH(
|
|
391
|
+
output, output_offset,
|
|
392
|
+
input, input_offset,
|
|
393
|
+
numBands, channel_count, cutoff = 0
|
|
394
|
+
) {
|
|
551
395
|
assert.isNonNegativeInteger(channel_count, 'channel_count');
|
|
552
396
|
assert.greaterThan(channel_count, 0, 'channel_count must be greater than 0');
|
|
553
397
|
|
|
@@ -575,13 +419,17 @@ function windowSH(output, output_offset, input, input_offset, numBands, channel_
|
|
|
575
419
|
// find a cut-off band that works
|
|
576
420
|
let l = numBands;
|
|
577
421
|
let r = cutoff;
|
|
422
|
+
|
|
578
423
|
for (let i = 0; i < 16 && l + 0.1 < r; i++) {
|
|
424
|
+
|
|
579
425
|
const m = 0.5 * (l + r);
|
|
426
|
+
|
|
580
427
|
if (shmin(windowing(SH, m, numBands)) < 0) {
|
|
581
428
|
r = m;
|
|
582
429
|
} else {
|
|
583
430
|
l = m;
|
|
584
431
|
}
|
|
432
|
+
|
|
585
433
|
}
|
|
586
434
|
|
|
587
435
|
// record minimum cutoff
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { sh3_dering_optimize_positive } from "./sh3_dering_optimize_positive.js";
|
|
2
2
|
|
|
3
|
-
test("de-ringing produces plausible numeric values", () => {
|
|
3
|
+
test("de-ringing produces plausible numeric values from 1", () => {
|
|
4
4
|
|
|
5
5
|
const result = [];
|
|
6
6
|
|
|
@@ -25,3 +25,29 @@ test("de-ringing produces plausible numeric values", () => {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
});
|
|
28
|
+
|
|
29
|
+
test("de-ringing produces plausible numeric values from -1", () => {
|
|
30
|
+
|
|
31
|
+
const result = [];
|
|
32
|
+
|
|
33
|
+
const harmonics = new Float32Array(9);
|
|
34
|
+
|
|
35
|
+
harmonics.fill(-1);
|
|
36
|
+
|
|
37
|
+
sh3_dering_optimize_positive(
|
|
38
|
+
result, 0,
|
|
39
|
+
harmonics,
|
|
40
|
+
0,
|
|
41
|
+
1
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < 9; i++) {
|
|
45
|
+
|
|
46
|
+
const element = result[i];
|
|
47
|
+
|
|
48
|
+
expect(element).not.toBeNaN();
|
|
49
|
+
expect(Number.isFinite(element)).toBe(true);
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {assert} from "../assert.js";
|
|
2
|
+
import {computeHashIntegerArray} from "../collection/array/computeHashIntegerArray.js";
|
|
3
|
+
import {EPSILON} from "../math/EPSILON.js";
|
|
4
|
+
import {epsilonEquals} from "../math/epsilonEquals.js";
|
|
5
|
+
import {computeHashFloat} from "../primitives/numbers/computeHashFloat.js";
|
|
2
6
|
import Vector3 from "./Vector3.js";
|
|
3
|
-
import { computeHashIntegerArray } from "../collection/array/computeHashIntegerArray.js";
|
|
4
|
-
import { computeHashFloat } from "../primitives/numbers/computeHashFloat.js";
|
|
5
|
-
import { epsilonEquals } from "../math/epsilonEquals.js";
|
|
6
|
-
import { EPSILON } from "../math/EPSILON.js";
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -11,24 +11,19 @@ import { EPSILON } from "../math/EPSILON.js";
|
|
|
11
11
|
* Mainly used inside particle systems for pick a motion direction at spawn
|
|
12
12
|
*/
|
|
13
13
|
export class ConicRay {
|
|
14
|
+
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
16
|
+
* Must be normalized
|
|
17
|
+
* @type {Vector3}
|
|
17
18
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* Semi-angle of the cone, that is the angle between the center axis and the edge of the cone
|
|
27
|
-
* In radians
|
|
28
|
-
* @type {number}
|
|
29
|
-
*/
|
|
30
|
-
this.angle = 0;
|
|
31
|
-
}
|
|
19
|
+
direction = new Vector3(0, 1, 0);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Half-angle of the cone, that is the angle between the center axis and the edge of the cone
|
|
23
|
+
* In radians
|
|
24
|
+
* @type {number}
|
|
25
|
+
*/
|
|
26
|
+
angle = 0;
|
|
32
27
|
|
|
33
28
|
toJSON() {
|
|
34
29
|
return {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {ConicRay} from "./ConicRay.js";
|
|
2
|
+
import Vector3 from "./Vector3.js";
|
|
3
|
+
|
|
4
|
+
test("constructor", () => {
|
|
5
|
+
const ray = new ConicRay();
|
|
6
|
+
|
|
7
|
+
expect(ray.angle).not.toBeNaN();
|
|
8
|
+
expect(typeof ray.angle).toBe("number");
|
|
9
|
+
expect(ray.direction).toBeDefined();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("sampleRandomDirection", () => {
|
|
13
|
+
|
|
14
|
+
const ray = new ConicRay();
|
|
15
|
+
|
|
16
|
+
ray.angle = Math.PI * 0.25;
|
|
17
|
+
|
|
18
|
+
const r = new Vector3();
|
|
19
|
+
|
|
20
|
+
ray.sampleRandomDirection(() => 0, r);
|
|
21
|
+
|
|
22
|
+
expect(r.length()).toBeCloseTo(1);
|
|
23
|
+
expect(r.angleTo(ray.direction)).toBeLessThanOrEqual(ray.angle);
|
|
24
|
+
});
|