@woosh/meep-engine 2.35.1 → 2.35.2

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.
@@ -19,18 +19,18 @@ export function aabb3_intersects_frustum_degree(
19
19
  frustum
20
20
  ) {
21
21
 
22
- let i = 0;
23
22
  let result = 2;
23
+ let i = 0;
24
24
 
25
25
  for (; i < 24; i += 4) {
26
26
 
27
- const p_nx = frustum[i];
28
- const p_ny = frustum[i + 1];
29
- const p_nz = frustum[i + 2];
30
- const p_c = frustum[i + 3];
27
+ const p_x = frustum[i];
28
+ const p_y = frustum[i + 1];
29
+ const p_z = frustum[i + 2];
30
+ const p_w = frustum[i + 3];
31
31
 
32
32
  const plane_side = computeAABB3PlaneSide(
33
- p_nx, p_ny, p_nz, p_c,
33
+ p_x, p_y, p_z, p_w,
34
34
  x0, y0, z0, x1, y1, z1
35
35
  );
36
36
 
@@ -13,13 +13,12 @@ let stackPointer = 0;
13
13
  */
14
14
  export function queryBinaryNode_CollectData(destination, destinationOffset, root) {
15
15
  let n;
16
+ let i = 0;
16
17
 
17
18
  const stackOffset = stackPointer;
18
19
 
19
20
  stack[stackPointer++] = root;
20
21
 
21
- let i = 0;
22
-
23
22
  while (stackPointer-- > stackOffset) {
24
23
 
25
24
  n = stack[stackPointer];
@@ -1,3 +1,6 @@
1
+ import { aabb3_intersects_frustum_degree } from "../aabb3/aabb3_intersects_frustum_degree.js";
2
+ import { queryBinaryNode_CollectData } from "./queryBinaryNode_CollectData.js";
3
+
1
4
  /**
2
5
  *
3
6
  * @type {(BinaryNode|LeafNode)[]}
@@ -30,32 +33,42 @@ export function queryBinaryNode_FrustumIntersections_Data(destination, destinati
30
33
 
31
34
  n = stack[stackPointer];
32
35
 
33
- const node_intersects_frustum = n.intersectFrustum_array(frustum);
36
+ const intersection_degree = aabb3_intersects_frustum_degree(
37
+ n.x0, n.y0, n.z0,
38
+ n.x1, n.y1, n.z1,
39
+ frustum
40
+ );
34
41
 
35
- if (!node_intersects_frustum) {
36
- continue;
37
- }
42
+ if (intersection_degree === 2) {
43
+ // fully inside
38
44
 
39
- if (n.isBinaryNode === true) {
45
+ offset += queryBinaryNode_CollectData(destination, offset, n);
40
46
 
41
- const right = n.right;
47
+ } else if (intersection_degree === 1) {
48
+ // partly inside
42
49
 
43
- if (right !== null) {
44
- stack[stackPointer++] = right;
45
- }
50
+ if (n.isBinaryNode === true) {
46
51
 
47
- const left = n.left;
52
+ const right = n.right;
48
53
 
49
- if (left !== null) {
50
- stack[stackPointer++] = left;
51
- }
54
+ if (right !== null) {
55
+ stack[stackPointer++] = right;
56
+ }
52
57
 
53
- } else {
54
- // leaf node
58
+ const left = n.left;
55
59
 
56
- destination[offset] = n.object;
60
+ if (left !== null) {
61
+ stack[stackPointer++] = left;
62
+ }
63
+
64
+ } else {
65
+ // leaf node
66
+
67
+ destination[offset] = n.object;
68
+
69
+ offset++;
70
+ }
57
71
 
58
- offset++;
59
72
  }
60
73
 
61
74
  }
@@ -176,7 +176,7 @@ export class HashMap {
176
176
  const mixed_hash = (hash >>> 16) ^ hash;
177
177
 
178
178
  // ensure index is non-negative
179
- const index = (2147483647) & mixed_hash;
179
+ const index = mixed_hash >>> 0;
180
180
 
181
181
  return index % this.__bucket_count;
182
182
  }
@@ -3,6 +3,7 @@ import { HighlightRenderElementSource } from "../plugin/HighlightRenderElementSo
3
3
  import Highlight from "../Highlight.js";
4
4
  import { OutlineRenderPlugin } from "../plugin/OutlineRenderPlugin.js";
5
5
  import { ShadedGeometry } from "../../mesh-v2/ShadedGeometry.js";
6
+ import { build_three_object } from "../../mesh-v2/build_three_object.js";
6
7
 
7
8
  class Supplier extends HighlightRenderElementSource {
8
9
  /**
@@ -31,6 +32,13 @@ class Supplier extends HighlightRenderElementSource {
31
32
  * @private
32
33
  */
33
34
  this.__group = null;
35
+
36
+ /**
37
+ *
38
+ * @type {WeakMap<ShadedGeometry, THREE.Object3D>}
39
+ * @private
40
+ */
41
+ this.__object_cache = new WeakMap();
34
42
  }
35
43
 
36
44
  collect(pool, group) {
@@ -77,13 +85,14 @@ class Supplier extends HighlightRenderElementSource {
77
85
  return;
78
86
  }
79
87
 
80
- const object = sg.__cached_object;
88
+ let object = this.__object_cache.get(sg);
81
89
 
82
- if (object === null) {
83
- // no renderable primitive
84
- return;
90
+ if(object === undefined){
91
+ object = build_three_object(sg);
85
92
  }
86
93
 
94
+ object.matrixWorld.elements = sg.transform;
95
+
87
96
  const renderElement = this.__pool.create();
88
97
 
89
98
  renderElement.definitions = elements.asArray();
@@ -1,9 +1,7 @@
1
- import { Line, LineSegments, Mesh } from "three";
2
1
  import { updateNodeByMatrix4AndBBB } from "../mesh/updateNodeByTransformAndBBB.js";
3
2
  import { LeafNode } from "../../../../core/bvh2/LeafNode.js";
4
3
  import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
5
4
  import { DrawMode } from "./DrawMode.js";
6
- import { applyTransformToThreeObject } from "../mesh/applyTransformToThreeObject.js";
7
5
  import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
8
6
 
9
7
  const _aabb3 = new AABB3();
@@ -12,42 +10,6 @@ const DEFAULT_FLAGS = ShadedGeometryFlags.CastShadow
12
10
  | ShadedGeometryFlags.ReceiveShadow
13
11
  ;
14
12
 
15
- /**
16
- *
17
- * @param {ShadedGeometry} sg
18
- * @returns {THREE.Object3D}
19
- */
20
- export function build_three_object(sg) {
21
-
22
- /**
23
- * @type {THREE.Object3D}
24
- */
25
- let object;
26
-
27
- const mode = sg.mode;
28
- const shader = sg.material;
29
- const geo = sg.geometry;
30
-
31
- if (mode === DrawMode.Triangles) {
32
- object = new Mesh(geo, shader);
33
- } else if (mode === DrawMode.Lines) {
34
- object = new Line(geo, shader);
35
- } else if (mode === DrawMode.LineSegments) {
36
- object = new LineSegments(geo, shader);
37
- } else {
38
- throw new Error(`Unsupported draw mode '${mode}'`);
39
- }
40
-
41
- object.matrixAutoUpdate = false;
42
- object.frustumCulled = false;
43
- object.matrixWorldNeedsUpdate = false;
44
-
45
- object.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
46
- object.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
47
-
48
- return object;
49
- }
50
-
51
13
  export class ShadedGeometry {
52
14
  constructor() {
53
15
  /**
@@ -67,13 +29,6 @@ export class ShadedGeometry {
67
29
  */
68
30
  this.mode = DrawMode.Triangles;
69
31
 
70
- /**
71
- *
72
- * @type {THREE.Object3D|null}
73
- * @private
74
- */
75
- this.__cached_object = null;
76
-
77
32
  /**
78
33
  *
79
34
  * @type {LeafNode<ShadedGeometry>}
@@ -88,13 +43,20 @@ export class ShadedGeometry {
88
43
  */
89
44
  this.__entity = -1;
90
45
 
46
+ /**
47
+ *
48
+ * @type {Transform|null}
49
+ * @private
50
+ */
51
+ this.__c_transform = null;
52
+
91
53
  /**
92
54
  * Transform matrix
93
55
  * Transient, assigned in the system
94
56
  * @type {number[]|null}
95
57
  * @private
96
58
  */
97
- this.__transform = null;
59
+ this.__transform = new Float32Array(16);
98
60
 
99
61
  /**
100
62
  * Transient property signifying how to render object
@@ -109,6 +71,14 @@ export class ShadedGeometry {
109
71
  this.flags = DEFAULT_FLAGS;
110
72
  }
111
73
 
74
+ /**
75
+ * @deprecated
76
+ * @private
77
+ */
78
+ get __cached_object(){
79
+ throw new Error('Deprecated');
80
+ }
81
+
112
82
  /**
113
83
  *
114
84
  * @param {number|ShadedGeometryFlags} flag
@@ -182,17 +152,7 @@ export class ShadedGeometry {
182
152
  * @return {null|number[]}
183
153
  */
184
154
  get transform() {
185
- if (this.__transform !== null) {
186
- return this.__transform;
187
- } else if (this.__cached_object !== null) {
188
- return this.__cached_object.matrix.elements;
189
- } else {
190
- return null;
191
- }
192
- }
193
-
194
- __build_object() {
195
- this.__cached_object = build_three_object(this);
155
+ return this.__transform;
196
156
  }
197
157
 
198
158
  get bvh() {
@@ -214,13 +174,6 @@ export class ShadedGeometry {
214
174
  if (geometry.boundingBox === null) {
215
175
  geometry.computeBoundingBox();
216
176
  }
217
-
218
- if (this.__cached_object === null) {
219
- this.__build_object();
220
- } else {
221
- this.__cached_object.material = material;
222
- this.__cached_object.geometry = geometry;
223
- }
224
177
  }
225
178
 
226
179
  /**
@@ -239,11 +192,8 @@ export class ShadedGeometry {
239
192
  }
240
193
 
241
194
  updateTransform() {
242
- const object_3d = this.__cached_object;
243
-
244
- // update matrix
245
- object_3d.updateMatrix();
246
- object_3d.updateMatrixWorld();
195
+ //
196
+ this.__c_transform.toMatrix4(this.__transform);
247
197
 
248
198
  // update bounds
249
199
  const gbb = this.geometry.boundingBox;
@@ -260,56 +210,7 @@ export class ShadedGeometry {
260
210
  max.z
261
211
  );
262
212
 
263
- updateNodeByMatrix4AndBBB(this.__bvh_leaf, _aabb3, object_3d.matrix.elements);
264
- }
265
-
266
- /**
267
- *
268
- * @param {number} x
269
- * @param {number} y
270
- * @param {number} z
271
- */
272
- setPositionByComponents(x, y, z) {
273
-
274
- this.__cached_object.position.set(x, y, z);
275
-
276
- this.updateTransform();
277
- }
278
-
279
- /**
280
- *
281
- * @param {number} x
282
- * @param {number} y
283
- * @param {number} z
284
- * @param {number} w
285
- */
286
- setRotationByComponents(x, y, z, w) {
287
-
288
- this.__cached_object.quaternion.set(x, y, z, w);
289
-
290
- this.updateTransform();
291
- }
292
-
293
- /**
294
- *
295
- * @param {number} x
296
- * @param {number} y
297
- * @param {number} z
298
- */
299
- setScaleByComponents(x, y, z) {
300
- this.__cached_object.scale.set(x, y, z);
301
-
302
- this.updateTransform();
303
- }
304
-
305
- /**
306
- *
307
- * @param {Transform} t
308
- */
309
- applyTransform(t) {
310
- applyTransformToThreeObject(this.__cached_object, t);
311
-
312
- this.updateTransform();
213
+ updateNodeByMatrix4AndBBB(this.__bvh_leaf, _aabb3, this.__transform);
313
214
  }
314
215
  }
315
216
 
@@ -133,11 +133,13 @@ export class ShadedGeometrySystem extends System {
133
133
  * @param {number} entity
134
134
  */
135
135
  link(sg, t, entity) {
136
- t.position.onChanged.add(sg.setPositionByComponents, sg);
137
- t.rotation.onChanged.add(sg.setRotationByComponents, sg);
138
- t.scale.onChanged.add(sg.setScaleByComponents, sg);
136
+ sg.__c_transform = t;
139
137
 
140
- sg.applyTransform(t);
138
+ t.position.onChanged.add(sg.updateTransform, sg);
139
+ t.rotation.onChanged.add(sg.updateTransform, sg);
140
+ t.scale.onChanged.add(sg.updateTransform, sg);
141
+
142
+ sg.updateTransform();
141
143
 
142
144
  const leaf_node = sg.bvh;
143
145
 
@@ -157,9 +159,9 @@ export class ShadedGeometrySystem extends System {
157
159
  * @param {number} entity
158
160
  */
159
161
  unlink(sg, t, entity) {
160
- t.position.onChanged.remove(sg.setPositionByComponents, sg);
161
- t.rotation.onChanged.remove(sg.setRotationByComponents, sg);
162
- t.scale.onChanged.remove(sg.setScaleByComponents, sg);
162
+ t.position.onChanged.remove(sg.updateTransform, sg);
163
+ t.rotation.onChanged.remove(sg.updateTransform, sg);
164
+ t.scale.onChanged.remove(sg.updateTransform, sg);
163
165
 
164
166
  sg.bvh.disconnect();
165
167
  }
@@ -0,0 +1,39 @@
1
+ import { DrawMode } from "./DrawMode.js";
2
+ import { Line, LineSegments, Mesh } from "three";
3
+ import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
4
+
5
+ /**
6
+ *
7
+ * @param {ShadedGeometry} sg
8
+ * @returns {THREE.Object3D}
9
+ */
10
+ export function build_three_object(sg) {
11
+
12
+ /**
13
+ * @type {THREE.Object3D}
14
+ */
15
+ let object;
16
+
17
+ const mode = sg.mode;
18
+ const shader = sg.material;
19
+ const geo = sg.geometry;
20
+
21
+ if (mode === DrawMode.Triangles) {
22
+ object = new Mesh(geo, shader);
23
+ } else if (mode === DrawMode.Lines) {
24
+ object = new Line(geo, shader);
25
+ } else if (mode === DrawMode.LineSegments) {
26
+ object = new LineSegments(geo, shader);
27
+ } else {
28
+ throw new Error(`Unsupported draw mode '${mode}'`);
29
+ }
30
+
31
+ object.matrixAutoUpdate = false;
32
+ object.frustumCulled = false;
33
+ object.matrixWorldNeedsUpdate = false;
34
+
35
+ object.castShadow = sg.getFlag(ShadedGeometryFlags.CastShadow);
36
+ object.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
37
+
38
+ return object;
39
+ }
@@ -1,6 +1,6 @@
1
1
  import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
2
- import { build_three_object } from "../ShadedGeometry.js";
3
2
  import { array_copy } from "../../../../../core/collection/array/copyArray.js";
3
+ import { build_three_object } from "../build_three_object.js";
4
4
 
5
5
  export class GenericRendererAdapter extends AbstractRenderAdapter {
6
6
  constructor() {
@@ -2,11 +2,42 @@ import { AbstractRenderAdapter } from "./AbstractRenderAdapter.js";
2
2
  import { HashMap } from "../../../../../core/collection/HashMap.js";
3
3
  import { InstancedMeshGroup } from "../../../geometry/instancing/InstancedMeshGroup.js";
4
4
  import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
5
+ import { DrawMode } from "../DrawMode.js";
5
6
 
6
7
  const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
7
8
  | ShadedGeometryFlags.ReceiveShadow
8
9
  ;
9
10
 
11
+ /**
12
+ *
13
+ * @param {ShadedGeometry} a
14
+ * @param {ShadedGeometry} b
15
+ * @returns {number}
16
+ */
17
+ function compare(a, b) {
18
+ const d_geometry = a.geometry.id - b.geometry.id;
19
+ if (d_geometry !== 0) {
20
+ return d_geometry;
21
+ }
22
+
23
+ const d_material = a.material.id - b.material.id;
24
+ if (d_material !== 0) {
25
+ return d_material;
26
+ }
27
+
28
+ const d_flags = (a.flags & INSTANCED_EQUALITY_FLAGS) - (b.flags & INSTANCED_EQUALITY_FLAGS);
29
+ if (d_flags !== 0) {
30
+ return d_flags;
31
+ }
32
+
33
+ const d_mode = a.mode - b.mode;
34
+ if (d_mode !== 0) {
35
+ return d_mode;
36
+ }
37
+
38
+ return 0;
39
+ }
40
+
10
41
  export class InstancedRendererAdapter extends AbstractRenderAdapter {
11
42
  constructor() {
12
43
  super();
@@ -18,11 +49,12 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
18
49
  */
19
50
  this.__instanced_meshes = new HashMap({
20
51
  keyHashFunction(sg) {
21
- return sg.geometry.id ^ sg.material.id;
52
+ return sg.geometry.id ^ sg.material.id ^ sg.mode;
22
53
  },
23
54
  keyEqualityFunction(a, b) {
24
55
  return a.material.id === b.material.id
25
56
  && a.geometry.id === b.geometry.id
57
+ && a.mode === b.mode
26
58
  && (a.flags & INSTANCED_EQUALITY_FLAGS) === (b.flags & INSTANCED_EQUALITY_FLAGS)
27
59
  ;
28
60
  }
@@ -45,7 +77,17 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
45
77
  __get_instanced_mesh(sg) {
46
78
  let im = this.__instanced_meshes.get(sg);
47
79
 
48
- if (im === undefined) {
80
+
81
+ if (im !== undefined) {
82
+
83
+ return im;
84
+
85
+ } else {
86
+
87
+ if (sg.mode !== DrawMode.Triangles) {
88
+ throw new Error(`Unsupported draw mode ${sg.mode}`);
89
+ }
90
+
49
91
  im = new InstancedMeshGroup();
50
92
  im.shrinkFactor = 0; // prevent shrinking as we're essentially rebuilding this geometry frame
51
93
 
@@ -56,9 +98,10 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
56
98
  im.mesh.receiveShadow = sg.getFlag(ShadedGeometryFlags.ReceiveShadow);
57
99
 
58
100
  this.__instanced_meshes.set(sg, im);
59
- }
60
101
 
61
- return im;
102
+ return im;
103
+
104
+ }
62
105
  }
63
106
 
64
107
  add(sg) {
@@ -66,7 +109,11 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
66
109
 
67
110
  const index = mesh.count;
68
111
 
69
- mesh.ensureCapacity(index + 1);
112
+ const new_size = index + 1;
113
+
114
+ if (new_size > mesh.capacity) {
115
+ mesh.ensureCapacity(new_size);
116
+ }
70
117
 
71
118
  mesh.setTransformAt(index, sg.transform);
72
119
 
@@ -80,13 +127,14 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
80
127
  }
81
128
 
82
129
  build_end() {
130
+ const objects = this.__objects;
83
131
 
84
132
  for (const activeMesh of this.__active_meshes) {
85
133
  // force underlying geometry to update
86
134
  activeMesh.setCount(activeMesh.getCount());
87
135
  activeMesh.requestAttributeUpdate();
88
136
 
89
- this.__objects[this.__object_count++] = activeMesh.mesh;
137
+ objects[this.__object_count++] = activeMesh.mesh;
90
138
  }
91
139
 
92
140
  }
@@ -16,6 +16,7 @@ import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
16
16
  import Vector3 from "../../../../../core/geom/Vector3.js";
17
17
  import Quaternion from "../../../../../core/geom/Quaternion.js";
18
18
  import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
19
+ import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
19
20
 
20
21
  const eh = new EngineHarness();
21
22
 
@@ -51,23 +52,31 @@ async function main(engine) {
51
52
 
52
53
  window.material = material;
53
54
 
54
- const geometry = new BoxBufferGeometry();
55
-
56
55
  const random = seededRandom(0);
57
56
 
58
- for (let i = 0; i < 100000; i++) {
57
+ const INSTANCE_COUNT = 20000;
58
+
59
+ const geometries = [];
60
+
61
+ for (let i = 0; i < 1000; i++) {
62
+ geometries.push(new BoxBufferGeometry());
63
+ }
59
64
 
65
+ for (let i = 0; i < INSTANCE_COUNT; i++) {
66
+ const geometry = randomFromArray(random, geometries);
60
67
  const sg = ShadedGeometry.from(geometry, material);
61
68
 
69
+ // sg.draw_method = DRAW_METHOD_PLAIN;
62
70
  sg.draw_method = DRAW_METHOD_INSTANCED;
71
+ // sg.draw_method = random() > 0.01 ? DRAW_METHOD_INSTANCED : DRAW_METHOD_PLAIN;
63
72
  sg.clearFlag(ShadedGeometryFlags.CastShadow | ShadedGeometryFlags.ReceiveShadow);
64
73
 
65
74
  new EntityBuilder()
66
75
  .add(Transform.fromJSON({
67
76
  position: {
68
- x: randomFloatBetween(random, -50, 50),
77
+ x: randomFloatBetween(random, 0, 20),
69
78
  y: randomFloatBetween(random, 0, 10),
70
- z: randomFloatBetween(random, -50, 50)
79
+ z: randomFloatBetween(random, 0, 20)
71
80
  },
72
81
  rotation: Quaternion.random(random),
73
82
  scale: 0.05
@@ -11,6 +11,7 @@ import { StaticMaterialCache } from "../../../asset/loaders/material/StaticMater
11
11
  import { composeCompile } from "../../material/composeCompile.js";
12
12
  import { typed_array_copy } from "../../../../core/collection/array/typed/typed_array_copy.js";
13
13
  import { rewriteMaterial } from "./rewriteMaterial.js";
14
+ import { max3 } from "../../../../core/math/max3.js";
14
15
 
15
16
  export class InstancedMeshGroup {
16
17
  /**
@@ -69,6 +70,13 @@ export class InstancedMeshGroup {
69
70
  */
70
71
  this.__attributeTransform = null;
71
72
 
73
+ /**
74
+ * Shortcut to buffer attribute data
75
+ * @type {Float32Array}
76
+ * @private
77
+ */
78
+ this.__attributeTransformArray = null;
79
+
72
80
  /**
73
81
  *
74
82
  * @type {Material}
@@ -167,7 +175,7 @@ export class InstancedMeshGroup {
167
175
  if (currentCapacity < size) {
168
176
  // grow
169
177
 
170
- const newCapacityRaw = Math.max(
178
+ const newCapacityRaw = max3(
171
179
  size,
172
180
  currentCapacity * this.growFactor,
173
181
  currentCapacity + this.growConstant
@@ -193,7 +201,7 @@ export class InstancedMeshGroup {
193
201
  * @param {number[]|ArrayLike<number>|Float32Array} transform 4x4 transform matrix of the instance
194
202
  */
195
203
  setTransformAt(index, transform) {
196
- this.__attributeTransform.array.set(transform, index * 16);
204
+ this.__attributeTransformArray.set(transform, index * 16);
197
205
  }
198
206
 
199
207
  requestAttributeUpdate() {
@@ -357,6 +365,7 @@ export class InstancedMeshGroup {
357
365
  }
358
366
 
359
367
  //rewrite old attributes
368
+ this.__attributeTransformArray = newTransformArray;
360
369
  this.__attributeTransform = new InstancedBufferAttribute(newTransformArray, 16);
361
370
  this.__attributeTransform.setUsage(StreamDrawUsage);
362
371
 
@@ -189,12 +189,13 @@ export class VGThreeRenderer {
189
189
  const ctx = instance_to_ctx.get(instance_id);
190
190
 
191
191
  const target_address = ctx.__patch_count * 3;
192
+ ctx.__patch_count++;
192
193
 
193
- ctx.__patches[target_address] = instance_id;
194
- ctx.__patches[target_address + 1] = geometry_id;
195
- ctx.__patches[target_address + 2] = patch_id;
194
+ const ctx_patches = ctx.__patches;
196
195
 
197
- ctx.__patch_count++;
196
+ ctx_patches[target_address] = instance_id;
197
+ ctx_patches[target_address + 1] = geometry_id;
198
+ ctx_patches[target_address + 2] = patch_id;
198
199
  }
199
200
 
200
201
  // build each context
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "productName": "Meep",
6
6
  "description": "production-ready JavaScript game engine based on Entity Component System Architecture",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.35.1",
8
+ "version": "2.35.2",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",