@woosh/meep-engine 2.36.11 → 2.36.12

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.
@@ -111,6 +111,7 @@ test("add and remove 5 nodes", () => {
111
111
 
112
112
  for (let i = 0; i < 5; i++) {
113
113
  const a = bvh.allocate_node();
114
+ bvh.node_set_user_data(a, a);
114
115
  bvh.insert_leaf(a);
115
116
 
116
117
  leaves.push(a);
@@ -127,6 +128,8 @@ test("add and remove 5 nodes", () => {
127
128
 
128
129
  const leaf = leaves.shift();
129
130
 
131
+ expect(bvh.node_get_user_data(leaf)).toBe(leaf);
132
+
130
133
  bvh.remove_leaf(leaf);
131
134
 
132
135
  removed_leaves.push(leaf);
@@ -0,0 +1,60 @@
1
+ //
2
+
3
+ import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
4
+
5
+ const traversal_stack = [];
6
+ /**
7
+ *
8
+ * @param {number[]} destination
9
+ * @param {number} destination_offset
10
+ * @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
11
+ * @param {number} node
12
+ */
13
+ export function bvh_collect_user_data(destination, destination_offset, bvh, node) {
14
+
15
+ if (node === NULL_NODE) {
16
+ return 0;
17
+ }
18
+
19
+ /**
20
+ *
21
+ * @type {number}
22
+ */
23
+ let traversal_cursor = 0;
24
+
25
+ traversal_stack[traversal_cursor++] = node;
26
+
27
+ let result_cursor = destination_offset;
28
+
29
+ while (traversal_cursor > 0) {
30
+ traversal_cursor--;
31
+
32
+ /**
33
+ *
34
+ * @type {number}
35
+ */
36
+ const node = traversal_stack[traversal_cursor];
37
+
38
+ const node_is_leaf = bvh.node_is_leaf(node);
39
+
40
+ if (!node_is_leaf) {
41
+
42
+ // read in-order
43
+ const child1 = bvh.node_get_child1(node);
44
+ const child2 = bvh.node_get_child2(node);
45
+
46
+ // write to stack in reverse order, so that fist child ends up being visited first
47
+ traversal_stack[traversal_cursor++] = child1;
48
+ traversal_stack[traversal_cursor++] = child2;
49
+
50
+ } else {
51
+ // leaf node
52
+
53
+ destination[result_cursor++] = bvh.node_get_user_data(node);
54
+ }
55
+ }
56
+
57
+ // drop stack frame
58
+
59
+ return result_cursor - destination_offset;
60
+ }
@@ -0,0 +1,85 @@
1
+ //
2
+ import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
3
+ import { aabb3_array_intersects_frustum_degree } from "../aabb3/aabb3_array_intersects_frustum_degree.js";
4
+ import { bvh_collect_user_data } from "./bvh_collect_user_data.js";
5
+
6
+ const traversal_stack = [];
7
+
8
+ const scratch_aabb = [];
9
+
10
+ /**
11
+ *
12
+ * @param {number[]} result
13
+ * @param {number} result_offset
14
+ * @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
15
+ * @param {number[]|Float32Array} frustum
16
+ */
17
+ export function bvh_query_user_data_by_frustum(
18
+ result,
19
+ result_offset,
20
+ bvh,
21
+ frustum
22
+ ) {
23
+ const root = bvh.root;
24
+
25
+ if (root === NULL_NODE) {
26
+ return 0;
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @type {number}
32
+ */
33
+ let traversal_cursor = 0;
34
+
35
+ traversal_stack[traversal_cursor++] = root;
36
+
37
+ let result_cursor = result_offset;
38
+
39
+ while (traversal_cursor > 0) {
40
+ traversal_cursor--;
41
+
42
+ /**
43
+ *
44
+ * @type {number}
45
+ */
46
+ const node = traversal_stack[traversal_cursor];
47
+
48
+ // test node against the ray
49
+ bvh.node_get_aabb(node, scratch_aabb);
50
+ const intersection = aabb3_array_intersects_frustum_degree(scratch_aabb, frustum);
51
+
52
+ if (intersection === 0) {
53
+ // fully outside
54
+ continue;
55
+ }
56
+
57
+ const node_is_leaf = bvh.node_is_leaf(node);
58
+
59
+ if (!node_is_leaf) {
60
+
61
+ if (intersection === 2) {
62
+ // fully inside
63
+ result_cursor += bvh_collect_user_data(result, result_cursor, bvh, node);
64
+ continue;
65
+ }
66
+
67
+ // read in-order
68
+ const child1 = bvh.node_get_child1(node);
69
+ const child2 = bvh.node_get_child2(node);
70
+
71
+ // write to stack in reverse order, so that fist child ends up being visited first
72
+ traversal_stack[traversal_cursor++] = child1;
73
+ traversal_stack[traversal_cursor++] = child2;
74
+
75
+ } else {
76
+ // leaf node
77
+
78
+ result[result_cursor++] = bvh.node_get_user_data(node);
79
+ }
80
+ }
81
+
82
+ // drop stack frame
83
+
84
+ return result_cursor - result_offset;
85
+ }
@@ -0,0 +1,79 @@
1
+ import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
2
+
3
+ /**
4
+ *
5
+ * @type {number[]}
6
+ */
7
+ const traversal_stack = [];
8
+
9
+ /**
10
+ *
11
+ * @type {number}
12
+ */
13
+ let traversal_cursor = 0;
14
+
15
+
16
+ /**
17
+ *
18
+ * @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
19
+ * @param {number[]} result
20
+ * @param {number} result_offset
21
+ * @param {BVHQuery} query
22
+ * @returns {number}
23
+ */
24
+ export function bvh_query_user_data_generic(
25
+ result, result_offset,
26
+ bvh, query
27
+ ) {
28
+ const stack_frame_address = traversal_cursor;
29
+
30
+ const root = bvh.root;
31
+
32
+ if (root === NULL_NODE) {
33
+ return 0;
34
+ }
35
+
36
+ traversal_stack[traversal_cursor++] = root;
37
+
38
+ let result_cursor = result_offset;
39
+
40
+ while (traversal_cursor > stack_frame_address) {
41
+ traversal_cursor--;
42
+
43
+ /**
44
+ *
45
+ * @type {number}
46
+ */
47
+ const node = traversal_stack[traversal_cursor];
48
+
49
+ // test node against the ray
50
+ const pass = query.evaluate(node, bvh);
51
+
52
+ if (!pass) {
53
+ continue;
54
+ }
55
+
56
+ const node_is_leaf = bvh.node_is_leaf(node);
57
+
58
+ if (!node_is_leaf) {
59
+
60
+ // read in-order
61
+ const child1 = bvh.node_get_child1(node);
62
+ const child2 = bvh.node_get_child2(node);
63
+
64
+ // write to stack in reverse order, so that fist child ends up being visited first
65
+ traversal_stack[traversal_cursor++] = child1;
66
+ traversal_stack[traversal_cursor++] = child2;
67
+
68
+ } else {
69
+ // leaf node
70
+
71
+ result[result_cursor++] = bvh.node_get_user_data(node);
72
+ }
73
+ }
74
+
75
+ // drop stack frame
76
+ traversal_cursor = stack_frame_address;
77
+
78
+ return result_cursor - result_offset;
79
+ }
@@ -332,6 +332,21 @@ class Mesh {
332
332
  return result;
333
333
  }
334
334
 
335
+ /**
336
+ *
337
+ * @param {string} url
338
+ * @returns {Mesh}
339
+ */
340
+ static fromURL(url) {
341
+ const r = new Mesh();
342
+
343
+ r.url = url;
344
+ r.castShadow = true;
345
+ r.receiveShadow = true;
346
+
347
+ return r;
348
+ }
349
+
335
350
  /**
336
351
  *
337
352
  * @param {string} name
@@ -228,8 +228,8 @@ export class ShadedGeometrySystem extends System {
228
228
  // insert BVH entry
229
229
  const bvh_node_id = this.__bvh_binary.allocate_node();
230
230
  this.__bvh_binary.node_set_aabb(bvh_node_id, sg.__bvh_aabb);
231
- this.__bvh_binary.insert_leaf(bvh_node_id);
232
231
  this.__bvh_binary.node_set_user_data(bvh_node_id, entity);
232
+ this.__bvh_binary.insert_leaf(bvh_node_id);
233
233
 
234
234
  sg.__bvh_tree = this.__bvh_binary;
235
235
  sg.__bvh_leaf_id = bvh_node_id;
@@ -8,9 +8,10 @@ import { GameAssetType } from "../../../../asset/GameAssetType.js";
8
8
  import { GLTFAssetLoader } from "../../../../asset/loaders/GLTFAssetLoader.js";
9
9
  import Vector3 from "../../../../../core/geom/Vector3.js";
10
10
  import { BehaviorSystem } from "../../../../intelligence/behavior/ecs/BehaviorSystem.js";
11
- import { BehaviorComponent } from "../../../../intelligence/behavior/ecs/BehaviorComponent.js";
12
- import { OrbitingBehavior } from "../../../../../../model/game/util/behavior/OrbitingBehavior.js";
13
11
  import { TransformAttachmentSystem } from "../../../../ecs/transform-attachment/TransformAttachmentSystem.js";
12
+ import { SGMeshEvents } from "./SGMeshEvents.js";
13
+ import { ShadedGeometry } from "../ShadedGeometry.js";
14
+ import { MeshSystem } from "../../mesh/MeshSystem.js";
14
15
 
15
16
  new EngineHarness().initialize({
16
17
  configuration(config, engine) {
@@ -18,6 +19,7 @@ new EngineHarness().initialize({
18
19
  new ShadedGeometrySystem(engine),
19
20
  new SGMeshSystem(engine),
20
21
  new BehaviorSystem(engine),
22
+ new MeshSystem(engine),
21
23
  new TransformAttachmentSystem()
22
24
  );
23
25
 
@@ -36,18 +38,32 @@ function main(engine) {
36
38
 
37
39
  const ecd = engine.entityManager.dataset;
38
40
 
39
- const mesh = SGMesh.fromURL("data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf");
41
+ // const mesh = SGMesh.fromURL("data/models/RTS_Buildings_Humans/18/Building_R_18_out/Building_R_18.gltf");
42
+ const mesh = SGMesh.fromURL("moicon/ztest_object_many_pieces/model.gltf");
43
+ // const mesh = Mesh.fromURL("moicon/ztest_object_many_pieces/model.gltf");
40
44
 
41
45
  new EntityBuilder()
42
46
  .add(Transform.fromJSON({
43
47
  position: new Vector3(10, 0, 10)
44
48
  }))
45
- // .add(SGMesh.fromURL("data/models/snaps/cube_blue.gltf"))
46
49
  .add(mesh)
47
- .add(BehaviorComponent.fromOne(OrbitingBehavior.from({
50
+ /* .add(BehaviorComponent.fromOne(OrbitingBehavior.from({
48
51
  center: new Vector3(10, 0, 10),
49
52
  radius: 5,
50
53
  rate: 2
51
- })))
54
+ })))*/
55
+ .addEventListener(SGMeshEvents.AssetLoaded, () => {
56
+ mesh.__node.traverse(n => {
57
+ /**
58
+ *
59
+ * @type {ShadedGeometry}
60
+ */
61
+ const sg = n.entity.getComponent(ShadedGeometry);
62
+
63
+ if (sg !== null) {
64
+ sg.draw_method = 1;
65
+ }
66
+ });
67
+ })
52
68
  .build(ecd);
53
69
  }
@@ -2,9 +2,14 @@ import { AbstractRenderAdapter } from "./adapters/AbstractRenderAdapter.js";
2
2
  import { InstancedRendererAdapter } from "./adapters/InstancedRendererAdapter.js";
3
3
  import { GenericRendererAdapter } from "./adapters/GenericRendererAdapter.js";
4
4
  import { assert } from "../../../../../core/assert.js";
5
- import { bvh_query_leaves_generic } from "../../../../../core/bvh2/bvh3/bvh_query_leaves_generic.js";
6
- import { BVHQueryIntersectsFrustum } from "../../../../../core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js";
7
5
  import { ShadedGeometry } from "../ShadedGeometry.js";
6
+ import { bvh_query_user_data_by_frustum } from "../../../../../core/bvh2/bvh3/bvh_query_user_data_by_frustum.js";
7
+
8
+ /**
9
+ *
10
+ * @type {number[]}
11
+ */
12
+ const collection_array = [];
8
13
 
9
14
  /**
10
15
  * 1 - collect visible meshes
@@ -84,19 +89,12 @@ export class ShadedGeometryRendererContext {
84
89
 
85
90
 
86
91
  // get all meshes
87
-
88
- const data = [];
89
-
90
- const query = BVHQueryIntersectsFrustum.from(view.frustum);
91
-
92
- const intersection_count = bvh_query_leaves_generic(data, 0, bvh, query);
92
+ const intersection_count = bvh_query_user_data_by_frustum(collection_array, 0, bvh, view.frustum);
93
93
 
94
94
  const sg_component_index = ecd.computeComponentTypeIndex(ShadedGeometry);
95
95
 
96
96
  for (i = 0; i < intersection_count; i++) {
97
- const node_index = data[i];
98
-
99
- const entity = bvh.node_get_user_data(node_index);
97
+ const entity = collection_array[i];
100
98
 
101
99
  /**
102
100
  *
@@ -8,11 +8,15 @@ import { computeGeometryEquality } from "../../../asset/loaders/geometry/geometr
8
8
  import { CachedAsyncMap } from "../../../../core/collection/map/CachedAsyncMap.js";
9
9
  import { AsyncRemoteHashMap } from "../../../../core/collection/map/AsyncRemoteHashMap.js";
10
10
  import { BufferGeometrySerializationAdapter } from "./serialization/BufferGeometrySerializationAdapter.js";
11
- import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
11
+ import {
12
+ MicronGeometryBinarySerializationAdapter
13
+ } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
12
14
  import { AsyncMapWrapper } from "../../../../core/collection/map/AsyncMapWrapper.js";
13
15
  import { MicronGeometry } from "../format/MicronGeometry.js";
14
16
  import { ArrayBufferLoader } from "../../../asset/loaders/ArrayBufferLoader.js";
15
17
  import { ASSET_TYPE_ARRAY_BUFFER, GLTFAssetTransformer } from "./GLTFAssetTransformer.js";
18
+ import { ShadedGeometrySystem } from "../../ecs/mesh-v2/ShadedGeometrySystem.js";
19
+ import { MicronShadedGeometryRenderAdapter } from "./shaded_geometry/MicronShadedGeometryRenderAdapter.js";
16
20
 
17
21
  /**
18
22
  *
@@ -85,6 +89,12 @@ export class MicronRenderPlugin extends EnginePlugin {
85
89
  */
86
90
  this.__asset_transformer = new GLTFAssetTransformer(this.__cache);
87
91
 
92
+ /**
93
+ *
94
+ * @type {ShadedGeometrySystem|null}
95
+ * @private
96
+ */
97
+ this.__sg_system = null;
88
98
  }
89
99
 
90
100
  /**
@@ -135,6 +145,58 @@ export class MicronRenderPlugin extends EnginePlugin {
135
145
  view.on.preRender.remove(observer);
136
146
  }
137
147
 
148
+ /**
149
+ *
150
+ * @param {System} system
151
+ * @private
152
+ */
153
+ __handle_system_added(system) {
154
+ if (this.__sg_system !== null) {
155
+ return;
156
+ }
157
+
158
+ if (!(system instanceof ShadedGeometrySystem)) {
159
+ return;
160
+ }
161
+
162
+ /**
163
+ *
164
+ * @type {ShadedGeometrySystem|null}
165
+ */
166
+ const sg_system = system;
167
+
168
+ sg_system.register_render_adapter(2, () => {
169
+ const adapter = new MicronShadedGeometryRenderAdapter();
170
+
171
+ adapter.ctx = this.__vgtr.ctx;
172
+
173
+ return adapter;
174
+ });
175
+
176
+ this.__sg_system = sg_system;
177
+ }
178
+
179
+ /**
180
+ *
181
+ * @param {System} system
182
+ * @private
183
+ */
184
+ __handle_system_removed(system) {
185
+ if (this.__sg_system === null) {
186
+ return;
187
+ }
188
+
189
+ if (!(system instanceof ShadedGeometrySystem)) {
190
+ return;
191
+ }
192
+
193
+ if (this.__sg_system !== system) {
194
+ return;
195
+ }
196
+
197
+ this.__sg_system.unregister_render_adapter(2);
198
+ }
199
+
138
200
  async startup() {
139
201
 
140
202
  const engine = this.engine;
@@ -167,6 +229,11 @@ export class MicronRenderPlugin extends EnginePlugin {
167
229
 
168
230
  this.__persisted_geometry.attach_storage(engine.storage);
169
231
 
232
+ engine.entityManager.on.systemAdded.add(this.__handle_system_added, this);
233
+ engine.entityManager.on.systemRemoved.add(this.__handle_system_removed, this);
234
+
235
+ engine.entityManager.systems.forEach(this.__handle_system_added, this);
236
+
170
237
  await super.startup();
171
238
  }
172
239
 
@@ -192,6 +259,11 @@ export class MicronRenderPlugin extends EnginePlugin {
192
259
  // clear all observer
193
260
  ge.views.elements.forEach(this.__handle_view_removed, this);
194
261
 
262
+ engine.entityManager.on.systemAdded.remove(this.__handle_system_added, this);
263
+ engine.entityManager.on.systemRemoved.remove(this.__handle_system_removed, this);
264
+
265
+ engine.entityManager.systems.forEach(this.__handle_system_removed, this);
266
+
195
267
  await super.shutdown();
196
268
  }
197
269
  }
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.36.11",
8
+ "version": "2.36.12",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",