@woosh/meep-engine 2.34.26 → 2.34.30
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.
- package/core/bvh2/aabb3/aabb3_array_contains_point.js +18 -0
- package/core/geom/3d/ray/ray_distance_to_point.js +14 -0
- package/core/geom/3d/sphere/sphere_array_intersects_point.js +15 -0
- package/engine/graphics/micron/build/PatchRepresentation.js +4 -0
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +5 -0
- package/engine/graphics/micron/build/hierarchy/buildAbstractPatchHierarchy.js +9 -4
- package/engine/graphics/micron/format/MicronGeometry.d.ts +3 -0
- package/engine/graphics/micron/format/MicronGeometry.js +30 -25
- package/engine/graphics/micron/format/MicronGeometryPatch.d.ts +3 -0
- package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.spec.js +63 -0
- package/engine/graphics/micron/format/validate_patch_bounds.js +69 -0
- package/package.json +1 -1
|
@@ -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,14 @@
|
|
|
1
|
+
import { v3_dot } from "../../v3_dot.js";
|
|
2
|
+
|
|
3
|
+
export function ray_distance_to_point(origin_x, origin_y, origin_z, direction_x, direction_y, direction_z,ref_x, ref_y, ref_z){
|
|
4
|
+
// find closest point
|
|
5
|
+
const sp0_x = ref_x - origin_x;
|
|
6
|
+
const sp0_y = ref_y - origin_y;
|
|
7
|
+
const sp0_z = ref_z - origin_z;
|
|
8
|
+
|
|
9
|
+
//
|
|
10
|
+
const d2 = v3_dot(direction_x, direction_y, direction_z, direction_x, direction_y, direction_z);
|
|
11
|
+
const d3 = v3_dot(direction_x, direction_y, direction_z, sp0_x, sp0_y, sp0_z);
|
|
12
|
+
|
|
13
|
+
return d3 / d2;
|
|
14
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -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:
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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,7 +3,6 @@ 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";
|
|
7
6
|
|
|
8
7
|
let id_counter = 0;
|
|
9
8
|
|
|
@@ -109,23 +108,7 @@ export class MicronGeometry {
|
|
|
109
108
|
// using group bounds because it's conservative, as we want to be able to hit LOD_0
|
|
110
109
|
|
|
111
110
|
// sphere test
|
|
112
|
-
if (!sphere_array_intersects_ray(patch.group_bounding_sphere,
|
|
113
|
-
origin_x, origin_y, origin_z,
|
|
114
|
-
direction_x, direction_y, direction_z
|
|
115
|
-
)) {
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
111
|
|
|
120
|
-
// box test (more expensive, different volume)
|
|
121
|
-
if (!aabb3_array_intersects_ray(
|
|
122
|
-
patch.group_bounding_box,
|
|
123
|
-
origin_x, origin_y, origin_z,
|
|
124
|
-
direction_x, direction_y, direction_z
|
|
125
|
-
)) {
|
|
126
|
-
// no intersection
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
112
|
|
|
130
113
|
if (patch.lod === 0) {
|
|
131
114
|
// LOD 0 - source geometry
|
|
@@ -133,12 +116,14 @@ export class MicronGeometry {
|
|
|
133
116
|
// cast against bounds
|
|
134
117
|
|
|
135
118
|
// sphere test
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
119
|
+
|
|
120
|
+
// TODO check what's wrong with sphere tests and re-enable them
|
|
121
|
+
// if (!sphere_array_intersects_ray(patch.bounding_sphere,
|
|
122
|
+
// origin_x, origin_y, origin_z,
|
|
123
|
+
// direction_x, direction_y, direction_z
|
|
124
|
+
// )) {
|
|
125
|
+
// continue;
|
|
126
|
+
// }
|
|
142
127
|
|
|
143
128
|
// box test
|
|
144
129
|
if (!aabb3_array_intersects_ray(
|
|
@@ -155,7 +140,7 @@ export class MicronGeometry {
|
|
|
155
140
|
|
|
156
141
|
const vertices = patch.vertex_attribute_arrays[position_attribute_index];
|
|
157
142
|
|
|
158
|
-
for (
|
|
143
|
+
for (i = 0; i < index_count;) {
|
|
159
144
|
const a = indices[i++];
|
|
160
145
|
const b = indices[i++];
|
|
161
146
|
const c = indices[i++];
|
|
@@ -197,12 +182,32 @@ export class MicronGeometry {
|
|
|
197
182
|
}
|
|
198
183
|
|
|
199
184
|
} else {
|
|
185
|
+
|
|
186
|
+
// TODO check what's wrong with sphere tests and re-enable them
|
|
187
|
+
// if (!sphere_array_intersects_ray(patch.group_bounding_sphere,
|
|
188
|
+
// origin_x, origin_y, origin_z,
|
|
189
|
+
// direction_x, direction_y, direction_z
|
|
190
|
+
// )) {
|
|
191
|
+
// continue;
|
|
192
|
+
// }
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
// box test (more expensive, different volume)
|
|
196
|
+
if (!aabb3_array_intersects_ray(
|
|
197
|
+
patch.group_bounding_box,
|
|
198
|
+
origin_x, origin_y, origin_z,
|
|
199
|
+
direction_x, direction_y, direction_z
|
|
200
|
+
)) {
|
|
201
|
+
// no intersection
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
|
|
200
205
|
// refine more
|
|
201
206
|
const children = patch.children;
|
|
202
207
|
|
|
203
208
|
const child_count = children.length;
|
|
204
209
|
|
|
205
|
-
for (
|
|
210
|
+
for (i = 0; i < child_count; i++) {
|
|
206
211
|
const child = children[i];
|
|
207
212
|
|
|
208
213
|
// push to stack
|
package/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.spec.js
ADDED
|
@@ -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.
|
|
8
|
+
"version": "2.34.30",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|