@woosh/meep-engine 2.44.7 → 2.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/core/cache/Cache.js +1 -1
  2. package/core/collection/HashMap.d.ts +1 -1
  3. package/core/collection/HashMap.js +2 -1
  4. package/core/localization/LanguageMetadata.js +48 -0
  5. package/core/localization/LocaleDataset.js +37 -0
  6. package/core/localization/Localization.js +253 -0
  7. package/core/model/node-graph/DataType.js +1 -1
  8. package/core/model/node-graph/node/Port.js +4 -0
  9. package/core/process/task/Task.js +22 -5
  10. package/core/process/task/util/iteratorTask.js +29 -0
  11. package/editor/view/ecs/components/items/ItemContainerController.stories.js +1 -1
  12. package/engine/Engine.js +1 -1
  13. package/engine/asset/AssetManager.js +4 -0
  14. package/engine/ecs/foliage/ViewState.js +7 -1
  15. package/engine/ecs/speaker/VoiceSystem.js +1 -1
  16. package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +17 -11
  17. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +37 -0
  18. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +19 -0
  19. package/engine/graphics/ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js +11 -2
  20. package/engine/graphics/render/forward_plus/LightManager.js +33 -123
  21. package/engine/graphics/render/forward_plus/SPECIFICATION.md +155 -0
  22. package/engine/graphics/render/forward_plus/assign_cluster.js +125 -0
  23. package/engine/graphics/render/forward_plus/model/Decal.js +6 -2
  24. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts +5 -0
  25. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +11 -4
  26. package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +3 -3
  27. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
  28. package/engine/graphics/render/forward_plus/sort_decal_data.js +102 -0
  29. package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +1 -1
  30. package/engine/input/devices/InputDeviceButton.d.ts +7 -0
  31. package/engine/input/devices/InputDeviceButton.js +22 -0
  32. package/engine/input/devices/KeyboardDevice.d.ts +11 -0
  33. package/engine/input/devices/KeyboardDevice.js +17 -7
  34. package/package.json +1 -1
  35. package/core/Localization.js +0 -199
@@ -395,7 +395,7 @@ export class Cache {
395
395
  }
396
396
 
397
397
  /**
398
- *
398
+ * Please note that the key will be stored inside the cache, so it must be treated as immutable
399
399
  * @param {Key} key
400
400
  * @param {function(Key):Value} compute
401
401
  * @param {*} [compute_context]
@@ -29,7 +29,7 @@ export class HashMap<K, V> implements Iterable<[V, K]> {
29
29
 
30
30
  forEach(callback: (value: V, key: K, map: this) => any, thisArg?: any): void
31
31
 
32
- [Symbol.iterator](): IterableIterator<[V, K]>
32
+ [Symbol.iterator](): IterableIterator<[K, V]>
33
33
 
34
34
  values(): IterableIterator<V>
35
35
 
@@ -40,6 +40,7 @@ const DEFAULT_LOAD_FACTOR = 0.75;
40
40
 
41
41
  /**
42
42
  * Implements part of {@link Map} interface
43
+ * @copyright Alex Goldring (c) 2023
43
44
  * @template K,V
44
45
  * @extends Map<K,V>
45
46
  */
@@ -519,7 +520,7 @@ export class HashMap {
519
520
  */
520
521
  const entry = bucket[i];
521
522
 
522
- yield [entry.value, entry.key];
523
+ yield [entry.key, entry.value];
523
524
  }
524
525
  }
525
526
 
@@ -0,0 +1,48 @@
1
+ import { assert } from "../assert.js";
2
+
3
+ /**
4
+ * Represents information about a language
5
+ */
6
+ export class LanguageMetadata {
7
+ /**
8
+ * Measured in characters per second
9
+ * @type {number}
10
+ */
11
+ reading_speed = 10
12
+
13
+ /**
14
+ * Ordered list of fallback languages, if no value is found for a key in this language, other languages will be attempted in order
15
+ * Identified by localization key
16
+ * @see {@link #locale}
17
+ * @type {string[]}
18
+ */
19
+ fallback_languages = []
20
+
21
+ /**
22
+ * Localization key,
23
+ * @see ISO 639
24
+ * @type {string}
25
+ */
26
+ locale = "";
27
+
28
+ fromJSON({
29
+ reading_speed = 10,
30
+ fallback_languages = []
31
+ }) {
32
+
33
+ assert.isNumber(reading_speed, 'reading_speed');
34
+ assert.greaterThan(reading_speed, 0, 'reading_speed');
35
+
36
+ this.reading_speed = reading_speed;
37
+
38
+ this.fallback_languages = fallback_languages;
39
+ }
40
+
41
+ static fromJSON(j) {
42
+ const r = new LanguageMetadata();
43
+
44
+ r.fromJSON(j);
45
+
46
+ return r;
47
+ }
48
+ }
@@ -0,0 +1,37 @@
1
+ //
2
+
3
+ import { assert } from "../assert.js";
4
+
5
+ /**
6
+ * Represents data for a single localization
7
+ */
8
+ export class LocaleDataset {
9
+ /**
10
+ * Localized strings, identified by localization key
11
+ * @type {Object<string>}
12
+ * @private
13
+ */
14
+ __strings = {}
15
+
16
+ /**
17
+ *
18
+ * Does a given key exist?
19
+ * @param {string} key
20
+ * @return {boolean}
21
+ */
22
+ hasString(key) {
23
+ assert.isString(key, 'key');
24
+
25
+ return this.__strings[key] !== undefined;
26
+ }
27
+
28
+ /**
29
+ *
30
+ * @param {string} key
31
+ * @returns {string|undefined}
32
+ */
33
+ getString(key) {
34
+ return this.__strings[key];
35
+ }
36
+
37
+ }
@@ -0,0 +1,253 @@
1
+ import levenshtein from "fast-levenshtein";
2
+ import { parseTooltipString } from "../../view/tooltip/gml/parser/parseTooltipString.js";
3
+ import { assert } from "../assert.js";
4
+ import ObservedString from "../model/ObservedString.js";
5
+ import { seedVariablesIntoTemplateString } from "../parser/seedVariablesIntoTemplateString.js";
6
+ import { STRING_TEMPLATE_VARIABLE_REGEX } from "../parser/STRING_TEMPLATE_VARIABLE_REGEX.js";
7
+ import { Cache } from "../cache/Cache.js";
8
+ import { computeStringHash } from "../primitives/strings/computeStringHash.js";
9
+ import { computeHashArray } from "../collection/array/computeHashArray.js";
10
+ import { LanguageMetadata } from "./LanguageMetadata.js";
11
+
12
+ /**
13
+ * Validation utility method
14
+ * @param {string} template
15
+ * @return {string}
16
+ */
17
+ function validationMockSeed(template) {
18
+
19
+ const result = template.replace(STRING_TEMPLATE_VARIABLE_REGEX, function (match, varName) {
20
+ return "0";
21
+ });
22
+
23
+ return result;
24
+ }
25
+
26
+ const EMPTY_SEED = Object.freeze({});
27
+
28
+ const DEFAULT_LANGUAGE_METADATA = Object.freeze(new LanguageMetadata());
29
+
30
+ export class Localization {
31
+ constructor() {
32
+ /**
33
+ *
34
+ * @type {AssetManager|null}
35
+ */
36
+ this.assetManager = null;
37
+
38
+ this.json = {};
39
+
40
+ /**
41
+ * @protected
42
+ * @type {LanguageMetadata}
43
+ */
44
+ this.language_metadata = DEFAULT_LANGUAGE_METADATA;
45
+
46
+ /**
47
+ *
48
+ * @type {ObservedString}
49
+ */
50
+ this.locale = new ObservedString('');
51
+
52
+ /**
53
+ * In debug mode error messages are a lot more verbose and helpful
54
+ * @type {boolean}
55
+ */
56
+ this.debug = true;
57
+
58
+ /**
59
+ * @type {Cache<string[], string>}
60
+ * @private
61
+ */
62
+ this.__failure_cache = new Cache({
63
+ maxWeight: 1024,
64
+ keyHashFunction: (key) => computeHashArray(key, computeStringHash)
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Measured in characters per second
70
+ * @deprecated use 'language_metadata' directly instead
71
+ * @return {number}
72
+ */
73
+ get reading_speed() {
74
+ return this.language_metadata.reading_speed;
75
+ }
76
+
77
+ /**
78
+ * Time required to read a piece of text, in seconds
79
+ * @param {string} text
80
+ * @returns {number} time in seconds
81
+ */
82
+ estimateReadingTime(text) {
83
+ assert.isString(text, 'text');
84
+
85
+ return text.length / this.reading_speed;
86
+ }
87
+
88
+ /**
89
+ *
90
+ * @param {AssetManager} am
91
+ */
92
+ setAssetManager(am) {
93
+ this.assetManager = am;
94
+ }
95
+
96
+ /**
97
+ * @returns {boolean}
98
+ * @param {function(key:string, error:*, original: string)} errorConsumer
99
+ */
100
+ validate(errorConsumer) {
101
+ let result = true;
102
+
103
+ for (let key in this.json) {
104
+ const value = this.json[key];
105
+
106
+ const seededValue = validationMockSeed(value);
107
+
108
+ try {
109
+ parseTooltipString(seededValue);
110
+ } catch (e) {
111
+ result = false;
112
+ errorConsumer(key, e, value);
113
+ }
114
+ }
115
+
116
+ return result;
117
+ }
118
+
119
+ /**
120
+ * Request locale switch
121
+ * Assumes a specific folder structure, each different locale is stored with its locale code as name, and there's also "languages.json" file expected to be in the folder
122
+ * @param {string} locale
123
+ * @param {string} path where to look for localization data
124
+ * @returns {Promise}
125
+ */
126
+ loadLocale(locale, path = 'data/database/text') {
127
+ assert.isString(locale, 'locale');
128
+ assert.isString(path, 'path');
129
+
130
+ const am = this.assetManager;
131
+
132
+ if (am === null) {
133
+ throw new Error('AssetManager is not set');
134
+ }
135
+
136
+ let _path = path.trim();
137
+
138
+ while (_path.endsWith('/') || _path.endsWith('\\')) {
139
+ // remove trailing slash if present
140
+ _path.slice(0, _path.length - 1);
141
+ }
142
+
143
+ const pLoadData = am.promise(`${_path}/${locale}.json`, "json")
144
+ .then(asset => {
145
+ const json = asset.create();
146
+
147
+ this.json = json;
148
+
149
+ this.locale.set(locale);
150
+ }, reason => {
151
+
152
+ console.error(`Failed to load locale data for locale '${locale}' : ${reason}`);
153
+
154
+ // reset data
155
+ this.json = {};
156
+
157
+ });
158
+
159
+ const pLoadMetadata = am.promise(`${_path}/languages.json`, "json")
160
+ .then(asset => {
161
+ const languages_metadata = asset.create();
162
+
163
+ this.language_metadata = LanguageMetadata.fromJSON(languages_metadata[locale]);
164
+ }, reason => {
165
+ console.error(`Failed to load language metadata: ${reason}`);
166
+
167
+ this.language_metadata = DEFAULT_LANGUAGE_METADATA;
168
+ });
169
+
170
+ return Promise.all([pLoadData, pLoadMetadata]);
171
+ }
172
+
173
+
174
+ /**
175
+ *
176
+ * @param {number} value
177
+ */
178
+ formatIntegerByThousands(value) {
179
+ const formatter = new Intl.NumberFormat(this.locale.getValue(), { useGrouping: true });
180
+
181
+ return formatter.format(value);
182
+ }
183
+
184
+ /**
185
+ *
186
+ * @param {string} id
187
+ * @param {Object} seed
188
+ * @private
189
+ */
190
+ __debugMissingKey(id, seed) {
191
+ const locale = this.locale.getValue();
192
+
193
+ const seed_string = JSON.stringify(seed);
194
+
195
+ const message = this.__failure_cache.getOrCompute([locale, id, seed_string], () => {
196
+
197
+ //try to find similar keys
198
+ const similarities = Object.keys(this.json).map(function (key) {
199
+ const distance = levenshtein.get(key, id);
200
+ return {
201
+ key,
202
+ distance
203
+ };
204
+ });
205
+
206
+ similarities.sort(function (a, b) {
207
+ return a.distance - b.distance;
208
+ });
209
+
210
+ const suggestions = similarities.slice(0, 3).map(p => p.key);
211
+
212
+ return `No localization value for id='${id}', seed=${seed_string}, approximate matches: ${suggestions.join(', ')}`;
213
+ });
214
+
215
+ console.warn(message);
216
+ }
217
+
218
+ /**
219
+ * Get a localized string by a key
220
+ * @param {string} key
221
+ * @param {object} [seed]
222
+ *
223
+ * @returns {string}
224
+ */
225
+ getString(key, seed = EMPTY_SEED) {
226
+ assert.isString(key, 'id');
227
+
228
+ const value = this.json[key];
229
+
230
+ if (value === undefined) {
231
+
232
+ if (this.debug) {
233
+ this.__debugMissingKey(key, seed)
234
+ }
235
+
236
+ //no value, provide substitute
237
+ return `@${key}`;
238
+
239
+ }
240
+
241
+ //value needs to be seeded
242
+ return seedVariablesIntoTemplateString(value, seed);
243
+ }
244
+
245
+ /**
246
+ * Does a given key exist?
247
+ * @param {string} key
248
+ * @return {boolean}
249
+ */
250
+ hasString(key) {
251
+ return this.json[key] !== undefined;
252
+ }
253
+ }
@@ -16,7 +16,7 @@ export class DataType {
16
16
  }
17
17
 
18
18
  toString() {
19
- return `{DataType: id=${this.id}, name='${this.name}' }`;
19
+ return `DataType{ id=${this.id}, name='${this.name}' }`;
20
20
  }
21
21
 
22
22
  /**
@@ -57,6 +57,10 @@ export class Port {
57
57
  ;
58
58
 
59
59
  }
60
+
61
+ toString() {
62
+ return `Port{ id=${this.id}, direction=${this.direction}, name=${this.name}, type=${this.dataType} }`;
63
+ }
60
64
  }
61
65
 
62
66
  /**
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { assert } from "../../assert.js";
7
7
  import Signal from "../../events/signal/Signal.js";
8
- import { noop, returnZero } from "../../function/Functions.js";
8
+ import { noop } from "../../function/Functions.js";
9
9
  import ObservedInteger from "../../model/ObservedInteger.js";
10
10
  import { TaskSignal } from "./TaskSignal.js";
11
11
  import TaskState from "./TaskState.js";
@@ -27,14 +27,14 @@ class Task {
27
27
  name,
28
28
  initializer = noop,
29
29
  cycleFunction,
30
- computeProgress = returnZero,
30
+ computeProgress,
31
31
  dependencies = [],
32
32
  estimatedDuration = 1
33
33
  }
34
34
  ) {
35
35
 
36
- assert.typeOf(cycleFunction, "function", 'cycleFunction');
37
- assert.typeOf(estimatedDuration, 'number', 'estimatedDuration');
36
+ assert.isFunction(cycleFunction, 'cycleFunction');
37
+ assert.isNumber(estimatedDuration, 'estimatedDuration');
38
38
 
39
39
 
40
40
  this.dependencies = dependencies;
@@ -59,7 +59,12 @@ class Task {
59
59
  */
60
60
  this.initialize = initializer;
61
61
 
62
- this.computeProgress = computeProgress;
62
+ if (computeProgress !== undefined) {
63
+
64
+ // override progress function
65
+ this.computeProgress = computeProgress;
66
+
67
+ }
63
68
 
64
69
  this.on = {
65
70
  started: new Signal(),
@@ -87,6 +92,18 @@ class Task {
87
92
  this.__executedCycleCount = 0;
88
93
  }
89
94
 
95
+ computeProgress() {
96
+
97
+ const cycles = this.__executedCycleCount;
98
+
99
+ if (cycles === 0) {
100
+ return 0;
101
+ }
102
+
103
+ // inverse logarithmic progression, never reaches 1
104
+ return 1 - (1 / cycles);
105
+ }
106
+
90
107
  /**
91
108
  * Time in milliseconds that the task has been executing for, suspended time does not count
92
109
  * @returns {number}
@@ -0,0 +1,29 @@
1
+ import Task from "../Task.js";
2
+ import { TaskSignal } from "../TaskSignal.js";
3
+ import { assert } from "../../../assert.js";
4
+
5
+ /**
6
+ *
7
+ * @param {string} name
8
+ * @param {Iterator} iterator
9
+ * @param {TaskSignal.Continue|TaskSignal.Yield} [cycle_signal] what to signal at the end of each iteration, Continue will provide better throughput, whereas Yield will produce very low load on the CPU
10
+ * @returns {Task}
11
+ */
12
+ export function iteratorTask(name, iterator, cycle_signal = TaskSignal.Continue) {
13
+ assert.defined(iterator, 'iterator');
14
+ assert.notNull(iterator, 'iterator');
15
+ assert.isFunction(iterator.next, 'iterator.next');
16
+
17
+ return new Task({
18
+ name,
19
+ cycleFunction() {
20
+ const next = iterator.next();
21
+
22
+ if (next.done) {
23
+ return TaskSignal.EndSuccess
24
+ } else {
25
+ return cycle_signal;
26
+ }
27
+ }
28
+ })
29
+ }
@@ -1,5 +1,5 @@
1
1
  import { storiesOf } from "@storybook/html/dist/client/preview";
2
- import { Localization } from "../../../../../core/Localization.js";
2
+ import { Localization } from "../../../../../core/localization/Localization.js";
3
3
  import { ItemContainerController } from "./ItemContainerController.js";
4
4
  import ItemContainer from "../../../../../../model/game/ecs/component/item_container/ItemContainer.js";
5
5
  import Item from "../../../../../../model/game/ecs/component/Item.js";
package/engine/Engine.js CHANGED
@@ -23,7 +23,7 @@ import EmptyView from "../view/elements/EmptyView.js";
23
23
  import { assert } from "../core/assert.js";
24
24
  import { StaticKnowledgeDatabase } from "./knowledge/database/StaticKnowledgeDatabase.js";
25
25
  import Ticker from "./simulation/Ticker.js";
26
- import { Localization } from "../core/Localization.js";
26
+ import { Localization } from "../core/localization/Localization.js";
27
27
  import { ModuleRegistry } from "../core/model/ModuleRegistry.js";
28
28
  import { BinarySerializationRegistry } from "./ecs/storage/binary/BinarySerializationRegistry.js";
29
29
  import { EnginePluginManager } from "./plugin/EnginePluginManager.js";
@@ -326,6 +326,10 @@ export class AssetManager {
326
326
  throw new Error("Path must be string. Path = " + JSON.stringify(path));
327
327
  }
328
328
 
329
+ if(typeof type !== "string"){
330
+ throw new TypeError(`type must be a string, instead was '${typeof type}'`);
331
+ }
332
+
329
333
  const assetDescription = new AssetDescription(path, type);
330
334
 
331
335
  const asset = this.assets.get(assetDescription);
@@ -1,6 +1,8 @@
1
1
  import { BitSet } from "../../../core/binary/BitSet.js";
2
2
  import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
3
- import { queryBinaryNode_FrustumIntersections_Data } from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
3
+ import {
4
+ queryBinaryNode_FrustumIntersections_Data
5
+ } from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
4
6
  import Quaternion from "../../../core/geom/Quaternion.js";
5
7
  import Vector3 from "../../../core/geom/Vector3.js";
6
8
  import { compose_matrix4_array } from "../../../core/geom/3d/compose_matrix4_array.js";
@@ -30,6 +32,10 @@ export class ViewState {
30
32
  * @type {InstancedMeshGroup}
31
33
  */
32
34
  this.instances = new InstancedMeshGroup();
35
+
36
+ // make shrinking unlikely to prevent thrashing
37
+ this.instances.shrinkFactor = 0.4;
38
+ this.instances.shrinkConstant = 1024;
33
39
 
34
40
  /**
35
41
  *
@@ -373,7 +373,7 @@ export class VoiceSystem extends AbstractContextSystem {
373
373
  // localized line may contain reference tags, the user will not see/read those, so we also compile line as pure text for estimating reading time
374
374
  const line_pure_text = gml.compileAsText(localized_line);
375
375
 
376
- const display_time_raw = localiation.computeReadingTime(line_pure_text);
376
+ const display_time_raw = localiation.estimateReadingTime(line_pure_text);
377
377
 
378
378
  const display_time = max2(TIMING_MINIMUM_READ_TIME, display_time_raw * line.displayDuration) + TIMING_NOTICE_DELAY;
379
379
 
@@ -15,7 +15,7 @@ import { GameAssetType } from "../../../../asset/GameAssetType.js";
15
15
  import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
16
16
  import '../../../../../../../../css/game.scss';
17
17
  import { countTask } from "../../../../../core/process/task/util/countTask.js";
18
- import Vector2 from "../../../../../core/geom/Vector2.js";
18
+ import Vector2, { v2_distance } from "../../../../../core/geom/Vector2.js";
19
19
  import { RotationBehavior } from "../../../../intelligence/behavior/util/RotationBehavior.js";
20
20
  import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
21
21
  import Vector3 from "../../../../../core/geom/Vector3.js";
@@ -270,14 +270,17 @@ function grid(ecd, offset_x, offset_y, x, y, size_x, size_y, spacing, textures)
270
270
  function makeNormalTestGridDecal(ecd, root_transform = new Transform()) {
271
271
  const uv = new OctahedralUvEncoder();
272
272
 
273
- const GRID_SIZE = 9;
273
+ const GRID_SIZE = 16;
274
274
 
275
275
  const CELL_SIZE = 1;
276
276
 
277
- const SPACING = CELL_SIZE*1.2;
277
+ const SPACING = CELL_SIZE * 1.2;
278
+ // const SPACING = CELL_SIZE * 0.6;
278
279
 
279
280
  const DEBUG_BOX = makeHelperBoxGeometry();
280
281
 
282
+ const random = seededRandom(7);
283
+
281
284
  for (let i = 0; i < GRID_SIZE; i++) {
282
285
  for (let j = 0; j < GRID_SIZE; j++) {
283
286
 
@@ -290,7 +293,7 @@ function makeNormalTestGridDecal(ecd, root_transform = new Transform()) {
290
293
  const decal = new Decal();
291
294
 
292
295
  // decal.uri = decal_urls[1];
293
- decal.uri ='moicon/ISO 7010 - Safety Signs (3)/ISO 7010 - Safety Signs/Emergency/400px/E001 – Emergency exit (left hand).png';
296
+ decal.uri = 'moicon/ISO 7010 - Safety Signs (3)/ISO 7010 - Safety Signs/Emergency/400px/E001 – Emergency exit (left hand).png';
294
297
 
295
298
  const entity = new EntityBuilder();
296
299
 
@@ -303,7 +306,7 @@ function makeNormalTestGridDecal(ecd, root_transform = new Transform()) {
303
306
  0,
304
307
  );
305
308
  transform.scale.setScalar(CELL_SIZE);
306
- transform.rotation._lookRotation(direction[0],direction[2], direction[1] , 0, 1, 0);
309
+ transform.rotation._lookRotation(direction[0], direction[2], direction[1], 0, 1, 0);
307
310
 
308
311
  transform.multiplyTransforms(root_transform, transform);
309
312
 
@@ -314,9 +317,12 @@ function makeNormalTestGridDecal(ecd, root_transform = new Transform()) {
314
317
  .add(decal)
315
318
  .build(ecd);
316
319
 
317
- setInterval(()=>{
318
- decal.priority = Math.random();
319
- },7000);
320
+ // setInterval(()=>{
321
+ // decal.priority = Math.random();
322
+ // },7000);
323
+
324
+ // decal.priority = randomIntegerBetween(random,0,4096);
325
+ decal.priority = v2_distance(i, j, GRID_SIZE * 0.5, GRID_SIZE * 0.5);
320
326
 
321
327
 
322
328
  // make an arrow helper
@@ -330,7 +336,7 @@ function makeNormalTestGridDecal(ecd, root_transform = new Transform()) {
330
336
  side: DoubleSide
331
337
  }), DrawMode.Triangles))
332
338
  .add(arrow_transform)
333
- .build(ecd);
339
+ .build(ecd);
334
340
  }
335
341
  }
336
342
  }
@@ -448,9 +454,9 @@ async function main(engine) {
448
454
  new EntityBuilder()
449
455
  .add(SGMesh.fromURL('data/models/snaps/cube_white.gltf'))
450
456
  .add(Transform.fromJSON({
451
- position:new Vector3(14,1,4.8),
457
+ position: new Vector3(14, 1, 4.8),
452
458
  rotation: t_forward_grid.rotation,
453
- scale: new Vector3(25,25,0.1)
459
+ scale: new Vector3(25, 25, 0.1)
454
460
  }))
455
461
  .build(ecd);
456
462