@woosh/meep-engine 2.33.36 → 2.33.40

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 (90) hide show
  1. package/core/bvh2/binary/2/BinaryUint32BVH.js +3 -3
  2. package/core/collection/HashMap.js +19 -12
  3. package/core/collection/array/typed/typed_array_copy.js +2 -2
  4. package/core/collection/table/RowFirstTable.js +13 -8
  5. package/core/collection/table/RowFirstTableSpec.js +6 -0
  6. package/core/color/Color.js +5 -9
  7. package/core/color/ColorUtils.js +4 -150
  8. package/core/color/YCbCr_to_rgb_uint24.js +20 -0
  9. package/core/color/hsv2rgb.js +54 -0
  10. package/core/color/int2rgb.js +12 -0
  11. package/core/color/parseHex.js +18 -0
  12. package/core/color/rgb2hex.js +16 -0
  13. package/core/color/rgb2hsv.js +47 -0
  14. package/core/color/rgb2uint24.js +17 -0
  15. package/core/color/rgb_to_YCbCr_uint24.js +18 -0
  16. package/core/geom/3d/aabb/aabb3_matrix4_project_by_corners.js +1 -1
  17. package/core/geom/3d/aabb/compute_aabb_from_points.js +28 -0
  18. package/core/geom/3d/morton/mortonEncode_magicbits.js +7 -6
  19. package/core/geom/3d/morton/v3_morton_encode_transformed.js +15 -11
  20. package/core/geom/3d/plane/orient3d_fast.js +51 -0
  21. package/core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js +5 -0
  22. package/core/geom/3d/tetrahedra/GetDepthForTetrahedronProbe.glsl +43 -0
  23. package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +177 -0
  24. package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.spec.js +66 -0
  25. package/core/geom/3d/tetrahedra/compute_circumsphere.js +271 -0
  26. package/core/geom/3d/tetrahedra/compute_delaunay_tetrahedral_mesh.js +50 -0
  27. package/core/geom/3d/tetrahedra/compute_delaunay_tetrahedral_mesh.spec.js +14 -0
  28. package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +77 -0
  29. package/core/geom/3d/tetrahedra/tetrahedra_collection.js +454 -0
  30. package/core/geom/3d/tetrahedra/tetrahedron_contains_point.js +26 -0
  31. package/core/geom/Quaternion.js +4 -0
  32. package/core/math/hash/murmur3_32.js +39 -0
  33. package/core/process/undo/ActionProcessor.d.ts +2 -0
  34. package/core/process/undo/ActionProcessor.js +15 -4
  35. package/editor/tools/FoliagePaintTool.js +1 -1
  36. package/editor/tools/GridPaintTool.js +1 -1
  37. package/engine/asset/loaders/GLTFAssetLoader.js +4 -8
  38. package/engine/ecs/System.d.ts +24 -1
  39. package/engine/ecs/foliage/InstancedFoliage.js +45 -0
  40. package/engine/ecs/foliage/ecs/InstancedMeshLayer.js +4 -0
  41. package/engine/ecs/storage/BinaryBufferSerializer.js +48 -38
  42. package/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.js +1 -1
  43. package/engine/ecs/terrain/ecs/splat/SplatMapOptimizerDebugger.js +1 -1
  44. package/engine/ecs/terrain/tiles/TerrainTile.js +1 -1
  45. package/engine/graphics/GraphicsEngine.js +7 -0
  46. package/engine/graphics/ecs/light/binding/fp/FPLightBinding.js +1 -1
  47. package/engine/graphics/ecs/mesh/Mesh.js +2 -2
  48. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +13 -0
  49. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +339 -314
  50. package/engine/graphics/micron/prototypeVirtualGeometry.js +4 -1
  51. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +6 -2
  52. package/engine/graphics/particles/node-based/rendering/billboard/ParticleBillboardShader.js +1 -1
  53. package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +20 -24
  54. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +100 -55
  55. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +7 -2
  56. package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +1 -0
  57. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -2
  58. package/engine/graphics/render/buffer/simple-fx/DepthLimitedBlur.js +9 -4
  59. package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +7 -1
  60. package/engine/graphics/render/forward_plus/LightManager.js +295 -51
  61. package/engine/graphics/render/forward_plus/LightManager.spec.js +1 -1
  62. package/engine/graphics/render/forward_plus/PointLightData.js +9 -13
  63. package/engine/graphics/render/forward_plus/cluster/compute_light_data_hash_0.js +1 -1
  64. package/engine/graphics/render/forward_plus/data/TextureBackedMemoryRegion.js +10 -1
  65. package/engine/graphics/render/forward_plus/debug/LightClusterVolumeMaterial.js +1 -1
  66. package/engine/graphics/render/forward_plus/debug/buildLightClusterWidget.js +3 -1
  67. package/engine/graphics/render/forward_plus/materials/FP_SHADER_CHUNK_ACCUMULATION.js +31 -18
  68. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +18 -4
  69. package/engine/graphics/render/forward_plus/model/AbstractLight.js +50 -0
  70. package/engine/graphics/render/forward_plus/model/Decal.js +68 -0
  71. package/engine/graphics/render/forward_plus/{PointLight.js → model/PointLight.js} +19 -11
  72. package/engine/graphics/render/forward_plus/{SpotLight.js → model/SpotLight.js} +20 -12
  73. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +1 -1
  74. package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +6 -5
  75. package/engine/graphics/render/forward_plus/{prototypeLightManager.js → prototype/prototypeLightManager.js} +100 -25
  76. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +29 -20
  77. package/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +2 -0
  78. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +1 -0
  79. package/engine/graphics/render/visibility/VisibilityComputer.js +8 -7
  80. package/engine/graphics/shaders/TerrainShader.js +5 -5
  81. package/engine/graphics/shadows/testShadowMapRendering.js +192 -0
  82. package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +19 -0
  83. package/engine/graphics/texture/atlas/CachingTextureAtlas.js +99 -0
  84. package/engine/graphics/texture/atlas/ManagedTextureAtlas.js +19 -39
  85. package/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +75 -0
  86. package/engine/graphics/texture/atlas/TextureAtlas.js +22 -2
  87. package/engine/reference/v2/Reference.d.ts +4 -0
  88. package/engine/reference/v2/Reference.js +3 -1
  89. package/package.json +2 -1
  90. package/view/elements/ColorPickerView.js +2 -1
@@ -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);
@@ -9,6 +9,12 @@ const frustum = new Frustum();
9
9
  */
10
10
  const objectFilters = [];
11
11
 
12
+ /**
13
+ *
14
+ * @type {function[]}
15
+ */
16
+ const objectFilterExecutors = [];
17
+
12
18
  export const SOURCE_RENDER_LAYER_PROPERTY = '@meep-render-layer';
13
19
 
14
20
  export class VisibilityComputer {
@@ -135,12 +141,6 @@ export class VisibilityComputer {
135
141
  // clear visible set
136
142
  // this.__output.initializeUpdate();
137
143
 
138
- /**
139
- *
140
- * @type {function[]}
141
- */
142
- const objectFilterExecutors = [];
143
-
144
144
  const filters = this.filters;
145
145
  const filterCount = filters.length;
146
146
 
@@ -151,7 +151,7 @@ export class VisibilityComputer {
151
151
 
152
152
  if (f.enabled && f.layerPredicate(layer)) {
153
153
  objectFilters[objectFilterCount] = f;
154
- objectFilterExecutors.push(f.objectPredicateExecute);
154
+ objectFilterExecutors[objectFilterCount] = f.objectPredicateExecute;
155
155
 
156
156
  objectFilterCount++;
157
157
  }
@@ -165,6 +165,7 @@ export class VisibilityComputer {
165
165
  f.objectPredicateInitialize(this.__view.camera);
166
166
  }
167
167
 
168
+ objectFilterExecutors.length = objectFilterCount;
168
169
 
169
170
  layer.buildVisibleSet(this.__frustums, objectFilterExecutors, this.__includeObject, this);
170
171
 
@@ -366,27 +366,27 @@ function fragment() {
366
366
  gl_FragColor = vec4( outgoingLight, diffuseColor.a );
367
367
 
368
368
  #if defined( TONE_MAPPING )
369
- gl_FragColor.rgb = toneMapping( pc_fragColor.rgb );
369
+ gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );
370
370
  #endif
371
371
 
372
372
  //encode fragment
373
- pc_fragColor = linearToOutputTexel( pc_fragColor );
373
+ gl_FragColor = linearToOutputTexel( gl_FragColor );
374
374
  #ifdef USE_FOG
375
375
  #ifdef FOG_EXP2
376
376
  float fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );
377
377
  #else
378
378
  float fogFactor = smoothstep( fogNear, fogFar, fogDepth );
379
379
  #endif
380
- gl_FragColor.rgb = mix( pc_fragColor.rgb, fogColor, fogFactor );
380
+ gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );
381
381
  #endif
382
382
 
383
383
  #ifdef PREMULTIPLIED_ALPHA
384
384
  // Get get normal blending with premultipled, use with CustomBlending, OneFactor, OneMinusSrcAlphaFactor, AddEquation.
385
- gl_FragColor.rgb *= pc_fragColor.a;
385
+ gl_FragColor.rgb *= gl_FragColor.a;
386
386
  #endif
387
387
 
388
388
  #ifdef DITHERING
389
- pc_fragColor.rgb = dithering( pc_fragColor.rgb );
389
+ gl_FragColor.rgb = dithering( gl_FragColor.rgb );
390
390
  #endif
391
391
  }
392
392
  `;
@@ -0,0 +1,192 @@
1
+ import { EngineHarness } from "../../EngineHarness.js";
2
+ import { loadSerializedScene } from "../../scene/SerializedScene.js";
3
+ import { EngineConfiguration } from "../../EngineConfiguration.js";
4
+ import { MeshSystem } from "../ecs/mesh/MeshSystem.js";
5
+ import GUIElementSystem from "../../ecs/gui/GUIElementSystem.js";
6
+ import HeadsUpDisplaySystem from "../../ecs/gui/hud/HeadsUpDisplaySystem.js";
7
+ import TagSystem from "../../ecs/systems/TagSystem.js";
8
+ import { AttachmentSocketsSystem } from "../../ecs/sockets/AttachmentSocketsSystem.js";
9
+ import { AttachmentSystem } from "../../ecs/attachment/AttachmentSystem.js";
10
+ import { SoundEmitterSystem } from "../../sound/ecs/emitter/SoundEmitterSystem.js";
11
+ import SoundControllerSystem from "../../sound/ecs/SoundControllerSystem.js";
12
+ import SoundListenerSystem from "../../sound/ecs/SoundListenerSystem.js";
13
+ import AnimationSystem from "../../ecs/systems/AnimationSystem.js";
14
+ import TopDownCameraControllerSystem from "../ecs/camera/topdown/TopDownCameraControllerSystem.js";
15
+ import { CameraSystem } from "../ecs/camera/CameraSystem.js";
16
+ import ClingToTerrainSystem from "../../ecs/terrain/ecs/ClingToTerrainSystem.js";
17
+ import TerrainSystem from "../../ecs/terrain/ecs/TerrainSystem.js";
18
+ import Trail2DSystem from "../ecs/trail2d/Trail2DSystem.js";
19
+ import { Foliage2System } from "../../ecs/foliage/ecs/Foliage2System.js";
20
+ import ViewportPositionSystem from "../../ecs/gui/position/ViewportPositionSystem.js";
21
+ import SynchronizePositionSystem from "../../ecs/systems/SynchronizePositionSystem.js";
22
+ import InputControllerSystem from "../../input/ecs/systems/InputControllerSystem.js";
23
+ import { InputSystem } from "../../input/ecs/systems/InputSystem.js";
24
+ import MeshHighlightSystem from "../ecs/highlight/system/MeshHighlightSystem.js";
25
+ import LightSystem from "../ecs/light/LightSystem.js";
26
+ import { BehaviorSystem } from "../../intelligence/behavior/ecs/BehaviorSystem.js";
27
+ import { SerializationMetadataSystem } from "../../ecs/systems/SerializationMetadataSystem.js";
28
+ import { PathDisplaySystem } from "../ecs/path/PathDisplaySystem.js";
29
+ import { ParticleEmitterSystem } from "../particles/ecs/ParticleEmitterSystem.js";
30
+ import { ShadedGeometrySystem } from "../ecs/mesh-v2/ShadedGeometrySystem.js";
31
+ import { ArrayBufferLoader } from "../../asset/loaders/ArrayBufferLoader.js";
32
+ import { initializeGameBinarySerializationRegistry } from "../../../../model/game/GameBinarySerializationRegistry.js";
33
+ import WaterSystem from "../ecs/water/WaterSystem.js";
34
+ import Army from "../../../../model/game/ecs/component/army/Army.js";
35
+ import Mesh from "../ecs/mesh/Mesh.js";
36
+ import EntityBuilder from "../../ecs/EntityBuilder.js";
37
+ import { buildCanvasViewFromTexture } from "../render/visibility/hiz/buildCanvasViewFromTexture.js";
38
+ import ViewportPosition from "../../ecs/gui/position/ViewportPosition.js";
39
+ import Vector2 from "../../../core/geom/Vector2.js";
40
+ import GUIElement from "../../ecs/gui/GUIElement.js";
41
+ import { enableEditor } from "../../../editor/enableEditor.js";
42
+ import { SerializationMetadata } from "../../ecs/components/SerializationMetadata.js";
43
+
44
+ const eh = new EngineHarness();
45
+
46
+ /**
47
+ *
48
+ * @param {Engine} engine
49
+ * @returns {EngineConfiguration}
50
+ */
51
+ function makeConfig(engine) {
52
+
53
+ const config = new EngineConfiguration();
54
+
55
+ /**
56
+ *
57
+ * @type {SoundEngine}
58
+ */
59
+ const sound = engine.sound;
60
+ const graphics = engine.graphics;
61
+ const assetManager = engine.assetManager;
62
+ const devices = engine.devices;
63
+
64
+ // graphics.renderer.shadowMap.type = BasicShadowMap;
65
+
66
+ const guiSystem = new GUIElementSystem(engine.gui.view, engine);
67
+ const headsUpDisplaySystem = new HeadsUpDisplaySystem(graphics);
68
+
69
+ config.addLoader('arraybuffer', new ArrayBufferLoader());
70
+
71
+ initializeGameBinarySerializationRegistry(engine.binarySerializationRegistry);
72
+
73
+ config.addManySystems(
74
+ new TagSystem(),
75
+ new AttachmentSocketsSystem(),
76
+ new AttachmentSystem(),
77
+ new SoundEmitterSystem(assetManager, sound.destination, sound.context),
78
+ new SoundControllerSystem(),
79
+ new SoundListenerSystem(sound.context),
80
+ guiSystem,
81
+ new AnimationSystem(graphics.viewport.size),
82
+ new TopDownCameraControllerSystem(graphics),
83
+ new CameraSystem(graphics.scene, graphics),
84
+ new MeshSystem(engine),
85
+ new ClingToTerrainSystem(),
86
+ new TerrainSystem(graphics, assetManager),
87
+ new Trail2DSystem(engine),
88
+ new Foliage2System(assetManager, graphics),
89
+ new ViewportPositionSystem(graphics.viewport.size),
90
+ new SynchronizePositionSystem(),
91
+ new InputControllerSystem(devices),
92
+ new InputSystem(devices),
93
+ new MeshHighlightSystem(engine),
94
+ new LightSystem(engine, {
95
+ shadowResolution: 2048
96
+ }),
97
+ headsUpDisplaySystem,
98
+ new BehaviorSystem(engine),
99
+ new SerializationMetadataSystem(),
100
+ new PathDisplaySystem(engine),
101
+ new ParticleEmitterSystem(engine),
102
+ new ShadedGeometrySystem(engine),
103
+ new WaterSystem(graphics)
104
+ );
105
+
106
+
107
+ // Knowledge
108
+
109
+ return config;
110
+ }
111
+
112
+ /**
113
+ *
114
+ * @param {Engine} engine
115
+ */
116
+ function get_three_light(engine) {
117
+
118
+ return engine.graphics.scene.children.find(l => l.isDirectionalLight);
119
+ }
120
+
121
+ /**
122
+ *
123
+ * @param {Engine} engine
124
+ */
125
+ function init_shadowmap_preview(engine) {
126
+ const ecd = engine.entityManager.dataset;
127
+
128
+ const graphics = engine.graphics;
129
+ const preview = buildCanvasViewFromTexture({
130
+ width: 512,
131
+ height: 512,
132
+ renderer: graphics.renderer,
133
+ texture: null
134
+ });
135
+
136
+ graphics.on.postOpaquePass.add(() => {
137
+
138
+ const light = get_three_light(engine);
139
+
140
+ if (light !== undefined) {
141
+ preview.texture = light.shadow.map.texture;
142
+
143
+ preview.render();
144
+ }
145
+ });
146
+
147
+
148
+ new EntityBuilder()
149
+ .add(ViewportPosition.fromJSON({
150
+ offset: new Vector2(10, 10)
151
+ }))
152
+ .add(GUIElement.fromView(preview.view))
153
+ .add(SerializationMetadata.Transient)
154
+ .build(ecd);
155
+ }
156
+
157
+ /**
158
+ *
159
+ * @param {Engine} engine
160
+ * @returns {Promise<void>}
161
+ */
162
+ async function main(engine) {
163
+
164
+ const ecd = engine.entityManager.dataset;
165
+ await loadSerializedScene('data/levels/character_creation/level.bin', ecd, engine);
166
+
167
+
168
+ const character = ecd.getAnyComponent(Army);
169
+
170
+ const entity = EntityBuilder.readFromDataset(character.entity, ecd);
171
+
172
+ entity.getComponent(Mesh).url = "data/models/Conqueror Mech/Conqueror Mech.gltf";
173
+
174
+ init_shadowmap_preview(engine);
175
+
176
+ window.light = get_three_light(engine);
177
+ }
178
+
179
+ async function init(engineHarness) {
180
+
181
+ const engine = await engineHarness.initialize();
182
+
183
+ const config = makeConfig(engine);
184
+
185
+ await config.apply(engine);
186
+
187
+ enableEditor(engine);
188
+
189
+ main(engine);
190
+ }
191
+
192
+ init(eh);
@@ -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,8 +5,9 @@
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.36",
8
+ "version": "2.33.40",
9
9
  "dependencies": {
10
+ "gl-matrix": "3.4.3",
10
11
  "fast-levenshtein": "2.0.6",
11
12
  "opentype.js": "1.3.3",
12
13
  "simplex-noise": "2.4.0",