@woosh/meep-engine 2.33.34 → 2.33.38

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 (67) hide show
  1. package/core/collection/HashMap.js +19 -12
  2. package/core/collection/table/RowFirstTable.js +13 -8
  3. package/core/collection/table/RowFirstTableSpec.js +6 -0
  4. package/core/color/Color.js +5 -9
  5. package/core/color/ColorUtils.js +4 -150
  6. package/core/color/YCbCr_to_rgb_uint24.js +20 -0
  7. package/core/color/hsv2rgb.js +54 -0
  8. package/core/color/int2rgb.js +12 -0
  9. package/core/color/parseHex.js +18 -0
  10. package/core/color/rgb2hex.js +16 -0
  11. package/core/color/rgb2hsv.js +47 -0
  12. package/core/color/rgb2uint24.js +17 -0
  13. package/core/color/rgb_to_YCbCr_uint24.js +18 -0
  14. package/core/geom/3d/aabb/compute_aabb_from_points.js +28 -0
  15. package/core/geom/3d/plane/orient3d_fast.js +51 -0
  16. package/core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js +5 -0
  17. package/core/geom/3d/tetrahedra/GetDepthForTetrahedronProbe.glsl +43 -0
  18. package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +177 -0
  19. package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.spec.js +66 -0
  20. package/core/geom/3d/tetrahedra/compute_circumsphere.js +271 -0
  21. package/core/geom/3d/tetrahedra/compute_delaunay_tetrahedral_mesh.js +50 -0
  22. package/core/geom/3d/tetrahedra/compute_delaunay_tetrahedral_mesh.spec.js +14 -0
  23. package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +77 -0
  24. package/core/geom/3d/tetrahedra/tetrahedra_collection.js +279 -0
  25. package/core/geom/3d/tetrahedra/tetrahedron_contains_point.js +25 -0
  26. package/core/geom/Quaternion.js +4 -0
  27. package/core/math/hash/murmur3_32.js +39 -0
  28. package/core/process/undo/ActionProcessor.d.ts +2 -0
  29. package/core/process/undo/ActionProcessor.js +15 -4
  30. package/editor/tools/FoliagePaintTool.js +1 -1
  31. package/editor/tools/GridPaintTool.js +1 -1
  32. package/engine/ecs/foliage/InstancedFoliage.js +45 -0
  33. package/engine/ecs/foliage/ecs/InstancedMeshLayer.js +4 -0
  34. package/engine/ecs/storage/BinaryBufferSerializer.js +48 -38
  35. package/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.js +1 -1
  36. package/engine/ecs/terrain/ecs/splat/SplatMapOptimizerDebugger.js +1 -1
  37. package/engine/ecs/terrain/tiles/TerrainTile.js +1 -1
  38. package/engine/graphics/GraphicsEngine.js +7 -0
  39. package/engine/graphics/ecs/mesh/Mesh.js +2 -2
  40. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +13 -0
  41. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +339 -314
  42. package/engine/graphics/micron/build/PatchRepresentation.js +1 -1
  43. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -1
  44. package/engine/graphics/micron/build/fill_patch_geometry_data.js +1 -1
  45. package/engine/graphics/micron/format/serialization/deserialize_patch.js +1 -1
  46. package/engine/graphics/micron/format/serialization/serialize_patch.js +1 -1
  47. package/engine/graphics/micron/prototypeVirtualGeometry.js +4 -1
  48. package/engine/graphics/micron/render/instanced/PatchDataTextures.js +3 -3
  49. package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -1
  50. package/engine/graphics/micron/render/instanced/shader/shader_rewrite_standard.js +1 -1
  51. package/engine/graphics/micron/render/makeThreeMeshFromVirtualGeometry.js +1 -1
  52. package/engine/graphics/micron/render/v1/MaterialContext.js +0 -24
  53. package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +2 -2
  54. package/engine/graphics/micron/render/v1/ThreeVirtualGeometryAdapter.js +1 -1
  55. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +7 -3
  56. package/engine/graphics/particles/node-based/rendering/billboard/ParticleBillboardShader.js +1 -1
  57. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +100 -55
  58. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +6 -1
  59. package/engine/graphics/particles/particular/engine/utils/volume/ParticleVolume.js +1 -0
  60. package/engine/graphics/render/forward_plus/cluster/compute_light_data_hash_0.js +1 -1
  61. package/engine/graphics/render/forward_plus/materials/fp_build_fragment_shader.js +17 -4
  62. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +1 -1
  63. package/engine/graphics/render/visibility/VisibilityComputer.js +8 -7
  64. package/engine/graphics/shaders/TerrainShader.js +5 -5
  65. package/engine/graphics/shadows/testShadowMapRendering.js +192 -0
  66. package/package.json +3 -1
  67. package/view/elements/ColorPickerView.js +2 -1
@@ -0,0 +1,279 @@
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
+
6
+ /**
7
+ * @readonly
8
+ * @type {number}
9
+ */
10
+ const LAYOUT_TETRA_BYTE_SIZE = 9 * 4;
11
+ const INVALID_NEIGHBOUR = 0xFFFFFFFF;
12
+
13
+ class Cavity {
14
+ constructor() {
15
+ this.indices = [];
16
+ this.__size = 0;
17
+ }
18
+
19
+ /**
20
+ *
21
+ * @param {number} i
22
+ */
23
+ push(i) {
24
+ this.indices[this.__size++] = i;
25
+ }
26
+
27
+ /**
28
+ *
29
+ * @param {number} i
30
+ * @returns {boolean}
31
+ */
32
+ includes(i) {
33
+ const n = this.__size;
34
+ for (let j = 0; j < n; j++) {
35
+ if (this.indices[j] === i) {
36
+ return true;
37
+ }
38
+ }
39
+
40
+ return false;
41
+ }
42
+
43
+ reset() {
44
+ this.__size = 0;
45
+ }
46
+ }
47
+
48
+ const SCRATCH_CAVITY = new Cavity();
49
+
50
+ /**
51
+ *
52
+ * Layout:
53
+ * vertex_id_a :: uint
54
+ * vertex_id_b :: uint
55
+ * vertex_id_c :: uint
56
+ * vertex_id_d :: uint
57
+ * neighbour_a :: uint - neighbour tetrahedron, opposite to vertex A
58
+ * neighbour_b :: uint - neighbour tetrahedron, opposite to vertex B
59
+ * neighbour_c :: uint - neighbour tetrahedron, opposite to vertex C
60
+ * neighbour_d :: uint - neighbour tetrahedron, opposite to vertex D
61
+ * sub_determinant :: float - ?
62
+ * Layout is similar to [1], but is interleaved for better cache locality
63
+ */
64
+ export class TetrahedraCollection {
65
+ constructor(initial_size) {
66
+ this.__buffer = new ArrayBuffer(initial_size * 4 * 9);
67
+
68
+ this.__view = new DataView(this.__buffer);
69
+
70
+ this.__capacity = initial_size;
71
+ this.__length = 0;
72
+
73
+
74
+ /**
75
+ * Marks which indices are in use
76
+ * @type {BitSet}
77
+ * @private
78
+ */
79
+ this.__occupancy = new BitSet();
80
+ }
81
+
82
+ /**
83
+ *
84
+ * @param {number} tetra_index
85
+ * @param {number} neighbour_index
86
+ * @returns {number}
87
+ */
88
+ getNeighbour(tetra_index, neighbour_index) {
89
+ const tetra_address = LAYOUT_TETRA_BYTE_SIZE * tetra_index;
90
+ return this.__view.getUint32(tetra_address + (4 + neighbour_index) * 4);
91
+ }
92
+
93
+ /**
94
+ *
95
+ * @param {number[]|Float32Array} points
96
+ * @param {number} a
97
+ * @param {number} b
98
+ * @param {number} c
99
+ * @param {number} d
100
+ */
101
+ append(points, a, b, c, d) {
102
+ const tetra_index = this.__length;
103
+ const address = tetra_index * LAYOUT_TETRA_BYTE_SIZE;
104
+
105
+ // TODO check if there's enough room
106
+
107
+ const view = this.__view;
108
+
109
+ view.setUint32(address, a);
110
+ view.setUint32(address + 4, b);
111
+ view.setUint32(address + 8, c);
112
+ view.setUint32(address + 12, d);
113
+
114
+ // set neighbours
115
+ view.setUint32(address + 16, INVALID_NEIGHBOUR);
116
+ view.setUint32(address + 20, INVALID_NEIGHBOUR);
117
+ view.setUint32(address + 24, INVALID_NEIGHBOUR);
118
+ view.setUint32(address + 28, INVALID_NEIGHBOUR);
119
+
120
+ this.__occupancy.set(tetra_index, true);
121
+
122
+ this.__length++;
123
+ }
124
+
125
+ /**
126
+ * Remove tetrahedron
127
+ * @param {number} tera_index
128
+ */
129
+ remove(tera_index) {
130
+ this.__occupancy.clear(tera_index);
131
+ }
132
+
133
+ /**
134
+ * Remove tetrahedrons who's points touch the "super-tetrahedron's" points that was inserted originally
135
+ * These points are identified by an offset + count parameters
136
+ * @param {number[]|Float32Array} points
137
+ * @param {number} range_start
138
+ * @param {number} range_end
139
+ */
140
+ removeTetrasConnectedToPoints(points, range_start, range_end) {
141
+ const data_view = this.__view;
142
+
143
+ const n = this.__length;
144
+
145
+ let i = 0;
146
+ let j = 0;
147
+
148
+ for (; i < n; i++) {
149
+
150
+ const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
151
+
152
+ for (j = 0; j < 4; j++) {
153
+ const point_index = data_view.getUint32(tet_address + 4 * i);
154
+
155
+ if (point_index >= range_start && point_index <= range_end) {
156
+ // point index is in range, tetra should be removed
157
+ this.remove(i);
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ /**
164
+ *
165
+ * @param {number[]} points
166
+ * @param {number} index
167
+ * @returns {number} index of tetra or -1 if no containing tetra found
168
+ */
169
+ findTetraContainingPoint(points, index) {
170
+ const data_view = this.__view;
171
+
172
+ // TODO improve this
173
+ const n = this.__length;
174
+ for (let i = 0; i < n; i++) {
175
+
176
+ const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
177
+
178
+ const a = data_view.getUint32(tet_address);
179
+ const b = data_view.getUint32(tet_address + 4);
180
+ const c = data_view.getUint32(tet_address + 8);
181
+ const d = data_view.getUint32(tet_address + 12);
182
+
183
+ if (tetrahedron_contains_point(points, a, b, c, d, index)) {
184
+ return i;
185
+ }
186
+ }
187
+
188
+ return -1;
189
+ }
190
+
191
+ /**
192
+ *
193
+ * @param {Cavity} cavity
194
+ * @param {number[]|Float32Array} points
195
+ * @param {number} index
196
+ */
197
+ computeCavity(cavity, points, index) {
198
+
199
+ // 1.identify tetrahedron that contains this point
200
+ const containing_tetra = this.findTetraContainingPoint(points, index);
201
+
202
+ assert.isNonNegativeInteger(containing_tetra, 'containing_tetra');
203
+
204
+ cavity.reset();
205
+
206
+ /**
207
+ *
208
+ * @type {number[]}
209
+ */
210
+ const open_set = [
211
+ containing_tetra
212
+ ];
213
+
214
+ /**
215
+ *
216
+ * @type {number[]}
217
+ */
218
+ const closed_set = [];
219
+
220
+ const data_view = this.__view;
221
+
222
+ // 2. find the Delaunay "cavity", a set of tetrahedrons who's circumsphere overlarlaps the point
223
+ // perform breadth-first expansion on the containing tetra to identify the cavity
224
+ while (open_set.length > 0) {
225
+ const tetra = open_set.pop();
226
+ cavity.push(tetra);
227
+ closed_set.push(tetra);
228
+
229
+ // get neighbours
230
+ for (let i = 0; i < 4; i++) {
231
+ const neighbour = this.getNeighbour(tetra, i);
232
+
233
+ if (
234
+ (neighbour === INVALID_NEIGHBOUR) // no neighbour
235
+ || closed_set.includes(neighbour) // already visited
236
+ || open_set.includes(neighbour) // already in open set
237
+ ) {
238
+
239
+ continue;
240
+ }
241
+
242
+ const neighbour_address = neighbour * LAYOUT_TETRA_BYTE_SIZE;
243
+
244
+ const a = data_view.getUint32(neighbour_address);
245
+ const b = data_view.getUint32(neighbour_address + 4);
246
+ const c = data_view.getUint32(neighbour_address + 8);
247
+ const d = data_view.getUint32(neighbour_address + 12);
248
+
249
+ // check neighbour
250
+ const is_in_sphere = point_in_tetrahedron_circumsphere(points, a, b, c, d, index);
251
+
252
+ if (is_in_sphere) {
253
+ open_set.push(neighbour);
254
+ } else {
255
+ // move directly to closed set
256
+ closed_set.push(neighbour);
257
+ }
258
+
259
+
260
+ }
261
+ }
262
+ }
263
+
264
+ /**
265
+ *
266
+ * @param {number[]|Float32Array} points
267
+ * @param {number} index
268
+ */
269
+ insertPoint(points, index) {
270
+ // Compute the cavity, that is the set of tetrahedra that need to be removed and rebuilt
271
+ this.computeCavity(SCRATCH_CAVITY, points, index);
272
+
273
+ // identify cavity "edge" - the set of tetras that are neighbours of the tetras that form the cavity
274
+
275
+ // 3. remove the cavity tetrahedrons
276
+
277
+ // 4. fill the cavity by creating new tetrahedrons connecting the point to the faces of cavity boundary
278
+ }
279
+ }
@@ -0,0 +1,25 @@
1
+ import { orient3d_fast } from "../plane/orient3d_fast.js";
2
+
3
+ /**
4
+ * Containment test, whether tetrahedron defined by A,B,C,D contains point E or not
5
+ * Implemented using planar tests on each of side of the tetrahedron
6
+ *
7
+ * NOTE: similar to https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/contrib/hxt/tetMesh/src/HXTSPR.c
8
+ * We skip identity checks and bounding box checks. Identity is a waste of time when building tetrahedral mesh,
9
+ * since each inserted point will be new to the mesh, box checks are not relevant as we don't track those
10
+ *
11
+ * @param {number[]} points
12
+ * @param {number} a
13
+ * @param {number} b
14
+ * @param {number} c
15
+ * @param {number} d
16
+ * @param {number} e
17
+ * @returns {boolean}
18
+ */
19
+ export function tetrahedron_contains_point(points, a, b, c, d, e) {
20
+ return !(orient3d_fast(points, b, d, c, e) > 0
21
+ || orient3d_fast(points, c, d, a, e) > 0
22
+ || orient3d_fast(points, d, b, a, e) > 0
23
+ || orient3d_fast(points, a, b, c, e) > 0
24
+ );
25
+ }
@@ -1298,6 +1298,10 @@ class Quaternion {
1298
1298
  this.set(x, y, z, w);
1299
1299
  }
1300
1300
 
1301
+ /**
1302
+ * Based on GDC talk from Bungie on destiny, compressing quaternions for animation
1303
+ * @param value
1304
+ */
1301
1305
  decodeFromUint32(value) {
1302
1306
  //read components
1303
1307
  const max = value & 0x3;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * NOTE: based on https://github.com/garycourt/murmurhash-js/blob/master/murmurhash3_gc.js
3
+ * @param {Uint32Array} key
4
+ * @param {number} seed
5
+ * @returns {number}
6
+ */
7
+ export function murmur3_32(key, seed) {
8
+ let h1 = seed;
9
+ let k1;
10
+ let i = 0;
11
+
12
+ const bytes = key.length;
13
+
14
+ while (i < bytes) {
15
+ k1 = key[i];
16
+ ++i;
17
+
18
+ k1 = ((((k1 & 0xffff) * 0xcc9e2d51) + ((((k1 >>> 16) * 0xcc9e2d51) & 0xffff) << 16)));
19
+ k1 = (k1 << 15) | (k1 >>> 17);
20
+ k1 = ((((k1 & 0xffff) * 0x1b873593) + ((((k1 >>> 16) * 0x1b873593) & 0xffff) << 16)));
21
+
22
+ h1 ^= k1;
23
+ h1 = (h1 << 13) | (h1 >>> 19);
24
+ h1 = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16)));
25
+ h1 = (((h1 & 0xffff) + 0x6b64) + ((((h1 >>> 16) + 0xe654) & 0xffff) << 16));
26
+ }
27
+
28
+ // mix in array length
29
+ h1 ^= bytes;
30
+
31
+ h1 ^= h1 >>> 16;
32
+ h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16));
33
+ h1 ^= h1 >>> 13;
34
+ h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)));
35
+ h1 ^= h1 >>> 16;
36
+
37
+ // cast to uint32
38
+ return h1 >>> 0;
39
+ }
@@ -22,4 +22,6 @@ export class ActionProcessor<CTX, MD> {
22
22
  doMany(actions: Action<CTX>[]): void
23
23
 
24
24
  do(action: Action<CTX>): this
25
+
26
+ clear(): void
25
27
  }
@@ -96,16 +96,24 @@ export class ActionProcessor {
96
96
  }
97
97
 
98
98
  /**
99
- * Drop records beyond a given limit. records are dropped in batches between marks.
99
+ * Remove all of the history
100
+ */
101
+ clear() {
102
+ // drop all of the history
103
+ this.dropHistory(Infinity);
104
+ }
105
+
106
+ /**
107
+ * Drop number of records from the history
100
108
  *
101
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
102
110
  * NOTE this method is used internally by {@link #mark} method
103
111
  *
104
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.
105
- * @param {number} limit maximum number of records to keep
113
+ * @param {number} drop_count maximum number of records to drop
106
114
  */
107
- dropHistory(limit) {
108
- const recordsToDrop = Math.min(limit, this.history.length);
115
+ dropHistory(drop_count) {
116
+ const recordsToDrop = Math.min(drop_count, this.history.length);
109
117
  if (recordsToDrop <= 0) {
110
118
  return;
111
119
  }
@@ -136,6 +144,9 @@ export class ActionProcessor {
136
144
 
137
145
  // dispatch signal
138
146
  dropped_marks.forEach(this.onMarkRemoved.send1, this.onMarkRemoved);
147
+
148
+ // update history
149
+
139
150
  }
140
151
 
141
152
  /**
@@ -2,11 +2,11 @@ import Tool from "./engine/Tool.js";
2
2
  import Vector1 from "../../core/geom/Vector1.js";
3
3
  import { obtainTerrain } from "../../../model/game/scenes/SceneUtils.js";
4
4
  import ObservedValue from "../../core/model/ObservedValue.js";
5
- import { parseHex } from "../../core/color/ColorUtils.js";
6
5
  import Vector4 from "../../core/geom/Vector4.js";
7
6
  import loadSampler2D from "../../engine/graphics/texture/sampler/loadSampler2D.js";
8
7
  import convertSampler2D2Canvas from "../../engine/graphics/texture/sampler/Sampler2D2Canvas.js";
9
8
  import { InstancedMeshComponent } from "../../engine/ecs/foliage/ecs/InstancedMeshComponent.js";
9
+ import { parseHex } from "../../core/color/parseHex.js";
10
10
 
11
11
  class FoliagePaintTool extends Tool {
12
12
  constructor() {
@@ -3,7 +3,6 @@ import GridPosition from "../../engine/grid/components/GridPosition.js";
3
3
  import GridObstacle from "../../engine/grid/components/GridObstacle.js";
4
4
  import { pick } from "../../../model/game/util/ScreenGridPicker.js";
5
5
  import Vector4 from "../../core/geom/Vector4.js";
6
- import { parseHex } from "../../core/color/ColorUtils.js";
7
6
  import ObservedValue from "../../core/model/ObservedValue.js";
8
7
  import Vector1 from "../../core/geom/Vector1.js";
9
8
  import WriteGridValueAction from "../actions/concrete/WriteGridValueAction.js";
@@ -12,6 +11,7 @@ import PaintTerrainOverlayAction from "../actions/concrete/PaintTerrainOverlayAc
12
11
  import { decodeMouseEventButtons, PointerDevice } from "../../engine/input/devices/PointerDevice.js";
13
12
  import Vector2 from "../../core/geom/Vector2.js";
14
13
  import TopDownCameraControllerSystem from "../../engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js";
14
+ import { parseHex } from "../../core/color/parseHex.js";
15
15
 
16
16
  class GridPaintTool extends Tool {
17
17
  constructor() {
@@ -61,12 +61,29 @@ export class InstancedFoliage {
61
61
  */
62
62
  this.instances = new InstancedMeshGroup();
63
63
 
64
+ /**
65
+ *
66
+ * @type {THREE.BufferGeometry|null}
67
+ */
64
68
  this.geometry = null;
69
+
70
+ /**
71
+ *
72
+ * @type {Vector4|Vector4}
73
+ */
65
74
  this.instanceBoundingSphere = new Vector4(0, 0, 0, 0);
66
75
 
67
76
 
77
+ /**
78
+ *
79
+ * @type {ThreeFrustumsIntersectionBVHVisitor}
80
+ */
68
81
  this.bvhVisibilityVisitor = new ThreeFrustumsIntersectionBVHVisitor();
69
82
 
83
+ /**
84
+ *
85
+ * @type {FoliageVisibilitySetBuilder}
86
+ */
70
87
  this.visibilitySetBuilder = new FoliageVisibilitySetBuilder();
71
88
  this.bvhVisibilityVisitor.collector = this.visibilitySetBuilder;
72
89
 
@@ -84,6 +101,10 @@ export class InstancedFoliage {
84
101
  this.__garbagePointer = 0;
85
102
  }
86
103
 
104
+ /**
105
+ *
106
+ * @returns {number}
107
+ */
87
108
  hash() {
88
109
  return this.data.hash();
89
110
  }
@@ -95,6 +116,25 @@ export class InstancedFoliage {
95
116
 
96
117
  }
97
118
 
119
+ /**
120
+ *
121
+ * @param {SurfacePoint3} contact
122
+ * @param {number} origin_x
123
+ * @param {number} origin_y
124
+ * @param {number} origin_z
125
+ * @param {number} direction_x
126
+ * @param {number} direction_y
127
+ * @param {number} direction_z
128
+ * @returns {number} index of the contact instance, or -1 if no hit found
129
+ */
130
+ raypick(
131
+ contact,
132
+ origin_x, origin_y, origin_z,
133
+ direction_x, direction_y, direction_z
134
+ ) {
135
+ throw new Error('Not implemented');
136
+ }
137
+
98
138
  dispose() {
99
139
  this.instances.dispose();
100
140
  }
@@ -212,6 +252,11 @@ export class InstancedFoliage {
212
252
  this.instanceBoundingSphere = computeGeometryBoundingSphereMiniball(this.geometry);
213
253
  }
214
254
 
255
+ /**
256
+ *
257
+ * @param {BufferGeometry} geometry
258
+ * @param {Material} material
259
+ */
215
260
  setInstance(geometry, material) {
216
261
  if (material === undefined) {
217
262
  throw new Error(`Material is undefined`);
@@ -40,6 +40,10 @@ export class InstancedMeshLayer {
40
40
  this.data.dispose();
41
41
  }
42
42
 
43
+ /**
44
+ *
45
+ * @returns {number}
46
+ */
43
47
  hash() {
44
48
 
45
49
  return computeHashIntegerArray(
@@ -5,6 +5,48 @@ import { COMPONENT_SERIALIZATION_TRANSIENT_FIELD } from "./COMPONENT_SERIALIZATI
5
5
  import { currentTimeInSeconds } from "../../Clock.js";
6
6
  import { BinaryObjectSerializationAdapter } from "./binary/object/BinaryObjectSerializationAdapter.js";
7
7
 
8
+ /**
9
+ * @template T
10
+ * @param {Class<T>|constructor|function|{serializable?:boolean}} componentClass
11
+ * @returns {boolean}
12
+ */
13
+ function isComponentClassSerializable(componentClass) {
14
+ return componentClass.serializable !== false;
15
+ }
16
+
17
+ /**
18
+ * Whether or not an entity should be serialized at all
19
+ * @param {number} entity
20
+ * @param {EntityComponentDataset} dataset
21
+ * @param {number} smComponentIndex
22
+ * @param {Object} componentInstance
23
+ * @returns {boolean}
24
+ */
25
+ function isEntityTransient(entity, dataset, smComponentIndex, componentInstance) {
26
+ if (smComponentIndex === -1) {
27
+ return false;
28
+ }
29
+
30
+ //check component instance flag
31
+ if (componentInstance[COMPONENT_SERIALIZATION_TRANSIENT_FIELD] === true) {
32
+ return true;
33
+ }
34
+
35
+
36
+ /**
37
+ *
38
+ * @type {SerializationMetadata}
39
+ */
40
+ const serializationMetadata = dataset.getComponentByIndex(entity, smComponentIndex);
41
+
42
+ if (serializationMetadata === undefined) {
43
+ return false;
44
+ }
45
+
46
+ const isTransient = serializationMetadata.getFlag(SerializationFlags.Transient);
47
+
48
+ return isTransient;
49
+ }
8
50
 
9
51
  class BinaryBufferSerialization {
10
52
  constructor() {
@@ -27,9 +69,8 @@ class BinaryBufferSerialization {
27
69
 
28
70
  const smComponentIndex = dataset.computeComponentTypeIndex(SerializationMetadata);
29
71
 
30
- const serializableComponentTypes = dataset.getComponentTypeMap().filter(function (componentClass) {
31
- return componentClass.serializable !== false;
32
- });
72
+ // get a list of serializable component classes
73
+ const serializableComponentTypes = dataset.getComponentTypeMap().filter(isComponentClassSerializable);
33
74
 
34
75
  const numSerializableTypes = serializableComponentTypes.length;
35
76
 
@@ -59,6 +100,9 @@ class BinaryBufferSerialization {
59
100
 
60
101
  const className = componentType.typeName;
61
102
 
103
+ if (className === undefined) {
104
+ throw new Error(`Component type has no .typeName property`);
105
+ }
62
106
 
63
107
  collectionSerializer.setClass(className);
64
108
  collectionSerializer.initialize({
@@ -83,7 +127,7 @@ class BinaryBufferSerialization {
83
127
  return;
84
128
  }
85
129
 
86
- assert.ok(entity >= lastEntity, `entity(=${entity}) < lastEntity(=${lastEntity})`)
130
+ assert.ok(entity >= lastEntity, `entity[=${entity}] < lastEntity[=${lastEntity}]`);
87
131
 
88
132
  //write only the entity step
89
133
  const step = entity - lastEntity;
@@ -127,38 +171,4 @@ class BinaryBufferSerialization {
127
171
  }
128
172
  }
129
173
 
130
- /**
131
- * Whether or not an entity should be serialized at all
132
- * @param {number} entity
133
- * @param {EntityComponentDataset} dataset
134
- * @param {number} smComponentIndex
135
- * @param {Object} componentInstance
136
- * @returns {boolean}
137
- */
138
- function isEntityTransient(entity, dataset, smComponentIndex, componentInstance) {
139
- if (smComponentIndex === -1) {
140
- return false;
141
- }
142
-
143
- //check component instance flag
144
- if (componentInstance[COMPONENT_SERIALIZATION_TRANSIENT_FIELD] === true) {
145
- return true;
146
- }
147
-
148
-
149
- /**
150
- *
151
- * @type {SerializationMetadata}
152
- */
153
- const serializationMetadata = dataset.getComponentByIndex(entity, smComponentIndex);
154
-
155
- if (serializationMetadata === undefined) {
156
- return false;
157
- }
158
-
159
- const isTransient = serializationMetadata.getFlag(SerializationFlags.Transient);
160
-
161
- return isTransient;
162
- }
163
-
164
174
  export default BinaryBufferSerialization;
@@ -88,7 +88,7 @@ export class BinaryCollectionSerializer {
88
88
  * @param {string} className
89
89
  */
90
90
  setClass(className) {
91
- assert.typeOf(className, 'string', 'className');
91
+ assert.isString(className, 'className');
92
92
 
93
93
  this.className = className;
94
94
  }
@@ -10,8 +10,8 @@ import SVG from "../../../../../view/SVG.js";
10
10
  import Vector2 from "../../../../../core/geom/Vector2.js";
11
11
  import Vector4 from "../../../../../core/geom/Vector4.js";
12
12
  import { MersenneTwister } from "../../../../../core/math/random/MersenneTwister.js";
13
- import { hsv2rgb } from "../../../../../core/color/ColorUtils.js";
14
13
  import { arrayPickBestElement } from "../../../../../core/collection/array/arrayPickBestElement.js";
14
+ import { hsv2rgb } from "../../../../../core/color/hsv2rgb.js";
15
15
 
16
16
  function removeAllChildren(node) {
17
17
  const children = node.children;
@@ -581,7 +581,7 @@ class TerrainTile {
581
581
  mesh.geometry = g;
582
582
 
583
583
  mesh.receiveShadow = true;
584
- mesh.castShadow = false;
584
+ mesh.castShadow = true;
585
585
 
586
586
  // console.timeEnd('total');
587
587
  // console.groupEnd();