@woosh/meep-engine 2.39.15 → 2.39.18

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 (29) hide show
  1. package/core/binary/int32_to_binary_string.js +18 -0
  2. package/core/cache/Cache.js +1 -1
  3. package/core/geom/3d/decompose_matrix_4_array.js +3 -1
  4. package/core/geom/3d/ray/ray3_array_apply_matrix4.js +15 -1
  5. package/editor/tools/v2/TransformControls.d.ts +15 -0
  6. package/editor/tools/v2/TransformControls.js +1782 -0
  7. package/editor/tools/v2/prototypeTransformControls.js +80 -0
  8. package/engine/asset/AssetManager.js +82 -23
  9. package/engine/ecs/parent/EntityNode.js +41 -13
  10. package/engine/ecs/terrain/ecs/Terrain.js +20 -21
  11. package/engine/ecs/terrain/ecs/layers/TerrainLayers.js +8 -3
  12. package/engine/ecs/transform/Transform.d.ts +2 -0
  13. package/engine/ecs/transform/Transform.js +6 -0
  14. package/engine/ecs/transform-attachment/TransformAttachment.js +13 -0
  15. package/engine/ecs/transform-attachment/TransformAttachmentSystem.js +138 -16
  16. package/engine/graphics/FrameRunner.js +8 -2
  17. package/engine/graphics/ecs/mesh-v2/DrawMode.js +4 -0
  18. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +77 -0
  19. package/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +10 -0
  20. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -30
  21. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +11 -0
  22. package/engine/graphics/ecs/mesh-v2/render/adapters/InstancedRendererAdapter.js +8 -32
  23. package/engine/graphics/ecs/mesh-v2/render/optimization/RuntimeDrawMethodOptimizer.js +6 -0
  24. package/engine/graphics/geometry/buffered/makeGeometryIndexed.js +23 -0
  25. package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +16 -4
  26. package/engine/graphics/geometry/buffered/query/GeometryVisitor.js +8 -1
  27. package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +14 -5
  28. package/engine/graphics/geometry/bvh/buffered/BinaryBVHFromBufferGeometry.js +56 -0
  29. package/package.json +1 -1
@@ -1,3 +1,5 @@
1
+ let global_count = 0;
2
+
1
3
  /**
2
4
  *
3
5
  */
@@ -33,7 +35,9 @@ export class FrameRunner {
33
35
  return false;
34
36
  }
35
37
 
36
- console.warn("FrameFunner.started");
38
+ console.warn(`FrameFunner.started[${global_count}]`);
39
+
40
+ global_count++;
37
41
 
38
42
  this.running = true;
39
43
 
@@ -66,7 +70,9 @@ export class FrameRunner {
66
70
  return false;
67
71
  }
68
72
 
69
- console.warn("FrameFunner.stopped");
73
+ global_count--;
74
+
75
+ console.warn(`FrameFunner.stopped[${global_count}]`);
70
76
 
71
77
  this.running = false;
72
78
  cancelAnimationFrame(this.animationFrameId);
@@ -1,3 +1,7 @@
1
+ /**
2
+ *
3
+ * @enum {number}
4
+ */
1
5
  export const DrawMode = {
2
6
  Triangles: 0,
3
7
  Lines: 2,
@@ -3,6 +3,9 @@ import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
3
3
  import { DrawMode } from "./DrawMode.js";
4
4
  import { ShadedGeometryFlags } from "./ShadedGeometryFlags.js";
5
5
  import { aabb3_matrix4_project } from "../../../../core/geom/3d/aabb/aabb3_matrix4_project.js";
6
+ import { mat4 } from "gl-matrix";
7
+ import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
8
+ import { GeometrySpatialQueryAccelerator } from "../../geometry/buffered/query/GeometrySpatialQueryAccelerator.js";
6
9
 
7
10
  /**
8
11
  * @readonly
@@ -12,12 +15,27 @@ const scratch_aabb3_array = new Float32Array(6);
12
15
 
13
16
  const DEFAULT_FLAGS = ShadedGeometryFlags.CastShadow
14
17
  | ShadedGeometryFlags.ReceiveShadow
18
+ | ShadedGeometryFlags.Visible
15
19
  ;
16
20
 
17
21
  const FLAG_SET_EQUALITY = ShadedGeometryFlags.CastShadow
18
22
  | ShadedGeometryFlags.ReceiveShadow
23
+ | ShadedGeometryFlags.DrawMethodLocked
24
+ | ShadedGeometryFlags.Visible
19
25
  ;
20
26
 
27
+ /**
28
+ *
29
+ * @type {Float32Array|mat4}
30
+ */
31
+ const scratch_m4 = new Float32Array(16);
32
+
33
+ /**
34
+ * @readonly
35
+ * @type {Float32Array}
36
+ */
37
+ const scratch_ray_0 = new Float32Array(6);
38
+
21
39
  export class ShadedGeometry {
22
40
  constructor() {
23
41
  /**
@@ -160,6 +178,30 @@ export class ShadedGeometry {
160
178
  ;
161
179
  }
162
180
 
181
+ /**
182
+ *
183
+ * @param {ShadedGeometry} other
184
+ */
185
+ copy(other) {
186
+ this.geometry = other.geometry;
187
+ this.material = other.material;
188
+ this.draw_method = other.draw_method;
189
+ this.mode = other.mode;
190
+ this.flags = other.flags;
191
+ }
192
+
193
+ /**
194
+ *
195
+ * @returns {ShadedGeometry}
196
+ */
197
+ clone() {
198
+ const r = new ShadedGeometry();
199
+
200
+ r.copy(this);
201
+
202
+ return r;
203
+ }
204
+
163
205
  /**
164
206
  * Current cached entity that this component is attached to
165
207
  * @return {number}
@@ -251,6 +293,41 @@ export class ShadedGeometry {
251
293
 
252
294
  aabb3_matrix4_project(this.__bvh_aabb, scratch_aabb3_array, this.transform);
253
295
  }
296
+
297
+ /**
298
+ *
299
+ * @param {SurfacePoint3} contact if found, contact is written here
300
+ * @param {ArrayLike<number>|number[]|Float32Array} ray 6-tuple: [origin_x, origin_y, origin_z, direction_x, direction_y, direction_z]
301
+ * @param {ArrayLike<number>|number[]|Float32Array} transform_matrix4
302
+ * @returns {boolean}
303
+ */
304
+ query_raycast_nearest(contact, ray, transform_matrix4) {
305
+
306
+ // get transform in local space
307
+ mat4.invert(scratch_m4, transform_matrix4);
308
+
309
+ // transform ray to local space
310
+ if (!ray3_array_apply_matrix4(scratch_ray_0, ray, scratch_m4)) {
311
+ // invalid transform matrix
312
+ return false;
313
+ }
314
+
315
+ const hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_array(
316
+ contact,
317
+ this.geometry,
318
+ scratch_ray_0
319
+ );
320
+
321
+ if (!hit_found) {
322
+ return false;
323
+ }
324
+
325
+ // transform hit contact into global space
326
+ contact.applyMatrix4(transform_matrix4);
327
+
328
+ return true;
329
+
330
+ }
254
331
  }
255
332
 
256
333
  /**
@@ -7,4 +7,14 @@ export const ShadedGeometryFlags = {
7
7
 
8
8
  CastShadow: 2,
9
9
  ReceiveShadow: 4,
10
+
11
+ /**
12
+ * Draw method is not allowed to change if this is on
13
+ */
14
+ DrawMethodLocked: 8,
15
+
16
+ /**
17
+ * If set to false will not render
18
+ */
19
+ Visible:16
10
20
  };
@@ -1,7 +1,6 @@
1
1
  import { ShadedGeometry } from "./ShadedGeometry.js";
2
2
  import { Transform } from "../../../ecs/transform/Transform.js";
3
3
  import { System } from "../../../ecs/System.js";
4
- import { GeometrySpatialQueryAccelerator } from "../../geometry/buffered/query/GeometrySpatialQueryAccelerator.js";
5
4
  import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
6
5
  import { v3_distance_sqr } from "../../../../core/geom/v3_distance_sqr.js";
7
6
  import { mat4 } from "gl-matrix";
@@ -9,7 +8,6 @@ import { returnTrue } from "../../../../core/function/Functions.js";
9
8
  import { ShadedGeometryRendererContext } from "./render/ShadedGeometryRendererContext.js";
10
9
  import { assert } from "../../../../core/assert.js";
11
10
  import { ray3_array_compose } from "../../../../core/geom/3d/ray/ray3_array_compose.js";
12
- import { ray3_array_apply_matrix4 } from "../../../../core/geom/3d/ray/ray3_array_apply_matrix4.js";
13
11
  import {
14
12
  ExplicitBinaryBoundingVolumeHierarchy
15
13
  } from "../../../../core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js";
@@ -382,31 +380,18 @@ export class ShadedGeometrySystem extends System {
382
380
 
383
381
  const m4 = sg.transform;
384
382
 
385
- // get transform in local space
386
- mat4.invert(scratch_m4, m4);
387
-
388
383
  ray3_array_compose(
389
384
  scratch_ray_0,
390
385
  origin_x, origin_y, origin_z,
391
386
  direction_x, direction_y, direction_z
392
387
  );
393
388
 
394
- // transform ray to local space
395
- ray3_array_apply_matrix4(scratch_ray_0, scratch_ray_0, scratch_m4);
396
-
397
- const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_array(
398
- scratch_point,
399
- sg.geometry,
400
- scratch_ray_0
401
- );
389
+ const geometry_hit_found = sg.query_raycast_nearest(scratch_point,scratch_ray_0,m4);
402
390
 
403
391
  if (!geometry_hit_found) {
404
392
  continue;
405
393
  }
406
394
 
407
- // transform hit contact into global space
408
- scratch_point.applyMatrix4(m4);
409
-
410
395
  result.push({
411
396
  entity,
412
397
  mesh: sg,
@@ -476,31 +461,18 @@ export class ShadedGeometrySystem extends System {
476
461
  */
477
462
  const m4 = sg.transform;
478
463
 
479
- // get transform in local space
480
- mat4.invert(scratch_m4, m4);
481
-
482
464
  ray3_array_compose(
483
465
  scratch_ray_0,
484
466
  origin_x, origin_y, origin_z,
485
467
  direction_x, direction_y, direction_z
486
468
  );
487
469
 
488
- // transform ray to local space
489
- ray3_array_apply_matrix4(scratch_ray_0, scratch_ray_0, scratch_m4);
490
-
491
- const geometry_hit_found = GeometrySpatialQueryAccelerator.INSTANCE.queryRaycastNearest_array(
492
- scratch_point,
493
- sg.geometry,
494
- scratch_ray_0
495
- );
470
+ const geometry_hit_found = sg.query_raycast_nearest(scratch_point,scratch_ray_0,m4);
496
471
 
497
472
  if (!geometry_hit_found) {
498
473
  continue;
499
474
  }
500
475
 
501
- // transform hit contact into global space
502
- scratch_point.applyMatrix4(m4);
503
-
504
476
  found_hit = true;
505
477
 
506
478
  const hit_position = scratch_point.position;
@@ -6,6 +6,7 @@ import { ShadedGeometry } from "../ShadedGeometry.js";
6
6
  import {
7
7
  bvh_query_user_data_overlaps_frustum
8
8
  } from "../../../../../core/bvh2/bvh3/bvh_query_user_data_overlaps_frustum.js";
9
+ import { ShadedGeometryFlags } from "../ShadedGeometryFlags.js";
9
10
 
10
11
  /**
11
12
  *
@@ -104,6 +105,16 @@ export class ShadedGeometryRendererContext {
104
105
  */
105
106
  const sg = ecd.getComponentByIndex(entity, sg_component_index);
106
107
 
108
+ if ((sg.flags & ShadedGeometryFlags.Visible) === 0) {
109
+ // not visible
110
+ continue;
111
+ }
112
+
113
+ if (!sg.material.visible) {
114
+ // material is not visible, skip
115
+ continue;
116
+ }
117
+
107
118
  const adapter = adapters[sg.draw_method];
108
119
 
109
120
  adapter.add(sg);
@@ -9,36 +9,6 @@ const INSTANCED_EQUALITY_FLAGS = ShadedGeometryFlags.CastShadow
9
9
  | ShadedGeometryFlags.ReceiveShadow
10
10
  ;
11
11
 
12
- /**
13
- *
14
- * @param {ShadedGeometry} a
15
- * @param {ShadedGeometry} b
16
- * @returns {number}
17
- */
18
- function compare(a, b) {
19
- const d_geometry = a.geometry.id - b.geometry.id;
20
- if (d_geometry !== 0) {
21
- return d_geometry;
22
- }
23
-
24
- const d_material = a.material.id - b.material.id;
25
- if (d_material !== 0) {
26
- return d_material;
27
- }
28
-
29
- const d_flags = (a.flags & INSTANCED_EQUALITY_FLAGS) - (b.flags & INSTANCED_EQUALITY_FLAGS);
30
- if (d_flags !== 0) {
31
- return d_flags;
32
- }
33
-
34
- const d_mode = a.mode - b.mode;
35
- if (d_mode !== 0) {
36
- return d_mode;
37
- }
38
-
39
- return 0;
40
- }
41
-
42
12
  export class InstancedRendererAdapter extends AbstractRenderAdapter {
43
13
  constructor() {
44
14
  super();
@@ -159,17 +129,23 @@ export class InstancedRendererAdapter extends AbstractRenderAdapter {
159
129
  clear() {
160
130
  super.clear();
161
131
 
162
- for (const activeMesh of this.__active_meshes) {
132
+ const meshes = this.__active_meshes;
133
+
134
+ for (const activeMesh of meshes) {
163
135
  activeMesh.setCount(0);
164
136
  }
165
137
 
166
- this.__active_meshes.clear();
138
+ meshes.clear();
167
139
  }
168
140
 
169
141
  dispose() {
142
+ this.clear();
143
+
170
144
  // release GPU memory
171
145
  this.__instanced_meshes.forEach((value, key) => {
172
146
  value.dispose();
173
147
  });
148
+
149
+ this.__instanced_meshes.clear();
174
150
  }
175
151
  }
@@ -1,4 +1,5 @@
1
1
  import { ShadedGeometry } from "../../ShadedGeometry.js";
2
+ import { ShadedGeometryFlags } from "../../ShadedGeometryFlags.js";
2
3
 
3
4
  export class RuntimeDrawMethodOptimizer {
4
5
  constructor() {
@@ -70,6 +71,11 @@ export class RuntimeDrawMethodOptimizer {
70
71
  return false;
71
72
  }
72
73
 
74
+ if (sg.getFlag(ShadedGeometryFlags.DrawMethodLocked)) {
75
+ // draw mode is locked, can't change
76
+ return false;
77
+ }
78
+
73
79
  const use_count = system.getGeometryUsageCounters().get(sg.geometry.id);
74
80
 
75
81
  /**
@@ -0,0 +1,23 @@
1
+ import { Float32BufferAttribute } from "three";
2
+
3
+ /**
4
+ *
5
+ * @param {THREE.BufferGeometry} geometry
6
+ */
7
+ export function makeGeometryIndexed(geometry) {
8
+ let index_attribute = geometry.getIndex();
9
+
10
+ if (index_attribute === null || index_attribute === undefined) {
11
+ const position_attribute = geometry.getAttribute('position');
12
+ // non-indexed geometry, build index
13
+ const array = new Float32Array(position_attribute.count * 3);
14
+
15
+ for (let i = 0; i < array.length; i++) {
16
+ array[i] = i;
17
+ }
18
+
19
+ index_attribute = new Float32BufferAttribute(array, 1, false);
20
+
21
+ geometry.setIndex(index_attribute);
22
+ }
23
+ }
@@ -1,5 +1,5 @@
1
1
  import { Cache } from "../../../../../core/cache/Cache.js";
2
- import { buildUnsorted } from "../../bvh/buffered/BinaryBVHFromBufferGeometry.js";
2
+ import { buildUnsorted, buildUnsortedUnindexed } from "../../bvh/buffered/BinaryBVHFromBufferGeometry.js";
3
3
  import { ClippingPlaneContainmentComputingVisitor } from "./ClippingPlaneContainmentComputingVisitor.js";
4
4
  import { RaycastNearestHitComputingVisitor } from "./RaycastNearestHitComputingVisitor.js";
5
5
  import { assert } from "../../../../../core/assert.js";
@@ -93,7 +93,15 @@ export class GeometrySpatialQueryAccelerator {
93
93
  assert.notNull(geometry, 'geometry');
94
94
  assert.defined(geometry, 'geometry');
95
95
 
96
- const bvh = this.__acquireBVH(geometry);
96
+
97
+ let bvh;
98
+
99
+ try {
100
+ bvh = this.__acquireBVH(geometry);
101
+ } catch (e) {
102
+ console.error(e);
103
+ return false;
104
+ }
97
105
 
98
106
  this.__visitor_raycast.reset();
99
107
 
@@ -174,9 +182,13 @@ export class GeometrySpatialQueryAccelerator {
174
182
  const index_attribute = geometry.getIndex();
175
183
 
176
184
  const de_interleaved_position_attribute = deinterleaveBufferAttribute(position_attribute);
177
- const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
178
-
179
185
  const vertices = de_interleaved_position_attribute.array;
186
+
187
+ if(index_attribute === undefined || index_attribute === null){
188
+ return buildUnsortedUnindexed(vertices);
189
+ }
190
+
191
+ const de_interleaved_index_attribute = deinterleaveBufferAttribute(index_attribute);
180
192
  const indices = de_interleaved_index_attribute.array;
181
193
 
182
194
  return buildUnsorted(vertices, indices);
@@ -60,7 +60,14 @@ export class GeometrySpatialAcceleratorVisitor extends IndexedBinaryBVHVisitor {
60
60
  setGeometry(geometry) {
61
61
  this.geometry = geometry;
62
62
 
63
- this.__buffer_indices = geometry.getIndex().array;
63
+ const index_attribute = geometry.getIndex();
64
+
65
+ if (index_attribute) {
66
+ this.__buffer_indices = index_attribute.array;
67
+ } else {
68
+ // no index attribute
69
+ this.__buffer_indices = null;
70
+ }
64
71
 
65
72
  const position_attribute = geometry.getAttribute('position');
66
73
 
@@ -110,11 +110,20 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
110
110
 
111
111
  const indices = this.__buffer_indices;
112
112
 
113
- assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
114
-
115
- const a = indices[index3];
116
- const b = indices[index3 + 1];
117
- const c = indices[index3 + 2];
113
+ let a, b, c;
114
+
115
+ if(indices !== null) {
116
+ assert.lessThan(index3 + 2, indices.length, 'triangle index overflow, possibly geometry changed but tree was not rebuilt?');
117
+
118
+ a = indices[index3];
119
+ b = indices[index3 + 1];
120
+ c = indices[index3 + 2];
121
+ }else{
122
+ // implicit indices
123
+ a = index3;
124
+ b = index3+1;
125
+ c = index3+2;
126
+ }
118
127
 
119
128
  const vertices = this.__buffer_vertices;
120
129
 
@@ -62,6 +62,62 @@ function buildUnsorted(vertices, indices) {
62
62
  return tree;
63
63
  }
64
64
 
65
+ /**
66
+ *
67
+ * @param {Float32Array|Float64Array|Array.<Number>} vertices
68
+ * @returns {IndexedBinaryBVH}
69
+ */
70
+ export function buildUnsortedUnindexed(vertices) {
71
+ //
72
+ const numNodes = vertices.length / 9;
73
+
74
+ const tree = new IndexedBinaryBVH();
75
+ tree.initialize(numNodes);
76
+
77
+ for (let i = 0; i < numNodes; i++) {
78
+
79
+ const index3 = i * 3;
80
+
81
+ // read triangle vertex indices
82
+ const iA = index3;
83
+ const iB = index3 + 1;
84
+ const iC = index3 + 2;
85
+
86
+ const a = iA * 3;
87
+ const b = iB * 3;
88
+ const c = iC * 3;
89
+
90
+ // read actual positions of each vertex
91
+ const aX = vertices[a];
92
+ const aY = vertices[a + 1];
93
+ const aZ = vertices[a + 2];
94
+
95
+ const bX = vertices[b];
96
+ const bY = vertices[b + 1];
97
+ const bZ = vertices[b + 2];
98
+
99
+ const cX = vertices[c];
100
+ const cY = vertices[c + 1];
101
+ const cZ = vertices[c + 2];
102
+
103
+ // compute bounds of the triangle
104
+ const x0 = min3(aX, bX, cX);
105
+ const y0 = min3(aY, bY, cY);
106
+ const z0 = min3(aZ, bZ, cZ);
107
+
108
+ const x1 = max3(aX, bX, cX);
109
+ const y1 = max3(aY, bY, cY);
110
+ const z1 = max3(aZ, bZ, cZ);
111
+
112
+ tree.writeLeaf(i, x0, y0, z0, x1, y1, z1);
113
+ }
114
+
115
+ // finalize build
116
+ tree.unsortedBuiltIntermediate();
117
+
118
+ return tree;
119
+ }
120
+
65
121
  export {
66
122
  buildUnsorted
67
123
  };
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.39.15",
8
+ "version": "2.39.18",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",