@woosh/meep-engine 2.33.37 → 2.33.41

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.
Files changed (46) hide show
  1. package/core/bvh2/binary/2/BinaryUint32BVH.js +3 -3
  2. package/core/collection/array/typed/typed_array_copy.js +2 -2
  3. package/core/geom/3d/aabb/aabb3_matrix4_project_by_corners.js +1 -1
  4. package/core/geom/3d/morton/mortonEncode_magicbits.js +7 -6
  5. package/core/geom/3d/morton/v3_morton_encode_transformed.js +15 -11
  6. package/core/geom/3d/plane/orient3d_fast.js +15 -9
  7. package/core/geom/3d/tetrahedra/GetDepthForTetrahedronProbe.glsl +43 -0
  8. package/core/geom/3d/tetrahedra/compute_delaunay_tetrahedral_mesh.js +20 -169
  9. package/core/geom/3d/tetrahedra/compute_delaunay_tetrahedral_mesh.spec.js +9 -0
  10. package/core/geom/3d/tetrahedra/tetrahedra_collection.js +454 -0
  11. package/core/geom/3d/tetrahedra/tetrahedron_contains_point.js +2 -1
  12. package/core/process/undo/ActionProcessor.js +8 -5
  13. package/engine/asset/loaders/GLTFAssetLoader.js +4 -8
  14. package/engine/ecs/System.d.ts +24 -1
  15. package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +1 -1
  16. package/engine/graphics/micron/prototypeVirtualGeometry.js +4 -1
  17. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +20 -24
  18. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +1 -1
  19. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -2
  20. package/engine/graphics/render/buffer/simple-fx/DepthLimitedBlur.js +9 -4
  21. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +7 -1
  22. package/engine/graphics/render/forward_plus/LightManager.js +295 -51
  23. package/engine/graphics/render/forward_plus/LightManager.spec.js +1 -1
  24. package/engine/graphics/render/forward_plus/PointLightData.js +9 -13
  25. package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +10 -1
  26. package/engine/graphics/render/forward_plus/debug/LightClusterVolumeMaterial.js +1 -1
  27. package/engine/graphics/render/forward_plus/debug/buildLightClusterWidget.js +3 -1
  28. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +31 -18
  29. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +1 -0
  30. package/engine/graphics/render/forward_plus/model/AbstractLight.js +50 -0
  31. package/engine/graphics/render/forward_plus/model/Decal.js +68 -0
  32. package/engine/graphics/render/forward_plus/{PointLight.js → model/PointLight.js} +19 -11
  33. package/engine/graphics/render/forward_plus/{SpotLight.js → model/SpotLight.js} +20 -12
  34. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +6 -5
  35. package/engine/graphics/render/forward_plus/{prototypeLightManager.js → prototype/prototypeLightManager.js} +100 -25
  36. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +29 -20
  37. package/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +2 -0
  38. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
  39. package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +19 -0
  40. package/engine/graphics/texture/atlas/CachingTextureAtlas.js +99 -0
  41. package/engine/graphics/texture/atlas/ManagedTextureAtlas.js +19 -39
  42. package/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +75 -0
  43. package/engine/graphics/texture/atlas/TextureAtlas.js +22 -2
  44. package/engine/reference/v2/Reference.d.ts +4 -0
  45. package/engine/reference/v2/Reference.js +3 -1
  46. package/package.json +1 -1
@@ -28,6 +28,7 @@ export function query_bvh_frustum_from_texture(
28
28
 
29
29
  let stackPointer = 1;
30
30
  let result = 0;
31
+ let plane_address;
31
32
 
32
33
  /**
33
34
  * After performing empirical tests, stack-based depth-first traversal turns out faster than using a queue
@@ -55,9 +56,7 @@ export function query_bvh_frustum_from_texture(
55
56
  const n_y1 = data_view.getFloat32(node_address + 16);
56
57
  const n_z1 = data_view.getFloat32(node_address + 20);
57
58
 
58
- for (let j = 0; j < 6; j++) {
59
-
60
- const plane_address = j * 4;
59
+ for (plane_address = 0; plane_address < 24; plane_address += 4) {
61
60
 
62
61
  const plane_normal_x = planes[plane_address];
63
62
  const plane_normal_y = planes[plane_address + 1];
@@ -84,41 +83,51 @@ export function query_bvh_frustum_from_texture(
84
83
  const left_index = (node_index << 1) + 1;
85
84
  const right_index = left_index + 1;
86
85
 
87
- if (left_index < last_valid_index) {
88
- stack[stackPointer] = left_index;
89
- stackPointer++;
90
- }
91
-
86
+ // left node ends up on top of the stack, which aligns with the desired access sequence
92
87
  if (right_index < last_valid_index) {
93
- stack[stackPointer] = right_index;
94
- stackPointer++;
88
+ stack[stackPointer++] = right_index;
89
+ // micro-optimization, since we know that right node is valid and left appears before that, left is valid too
90
+ stack[stackPointer++] = left_index;
91
+ } else if (left_index < last_valid_index) {
92
+ stack[stackPointer++] = left_index;
95
93
  }
96
94
 
97
95
 
98
96
  } else {
99
97
  // leaf node
100
98
  const leaf_index = node_index - binary_node_count;
99
+
101
100
  const node_address = leaf_index * BVH_LEAF_NODE_SIZE + binary_node_count * BVH_BINARY_NODE_SIZE;
102
101
 
103
- const light_index = data_view.getUint32(node_address + 24);
102
+ const light_descriptor = data_view.getUint32(node_address + 24);
103
+
104
+ const light_type = light_descriptor & 3;
105
+ const light_texel_index = light_descriptor >> 2;
104
106
 
105
- const light_address = light_index * 8;
107
+ const light_address = light_texel_index * 4;
106
108
 
107
- // TODO figure out light type from address
109
+ if (light_type === 0) {
110
+ // Point light
108
111
 
112
+ const light_x = source_data[light_address];
113
+ const light_y = source_data[light_address + 1];
114
+ const light_z = source_data[light_address + 2];
109
115
 
110
- const light_x = source_data[light_address];
111
- const light_y = source_data[light_address + 1];
112
- const light_z = source_data[light_address + 2];
116
+ const radius = source_data[light_address + 3];
113
117
 
114
- const radius = source_data[light_address + 3];
118
+ if (!point_light_inside_volume(light_x, light_y, light_z, radius, points, planes)) {
119
+ continue;
120
+ }
121
+ } else if (light_type === 3) {
122
+ // decal
123
+ debugger;
115
124
 
116
- if (!point_light_inside_volume(light_x, light_y, light_z, radius, points, planes)) {
117
- continue;
125
+ } else {
126
+ throw new Error('Unsupported light type');
118
127
  }
119
128
 
120
129
  // write to output
121
- destination[destination_offset + result] = light_index;
130
+ destination[destination_offset + result] = light_descriptor;
122
131
 
123
132
  result++;
124
133
  }
@@ -14,4 +14,6 @@ export class IncrementalDeltaSet<T> {
14
14
  initializeUpdate(): void
15
15
 
16
16
  finalizeUpdate(): void
17
+
18
+ sort(f: (T) => number, ctx?: any): void
17
19
  }
@@ -74,6 +74,7 @@ export class IncrementalDeltaSet {
74
74
  *
75
75
  * @param {function(T):number} score_function
76
76
  * @param {*} [score_context]
77
+ * @returns {void}
77
78
  */
78
79
  sort(score_function, score_context) {
79
80
  arrayQuickSort(this.elements, score_function, score_context, 0, this.size - 1);
@@ -0,0 +1,19 @@
1
+ export class AbstractTextureAtlas {
2
+ /**
3
+ *
4
+ * @param {Sampler2D} sampler
5
+ * @returns {AtlasPatch}
6
+ */
7
+ add(sampler) {
8
+ throw new Error('Not Implemented');
9
+ }
10
+
11
+ /**
12
+ *
13
+ * @param {AtlasPatch} patch
14
+ * @returns {boolean}
15
+ */
16
+ remove(patch) {
17
+ throw new Error('Not Implemented')
18
+ }
19
+ }
@@ -0,0 +1,99 @@
1
+ import { Cache } from "../../../../core/cache/Cache.js";
2
+ import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
3
+
4
+ /**
5
+ * 4Mb
6
+ * @type {number}
7
+ */
8
+ const DEFAULT_CACHE_SIZE = 4194304;
9
+
10
+ export class CachingTextureAtlas extends AbstractTextureAtlas {
11
+ /**
12
+ *
13
+ * @param {AbstractTextureAtlas} atlas
14
+ * @param {number} cache_size
15
+ */
16
+ constructor({
17
+ atlas,
18
+ cache_size = DEFAULT_CACHE_SIZE
19
+ }) {
20
+ super();
21
+
22
+ /**
23
+ *
24
+ * @type {Cache<Sampler2D, AtlasPatch>}
25
+ * @private
26
+ */
27
+ this.__cached_patches = new Cache({
28
+ maxWeight: cache_size,
29
+ keyWeigher(sampler) {
30
+ return sampler.computeByteSize();
31
+ }
32
+ });
33
+
34
+ /**
35
+ *
36
+ * @type {TextureAtlas}
37
+ * @private
38
+ */
39
+ this.__atals = atlas;
40
+
41
+ this.__cached_patches.onEvicted.add(this.__handle_cache_eviction, this);
42
+ }
43
+
44
+ /**
45
+ *
46
+ * @returns {AbstractTextureAtlas}
47
+ */
48
+ get atlas() {
49
+ return this.__atals;
50
+ }
51
+
52
+ /**
53
+ *
54
+ * @param {Sampler2D} sampler
55
+ * @param {AtlasPatch} patch
56
+ * @private
57
+ */
58
+ __handle_cache_eviction(sampler, patch) {
59
+ this.__atals.remove(patch);
60
+ }
61
+
62
+ reset() {
63
+ this.__cached_patches.drop();
64
+ this.__atals.reset();
65
+ }
66
+
67
+ /**
68
+ *
69
+ * @param {Sampler2D} sampler
70
+ * @returns {AtlasPatch}
71
+ */
72
+ add(sampler) {
73
+ const existing_patch = this.__cached_patches.get(sampler);
74
+
75
+ if (existing_patch !== null) {
76
+ // cache hit
77
+ return existing_patch;
78
+ }
79
+
80
+ return this.__atals.add(sampler);
81
+ }
82
+
83
+ /**
84
+ *
85
+ * @param {AtlasPatch} patch
86
+ */
87
+ remove(patch) {
88
+
89
+ // validate presence of patch in the atlas
90
+ if (!this.__atals.contains(patch)) {
91
+ return false;
92
+ }
93
+
94
+ // push to cache, let eviction logic handle the rest
95
+ this.__cached_patches.put(patch.sampler, patch);
96
+
97
+ return true;
98
+ }
99
+ }
@@ -1,14 +1,12 @@
1
1
  import { TextureAtlas } from "./TextureAtlas.js";
2
2
  import { ReferenceManager } from "../../../reference/v1/ReferenceManager.js";
3
3
  import { Sampler2D } from "../sampler/Sampler2D.js";
4
- import { Cache } from "../../../../core/cache/Cache.js";
5
4
  import { GameAssetType } from "../../../asset/GameAssetType.js";
6
5
  import { HashMap } from "../../../../core/collection/HashMap.js";
7
6
  import { strictEquals } from "../../../../core/function/Functions.js";
8
7
  import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js";
9
8
  import { copy_Sampler2D_channel_data } from "../sampler/copy_Sampler2D_channel_data.js";
10
-
11
- const CACHE_SIZE = 4194304;
9
+ import { CachingTextureAtlas } from "./CachingTextureAtlas.js";
12
10
 
13
11
  export class ManagedAtlas {
14
12
  /**
@@ -26,28 +24,20 @@ export class ManagedAtlas {
26
24
 
27
25
  /**
28
26
  *
29
- * @type {TextureAtlas}
27
+ * @type {WeakMap<string, Sampler2D>}
28
+ * @private
30
29
  */
31
- this.atlas = atlas;
30
+ this.__cached_samplers = new Map();
31
+ const cached_samplers = this.__cached_samplers;
32
32
 
33
+ const cached_atlas = new CachingTextureAtlas({ atlas });
34
+ this.__caching_atlas = cached_atlas;
33
35
 
34
36
  /**
35
37
  *
36
- * @type {Cache<String, AtlasPatch>}
38
+ * @type {TextureAtlas}
37
39
  */
38
- const patchesInactive = new Cache({
39
- maxWeight: CACHE_SIZE,
40
- keyHashFunction: computeStringHash,
41
- keyEqualityFunction: strictEquals,
42
- valueWeigher(patch) {
43
- return patch.sampler.data.length;
44
- }
45
- });
46
-
47
- // watch for patches being removed
48
- patchesInactive.onRemoved.add((key, value) => {
49
- atlas.remove(value);
50
- });
40
+ this.atlas = atlas;
51
41
 
52
42
  /**
53
43
  *
@@ -64,19 +54,12 @@ export class ManagedAtlas {
64
54
  */
65
55
  this.patchesActive = activePatches;
66
56
 
67
- /**
68
- * @private
69
- * @type {Cache<String, AtlasPatch>}
70
- */
71
- this.patchesInactive = patchesInactive;
72
-
73
57
  /**
74
58
  * Automatically update TextureAtlas
75
59
  * @type {boolean}
76
60
  */
77
61
  this.autoUpdate = true;
78
62
 
79
-
80
63
  this.rebuildDelay = 200; //in milliseconds
81
64
 
82
65
  let counterLoadingAssets = 0;
@@ -97,7 +80,7 @@ export class ManagedAtlas {
97
80
 
98
81
  /**
99
82
  *
100
- * @param {String} url
83
+ * @param {string} url
101
84
  * @returns {Promise<AtlasPatch>}
102
85
  */
103
86
  function creator(url) {
@@ -110,14 +93,10 @@ export class ManagedAtlas {
110
93
  return;
111
94
  }
112
95
 
113
- patch = patchesInactive.get(url);
114
-
115
- if (patch !== null) {
116
- //move to active
117
- patchesInactive.silentRemove(url);
118
-
119
- activePatches.set(url, patch);
96
+ const cached_sampler = cached_samplers.get(url);
120
97
 
98
+ if (cached_sampler !== undefined) {
99
+ patch = cached_atlas.add(cached_sampler);
121
100
  resolve(patch);
122
101
  return;
123
102
  }
@@ -154,7 +133,10 @@ export class ManagedAtlas {
154
133
  sampler = source;
155
134
  }
156
135
 
157
- const patch = atlas.add(sampler);
136
+ cached_samplers.set(url, sampler);
137
+
138
+
139
+ const patch = cached_atlas.add(sampler);
158
140
 
159
141
  //record active patch
160
142
  activePatches.set(url, patch);
@@ -197,8 +179,7 @@ export class ManagedAtlas {
197
179
  //remove from active
198
180
  activePatches.delete(url);
199
181
 
200
- //put into inactive set
201
- patchesInactive.put(url, patch);
182
+ self.__caching_atlas.remove(patch);
202
183
  }
203
184
  });
204
185
  }
@@ -218,8 +199,7 @@ export class ManagedAtlas {
218
199
 
219
200
  reset() {
220
201
  this.references.reset();
221
- this.atlas.reset();
222
- this.patchesInactive.drop();
202
+ this.__caching_atlas.reset();
223
203
  this.patchesActive.clear();
224
204
  }
225
205
 
@@ -0,0 +1,75 @@
1
+ import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
2
+ import { Reference } from "../../../reference/v2/Reference.js";
3
+
4
+ export class ReferencedTextureAtlas extends AbstractTextureAtlas {
5
+ /**
6
+ *
7
+ * @param {AbstractTextureAtlas} atlas
8
+ */
9
+ constructor(atlas) {
10
+ super();
11
+
12
+ this.__atlas = atlas;
13
+
14
+ /**
15
+ *
16
+ * @type {Map<Sampler2D, AtlasPatch>}
17
+ * @private
18
+ */
19
+ this.__patches = new Map();
20
+ /**
21
+ *
22
+ * @type {Map<AtlasPatch, number>}
23
+ * @private
24
+ */
25
+ this.__ref_counts = new Map();
26
+
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @param {Reference} ref
32
+ * @param {AtlasPatch} patch
33
+ * @private
34
+ */
35
+ __handle_ref_release(ref, patch) {
36
+ const ref_counts = this.__ref_counts;
37
+
38
+ const ref_count = ref_counts.get(patch);
39
+ ref_counts.set(patch, ref_count - 1);
40
+
41
+ if (ref_count === 1) {
42
+ // clear patch
43
+ this.__atlas.remove(patch);
44
+ }
45
+ }
46
+
47
+
48
+ /**
49
+ *
50
+ * @param {Sampler2D} sampler
51
+ * @returns {Reference<AtlasPatch>}
52
+ */
53
+ acquire(sampler) {
54
+
55
+ let patch = this.__patches.get(sampler);
56
+
57
+ const ref_counts = this.__ref_counts;
58
+
59
+ const atlas = this.__atlas;
60
+
61
+ if (patch === undefined) {
62
+ patch = atlas.add(sampler);
63
+ ref_counts.set(patch, 1)
64
+ } else {
65
+ ref_counts.set(patch, ref_counts.get(patch) + 1);
66
+ }
67
+
68
+ const ref = new Reference();
69
+ ref.bind(patch);
70
+
71
+ ref.onReleased.add(this.__handle_ref_release, this);
72
+
73
+ return ref;
74
+ }
75
+ }
@@ -11,8 +11,9 @@ import { assert } from "../../../../core/assert.js";
11
11
  import { DataType } from "../../../../core/collection/table/DataType.js";
12
12
  import { DataType2TypedArrayConstructorMapping } from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
13
13
  import { invokeObjectClone } from "../../../../core/model/ObjectUtils.js";
14
+ import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
14
15
 
15
- export class TextureAtlas {
16
+ export class TextureAtlas extends AbstractTextureAtlas {
16
17
  /**
17
18
  *
18
19
  * @param {number} [size]
@@ -20,6 +21,8 @@ export class TextureAtlas {
20
21
  * @constructor
21
22
  */
22
23
  constructor(size = 16, data_type = DataType.Uint8) {
24
+ super();
25
+
23
26
  /**
24
27
  *
25
28
  * @type {IdPool}
@@ -68,6 +71,23 @@ export class TextureAtlas {
68
71
  this.__needsUpdate = false;
69
72
  }
70
73
 
74
+ /**
75
+ *
76
+ * @param {Sampler2D} sampler
77
+ * @returns {AtlasPatch|undefined}
78
+ */
79
+ getPatch(sampler) {
80
+ const patches = this.patches;
81
+ const patch_count = patches.length;
82
+ for (let i = 0; i < patch_count; i++) {
83
+ const patch = patches[i];
84
+
85
+ if (patch.sampler === sampler) {
86
+ return patch;
87
+ }
88
+ }
89
+ }
90
+
71
91
  /**
72
92
  * Whether or not current state of atlas requires calling {#update}
73
93
  * @returns {boolean}
@@ -222,7 +242,7 @@ export class TextureAtlas {
222
242
  /**
223
243
  *
224
244
  * @param {Sampler2D} sampler
225
- * @param {number} padding
245
+ * @param {number} [padding]
226
246
  * @return {AtlasPatch}
227
247
  */
228
248
  add(sampler, padding = 4) {
@@ -1,4 +1,8 @@
1
+ import Signal from "../../../core/events/signal/Signal";
2
+
1
3
  export class Reference<T> {
4
+ readonly onReleased: Signal<Reference<T>, T>
5
+
2
6
  getValue(): T | null
3
7
 
4
8
  release(): void
@@ -73,12 +73,14 @@ export class Reference {
73
73
  return;
74
74
  }
75
75
 
76
+ const v = this.__value;
77
+
76
78
  // prevent further usage of the reference
77
79
  this.__value = null;
78
80
 
79
81
  this.__is_bound = false;
80
82
 
81
- this.__onReleased.send1(this);
83
+ this.__onReleased.send2(this,v);
82
84
  }
83
85
  }
84
86
 
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.33.37",
8
+ "version": "2.33.41",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",