@woosh/meep-engine 2.34.19 → 2.34.24
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/core/binary/BitSet.js +20 -0
- package/core/bvh2/aabb3/aabb3_nearest_point_on_surface.js +65 -0
- package/core/collection/list/List.js +30 -0
- package/core/geom/3d/shape/UnitCubeShape3D.js +7 -37
- package/core/geom/3d/{sphereIntersectsPoint.js → sphere/sphereIntersectsPoint.js} +0 -0
- package/core/geom/3d/sphere/sphere_array_intersects_ray.js +25 -0
- package/core/geom/3d/sphere/sphere_intersects_ray.js +51 -0
- package/core/model/object/invokeObjectClone.js +2 -0
- package/core/model/object/invokeObjectCompare.js +9 -0
- package/engine/graphics/micron/build/hierarchy/merge_patches.js +7 -1
- package/engine/graphics/micron/format/MicronGeometry.js +24 -6
- package/engine/graphics/micron/format/serialization/deserialize_patch.js +40 -11
- package/engine/graphics/render/forward_plus/LightManager.js +23 -6
- package/engine/graphics/render/forward_plus/PointLightData.js +9 -0
- package/engine/graphics/render/forward_plus/model/AbstractLight.js +16 -0
- package/engine/graphics/render/layers/RenderLayer.js +3 -2
- package/engine/graphics/render/view/CameraView.js +2 -1
- package/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +2 -2
- package/engine/graphics/render/visibility/IncrementalDeltaSet.js +95 -20
- package/engine/graphics/render/visibility/IncrementalDeltaSet.spec.js +46 -0
- package/engine/graphics/three/compare_three_objects.js +8 -0
- package/engine/sound/ecs/emitter/SoundEmitter.js +59 -0
- package/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +8 -0
- package/engine/sound/ecs/emitter/SoundEmitterSystem.js +2 -1
- package/engine/sound/ecs/emitter/SoundTrack.js +41 -0
- package/package.json +1 -1
package/core/binary/BitSet.js
CHANGED
|
@@ -509,6 +509,26 @@ BitSet.prototype.getAndClear = function (index) {
|
|
|
509
509
|
return v;
|
|
510
510
|
};
|
|
511
511
|
|
|
512
|
+
/**
|
|
513
|
+
*
|
|
514
|
+
* @param {number} distance
|
|
515
|
+
* @param {number} start_index
|
|
516
|
+
* @param {number} end_index
|
|
517
|
+
*/
|
|
518
|
+
BitSet.prototype.shift = function (distance, start_index, end_index) {
|
|
519
|
+
if (distance > 0) {
|
|
520
|
+
for (let i = end_index; i >= start_index; i--) {
|
|
521
|
+
const v = this.get(i);
|
|
522
|
+
this.set(i + distance, v);
|
|
523
|
+
}
|
|
524
|
+
} else {
|
|
525
|
+
for (let i = start_index; i <= end_index; i++) {
|
|
526
|
+
const v = this.get(i);
|
|
527
|
+
this.set(i + distance, v);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
512
532
|
/**
|
|
513
533
|
* Sets all of the bits in this BitSet to false.
|
|
514
534
|
*/
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { clamp } from "../../math/clamp.js";
|
|
2
|
+
import { min2 } from "../../math/min2.js";
|
|
3
|
+
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {number[]|ArrayLike<number>} result
|
|
9
|
+
* @param {number} x0
|
|
10
|
+
* @param {number} y0
|
|
11
|
+
* @param {number} z0
|
|
12
|
+
* @param {number} x1
|
|
13
|
+
* @param {number} y1
|
|
14
|
+
* @param {number} z1
|
|
15
|
+
* @param {number} r_x
|
|
16
|
+
* @param {number} r_y
|
|
17
|
+
* @param {number} r_z
|
|
18
|
+
*/
|
|
19
|
+
export function aabb3_nearest_point_on_surface(result, x0, y0, z0, x1, y1, z1, r_x, r_y, r_z) {
|
|
20
|
+
const ar_x0 = Math.abs(r_x - x0);
|
|
21
|
+
const ar_x1 = Math.abs(r_x - x1);
|
|
22
|
+
const ar_x_min = min2(ar_x0, ar_x1);
|
|
23
|
+
|
|
24
|
+
const ar_y0 = Math.abs(r_y - y0);
|
|
25
|
+
const ar_y1 = Math.abs(r_y - y1);
|
|
26
|
+
const ar_y_min = min2(ar_y0, ar_y1);
|
|
27
|
+
|
|
28
|
+
const ar_z0 = Math.abs(r_z - z0);
|
|
29
|
+
const ar_z1 = Math.abs(r_z - z1);
|
|
30
|
+
const ar_z_min = min2(ar_z0, ar_z1);
|
|
31
|
+
|
|
32
|
+
// figure out closest face to the reference point
|
|
33
|
+
if (ar_x_min > ar_y_min && ar_x_min > ar_z_min) {
|
|
34
|
+
// X is smallest, project onto X axis
|
|
35
|
+
if (ar_x0 <= ar_x1) {
|
|
36
|
+
result[0] = x0;
|
|
37
|
+
} else {
|
|
38
|
+
result[0] = x1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
result[1] = clamp(r_y, y0, y1);
|
|
42
|
+
result[2] = clamp(r_z, z0, z1);
|
|
43
|
+
} else if (ar_y_min > ar_x_min && ar_y_min > ar_z_min) {
|
|
44
|
+
// Y is smallest, project onto X axis
|
|
45
|
+
if (ar_y0 <= ar_y1) {
|
|
46
|
+
result[1] = y0;
|
|
47
|
+
} else {
|
|
48
|
+
result[1] = y1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
result[0] = clamp(r_x, x0, x1);
|
|
52
|
+
result[2] = clamp(r_z, z0, z1);
|
|
53
|
+
} else {
|
|
54
|
+
// project onto Z axis
|
|
55
|
+
|
|
56
|
+
if (ar_z0 <= ar_z1) {
|
|
57
|
+
result[2] = z0;
|
|
58
|
+
} else {
|
|
59
|
+
result[2] = z1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
result[0] = clamp(r_x, x0, x1);
|
|
63
|
+
result[1] = clamp(r_y, y0, y1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -919,4 +919,34 @@ List.prototype.equals = function (other) {
|
|
|
919
919
|
return true;
|
|
920
920
|
};
|
|
921
921
|
|
|
922
|
+
/**
|
|
923
|
+
*
|
|
924
|
+
* @param {List<T>} other
|
|
925
|
+
* @returns {number}
|
|
926
|
+
*/
|
|
927
|
+
List.prototype.compare = function (other) {
|
|
928
|
+
const l = this.length;
|
|
929
|
+
|
|
930
|
+
const other_length = other.length;
|
|
931
|
+
if (l !== other_length) {
|
|
932
|
+
return l - other_length;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
for (let i = 0; i < l; i++) {
|
|
936
|
+
const a = this.get(i);
|
|
937
|
+
|
|
938
|
+
const b = other.get(i);
|
|
939
|
+
|
|
940
|
+
const delta = a.compare(b);
|
|
941
|
+
|
|
942
|
+
if (delta !== 0) {
|
|
943
|
+
return delta;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// same
|
|
949
|
+
return 0;
|
|
950
|
+
};
|
|
951
|
+
|
|
922
952
|
export default List;
|
|
@@ -4,8 +4,8 @@ import { v3_length } from "../../v3_length.js";
|
|
|
4
4
|
import { max2 } from "../../../math/max2.js";
|
|
5
5
|
import { max3 } from "../../../math/max3.js";
|
|
6
6
|
import { min2 } from "../../../math/min2.js";
|
|
7
|
-
import { clamp } from "../../../math/clamp.js";
|
|
8
7
|
import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
|
|
8
|
+
import { aabb3_nearest_point_on_surface } from "../../../bvh2/aabb3/aabb3_nearest_point_on_surface.js";
|
|
9
9
|
|
|
10
10
|
export class UnitCubeShape3D extends AbstractShape3D {
|
|
11
11
|
|
|
@@ -18,43 +18,13 @@ export class UnitCubeShape3D extends AbstractShape3D {
|
|
|
18
18
|
const r_y = reference[1];
|
|
19
19
|
const r_z = reference[2];
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
aabb3_nearest_point_on_surface(
|
|
22
|
+
result,
|
|
23
|
+
-0.5, -0.5, -0.5,
|
|
24
|
+
0.5, 0.5, 0.5,
|
|
25
|
+
r_x, r_y, r_z
|
|
26
|
+
);
|
|
25
27
|
|
|
26
|
-
if (ar_x > ar_y && ar_x > ar_z) {
|
|
27
|
-
// X is smallest, project onto X axis
|
|
28
|
-
if (r_x <= 0) {
|
|
29
|
-
result[0] = -0.5;
|
|
30
|
-
} else {
|
|
31
|
-
result[0] = 0.5;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
result[1] = clamp(r_y, -0.5, 0.5);
|
|
35
|
-
result[2] = clamp(r_z, -0.5, 0.5);
|
|
36
|
-
} else if (ar_y > ar_x && ar_y > ar_z) {
|
|
37
|
-
// Y is smallest, project onto X axis
|
|
38
|
-
if (r_y <= 0) {
|
|
39
|
-
result[1] = -0.5;
|
|
40
|
-
} else {
|
|
41
|
-
result[1] = 0.5;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
result[0] = clamp(r_x, -0.5, 0.5);
|
|
45
|
-
result[2] = clamp(r_z, -0.5, 0.5);
|
|
46
|
-
} else {
|
|
47
|
-
// project onto Z axis
|
|
48
|
-
|
|
49
|
-
if (r_z <= 0) {
|
|
50
|
-
result[2] = -0.5;
|
|
51
|
-
} else {
|
|
52
|
-
result[2] = 0.5;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
result[0] = clamp(r_x, -0.5, 0.5);
|
|
56
|
-
result[1] = clamp(r_y, -0.5, 0.5);
|
|
57
|
-
}
|
|
58
28
|
}
|
|
59
29
|
|
|
60
30
|
signed_distance_gradient_at_point(result, point) {
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import { sphere_intersects_ray } from "./sphere_intersects_ray.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {number[]|ArrayLike<number>} sphere
|
|
8
|
+
* @param {number} origin_x
|
|
9
|
+
* @param {number} origin_y
|
|
10
|
+
* @param {number} origin_z
|
|
11
|
+
* @param {number} direction_x
|
|
12
|
+
* @param {number} direction_y
|
|
13
|
+
* @param {number} direction_z
|
|
14
|
+
* @returns {boolean}
|
|
15
|
+
*/
|
|
16
|
+
export function sphere_array_intersects_ray(
|
|
17
|
+
sphere,
|
|
18
|
+
origin_x, origin_y, origin_z,
|
|
19
|
+
direction_x, direction_y, direction_z
|
|
20
|
+
) {
|
|
21
|
+
return sphere_intersects_ray(sphere[0], sphere[1], sphere[2], sphere[3],
|
|
22
|
+
origin_x, origin_y, origin_z,
|
|
23
|
+
direction_x, direction_y, direction_z
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import { v3_dot } from "../../v3_dot.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {number} center_x
|
|
8
|
+
* @param {number} center_y
|
|
9
|
+
* @param {number} center_z
|
|
10
|
+
* @param {number} radius
|
|
11
|
+
* @param {number} origin_x
|
|
12
|
+
* @param {number} origin_y
|
|
13
|
+
* @param {number} origin_z
|
|
14
|
+
* @param {number} direction_x
|
|
15
|
+
* @param {number} direction_y
|
|
16
|
+
* @param {number} direction_z
|
|
17
|
+
* @returns {boolean}
|
|
18
|
+
*/
|
|
19
|
+
export function sphere_intersects_ray(
|
|
20
|
+
center_x, center_y, center_z, radius,
|
|
21
|
+
origin_x, origin_y, origin_z,
|
|
22
|
+
direction_x, direction_y, direction_z
|
|
23
|
+
) {
|
|
24
|
+
const delta_x = center_x - origin_x;
|
|
25
|
+
const delta_y = center_y - origin_y;
|
|
26
|
+
const delta_z = center_z - origin_z;
|
|
27
|
+
|
|
28
|
+
const tca = v3_dot(delta_x, delta_y, delta_z, direction_x, direction_y, direction_z);
|
|
29
|
+
const d2 = v3_dot(delta_x, delta_y, delta_z, delta_x, delta_y, delta_z) - tca * tca;
|
|
30
|
+
|
|
31
|
+
const radius2 = radius * radius;
|
|
32
|
+
|
|
33
|
+
if (d2 > radius2) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const thc = Math.sqrt(radius2 - d2);
|
|
38
|
+
|
|
39
|
+
// t0 = first intersect point - entrance on front of sphere
|
|
40
|
+
const t0 = tca - thc;
|
|
41
|
+
|
|
42
|
+
// t1 = second intersect point - exit point on back of sphere
|
|
43
|
+
const t1 = tca + thc;
|
|
44
|
+
|
|
45
|
+
// test to see if both t0 and t1 are behind the ray - if so, no intersection
|
|
46
|
+
if (t0 < 0 && t1 < 0) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
@@ -513,7 +513,13 @@ export async function merge_patches(
|
|
|
513
513
|
return 0;
|
|
514
514
|
} else if (node_count === 1) {
|
|
515
515
|
// only 1 patch, no merge opportunity, forward it to output directly
|
|
516
|
-
|
|
516
|
+
const node = nodes[0];
|
|
517
|
+
|
|
518
|
+
//set group bounds to produce a valid root
|
|
519
|
+
node.group_aabb.copy(node.bounding_box);
|
|
520
|
+
node.group_bounding_sphere.set(node.bounding_sphere);
|
|
521
|
+
|
|
522
|
+
output[output_offset.value++] = node;
|
|
517
523
|
return 1;
|
|
518
524
|
} else {
|
|
519
525
|
|
|
@@ -3,6 +3,7 @@ import { assert } from "../../../../core/assert.js";
|
|
|
3
3
|
import { computeTriangleRayIntersection } from "../../../../core/geom/3d/triangle/computeTriangleRayIntersection.js";
|
|
4
4
|
import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
|
|
5
5
|
import { aabb3_array_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_array_intersects_ray.js";
|
|
6
|
+
import { sphere_array_intersects_ray } from "../../../../core/geom/3d/sphere/sphere_array_intersects_ray.js";
|
|
6
7
|
|
|
7
8
|
let id_counter = 0;
|
|
8
9
|
|
|
@@ -104,16 +105,23 @@ export class MicronGeometry {
|
|
|
104
105
|
|
|
105
106
|
const patch = stack[stack_cursor];
|
|
106
107
|
|
|
107
|
-
// using group
|
|
108
|
-
const bb = patch.group_bounding_box;
|
|
108
|
+
// using group bounds because it's conservative, as we want to be able to hit LOD_0
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
// sphere test
|
|
111
|
+
if (!sphere_array_intersects_ray(patch.group_bounding_sphere,
|
|
112
112
|
origin_x, origin_y, origin_z,
|
|
113
113
|
direction_x, direction_y, direction_z
|
|
114
|
-
)
|
|
114
|
+
)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
115
118
|
|
|
116
|
-
|
|
119
|
+
// box test (more expensive, different volume)
|
|
120
|
+
if (!aabb3_array_intersects_ray(
|
|
121
|
+
patch.group_bounding_box,
|
|
122
|
+
origin_x, origin_y, origin_z,
|
|
123
|
+
direction_x, direction_y, direction_z
|
|
124
|
+
)) {
|
|
117
125
|
// no intersection
|
|
118
126
|
continue;
|
|
119
127
|
}
|
|
@@ -122,6 +130,16 @@ export class MicronGeometry {
|
|
|
122
130
|
// LOD 0 - source geometry
|
|
123
131
|
|
|
124
132
|
// cast against bounds
|
|
133
|
+
|
|
134
|
+
// sphere test
|
|
135
|
+
if (!sphere_array_intersects_ray(patch.bounding_sphere,
|
|
136
|
+
origin_x, origin_y, origin_z,
|
|
137
|
+
direction_x, direction_y, direction_z
|
|
138
|
+
)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// box test
|
|
125
143
|
if (!aabb3_array_intersects_ray(
|
|
126
144
|
patch.bounding_box,
|
|
127
145
|
origin_x, origin_y, origin_z,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { aabb3_build_corners } from "../../../../../core/geom/3d/aabb/aabb3_build_corners.js";
|
|
2
2
|
import { DataTypeByteSizes } from "../../../../../core/collection/table/DataTypeByteSizes.js";
|
|
3
3
|
import { DataType2TypedArrayConstructorMapping } from "../../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
|
|
4
|
+
import { v3_distance } from "../../../../../core/geom/v3_distance.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
@@ -18,17 +19,6 @@ export function deserialize_patch(buffer, patch, vertex_spec, patch_array) {
|
|
|
18
19
|
buffer.readFloat32Array(gbb, 0, 6);
|
|
19
20
|
buffer.readFloat32Array(patch.group_bounding_sphere, 0, 4);
|
|
20
21
|
|
|
21
|
-
// reconstruct corners
|
|
22
|
-
aabb3_build_corners(
|
|
23
|
-
patch.group_bounding_box_corners,
|
|
24
|
-
0,
|
|
25
|
-
gbb[0],
|
|
26
|
-
gbb[1],
|
|
27
|
-
gbb[2],
|
|
28
|
-
gbb[3],
|
|
29
|
-
gbb[4],
|
|
30
|
-
gbb[5]
|
|
31
|
-
);
|
|
32
22
|
|
|
33
23
|
patch.group_error = buffer.readFloat32();
|
|
34
24
|
patch.lod = buffer.readUintVar();
|
|
@@ -101,4 +91,43 @@ export function deserialize_patch(buffer, patch, vertex_spec, patch_array) {
|
|
|
101
91
|
|
|
102
92
|
patch.vertex_attribute_arrays[i] = array;
|
|
103
93
|
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
// validate and fix group bounds as necessary
|
|
97
|
+
if (
|
|
98
|
+
patch.group_bounding_box[0] > patch.bounding_box[0] // x0
|
|
99
|
+
|| patch.group_bounding_box[1] > patch.bounding_box[1] // y0
|
|
100
|
+
|| patch.group_bounding_box[2] > patch.bounding_box[2] // x0
|
|
101
|
+
|| patch.group_bounding_box[3] < patch.bounding_box[3] // x1
|
|
102
|
+
|| patch.group_bounding_box[4] < patch.bounding_box[4] // y1
|
|
103
|
+
|| patch.group_bounding_box[5] < patch.bounding_box[5] // z1
|
|
104
|
+
) {
|
|
105
|
+
// bounds are violated, fix
|
|
106
|
+
patch.group_bounding_box.set(patch.bounding_box);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (v3_distance(
|
|
110
|
+
patch.group_bounding_sphere[0],
|
|
111
|
+
patch.group_bounding_sphere[1],
|
|
112
|
+
patch.group_bounding_sphere[2],
|
|
113
|
+
patch.bounding_sphere[0],
|
|
114
|
+
patch.bounding_sphere[1],
|
|
115
|
+
patch.bounding_sphere[2]
|
|
116
|
+
) + patch.bounding_sphere[3] > patch.group_bounding_sphere[3]) {
|
|
117
|
+
// group's sphere bounds are violated, fix
|
|
118
|
+
patch.group_bounding_sphere.set(patch.bounding_sphere);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
// reconstruct corners
|
|
123
|
+
aabb3_build_corners(
|
|
124
|
+
patch.group_bounding_box_corners,
|
|
125
|
+
0,
|
|
126
|
+
gbb[0],
|
|
127
|
+
gbb[1],
|
|
128
|
+
gbb[2],
|
|
129
|
+
gbb[3],
|
|
130
|
+
gbb[4],
|
|
131
|
+
gbb[5]
|
|
132
|
+
);
|
|
104
133
|
}
|
|
@@ -42,6 +42,9 @@ import { Decal } from "./model/Decal.js";
|
|
|
42
42
|
import { ReferencedTextureAtlas } from "../../texture/atlas/ReferencedTextureAtlas.js";
|
|
43
43
|
import { v3_morton_encode_transformed } from "../../../../core/geom/3d/morton/v3_morton_encode_transformed.js";
|
|
44
44
|
import { v3_distance } from "../../../../core/geom/v3_distance.js";
|
|
45
|
+
import { array_copy } from "../../../../core/collection/array/copyArray.js";
|
|
46
|
+
import { arrayQuickSort } from "../../../../core/collection/array/arrayQuickSort.js";
|
|
47
|
+
import { invokeObjectCompare } from "../../../../core/model/object/invokeObjectCompare.js";
|
|
45
48
|
|
|
46
49
|
const LOOKUP_CACHE_SIZE = 1024; // must be power of two
|
|
47
50
|
|
|
@@ -227,7 +230,13 @@ export class LightManager {
|
|
|
227
230
|
* @readonly
|
|
228
231
|
* @private
|
|
229
232
|
*/
|
|
230
|
-
this.__visible_lights = new IncrementalDeltaSet();
|
|
233
|
+
this.__visible_lights = new IncrementalDeltaSet(invokeObjectCompare);
|
|
234
|
+
/**
|
|
235
|
+
*
|
|
236
|
+
* @type {PointLightData[]}
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
this.__sorted_visible_lights = [];
|
|
231
240
|
|
|
232
241
|
/**
|
|
233
242
|
*
|
|
@@ -520,10 +529,18 @@ export class LightManager {
|
|
|
520
529
|
* @private
|
|
521
530
|
*/
|
|
522
531
|
__sort_visible_light() {
|
|
523
|
-
this.
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
532
|
+
const sorted_lights = this.__sorted_visible_lights;
|
|
533
|
+
const visible_light_set = this.__visible_lights;
|
|
534
|
+
const visible_light_count = visible_light_set.size;
|
|
535
|
+
|
|
536
|
+
if (sorted_lights.length > visible_light_count) {
|
|
537
|
+
// crop array if it's too big
|
|
538
|
+
sorted_lights.splice(visible_light_count, sorted_lights.length - visible_light_count)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
array_copy(visible_light_set.elements, 0, sorted_lights, 0, visible_light_count);
|
|
542
|
+
|
|
543
|
+
arrayQuickSort(sorted_lights, this.__sort_visible_light_score, this, 0, visible_light_count - 1);
|
|
527
544
|
}
|
|
528
545
|
|
|
529
546
|
__update_visible_bvh() {
|
|
@@ -615,7 +632,7 @@ export class LightManager {
|
|
|
615
632
|
*
|
|
616
633
|
* @type {PointLightData[]}
|
|
617
634
|
*/
|
|
618
|
-
const visible_lights = this.
|
|
635
|
+
const visible_lights = this.__sorted_visible_lights;
|
|
619
636
|
|
|
620
637
|
// write light data into texture
|
|
621
638
|
const visible_light_count = visible_lights.length;
|
|
@@ -21,6 +21,15 @@ export class PointLightData {
|
|
|
21
21
|
this.bvh_leaf_main = new LeafNode(this, 0, 0, 0, 0, 0, 0);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {PointLightData} other
|
|
27
|
+
* @returns {number}
|
|
28
|
+
*/
|
|
29
|
+
compare(other) {
|
|
30
|
+
return this.light.compare(other.light);
|
|
31
|
+
}
|
|
32
|
+
|
|
24
33
|
update() {
|
|
25
34
|
|
|
26
35
|
const leaf = this.bvh_leaf_main;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
let id_counter = 0;
|
|
2
|
+
|
|
1
3
|
export class AbstractLight {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.id = id_counter++;
|
|
6
|
+
}
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
9
|
*
|
|
@@ -47,4 +52,15 @@ export class AbstractLight {
|
|
|
47
52
|
toArray(destination, address) {
|
|
48
53
|
throw new Error('Not Implemented');
|
|
49
54
|
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {AbstractLight} other
|
|
59
|
+
* @returns {number}
|
|
60
|
+
*/
|
|
61
|
+
compare(other) {
|
|
62
|
+
return this.id - other.id;
|
|
63
|
+
}
|
|
50
64
|
}
|
|
65
|
+
|
|
66
|
+
AbstractLight.prototype.type = 'Abstract';
|
|
@@ -12,6 +12,7 @@ import { ThreeFrustumsIntersectionBVHVisitor } from "../../../../core/bvh2/trave
|
|
|
12
12
|
import { traverseBinaryNodeUsingVisitor } from "../../../../core/bvh2/traversal/traverseBinaryNodeUsingVisitor.js";
|
|
13
13
|
import { ThreeClippingPlaneComputingBVHVisitor } from "../../../../core/bvh2/traversal/ThreeClippingPlaneComputingBVHVisitor.js";
|
|
14
14
|
import { RenderLayerState } from "./RenderLayerState.js";
|
|
15
|
+
import { compare_three_objects } from "../../three/compare_three_objects.js";
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class VisibleLeafCollector extends BVHVisitor {
|
|
@@ -109,9 +110,9 @@ export class RenderLayer {
|
|
|
109
110
|
|
|
110
111
|
/**
|
|
111
112
|
* Contains visible elements across all views, if element is in at least one view - it will be here
|
|
112
|
-
* @type {IncrementalDeltaSet<Object3D>}
|
|
113
|
+
* @type {IncrementalDeltaSet<THREE.Object3D>}
|
|
113
114
|
*/
|
|
114
|
-
this.visibleSet = new IncrementalDeltaSet();
|
|
115
|
+
this.visibleSet = new IncrementalDeltaSet(compare_three_objects);
|
|
115
116
|
|
|
116
117
|
/**
|
|
117
118
|
*
|
|
@@ -5,6 +5,7 @@ import { frustumFromCamera } from "../../ecs/camera/CameraSystem.js";
|
|
|
5
5
|
import { Frustum } from "three";
|
|
6
6
|
import { read_frustum_planes_to_array } from "../forward_plus/cluster/read_frustum_planes_to_array.js";
|
|
7
7
|
import Signal from "../../../../core/events/signal/Signal.js";
|
|
8
|
+
import { compare_three_objects } from "../../three/compare_three_objects.js";
|
|
8
9
|
|
|
9
10
|
const DEFAULT_FLAGS = CameraViewFlags.Active
|
|
10
11
|
| CameraViewFlags.AdaptivePlaneNear
|
|
@@ -52,7 +53,7 @@ export class CameraView {
|
|
|
52
53
|
*
|
|
53
54
|
* @type {IncrementalDeltaSet<THREE.Object3D>}
|
|
54
55
|
*/
|
|
55
|
-
this.visible_objects = new IncrementalDeltaSet();
|
|
56
|
+
this.visible_objects = new IncrementalDeltaSet(compare_three_objects);
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
*
|
|
@@ -3,6 +3,8 @@ export class IncrementalDeltaSet<T> {
|
|
|
3
3
|
version: number
|
|
4
4
|
size: number
|
|
5
5
|
|
|
6
|
+
constructor(compare: (a: T, b: T) => number)
|
|
7
|
+
|
|
6
8
|
contains(element: T): boolean
|
|
7
9
|
|
|
8
10
|
push(element: T): void
|
|
@@ -14,6 +16,4 @@ export class IncrementalDeltaSet<T> {
|
|
|
14
16
|
initializeUpdate(): void
|
|
15
17
|
|
|
16
18
|
finalizeUpdate(): void
|
|
17
|
-
|
|
18
|
-
sort(f: (T) => number, ctx?: any): void
|
|
19
19
|
}
|
|
@@ -2,7 +2,7 @@ import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
|
2
2
|
import Signal from "../../../../core/events/signal/Signal.js";
|
|
3
3
|
import { assert } from "../../../../core/assert.js";
|
|
4
4
|
import { IllegalStateException } from "../../../../core/fsm/exceptions/IllegalStateException.js";
|
|
5
|
-
import {
|
|
5
|
+
import { binarySearchHighIndex } from "../../../../core/collection/array/binarySearchHighIndex.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @readonly
|
|
@@ -16,15 +16,30 @@ const IncrementalDeltaSetState = {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* accelerated Set data structure optimized for incremental re-building
|
|
19
|
+
* Always sorted
|
|
19
20
|
* @template V
|
|
20
21
|
*/
|
|
21
22
|
export class IncrementalDeltaSet {
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {function(V,V):number} compare stable comparator
|
|
26
|
+
*/
|
|
27
|
+
constructor(compare) {
|
|
28
|
+
assert.isFunction(compare, 'compare');
|
|
29
|
+
|
|
23
30
|
/**
|
|
24
31
|
*
|
|
25
32
|
* @type {V[]}
|
|
33
|
+
* @private
|
|
26
34
|
*/
|
|
27
|
-
this.
|
|
35
|
+
this.__elements = [];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @type {function(V, V): number}
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
this.__compare = compare;
|
|
28
43
|
|
|
29
44
|
/**
|
|
30
45
|
* Current version of the state, each time the set is updated - version changes
|
|
@@ -69,15 +84,39 @@ export class IncrementalDeltaSet {
|
|
|
69
84
|
this.state = IncrementalDeltaSetState.Clear;
|
|
70
85
|
}
|
|
71
86
|
|
|
87
|
+
/**
|
|
88
|
+
*
|
|
89
|
+
* @return {V[]}
|
|
90
|
+
*/
|
|
91
|
+
get elements() {
|
|
92
|
+
return this.__elements;
|
|
93
|
+
}
|
|
72
94
|
|
|
73
95
|
/**
|
|
74
96
|
*
|
|
97
|
+
* @param {(V)=>any} visitor
|
|
98
|
+
* @param {*} [visitorContext]
|
|
99
|
+
*/
|
|
100
|
+
forEach(visitor, visitorContext) {
|
|
101
|
+
const n = this.size;
|
|
102
|
+
const elements = this.__elements;
|
|
103
|
+
|
|
104
|
+
for (let i = 0; i < n; i++) {
|
|
105
|
+
const el = elements[i];
|
|
106
|
+
|
|
107
|
+
visitor.call(visitorContext, el);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @deprecated
|
|
75
114
|
* @param {function(T):number} score_function
|
|
76
115
|
* @param {*} [score_context]
|
|
77
116
|
* @returns {void}
|
|
78
117
|
*/
|
|
79
118
|
sort(score_function, score_context) {
|
|
80
|
-
|
|
119
|
+
throw new Error('Deprecated, the set is always sorted');
|
|
81
120
|
}
|
|
82
121
|
|
|
83
122
|
/**
|
|
@@ -86,7 +125,33 @@ export class IncrementalDeltaSet {
|
|
|
86
125
|
* @returns {boolean}
|
|
87
126
|
*/
|
|
88
127
|
contains(element) {
|
|
89
|
-
return this.
|
|
128
|
+
return this.__indexOf(element) !== -1;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
*
|
|
133
|
+
* @param {V} element
|
|
134
|
+
* @return {number}
|
|
135
|
+
* @private
|
|
136
|
+
*/
|
|
137
|
+
__indexOf(element) {
|
|
138
|
+
const i = this.__indexExpected(element);
|
|
139
|
+
|
|
140
|
+
if (this.__elements[i] === element) {
|
|
141
|
+
return i;
|
|
142
|
+
} else {
|
|
143
|
+
return -1;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
*
|
|
149
|
+
* @param {V} element
|
|
150
|
+
* @return {number}
|
|
151
|
+
* @private
|
|
152
|
+
*/
|
|
153
|
+
__indexExpected(element) {
|
|
154
|
+
return binarySearchHighIndex(this.__elements, element, this.__compare, 0, this.size - 1);
|
|
90
155
|
}
|
|
91
156
|
|
|
92
157
|
/**
|
|
@@ -99,10 +164,10 @@ export class IncrementalDeltaSet {
|
|
|
99
164
|
throw new IllegalStateException("Cannot remove during build");
|
|
100
165
|
}
|
|
101
166
|
|
|
102
|
-
const i = this.
|
|
167
|
+
const i = this.__indexOf(element);
|
|
103
168
|
|
|
104
169
|
if (i !== -1) {
|
|
105
|
-
this.
|
|
170
|
+
this.__elements.splice(i, 1);
|
|
106
171
|
this.size--;
|
|
107
172
|
|
|
108
173
|
this.version++;
|
|
@@ -119,7 +184,7 @@ export class IncrementalDeltaSet {
|
|
|
119
184
|
return;
|
|
120
185
|
}
|
|
121
186
|
|
|
122
|
-
this.
|
|
187
|
+
this.__elements.splice(0, this.size);
|
|
123
188
|
this.size = 0;
|
|
124
189
|
this.flags.reset();
|
|
125
190
|
|
|
@@ -153,14 +218,17 @@ export class IncrementalDeltaSet {
|
|
|
153
218
|
let deletions = 0;
|
|
154
219
|
|
|
155
220
|
//go through all dirty flags and remove corresponding elements
|
|
221
|
+
const flags = this.flags;
|
|
222
|
+
const elements = this.__elements;
|
|
223
|
+
|
|
156
224
|
for (
|
|
157
|
-
let i =
|
|
225
|
+
let i = flags.nextSetBit(0);
|
|
158
226
|
i !== -1;
|
|
159
|
-
i =
|
|
227
|
+
i = flags.nextSetBit(i + 1)
|
|
160
228
|
) {
|
|
161
229
|
const index = i - deletions;
|
|
162
230
|
|
|
163
|
-
const removed =
|
|
231
|
+
const removed = elements.splice(index, 1);
|
|
164
232
|
|
|
165
233
|
this.onRemoved.send1(removed[0]);
|
|
166
234
|
|
|
@@ -170,7 +238,7 @@ export class IncrementalDeltaSet {
|
|
|
170
238
|
//update size
|
|
171
239
|
this.size -= deletions;
|
|
172
240
|
|
|
173
|
-
|
|
241
|
+
flags.reset();
|
|
174
242
|
|
|
175
243
|
this.state = IncrementalDeltaSetState.Ready;
|
|
176
244
|
|
|
@@ -184,19 +252,26 @@ export class IncrementalDeltaSet {
|
|
|
184
252
|
*/
|
|
185
253
|
push(element) {
|
|
186
254
|
//check if element is already in the set
|
|
187
|
-
const
|
|
188
|
-
const i = elements.indexOf(element); //TODO this can probably be done faster. Maybe use a bloom filter? or some kind of a hash
|
|
255
|
+
const index = this.__indexExpected(element);
|
|
189
256
|
|
|
190
|
-
|
|
191
|
-
|
|
257
|
+
const elements = this.__elements;
|
|
258
|
+
|
|
259
|
+
if (elements[index] !== element) {
|
|
260
|
+
// element is not in the set
|
|
261
|
+
|
|
262
|
+
// shift flags to make space for it
|
|
263
|
+
this.flags.shift(1, index, this.size);
|
|
264
|
+
|
|
265
|
+
// insert
|
|
266
|
+
elements.splice(index, 0, element);
|
|
192
267
|
this.size++;
|
|
193
268
|
|
|
194
269
|
this.onAdded.send1(element);
|
|
195
|
-
} else {
|
|
196
|
-
//Existing element. We're keeping it. clear dirty flag
|
|
197
|
-
this.flags.clear(i);
|
|
198
270
|
}
|
|
199
271
|
|
|
272
|
+
// clear flag for inserted element
|
|
273
|
+
this.flags.clear(index);
|
|
274
|
+
|
|
200
275
|
}
|
|
201
276
|
|
|
202
277
|
/**
|
|
@@ -204,7 +279,7 @@ export class IncrementalDeltaSet {
|
|
|
204
279
|
* @param {IncrementalDeltaSet<V>} other
|
|
205
280
|
*/
|
|
206
281
|
pushOther(other) {
|
|
207
|
-
const elements = other.
|
|
282
|
+
const elements = other.__elements;
|
|
208
283
|
const n = other.size;
|
|
209
284
|
for (let i = 0; i < n; i++) {
|
|
210
285
|
const el = elements[i];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { IncrementalDeltaSet } from "./IncrementalDeltaSet.js";
|
|
2
|
+
import { compareNumbersAscending } from "../../../../core/function/Functions.js";
|
|
3
|
+
|
|
4
|
+
test('set is sorted after insert, push 1,2', () => {
|
|
5
|
+
const set = new IncrementalDeltaSet(compareNumbersAscending);
|
|
6
|
+
|
|
7
|
+
set.push(1);
|
|
8
|
+
set.push(2);
|
|
9
|
+
|
|
10
|
+
expect(set.elements[0]).toBe(1);
|
|
11
|
+
expect(set.elements[1]).toBe(2);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('set is sorted after insert, push 2,1', () => {
|
|
15
|
+
const set = new IncrementalDeltaSet(compareNumbersAscending);
|
|
16
|
+
|
|
17
|
+
set.push(2);
|
|
18
|
+
set.push(1);
|
|
19
|
+
|
|
20
|
+
expect(set.elements[0]).toBe(1);
|
|
21
|
+
expect(set.elements[1]).toBe(2);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('set is sorted after insert, push 1,2,3', () => {
|
|
25
|
+
const set = new IncrementalDeltaSet(compareNumbersAscending);
|
|
26
|
+
|
|
27
|
+
set.push(1);
|
|
28
|
+
set.push(2);
|
|
29
|
+
set.push(3);
|
|
30
|
+
|
|
31
|
+
expect(set.elements[0]).toBe(1);
|
|
32
|
+
expect(set.elements[1]).toBe(2);
|
|
33
|
+
expect(set.elements[2]).toBe(3);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('set is sorted after insert, push 3,2,1', () => {
|
|
37
|
+
const set = new IncrementalDeltaSet(compareNumbersAscending);
|
|
38
|
+
|
|
39
|
+
set.push(3);
|
|
40
|
+
set.push(2);
|
|
41
|
+
set.push(1);
|
|
42
|
+
|
|
43
|
+
expect(set.elements[0]).toBe(1);
|
|
44
|
+
expect(set.elements[1]).toBe(2);
|
|
45
|
+
expect(set.elements[2]).toBe(3);
|
|
46
|
+
});
|
|
@@ -16,6 +16,8 @@ import { objectKeyByValue } from "../../../../core/model/object/objectKeyByValue
|
|
|
16
16
|
import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js";
|
|
17
17
|
import { computeHashIntegerArray } from "../../../../core/collection/array/computeHashIntegerArray.js";
|
|
18
18
|
import { computeHashFloat } from "../../../../core/math/hash/computeHashFloat.js";
|
|
19
|
+
import { compareStrings } from "../../../../core/primitives/strings/compareStrings.js";
|
|
20
|
+
import { compareNumbers } from "../../../../core/primitives/numbers/compareNumbers.js";
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Convert decibel to percentage volume
|
|
@@ -127,6 +129,63 @@ export class SoundEmitter {
|
|
|
127
129
|
|
|
128
130
|
}
|
|
129
131
|
|
|
132
|
+
/**
|
|
133
|
+
*
|
|
134
|
+
* @param {SoundEmitter} other
|
|
135
|
+
* @returns number
|
|
136
|
+
*/
|
|
137
|
+
compare(other) {
|
|
138
|
+
const tracks = this.tracks.compare(other.tracks);
|
|
139
|
+
|
|
140
|
+
if (tracks !== 0) {
|
|
141
|
+
return tracks;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const channel = compareStrings(this.channel, other.channel);
|
|
145
|
+
|
|
146
|
+
if (channel !== 0) {
|
|
147
|
+
return channel;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const distanceMin = compareNumbers(this.__distanceMin, other.__distanceMin);
|
|
151
|
+
|
|
152
|
+
if (distanceMin !== 0) {
|
|
153
|
+
return distanceMin;
|
|
154
|
+
}
|
|
155
|
+
const distanceMax = compareNumbers(this.__distanceMax, other.__distanceMax);
|
|
156
|
+
|
|
157
|
+
if (distanceMax !== 0) {
|
|
158
|
+
return distanceMax;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const panningModel = compareNumbers(this.panningModel, other.panningModel);
|
|
162
|
+
|
|
163
|
+
if (panningModel !== 0) {
|
|
164
|
+
return panningModel;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const attenuation = compareNumbers(this.attenuation, other.attenuation);
|
|
168
|
+
|
|
169
|
+
if (attenuation !== 0) {
|
|
170
|
+
return attenuation;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const flags = compareNumbers(this.flags, other.flags);
|
|
174
|
+
|
|
175
|
+
if (flags !== 0) {
|
|
176
|
+
return flags;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const volume = compareNumbers(this.volume.getValue(), other.volume.getValue());
|
|
180
|
+
|
|
181
|
+
if (volume !== 0) {
|
|
182
|
+
return volume;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
130
189
|
|
|
131
190
|
/**
|
|
132
191
|
*
|
|
@@ -45,6 +45,14 @@ export class SoundEmitterComponentContext {
|
|
|
45
45
|
this.__isConnected = false;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param {SoundEmitterComponentContext} other
|
|
51
|
+
*/
|
|
52
|
+
compare(other) {
|
|
53
|
+
return this.emitter.compare(other.emitter);
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
update() {
|
|
49
57
|
|
|
50
58
|
const position = this.transform.position;
|
|
@@ -18,6 +18,7 @@ import { tryRotateSingleNode } from "../../../../core/bvh2/transform/RotationOpt
|
|
|
18
18
|
import { SoundEmitterComponentContext } from "./SoundEmitterComponentContext.js";
|
|
19
19
|
import { SoundEmitterFlags } from "./SoundEmitterFlags.js";
|
|
20
20
|
import { SoundEmitterChannel } from "./SoundEmitterChannel.js";
|
|
21
|
+
import { invokeObjectCompare } from "../../../../core/model/object/invokeObjectCompare.js";
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* @readonly
|
|
@@ -96,7 +97,7 @@ export class SoundEmitterSystem extends System {
|
|
|
96
97
|
*
|
|
97
98
|
* @type {IncrementalDeltaSet<SoundEmitterComponentContext>}
|
|
98
99
|
*/
|
|
99
|
-
this.activeSet = new IncrementalDeltaSet();
|
|
100
|
+
this.activeSet = new IncrementalDeltaSet(invokeObjectCompare);
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
103
|
* Spatial index
|
|
@@ -4,6 +4,8 @@ import { assert } from "../../../../core/assert.js";
|
|
|
4
4
|
import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js";
|
|
5
5
|
import { computeHashIntegerArray } from "../../../../core/collection/array/computeHashIntegerArray.js";
|
|
6
6
|
import { computeHashFloat } from "../../../../core/math/hash/computeHashFloat.js";
|
|
7
|
+
import { compareStrings } from "../../../../core/primitives/strings/compareStrings.js";
|
|
8
|
+
import { compareNumbers } from "../../../../core/primitives/numbers/compareNumbers.js";
|
|
7
9
|
|
|
8
10
|
const DEFAULT_FLAGS = SoundTrackFlags.StartWhenReady;
|
|
9
11
|
|
|
@@ -55,6 +57,45 @@ export class SoundTrack {
|
|
|
55
57
|
this.nodes = null;
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
/**
|
|
61
|
+
*
|
|
62
|
+
* @param {SoundTrack} other
|
|
63
|
+
* @returns number
|
|
64
|
+
*/
|
|
65
|
+
compare(other) {
|
|
66
|
+
const url = compareStrings(this.url, other.url);
|
|
67
|
+
|
|
68
|
+
if (url !== 0) {
|
|
69
|
+
return url;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const time = compareNumbers(this.time, other.time);
|
|
73
|
+
|
|
74
|
+
if (time !== 0) {
|
|
75
|
+
return time;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const channel = compareStrings(this.channel, other.channel);
|
|
79
|
+
|
|
80
|
+
if (channel !== 0) {
|
|
81
|
+
return channel;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const volume = compareNumbers(this.__volume, other.__volume);
|
|
85
|
+
|
|
86
|
+
if (volume !== 0) {
|
|
87
|
+
return volume;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const flags = compareNumbers(this.flags, other.flags);
|
|
91
|
+
|
|
92
|
+
if (flags !== 0) {
|
|
93
|
+
return flags;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
58
99
|
/**
|
|
59
100
|
*
|
|
60
101
|
* @param {number|SoundEmitterFlags} flag
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.34.
|
|
8
|
+
"version": "2.34.24",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|