@woosh/meep-engine 2.34.27 → 2.34.31

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.
@@ -0,0 +1,18 @@
1
+ //
2
+
3
+ /**
4
+ *
5
+ * @param {ArrayLike<number>|number[]} aabb
6
+ * @param {number} x
7
+ * @param {number} y
8
+ * @param {number} z
9
+ * @return {boolean}
10
+ */
11
+ export function aabb3_array_contains_point(aabb, x, y, z) {
12
+ return x >= aabb[0]
13
+ && x <= aabb[3]
14
+ && y >= aabb[1]
15
+ && y <= aabb[4]
16
+ && z >= aabb[2]
17
+ && z <= aabb[5];
18
+ }
@@ -0,0 +1,15 @@
1
+ import { sphereIntersectsPoint } from "./sphereIntersectsPoint.js";
2
+
3
+ //
4
+
5
+ /**
6
+ *
7
+ * @param {ArrayLike<number>|number[]} sphere
8
+ * @param {number} x
9
+ * @param {number} y
10
+ * @param {number} z
11
+ * @return {boolean}
12
+ */
13
+ export function sphere_array_intersects_point(sphere, x, y, z) {
14
+ return sphereIntersectsPoint(sphere[0], sphere[1], sphere[2], sphere[3], x, y, z);
15
+ }
@@ -1,7 +1,6 @@
1
1
  //
2
2
 
3
3
  import { v3_dot } from "../../v3_dot.js";
4
- import { ray_distance_to_point } from "../ray/ray_distance_to_point.js";
5
4
 
6
5
  /**
7
6
  *
@@ -31,6 +31,10 @@ export class PatchRepresentation {
31
31
  Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY
32
32
  );
33
33
 
34
+ /**
35
+ *
36
+ * @type {AABB3}
37
+ */
34
38
  this.group_aabb = new AABB3(0, 0, 0, 0, 0, 0);
35
39
 
36
40
  /**
@@ -202,6 +202,11 @@ export async function buildMicronGeometryFromBufferGeometry(input) {
202
202
 
203
203
 
204
204
  const t_build_hierarchy_start = current_time_millis();
205
+
206
+ /**
207
+ *
208
+ * @type {PatchRepresentation}
209
+ */
205
210
  const root = await buildAbstractPatchHierarchy(patches);
206
211
 
207
212
  if (PRINT_VERBOSE_STATS) {
@@ -48,13 +48,15 @@ async function assemble_graph(nodes) {
48
48
  */
49
49
  let __nodes = nodes.slice();
50
50
 
51
+ const initial_node_count = __nodes.length;
52
+
51
53
  /**
52
54
  *
53
55
  * @type {{value: number}}
54
56
  * @private
55
57
  */
56
58
  const __node_count = {
57
- value: __nodes.length
59
+ value: initial_node_count
58
60
  };
59
61
 
60
62
  let level = 0;
@@ -136,9 +138,12 @@ async function assemble_graph(nodes) {
136
138
  // return root
137
139
  const root = __nodes[0];
138
140
 
139
- //set group bounds to produce a valid root
140
- root.group_aabb.copy(root.bounding_box);
141
- root.group_bounding_sphere.set(root.bounding_sphere);
141
+ if (initial_node_count === 1) {
142
+ // there are no children, whole hierarchy is just one node, set group bounds to equal node bounds
143
+ root.group_bounding_sphere.set(root.bounding_sphere);
144
+ root.group_aabb.copy(root.bounding_box);
145
+ }
146
+
142
147
 
143
148
  return root;
144
149
  }
@@ -1,6 +1,7 @@
1
1
  import {BufferGeometry} from "three";
2
2
  import {VertexDataSpec} from "../../geometry/VertexDataSpec";
3
3
  import {SurfacePoint3} from "../../../../core/geom/3d/SurfacePoint3";
4
+ import {MicronGeometryPatch} from "./MicronGeometryPatch";
4
5
 
5
6
  export class MicronGeometry {
6
7
  vertex_spec: VertexDataSpec
@@ -14,4 +15,6 @@ export class MicronGeometry {
14
15
  ): SurfacePoint3[]
15
16
 
16
17
  readonly isMicronGeometry: boolean
18
+
19
+ readonly patches: MicronGeometryPatch[]
17
20
  }
@@ -3,6 +3,7 @@ import { assert } from "../../../../core/assert.js";
3
3
  import { computeTriangleRayIntersection } from "../../../../core/geom/3d/triangle/computeTriangleRayIntersection.js";
4
4
  import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
5
5
  import { aabb3_array_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_array_intersects_ray.js";
6
+ import { sphere_array_intersects_ray } from "../../../../core/geom/3d/sphere/sphere_array_intersects_ray.js";
6
7
 
7
8
  let id_counter = 0;
8
9
 
@@ -105,43 +106,18 @@ export class MicronGeometry {
105
106
 
106
107
  const patch = stack[stack_cursor];
107
108
 
108
- // using group bounds because it's conservative, as we want to be able to hit LOD_0
109
-
110
- // sphere test
111
-
112
- // TODO check what's wrong with sphere tests and re-enable them
113
- // if (!sphere_array_intersects_ray(patch.group_bounding_sphere,
114
- // origin_x, origin_y, origin_z,
115
- // direction_x, direction_y, direction_z
116
- // )) {
117
- // continue;
118
- // }
119
-
120
-
121
- // box test (more expensive, different volume)
122
- if (!aabb3_array_intersects_ray(
123
- patch.group_bounding_box,
124
- origin_x, origin_y, origin_z,
125
- direction_x, direction_y, direction_z
126
- )) {
127
- // no intersection
128
- continue;
129
- }
130
-
131
109
  if (patch.lod === 0) {
132
110
  // LOD 0 - source geometry
133
111
 
134
112
  // cast against bounds
135
113
 
136
114
  // sphere test
137
-
138
- // TODO check what's wrong with sphere tests and re-enable them
139
- // if (!sphere_array_intersects_ray(patch.bounding_sphere,
140
- // origin_x, origin_y, origin_z,
141
- // direction_x, direction_y, direction_z
142
- // )) {
143
- // continue;
144
- // }
115
+ if (!sphere_array_intersects_ray(patch.bounding_sphere,
116
+ origin_x, origin_y, origin_z,
117
+ direction_x, direction_y, direction_z
118
+ )) {
119
+ continue;
120
+ }
145
121
 
146
122
  // box test
147
123
  if (!aabb3_array_intersects_ray(
@@ -200,6 +176,28 @@ export class MicronGeometry {
200
176
  }
201
177
 
202
178
  } else {
179
+
180
+ // using group bounds because it's conservative, as we want to be able to hit LOD_0
181
+
182
+ // sphere test
183
+ if (!sphere_array_intersects_ray(patch.group_bounding_sphere,
184
+ origin_x, origin_y, origin_z,
185
+ direction_x, direction_y, direction_z
186
+ )) {
187
+ continue;
188
+ }
189
+
190
+
191
+ // box test (more expensive, different volume)
192
+ if (!aabb3_array_intersects_ray(
193
+ patch.group_bounding_box,
194
+ origin_x, origin_y, origin_z,
195
+ direction_x, direction_y, direction_z
196
+ )) {
197
+ // no intersection
198
+ continue;
199
+ }
200
+
203
201
  // refine more
204
202
  const children = patch.children;
205
203
 
@@ -0,0 +1,3 @@
1
+ export class MicronGeometryPatch {
2
+
3
+ }
@@ -0,0 +1,63 @@
1
+ import { MicronGeometryPatch } from "../MicronGeometryPatch.js";
2
+ import { BinaryBuffer } from "../../../../../core/binary/BinaryBuffer.js";
3
+ import { MicronGeometry } from "../MicronGeometry.js";
4
+ import { VertexDataSpec } from "../../../geometry/VertexDataSpec.js";
5
+ import { AttributeSpec } from "../../../geometry/AttributeSpec.js";
6
+ import { DataType } from "../../../../../core/collection/table/DataType.js";
7
+ import { MicronGeometryBinarySerializationAdapter } from "./MicronGeometryBinarySerializationAdapter.js";
8
+
9
+ function sampleGeometry() {
10
+ const a = new MicronGeometryPatch();
11
+
12
+ a.vertex_attribute_arrays[0] = new Uint8Array([
13
+ 7, 11, 13,
14
+ 17, 23, 29,
15
+ 31, 39, 43
16
+ ]);
17
+ a.vertex_count = 3;
18
+
19
+ a.face_indices = new Uint8Array([1, 2, 3]);
20
+ a.polygon_count = 1;
21
+
22
+ a.group_error = 1.234;
23
+
24
+ a.bounding_box.set([7, 11, 13, 31, 39, 43]);
25
+ a.group_bounding_box.set([7, 11, 13, 31, 39, 43]);
26
+ a.bounding_sphere.set([19, 25, 28, 50.1]);
27
+ a.group_bounding_sphere.set([19, 25, 28, 50.1]);
28
+
29
+ const g_a = new MicronGeometry();
30
+
31
+ const vertex_spec = new VertexDataSpec();
32
+ vertex_spec.add(AttributeSpec.fromJSON({
33
+ name: 'position',
34
+ type: DataType.Uint8,
35
+ itemSize: 3,
36
+ normalized: false
37
+ }));
38
+
39
+ g_a.vertex_spec = vertex_spec;
40
+ g_a.root = a;
41
+ g_a.initialize();
42
+
43
+ return g_a;
44
+ }
45
+
46
+ test("serialization/deserialization consistency", () => {
47
+ const g_a = sampleGeometry();
48
+
49
+ const buffer = new BinaryBuffer();
50
+
51
+ const adapter = new MicronGeometryBinarySerializationAdapter();
52
+
53
+ adapter.serialize(buffer, g_a);
54
+
55
+
56
+ const g_b = new MicronGeometry();
57
+
58
+ buffer.position = 0;
59
+ adapter.deserialize(buffer, g_b);
60
+
61
+ expect(g_b.vertex_spec.equals(g_a.vertex_spec)).toBe(true);
62
+ expect(g_b.patches.length).toEqual(g_a.patches.length);
63
+ });
@@ -0,0 +1,69 @@
1
+ import { noop } from "../../../../core/function/Functions.js";
2
+ import { aabb3_array_contains_point } from "../../../../core/bvh2/aabb3/aabb3_array_contains_point.js";
3
+ import { sphere_array_intersects_point } from "../../../../core/geom/3d/sphere/sphere_array_intersects_point.js";
4
+
5
+ /**
6
+ *
7
+ * @param {MicronGeometryPatch} patch
8
+ * @param {VertexDataSpec} vertex_spec
9
+ * @param {function(string)} [error_consumer]
10
+ * @returns {boolean}
11
+ */
12
+ export function validate_patch_bounds(patch, vertex_spec, error_consumer = noop) {
13
+ const position_attribute_index = vertex_spec.getAttributeIndexByName('position');
14
+
15
+ if (position_attribute_index === -1) {
16
+ error_consumer(`No 'position' attribute found`);
17
+ // technically any bounds are valid if there is no position
18
+ return true;
19
+ }
20
+
21
+ const position_data = patch.vertex_attribute_arrays[position_attribute_index];
22
+
23
+ let b_sphere_valid = true;
24
+ let b_box_valid = true;
25
+ let gb_sphere_valid = true;
26
+ let gb_box_valid = true;
27
+
28
+ for (let i = 0; i < this.vertex_count; i++) {
29
+ const i3 = i * 3;
30
+
31
+ const x = position_data[i3];
32
+ const y = position_data[i3 + 1];
33
+ const z = position_data[i3 + 2];
34
+
35
+ if (!aabb3_array_contains_point(patch.bounding_box, x, y, z)) {
36
+ b_box_valid = false;
37
+ }
38
+
39
+ if (!aabb3_array_contains_point(patch.group_bounding_box, x, y, z)) {
40
+ gb_box_valid = false;
41
+ }
42
+
43
+ if (!sphere_array_intersects_point(patch.bounding_sphere, x, y, z)) {
44
+ b_sphere_valid = false;
45
+ }
46
+
47
+ if (!sphere_array_intersects_point(patch.group_bounding_sphere, x, y, z)) {
48
+ gb_sphere_valid = false;
49
+ }
50
+ }
51
+
52
+ if (!b_sphere_valid) {
53
+ error_consumer('.bounding_sphere is violated');
54
+ }
55
+
56
+ if (!gb_sphere_valid) {
57
+ error_consumer('.group_bounding_sphere is violated');
58
+ }
59
+
60
+ if (!b_box_valid) {
61
+ error_consumer('.bounding_box is violated');
62
+ }
63
+
64
+ if (!gb_box_valid) {
65
+ error_consumer('.group_bounding_box is violated');
66
+ }
67
+
68
+ return b_sphere_valid && gb_sphere_valid && b_box_valid && gb_box_valid;
69
+ }
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.34.27",
8
+ "version": "2.34.31",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",