@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
@@ -0,0 +1,454 @@
1
+ import { tetrahedron_contains_point } from "./tetrahedron_contains_point.js";
2
+ import { assert } from "../../../assert.js";
3
+ import { point_in_tetrahedron_circumsphere } from "./point_in_tetrahedron_circumsphere.js";
4
+ import { BitSet } from "../../../binary/BitSet.js";
5
+ import { typed_array_copy } from "../../../collection/array/typed/typed_array_copy.js";
6
+ import { max3 } from "../../../math/max3.js";
7
+
8
+ /**
9
+ * @readonly
10
+ * @type {number}
11
+ */
12
+ const LAYOUT_TETRA_BYTE_SIZE = 9 * 4;
13
+
14
+ /**
15
+ * @readonly
16
+ * @type {number}
17
+ */
18
+ const INVALID_NEIGHBOUR = 0xFFFFFFFF;
19
+
20
+ class Cavity {
21
+ constructor() {
22
+ this.indices = [];
23
+
24
+ /**
25
+ *
26
+ * @type {number}
27
+ */
28
+ this.size = 0;
29
+ }
30
+
31
+ update() {
32
+ // compute in/out state for each side of each tetra
33
+ }
34
+
35
+ /**
36
+ *
37
+ * @param {number} i
38
+ */
39
+ push(i) {
40
+ this.indices[this.size++] = i;
41
+ }
42
+
43
+ /**
44
+ *
45
+ * @param {number} i
46
+ * @returns {boolean}
47
+ */
48
+ includes(i) {
49
+ const n = this.size;
50
+ for (let j = 0; j < n; j++) {
51
+ if (this.indices[j] === i) {
52
+ return true;
53
+ }
54
+ }
55
+
56
+ return false;
57
+ }
58
+
59
+ reset() {
60
+ this.size = 0;
61
+ }
62
+ }
63
+
64
+ const SCRATCH_CAVITY = new Cavity();
65
+
66
+ /**
67
+ *
68
+ * Layout:
69
+ * vertex_id_a :: uint
70
+ * vertex_id_b :: uint
71
+ * vertex_id_c :: uint
72
+ * vertex_id_d :: uint
73
+ * neighbour_a :: uint - neighbour tetrahedron, opposite to vertex A
74
+ * neighbour_b :: uint - neighbour tetrahedron, opposite to vertex B
75
+ * neighbour_c :: uint - neighbour tetrahedron, opposite to vertex C
76
+ * neighbour_d :: uint - neighbour tetrahedron, opposite to vertex D
77
+ * sub_determinant :: float - ?
78
+ * Layout is similar to [1], but is interleaved for better cache locality
79
+ */
80
+ export class TetrahedraCollection {
81
+ constructor(initial_size) {
82
+ this.__buffer = new ArrayBuffer(initial_size * LAYOUT_TETRA_BYTE_SIZE);
83
+
84
+ this.__view = new DataView(this.__buffer);
85
+
86
+ this.__capacity = initial_size;
87
+ this.__length = 0;
88
+
89
+
90
+ /**
91
+ * Marks which indices are in use
92
+ * @type {BitSet}
93
+ * @private
94
+ */
95
+ this.__occupancy = new BitSet();
96
+ }
97
+
98
+ /**
99
+ *
100
+ * @param {number} n
101
+ */
102
+ setCapacity(n) {
103
+ if (n === this.__capacity) {
104
+ // do nothing
105
+ return;
106
+ }
107
+
108
+ if (n < this.__length) {
109
+ throw new Error('Dropping information, not supported');
110
+ }
111
+
112
+ // allocate new buffer
113
+ const new_buffer = new ArrayBuffer(n * LAYOUT_TETRA_BYTE_SIZE);
114
+
115
+ // move data across from old buffer to the new one
116
+ const destination_uint8 = new Uint8Array(new_buffer);
117
+ const source_uint8 = new Uint8Array(this.__buffer);
118
+
119
+ typed_array_copy(source_uint8, destination_uint8);
120
+
121
+ // set new buffer
122
+ this.__buffer = new_buffer;
123
+ this.__view = new DataView(new_buffer);
124
+ }
125
+
126
+ /**
127
+ *
128
+ * @param {number} n
129
+ */
130
+ ensureCapacity(n) {
131
+
132
+ const new_capacity = max3(
133
+ n,
134
+ this.__capacity * 1.2,
135
+ this.__capacity + 32
136
+ );
137
+
138
+ this.setCapacity(new_capacity);
139
+ }
140
+
141
+ /**
142
+ *
143
+ * @param {number} tetra_index
144
+ * @param {number} neighbour_index
145
+ * @returns {number}
146
+ */
147
+ getNeighbour(tetra_index, neighbour_index) {
148
+ const tetra_address = LAYOUT_TETRA_BYTE_SIZE * tetra_index;
149
+ return this.__view.getUint32(tetra_address + (4 + neighbour_index) * 4);
150
+ }
151
+
152
+ /**
153
+ *
154
+ * @param {number} tetra_index
155
+ * @param {number} neighbour_index which neighbour to set (0..11)
156
+ * @param {number} neighbour index of the neighbour
157
+ */
158
+ setNeighbour(tetra_index, neighbour_index, neighbour) {
159
+ const tetra_address = LAYOUT_TETRA_BYTE_SIZE * tetra_index;
160
+ return this.__view.setUint32(tetra_address + (4 + neighbour_index) * 4, neighbour);
161
+ }
162
+
163
+ /**
164
+ *
165
+ * @param {number[]|Float32Array} points
166
+ * @param {number} a
167
+ * @param {number} b
168
+ * @param {number} c
169
+ * @param {number} d
170
+ * @returns {number} index of the new tetra
171
+ */
172
+ append(points, a, b, c, d) {
173
+ const tetra_index = this.__occupancy.nextClearBit(0);
174
+ const address = tetra_index * LAYOUT_TETRA_BYTE_SIZE;
175
+
176
+ if (tetra_index >= this.__capacity) {
177
+ // needs to be increased in size
178
+ this.ensureCapacity(tetra_index);
179
+ }
180
+
181
+ const view = this.__view;
182
+
183
+ view.setUint32(address, a);
184
+ view.setUint32(address + 4, b);
185
+ view.setUint32(address + 8, c);
186
+ view.setUint32(address + 12, d);
187
+
188
+ // set neighbours
189
+ view.setUint32(address + 16, INVALID_NEIGHBOUR);
190
+ view.setUint32(address + 20, INVALID_NEIGHBOUR);
191
+ view.setUint32(address + 24, INVALID_NEIGHBOUR);
192
+ view.setUint32(address + 28, INVALID_NEIGHBOUR);
193
+
194
+ this.__occupancy.set(tetra_index, true);
195
+
196
+ this.__length++;
197
+
198
+ return tetra_index;
199
+ }
200
+
201
+ /**
202
+ * Remove tetrahedron
203
+ * @param {number} tera_index
204
+ */
205
+ remove(tera_index) {
206
+
207
+ // find neighbours and remove reference to self
208
+ for (let i = 0; i < 4; i++) {
209
+ const neighbour_encoded = this.getNeighbour(tera_index, i);
210
+
211
+ if (neighbour_encoded === INVALID_NEIGHBOUR) {
212
+ // no neighbour
213
+ continue;
214
+ }
215
+
216
+ // get tetrahedra index and point index
217
+ const neighbour_index = neighbour_encoded >> 2;
218
+ const neighbour_point = neighbour_encoded & 4;
219
+
220
+ // clear reference to self
221
+ this.setNeighbour(neighbour_index, neighbour_point, INVALID_NEIGHBOUR);
222
+ }
223
+
224
+ // mark as dead
225
+ this.__occupancy.clear(tera_index);
226
+ this.__length--;
227
+ }
228
+
229
+ /**
230
+ * Remove tetrahedrons who's points touch the "super-tetrahedron's" points that was inserted originally
231
+ * These points are identified by an offset + count parameters
232
+ * @param {number[]|Float32Array} points
233
+ * @param {number} range_start
234
+ * @param {number} range_end
235
+ */
236
+ removeTetrasConnectedToPoints(points, range_start, range_end) {
237
+ const data_view = this.__view;
238
+
239
+ let i = 0;
240
+ let j = 0;
241
+
242
+ const occupancy = this.__occupancy;
243
+ for (i = occupancy.nextSetBit(0); i !== -1; i = occupancy.nextSetBit(i + 1)) {
244
+
245
+ const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
246
+
247
+ for (j = 0; j < 4; j++) {
248
+ const point_index = data_view.getUint32(tet_address + 4 * i);
249
+
250
+ if (point_index >= range_start && point_index <= range_end) {
251
+ // point index is in range, tetra should be removed
252
+ this.remove(i);
253
+ break;
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+ /**
260
+ *
261
+ * @param {number[]} points
262
+ * @param {number} index
263
+ * @returns {number} index of tetra or -1 if no containing tetra found
264
+ */
265
+ findTetraContainingPoint(points, index) {
266
+ const data_view = this.__view;
267
+
268
+ // TODO improve this
269
+ const n = this.__length;
270
+ for (let i = 0; i < n; i++) {
271
+
272
+ const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
273
+
274
+ const a = data_view.getUint32(tet_address);
275
+ const b = data_view.getUint32(tet_address + 4);
276
+ const c = data_view.getUint32(tet_address + 8);
277
+ const d = data_view.getUint32(tet_address + 12);
278
+
279
+ if (tetrahedron_contains_point(points, a, b, c, d, index)) {
280
+ return i;
281
+ }
282
+ }
283
+
284
+ return -1;
285
+ }
286
+
287
+ /**
288
+ *
289
+ * @param {Cavity} cavity
290
+ * @param {number[]|Float32Array} points
291
+ * @param {number} index
292
+ */
293
+ computeCavity(cavity, points, index) {
294
+
295
+ // 1.identify tetrahedron that contains this point
296
+ const containing_tetra = this.findTetraContainingPoint(points, index);
297
+
298
+ assert.isNonNegativeInteger(containing_tetra, 'containing_tetra');
299
+
300
+ cavity.reset();
301
+
302
+ /**
303
+ *
304
+ * @type {number[]}
305
+ */
306
+ const open_set = [
307
+ containing_tetra
308
+ ];
309
+
310
+ /**
311
+ *
312
+ * @type {number[]}
313
+ */
314
+ const closed_set = [];
315
+
316
+ const data_view = this.__view;
317
+
318
+ // 2. find the Delaunay "cavity", a set of tetrahedrons who's circumsphere overlarlaps the point
319
+ // perform breadth-first expansion on the containing tetra to identify the cavity
320
+ while (open_set.length > 0) {
321
+ const tetra = open_set.pop();
322
+ cavity.push(tetra);
323
+ closed_set.push(tetra);
324
+
325
+ // get neighbours
326
+ for (let i = 0; i < 4; i++) {
327
+ const neighbour_encoded = this.getNeighbour(tetra, i);
328
+ const neighbour_tetra_index = neighbour_encoded >> 2;
329
+
330
+ if (
331
+ (neighbour_encoded === INVALID_NEIGHBOUR) // no neighbour
332
+ || closed_set.includes(neighbour_tetra_index) // already visited
333
+ || open_set.includes(neighbour_tetra_index) // already in open set
334
+ ) {
335
+
336
+ continue;
337
+ }
338
+
339
+ const neighbour_address = neighbour_tetra_index * LAYOUT_TETRA_BYTE_SIZE;
340
+
341
+ const a = data_view.getUint32(neighbour_address);
342
+ const b = data_view.getUint32(neighbour_address + 4);
343
+ const c = data_view.getUint32(neighbour_address + 8);
344
+ const d = data_view.getUint32(neighbour_address + 12);
345
+
346
+ // check neighbour
347
+ const is_in_sphere = point_in_tetrahedron_circumsphere(points, a, b, c, d, index);
348
+
349
+ if (is_in_sphere) {
350
+ open_set.push(neighbour_tetra_index);
351
+ } else {
352
+ // move directly to closed set
353
+ closed_set.push(neighbour_tetra_index);
354
+ }
355
+
356
+
357
+ }
358
+ }
359
+ }
360
+
361
+ /**
362
+ *
363
+ * @param {number[]|Float32Array} points
364
+ * @param {number} index
365
+ */
366
+ insertPoint(points, index) {
367
+ // Compute the cavity, that is the set of tetrahedra that need to be removed and rebuilt
368
+ this.computeCavity(SCRATCH_CAVITY, points, index);
369
+
370
+
371
+ // identify cavity "edge" - the set of tetras that are neighbours of the tetras that form the cavity
372
+ const cavity_size = SCRATCH_CAVITY.size;
373
+ const cavity_indices = SCRATCH_CAVITY.indices;
374
+ const data = this.__view;
375
+
376
+ for (let i = 0; i < cavity_size; i++) {
377
+ const cavity_index = cavity_indices[i];
378
+
379
+ // take each side of the tetra
380
+ const tetra_address = cavity_index * LAYOUT_TETRA_BYTE_SIZE;
381
+
382
+ const a = data.getUint32(tetra_address);
383
+ const b = data.getUint32(tetra_address + 4);
384
+ const c = data.getUint32(tetra_address + 8);
385
+ const d = data.getUint32(tetra_address + 12);
386
+
387
+ // attempt to form 4 tetras using the sides of the cavity
388
+ const a_neighbour = data.getUint32(tetra_address + 16);
389
+ const a_neighbour_index = a_neighbour >> 2;
390
+
391
+ const b_neighbour = data.getUint32(tetra_address + 20);
392
+ const b_neighbour_index = b_neighbour >> 2;
393
+
394
+ const c_neighbour = data.getUint32(tetra_address + 24);
395
+ const c_neighbour_index = c_neighbour >> 2;
396
+
397
+ const d_neighbour = data.getUint32(tetra_address + 28);
398
+ const d_neighbour_index = d_neighbour >> 2;
399
+
400
+
401
+ if (a_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(a_neighbour_index) === 0) {
402
+ // ABC is a valid side
403
+ const tet = this.append(points, b, d, c, index);
404
+ // patch in neighbours
405
+ if (a_neighbour !== INVALID_NEIGHBOUR) {
406
+ this.setNeighbour(tet, 3, a_neighbour);
407
+ this.setNeighbour(a_neighbour_index, a_neighbour & 3, tet);
408
+ }
409
+ }
410
+ if (b_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(b_neighbour_index) === 0) {
411
+ // ABC is a valid side
412
+ const tet = this.append(points, c, d, a, index);
413
+ if (b_neighbour !== INVALID_NEIGHBOUR) {
414
+ this.setNeighbour(tet, 3, b_neighbour);
415
+ this.setNeighbour(b_neighbour_index, b_neighbour & 3, tet);
416
+ }
417
+ }
418
+ if (c_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(c_neighbour_index) === 0) {
419
+ // ABC is a valid side
420
+ const tet = this.append(points, d, b, a, index);
421
+ if (c_neighbour !== INVALID_NEIGHBOUR) {
422
+ this.setNeighbour(tet, 3, c_neighbour);
423
+ this.setNeighbour(c_neighbour_index, c_neighbour & 3, tet);
424
+ }
425
+ }
426
+ if (d_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(d_neighbour_index) === 0) {
427
+ // ABC is a valid side
428
+ const tet = this.append(points, a, b, c, index);
429
+ if (d_neighbour !== INVALID_NEIGHBOUR) {
430
+ this.setNeighbour(tet, 3, d_neighbour);
431
+ this.setNeighbour(d_neighbour_index, d_neighbour & 3, tet);
432
+ }
433
+ }
434
+ }
435
+
436
+
437
+ // 3. remove the cavity tetrahedrons
438
+ for (let i = 0; i < cavity_size; i++) {
439
+ const cavity_index = cavity_indices[i];
440
+
441
+ // clear out cavity, connectivity was already patched in the previous step
442
+ this.__occupancy.set(cavity_index, false);
443
+ }
444
+ }
445
+
446
+ /**
447
+ * optimize tetrahedrons to reduce number of thin and long tetras
448
+ * @see https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/contrib/hxt/tetMesh/src/HXTSPR.c
449
+ */
450
+ optimize() {
451
+
452
+ throw new Error('Not Implemented');
453
+ }
454
+ }
@@ -17,7 +17,8 @@ import { orient3d_fast } from "../plane/orient3d_fast.js";
17
17
  * @returns {boolean}
18
18
  */
19
19
  export function tetrahedron_contains_point(points, a, b, c, d, e) {
20
- return !(orient3d_fast(points, b, d, c, e) > 0
20
+ return !(
21
+ orient3d_fast(points, b, d, c, e) > 0
21
22
  || orient3d_fast(points, c, d, a, e) > 0
22
23
  || orient3d_fast(points, d, b, a, e) > 0
23
24
  || orient3d_fast(points, a, b, c, e) > 0
@@ -100,20 +100,20 @@ export class ActionProcessor {
100
100
  */
101
101
  clear() {
102
102
  // drop all of the history
103
- this.dropHistory(0);
103
+ this.dropHistory(Infinity);
104
104
  }
105
105
 
106
106
  /**
107
- * Drop records beyond a given limit. records are dropped in batches between marks.
107
+ * Drop number of records from the history
108
108
  *
109
109
  * NOTE valid use-cases for this method from the outside are: 1) memory management and 1) removing access to a set of previous actions
110
110
  * NOTE this method is used internally by {@link #mark} method
111
111
  *
112
112
  * @example if there are 2 marks A at record 9 and B at record 11, and requested limit is 10 - 9 records will be kept as records 10 and 11 belong to the same batch and will be removed together.
113
- * @param {number} limit maximum number of records to keep
113
+ * @param {number} drop_count maximum number of records to drop
114
114
  */
115
- dropHistory(limit) {
116
- const recordsToDrop = Math.min(limit, this.history.length);
115
+ dropHistory(drop_count) {
116
+ const recordsToDrop = Math.min(drop_count, this.history.length);
117
117
  if (recordsToDrop <= 0) {
118
118
  return;
119
119
  }
@@ -144,6 +144,9 @@ export class ActionProcessor {
144
144
 
145
145
  // dispatch signal
146
146
  dropped_marks.forEach(this.onMarkRemoved.send1, this.onMarkRemoved);
147
+
148
+ // update history
149
+
147
150
  }
148
151
 
149
152
  /**
@@ -337,16 +337,12 @@ export class GLTFAssetLoader extends AssetLoader {
337
337
  return;
338
338
  }
339
339
 
340
- //find a child that is a mesh
341
- const meshes = scene.children.filter(isMesh);
342
340
 
343
- let root;
341
+ let root = scene;
344
342
 
345
- if (meshes.length !== 1) {
346
- //use the whole scene
347
- root = scene;
348
- } else {
349
- root = meshes[0];
343
+ if (children.length === 1 && isMesh(children[0])) {
344
+ // scene only contains a single mesh, use that directly
345
+ root = children[0];
350
346
  }
351
347
 
352
348
  traverseThreeObject(root, this.__prepareObjectMaterial, this);
@@ -1,3 +1,26 @@
1
- export class System {
1
+ import {EntityManager} from "./EntityManager";
2
2
 
3
+ interface Type<T> extends Function {
4
+ new(...args: any[]): T;
5
+ }
6
+
7
+ export class System<A, B = undefined, C = undefined, D = undefined, E = undefined> {
8
+ dependencies: Type<any>[]
9
+
10
+ startup(em: EntityManager, ready_callback: () => void, error_callback: () => void): void
11
+
12
+ shutdown(em: EntityManager, ready_callback: () => void, error_callback: () => void): void
13
+
14
+ link(a: A, entity: number): void
15
+ link(a: A, b: B, entity: number): void
16
+ link(a: A, b: B, c: C, entity: number): void
17
+ link(a: A, b: B, c: C, d: D, entity: number): void
18
+ link(a: A, b: B, c: C, d: D, e: E, entity: number): void
19
+
20
+ unlink(a: A, entity: number): void
21
+ unlink(a: A, b: B, entity: number): void
22
+ unlink(a: A, b: B, c: C, d: D, entity: number): void
23
+ unlink(a: A, b: B, c: C, d: D, e: E, entity: number): void
24
+
25
+ update(time_delta: number): void
3
26
  }
@@ -1,5 +1,5 @@
1
1
  import { LightBinding } from "../LightBinding.js";
2
- import { PointLight } from "../../../../render/forward_plus/PointLight.js";
2
+ import { PointLight } from "../../../../render/forward_plus/model/PointLight.js";
3
3
 
4
4
  export class FPLightBinding extends LightBinding {
5
5
  constructor() {
@@ -456,7 +456,7 @@ function init() {
456
456
 
457
457
  // sample_gltf_sponza();
458
458
  // sample_gltf_rts_factory();
459
- sample_lucy();
459
+ // sample_lucy();
460
460
  // sample_gltf_hapro_2();
461
461
  // sample_gltf_hapro_1();
462
462
  // sample_gltf_broken_isiflow();
@@ -465,6 +465,9 @@ function init() {
465
465
  // gltf_sample('data/models/moicon/08-clickable-assets/model.gltf');
466
466
  // gltf_sample('data/models/moicon/05-ground-floor/model.gltf');
467
467
  // gltf_sample('data/models/moicon/isiflow_Oct_15_21/0/model.gltf');
468
+ // gltf_sample('moicon/29_Dec_2021_Nammo/1/model.gltf');
469
+ // gltf_sample('moicon/29_Dec_2021_Nammo/1-onematerial/model.gltf');
470
+ gltf_sample('moicon/29_Dec_2021_Nammo/2/model.gltf');
468
471
 
469
472
  document.addEventListener("mousemove", onDocumentMouseMove);
470
473
 
@@ -2,7 +2,6 @@ import { inverseLerp } from "../../../../../../core/math/inverseLerp.js";
2
2
  import { assert } from "../../../../../../core/assert.js";
3
3
  import { max2 } from "../../../../../../core/math/max2.js";
4
4
  import { min2 } from "../../../../../../core/math/min2.js";
5
- import { mix } from "../../../../../../core/math/mix.js";
6
5
  import { ParameterLookupTableFlags } from "./ParameterLookupTableFlags.js";
7
6
  import { ParameterLookupTableSerializationAdapter } from "../emitter/serde/ParameterLookupTableSerializationAdapter.js";
8
7
  import { computeHashIntegerArray } from "../../../../../../core/collection/array/computeHashIntegerArray.js";
@@ -125,7 +124,7 @@ export class ParameterLookupTable {
125
124
  */
126
125
  sample(position, result) {
127
126
  assert.isNumber(position, 'position');
128
- assert.greaterThanOrEqual(position, 0, 'position');
127
+ // assert.greaterThanOrEqual(position, 0, 'position');
129
128
  // assert.ok(position >= 0 && position <= 1, `position must be between 0 and 1, instead was ${position}`);
130
129
 
131
130
  const itemSize = this.itemSize;
@@ -140,32 +139,28 @@ export class ParameterLookupTable {
140
139
  let highIndex = lowIndex;
141
140
  let fraction = 0;
142
141
 
143
- //find position index
144
- for (i = 0; i < numValues; i++) {
145
- //NOTE: no complex search is used, since for small data sizes linear scan is typically faster
146
- const p = positions[i];
142
+ if (position <= positions[0]) {
147
143
 
148
- if (p === position) {
144
+ // special case, seek position is at or before the start of the table
145
+ lowIndex = 0;
146
+ highIndex = 0;
149
147
 
150
- // found the exact match
151
- lowIndex = i;
152
- highIndex = i;
153
- fraction = 0;
154
- break;
148
+ } else {
149
+
150
+ //find position index
151
+ for (i = 1; i < numValues; i++) {
152
+ //NOTE: no complex search is used, since for small data sizes linear scan is typically faster
153
+ const p = positions[i];
155
154
 
156
- } else if (p > position) {
157
- // next position if over the seek position
158
- highIndex = i;
159
- if (i === 0) {
160
- lowIndex = i;
161
- fraction = 0;
162
- } else {
155
+ if (p >= position) {
156
+ // next position if over the seek position
157
+ highIndex = i;
163
158
  lowIndex = i - 1;
164
- const prevPosition = positions[lowIndex];
165
- fraction = inverseLerp(prevPosition, p, position);
166
- }
167
159
 
168
- break;
160
+ fraction = inverseLerp(positions[lowIndex], p, position);
161
+
162
+ break;
163
+ }
169
164
  }
170
165
  }
171
166
 
@@ -177,7 +172,8 @@ export class ParameterLookupTable {
177
172
  const lowValue = data[low_offset + i];
178
173
  const highValue = data[high_offset + i];
179
174
 
180
- const value = mix(lowValue, highValue, fraction);
175
+ // inlined for speed: mix(low, high, fraction)
176
+ const value = lowValue * (1 - fraction) + highValue * fraction;
181
177
 
182
178
  result[i] = value;
183
179
  }
@@ -117,7 +117,7 @@ export class ShaderManager {
117
117
  generateMipmaps: true,
118
118
  minFilter: LinearMipMapLinearFilter,
119
119
  magFilter: LinearFilter,
120
- anisotropy: 0
120
+ anisotropy: 0 // sprites are always facing the screen, anisotropic filtering would be pointless
121
121
  });
122
122
 
123
123
  this.spriteTexture.name = 'Sprite sheet';
@@ -609,8 +609,8 @@ async function main(engine) {
609
609
 
610
610
  engine.graphics.renderer.setClearColor('rgba(99,99,99,1)');
611
611
 
612
- // await sample_scene_nam(engine);
613
- await sample_scene_0(engine);
612
+ await sample_scene_nam(engine);
613
+ // await sample_scene_0(engine);
614
614
  }
615
615
 
616
616
  /**