@woosh/meep-engine 2.35.15 → 2.36.0
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/binary/BinaryBuffer.js +42 -17
- package/core/bvh2/BinaryNode.js +1 -1
- package/core/bvh2/aabb3/AABB3.js +2 -2
- package/core/bvh2/aabb3/aabb3_array_combine.js +20 -0
- package/core/bvh2/aabb3/aabb3_array_intersects_frustum_array.js +20 -0
- package/core/bvh2/aabb3/aabb3_array_intersects_ray.js +1 -0
- package/core/bvh2/aabb3/aabb3_array_intersects_ray_array.js +14 -0
- package/core/bvh2/{aabb3_combined_surface_area.js → aabb3/aabb3_combined_surface_area.js} +3 -3
- package/core/bvh2/aabb3/aabb3_intersects_frustum_array.js +1 -19
- package/core/bvh2/bvh3/BVHNodeProxy.js +53 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +848 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.spec.js +142 -0
- package/core/bvh2/bvh3/bvh_query_leaves_generic.js +79 -0
- package/core/bvh2/bvh3/bvh_query_leaves_ray.js +95 -0
- package/core/bvh2/bvh3/query/BVHQuery.js +11 -0
- package/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +36 -0
- package/core/bvh2/bvh3/query/BVHQueryIntersectsRay.js +36 -0
- package/core/collection/array/copyArray.js +2 -2
- package/core/collection/array/typed/uint_array_for_count.js +17 -0
- package/core/collection/table/RowFirstTable.js +25 -7
- package/core/collection/table/RowFirstTableSpec.js +4 -4
- package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +1 -1
- package/{engine/graphics/util → core/geom/3d/aabb}/computeBoundingBoxFromVertexData.js +1 -1
- package/core/geom/3d/compose_matrix4_array.js +53 -0
- package/{engine/graphics/util → core/geom/3d}/decompose_matrix_4_array.js +0 -0
- package/core/geom/Vector1.js +2 -3
- package/engine/asset/loaders/GLTFAssetLoader.js +3 -0
- package/engine/asset/loaders/gltf/GLTFAssetTransformMikkTSpaceTangents.js +27 -0
- package/engine/ecs/EntityComponentDataset.js +7 -4
- package/engine/ecs/foliage/InstancedFoliage.js +1 -1
- package/engine/ecs/foliage/ViewState.js +1 -1
- package/engine/ecs/transform/Transform.js +2 -2
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.d.ts +5 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +46 -12
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +81 -95
- package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +16 -5
- package/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +1 -0
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +3 -4
- package/engine/graphics/ecs/path/PathDisplaySystem.js +2 -1
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +8 -8
- package/engine/graphics/ecs/path/tube/CapType.d.ts +5 -0
- package/engine/graphics/ecs/path/tube/CapType.js +9 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +2 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +10 -1
- package/engine/graphics/ecs/path/tube/build/GeometryOutput.js +90 -0
- package/engine/graphics/ecs/path/tube/build/build_geometry_catmullrom.js +3 -2
- package/engine/graphics/ecs/path/tube/build/build_geometry_linear.js +1 -1
- package/engine/graphics/ecs/path/tube/build/computeFrenetFrames.js +1 -2
- package/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +353 -91
- package/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +390 -0
- package/engine/graphics/geometry/MikkT/MikkTSpace.js +2210 -0
- package/engine/graphics/geometry/MikkT/MikkTSpace.spec.js +22 -0
- package/engine/graphics/geometry/MikkT/buffer_geometry_ensure_tangents.js +34 -0
- package/engine/graphics/geometry/MikkT/buffer_geometry_generate_tangents.js +28 -0
- package/engine/graphics/{compute_geometry_polycount.js → geometry/compute_geometry_polycount.js} +0 -0
- package/engine/graphics/geometry/skining/computeSkinnedMeshBoundingVolumes.js +1 -1
- package/engine/graphics/micron/build/fill_patch_geometry_data.js +1 -18
- package/engine/graphics/micron/format/MicronGeometry.js +7 -4
- package/engine/graphics/micron/format/micron_build_proxy_geometry.js +203 -0
- package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.js +83 -0
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +63 -19
- package/engine/graphics/micron/plugin/GLTF_MICRON_ID_FIELD.js +5 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -4
- package/engine/graphics/micron/prototypeMicronProxyBuild.js +227 -0
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +2 -2
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +2 -2
- package/engine/graphics/render/forward_plus/LightManager.js +5 -5
- package/engine/graphics/render/forward_plus/data/channelCountToThreIntegerTextureType.js +3 -3
- package/engine/graphics/texture/channelCountToThreeTextureFormat.js +2 -2
- package/engine/graphics/util/composeMatrix4.js +1 -53
- package/engine/graphics/util/composeMatrix4RotationScale.js +1 -1
- package/engine/intelligence/behavior/ecs/BehaviorComponent.js +1 -1
- package/engine/intelligence/blackboard/AbstractBlackboard.js +9 -0
- package/engine/navigation/grid/FastBinaryHeap.js +13 -2
- package/engine/notify/Notification.js +1 -1
- package/engine/ui/notification/ViewEmitter.js +7 -1
- package/engine/ui/notification/notificationGenerator.js +1 -1
- package/engine/ui/scene/SceneGUIContext.js +11 -130
- package/engine/ui/scene/initializeNotifications.js +141 -0
- package/package.json +1 -1
- package/view/elements/notify/NotificationView.js +1 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { genTangSpace, SMikkTSpaceContext } from "./MikkTSpace.js";
|
|
2
|
+
|
|
3
|
+
test('empty geometry', () => {
|
|
4
|
+
const ctx = new SMikkTSpaceContext();
|
|
5
|
+
|
|
6
|
+
expect(() => {
|
|
7
|
+
genTangSpace(ctx);
|
|
8
|
+
}).not.toThrow();
|
|
9
|
+
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('single triangle', () => {
|
|
13
|
+
const ctx = new SMikkTSpaceContext();
|
|
14
|
+
|
|
15
|
+
ctx.geometry_buffer_index = [0, 1, 2];
|
|
16
|
+
ctx.geometry_buffer_vertex_position = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
17
|
+
ctx.geometry_buffer_vertex_normal = [0, 1, 0, 0, 1, 0, 0, 1, 0];
|
|
18
|
+
ctx.geometry_buffer_vertex_uv = [0, 0, 0, 0, 0, 0];
|
|
19
|
+
|
|
20
|
+
genTangSpace(ctx);
|
|
21
|
+
|
|
22
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { buffer_geometry_generate_tangents } from "./buffer_geometry_generate_tangents.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {THREE.BufferGeometry} geo
|
|
6
|
+
*/
|
|
7
|
+
export function buffer_geometry_ensure_tangents(geo) {
|
|
8
|
+
if (geo.getAttribute('tangent') !== undefined) {
|
|
9
|
+
// already got tangents
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (geo.getIndex() === null) {
|
|
14
|
+
// non-indexed, unsupported
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (geo.getAttribute('normal') === undefined) {
|
|
19
|
+
// no normals
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (geo.getAttribute('uv') === undefined) {
|
|
24
|
+
// UVs are required by the algorithm
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (geo.getAttribute('position') === undefined) {
|
|
29
|
+
// positions are required as well
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
buffer_geometry_generate_tangents(geo);
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BufferAttribute } from "three";
|
|
2
|
+
import { genTangSpace, SMikkTSpaceContext } from "./MikkTSpace.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* only works with indexed geometries
|
|
6
|
+
* @param {THREE.BufferGeometry} geo
|
|
7
|
+
*/
|
|
8
|
+
export function buffer_geometry_generate_tangents(geo) {
|
|
9
|
+
|
|
10
|
+
const attribute_position = geo.getAttribute('position');
|
|
11
|
+
|
|
12
|
+
if (geo.getAttribute('tangent') === undefined) {
|
|
13
|
+
geo.setAttribute('tangent', new BufferAttribute(new Float32Array(attribute_position.count * 4), 4, false));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const attribute_tangent = geo.getAttribute('tangent');
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const ctx = new SMikkTSpaceContext();
|
|
20
|
+
|
|
21
|
+
ctx.geometry_buffer_index = geo.getIndex().array;
|
|
22
|
+
ctx.geometry_buffer_vertex_position = attribute_position.array;
|
|
23
|
+
ctx.geometry_buffer_vertex_normal = geo.getAttribute('normal').array;
|
|
24
|
+
ctx.geometry_buffer_vertex_uv = geo.getAttribute('uv').array;
|
|
25
|
+
ctx.geometry_buffer_vertex_tangent = attribute_tangent.array;
|
|
26
|
+
|
|
27
|
+
genTangSpace(ctx);
|
|
28
|
+
}
|
package/engine/graphics/{compute_geometry_polycount.js → geometry/compute_geometry_polycount.js}
RENAMED
|
File without changes
|
|
@@ -3,7 +3,7 @@ import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
|
3
3
|
import Vector4 from "../../../../core/geom/Vector4.js";
|
|
4
4
|
import { computeBoundingSphereFromVertexData } from "../computeBoundingSphereFromVertexData.js";
|
|
5
5
|
import { Box3, Sphere as ThreeSphere, Vector3 as ThreeVector3 } from "three";
|
|
6
|
-
import { computeBoundingBoxFromVertexData } from "
|
|
6
|
+
import { computeBoundingBoxFromVertexData } from "../../../../core/geom/3d/aabb/computeBoundingBoxFromVertexData.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {number} count
|
|
4
|
-
* @returns {Function}
|
|
5
|
-
* @constructor
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
1
|
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
9
2
|
import { passThrough } from "../../../../core/function/Functions.js";
|
|
10
3
|
import { to_half_float_uint16 } from "../../../../core/binary/to_half_float_uint16.js";
|
|
@@ -12,17 +5,7 @@ import { compute_micron_buffer_array_constructor } from "./compute_micron_buffer
|
|
|
12
5
|
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
13
6
|
import { dataTypeByteSize } from "../../../../core/collection/table/DataTypeByteSizes.js";
|
|
14
7
|
import { clamp } from "../../../../core/math/clamp.js";
|
|
15
|
-
|
|
16
|
-
function UintArrayForCount(count) {
|
|
17
|
-
|
|
18
|
-
if (count <= 256) {
|
|
19
|
-
return Uint8Array;
|
|
20
|
-
} else if (count <= 65536) {
|
|
21
|
-
return Uint16Array;
|
|
22
|
-
} else {
|
|
23
|
-
throw new Error(`Unsupported size ${count}`)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
8
|
+
import { UintArrayForCount } from "../../../../core/collection/array/typed/uint_array_for_count.js";
|
|
26
9
|
|
|
27
10
|
/**
|
|
28
11
|
* @param {number} vertex_count
|
|
@@ -5,6 +5,7 @@ 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
6
|
import { sphere_array_intersects_ray } from "../../../../core/geom/3d/sphere/sphere_array_intersects_ray.js";
|
|
7
7
|
import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
8
|
+
import { micron_build_proxy_geometry } from "./micron_build_proxy_geometry.js";
|
|
8
9
|
|
|
9
10
|
let id_counter = 0;
|
|
10
11
|
|
|
@@ -286,11 +287,13 @@ export class MicronGeometry {
|
|
|
286
287
|
|
|
287
288
|
/**
|
|
288
289
|
* Build geometry proxy from the patches
|
|
289
|
-
* @param {number} fraction percentage of the original geometry to keep
|
|
290
|
-
* @param {number} min minimum number of triangles to keep, this will be respected first before percentage value
|
|
290
|
+
* @param {number} [fraction] percentage of the original geometry to keep
|
|
291
|
+
* @param {number} [min] minimum number of triangles to keep, this will be respected first before percentage value
|
|
291
292
|
*/
|
|
292
|
-
buildProxy(fraction, min) {
|
|
293
|
-
|
|
293
|
+
buildProxy(fraction = 0.05, min = 2048) {
|
|
294
|
+
const bufferGeometry = micron_build_proxy_geometry(this, fraction, min);
|
|
295
|
+
|
|
296
|
+
this.__proxy = bufferGeometry;
|
|
294
297
|
}
|
|
295
298
|
|
|
296
299
|
computeByteSize() {
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import BinaryHeap from "../../../navigation/grid/FastBinaryHeap.js";
|
|
4
|
+
import { BufferAttribute, BufferGeometry } from "three";
|
|
5
|
+
import { UintArrayForCount } from "../../../../core/collection/array/typed/uint_array_for_count.js";
|
|
6
|
+
import { compute_typed_array_constructor_from_data_type } from "../../../../core/collection/table/DataType2TypedArrayConstructorMapping.js";
|
|
7
|
+
import { BitSet } from "../../../../core/binary/BitSet.js";
|
|
8
|
+
import { min2 } from "../../../../core/math/min2.js";
|
|
9
|
+
import { max2 } from "../../../../core/math/max2.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {MicronGeometry} micron_geometry
|
|
14
|
+
* @param {number} fraction
|
|
15
|
+
* @param {number} min_face_count
|
|
16
|
+
* @returns {MicronGeometryPatch[]}
|
|
17
|
+
*/
|
|
18
|
+
function collect_patches(micron_geometry, fraction, min_face_count) {
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @type {BinaryHeap<MicronGeometryPatch>}
|
|
22
|
+
*/
|
|
23
|
+
const heap = new BinaryHeap(patch => {
|
|
24
|
+
// LOD is a good proxy for how much detail there is in a patch
|
|
25
|
+
return -patch.lod;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
let closed_set = new BitSet();
|
|
29
|
+
|
|
30
|
+
let current_polycount = 0;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @param {MicronGeometryPatch} patch
|
|
35
|
+
*/
|
|
36
|
+
function add(patch) {
|
|
37
|
+
|
|
38
|
+
closed_set.set(patch.id, true);
|
|
39
|
+
|
|
40
|
+
heap.push(patch);
|
|
41
|
+
|
|
42
|
+
current_polycount += patch.polygon_count;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {MicronGeometryPatch} patch
|
|
48
|
+
*/
|
|
49
|
+
function refine(patch) {
|
|
50
|
+
const children = patch.children;
|
|
51
|
+
const child_count = children.length;
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < child_count; i++) {
|
|
55
|
+
const child = children[i];
|
|
56
|
+
|
|
57
|
+
if (closed_set.get(child.id)) {
|
|
58
|
+
// already refined
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
add(child);
|
|
63
|
+
|
|
64
|
+
const parents = child.parents;
|
|
65
|
+
|
|
66
|
+
const parent_count = parents.length;
|
|
67
|
+
for (let j = 0; j < parent_count; j++) {
|
|
68
|
+
const parent = parents[j];
|
|
69
|
+
|
|
70
|
+
if (parent === parent) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// remove and refine other patches in the same group
|
|
75
|
+
if (heap.delete(parent)) {
|
|
76
|
+
refine(parent);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
add(micron_geometry.root);
|
|
83
|
+
|
|
84
|
+
const target_polycount_threshold = max2(
|
|
85
|
+
micron_geometry.source_triangle_count * fraction,
|
|
86
|
+
min2(
|
|
87
|
+
min_face_count,
|
|
88
|
+
micron_geometry.source_triangle_count
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
while (current_polycount < target_polycount_threshold) {
|
|
93
|
+
const p = heap.peek();
|
|
94
|
+
|
|
95
|
+
if (p === undefined || p.lod === 0) {
|
|
96
|
+
// no refinement possible
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
heap.pop();
|
|
101
|
+
|
|
102
|
+
current_polycount -= p.polygon_count;
|
|
103
|
+
|
|
104
|
+
refine(p);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const result = [];
|
|
108
|
+
|
|
109
|
+
// collect
|
|
110
|
+
while (!heap.isEmpty()) {
|
|
111
|
+
result.push(heap.pop());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
* @param {MicronGeometryPatch[]} patches
|
|
120
|
+
* @param {VertexDataSpec} vertex_spec
|
|
121
|
+
* @returns {THREE.BufferGeometry}
|
|
122
|
+
*/
|
|
123
|
+
function assemble_patches_to_geometry(patches, vertex_spec) {
|
|
124
|
+
const geo = new BufferGeometry();
|
|
125
|
+
|
|
126
|
+
//compute total number of vertices and faces
|
|
127
|
+
let total_faces = 0;
|
|
128
|
+
let total_vertices = 0;
|
|
129
|
+
|
|
130
|
+
for (let i = 0; i < patches.length; i++) {
|
|
131
|
+
const patch = patches[i];
|
|
132
|
+
|
|
133
|
+
total_faces += patch.polygon_count;
|
|
134
|
+
total_vertices += patch.vertex_count;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const index_data = new (UintArrayForCount(total_vertices))(total_faces * 3);
|
|
138
|
+
|
|
139
|
+
geo.setIndex(new BufferAttribute(index_data, 1, false));
|
|
140
|
+
|
|
141
|
+
const attribute_arrays = [];
|
|
142
|
+
|
|
143
|
+
const attribute_specs = vertex_spec.attributes;
|
|
144
|
+
const attribute_count = attribute_specs.length;
|
|
145
|
+
for (let i = 0; i < attribute_count; i++) {
|
|
146
|
+
const attribute = attribute_specs[i];
|
|
147
|
+
|
|
148
|
+
const TA = compute_typed_array_constructor_from_data_type(attribute.type);
|
|
149
|
+
|
|
150
|
+
const attribute_data = new TA(total_vertices * 3);
|
|
151
|
+
|
|
152
|
+
attribute_arrays[i] = attribute_data;
|
|
153
|
+
|
|
154
|
+
geo.setAttribute(attribute.name, new BufferAttribute(attribute_data, attribute.itemSize, attribute.normalized));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let index_cursor = 0;
|
|
158
|
+
let vertex_cursor = 0;
|
|
159
|
+
|
|
160
|
+
// add patches to resulting geometry
|
|
161
|
+
for (let i = 0; i < patches.length; i++) {
|
|
162
|
+
const patch = patches[i];
|
|
163
|
+
|
|
164
|
+
const local_index_size = patch.polygon_count * 3;
|
|
165
|
+
|
|
166
|
+
// copy transformed indices
|
|
167
|
+
for (let j = 0; j < local_index_size; j++) {
|
|
168
|
+
const local_index = patch.face_indices[j];
|
|
169
|
+
|
|
170
|
+
index_data[index_cursor + j] = local_index + vertex_cursor;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// copy vertex data
|
|
174
|
+
|
|
175
|
+
for (let j = 0; j < attribute_count; j++) {
|
|
176
|
+
const attribute_destination = attribute_arrays[j];
|
|
177
|
+
|
|
178
|
+
const attribute_source = patch.vertex_attribute_arrays[j];
|
|
179
|
+
const destination_offset = vertex_cursor * attribute_specs[j].itemSize;
|
|
180
|
+
|
|
181
|
+
attribute_destination.set(attribute_source, destination_offset);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
vertex_cursor += patch.vertex_count;
|
|
185
|
+
index_cursor += local_index_size;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return geo;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
*
|
|
194
|
+
* @param {MicronGeometry} micron_geometry
|
|
195
|
+
* @param {number} fraction
|
|
196
|
+
* @param {number} [min_face_count]
|
|
197
|
+
* @returns {THREE.BufferGeometry}
|
|
198
|
+
*/
|
|
199
|
+
export function micron_build_proxy_geometry(micron_geometry, fraction, min_face_count = 128) {
|
|
200
|
+
const patches = collect_patches(micron_geometry, fraction, min_face_count);
|
|
201
|
+
|
|
202
|
+
return assemble_patches_to_geometry(patches, micron_geometry.vertex_spec);
|
|
203
|
+
}
|
package/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { MicronGeometryBinarySerializationAdapter } from "../MicronGeometryBinarySerializationAdapter.js";
|
|
2
|
+
import { MicronGeometry } from "../../MicronGeometry.js";
|
|
3
|
+
|
|
4
|
+
const SUPPORTED_ADAPTER_VERSION = 0;
|
|
5
|
+
const HEADER_MAGIC_TEXT = 'MICRON#001';
|
|
6
|
+
|
|
7
|
+
function obtain_micron_adapter() {
|
|
8
|
+
|
|
9
|
+
const ga = new MicronGeometryBinarySerializationAdapter();
|
|
10
|
+
|
|
11
|
+
if (ga.version !== SUPPORTED_ADAPTER_VERSION) {
|
|
12
|
+
throw new Error(`Incorrect version of serialization adapter, expected ${SUPPORTED_ADAPTER_VERSION}, instead got ${ga.version}`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return ga;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param {MicronGeometry[]} destination
|
|
21
|
+
* @param {BinaryBuffer} buffer
|
|
22
|
+
* @returns {number} how many geometries were read
|
|
23
|
+
*/
|
|
24
|
+
export function deserialize_geometry_collection(destination, buffer) {
|
|
25
|
+
// read header
|
|
26
|
+
const header_text = buffer.readASCIICharacters(HEADER_MAGIC_TEXT.length);
|
|
27
|
+
|
|
28
|
+
if (header_text !== HEADER_MAGIC_TEXT) {
|
|
29
|
+
throw new Error(`Wrong header magic, expected '${HEADER_MAGIC_TEXT}', instead got '${header_text}'`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// read how many geometries we're expecting
|
|
33
|
+
const geometry_occupies_count = buffer.readUint32();
|
|
34
|
+
|
|
35
|
+
const ga = obtain_micron_adapter();
|
|
36
|
+
|
|
37
|
+
for (let i = 0; i < geometry_occupies_count; i++) {
|
|
38
|
+
// read key
|
|
39
|
+
const key = buffer.readUint32();
|
|
40
|
+
|
|
41
|
+
const geometry = new MicronGeometry();
|
|
42
|
+
|
|
43
|
+
ga.deserialize(buffer, geometry);
|
|
44
|
+
|
|
45
|
+
destination[key] = geometry;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return geometry_occupies_count;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param {MicronGeometry[]} geometries
|
|
54
|
+
* @param {BinaryBuffer} buffer
|
|
55
|
+
*/
|
|
56
|
+
export function serialize_geometry_collection(geometries, buffer) {
|
|
57
|
+
// write header
|
|
58
|
+
buffer.writeASCIIString(HEADER_MAGIC_TEXT); // magic bytes
|
|
59
|
+
|
|
60
|
+
// count geometries
|
|
61
|
+
let geometry_occupied_count = 0;
|
|
62
|
+
const geometry_count = geometries.length;
|
|
63
|
+
for (let i = 0; i < geometry_count; i++) {
|
|
64
|
+
if (geometries[i] === undefined) {
|
|
65
|
+
geometry_occupied_count++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
buffer.writeUint32(geometry_occupied_count); // how many geometries to expect
|
|
70
|
+
|
|
71
|
+
const ga = obtain_micron_adapter();
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < geometry_count; i++) {
|
|
74
|
+
const geometry = geometries[i];
|
|
75
|
+
if (geometry === undefined) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
buffer.writeUint32(i); // key
|
|
80
|
+
|
|
81
|
+
ga.serialize(buffer, geometry);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { AssetTransformer } from "../../../asset/AssetTransformer.js";
|
|
2
|
-
import { MicronGeometryBinarySerializationAdapter } from "../format/serialization/MicronGeometryBinarySerializationAdapter.js";
|
|
3
|
-
import { MICRON_URI_FIELD } from "../MICRON_URI_FIELD.js";
|
|
4
2
|
import { computePathDirectory } from "../../../../core/FilePath.js";
|
|
5
3
|
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
6
4
|
import { MicronGeometry } from "../format/MicronGeometry.js";
|
|
7
5
|
import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
|
|
8
6
|
import { async_traverse_three_object } from "../../../asset/loaders/async_traverse_three_object.js";
|
|
9
7
|
import { convert_three_object_to_micron } from "../convert_three_object_to_micron.js";
|
|
10
|
-
import { compute_geometry_polycount } from "../../compute_geometry_polycount.js";
|
|
8
|
+
import { compute_geometry_polycount } from "../../geometry/compute_geometry_polycount.js";
|
|
11
9
|
import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
|
|
12
10
|
import { max2 } from "../../../../core/math/max2.js";
|
|
11
|
+
import { deserialize_geometry_collection } from "../format/serialization/collection/geometry_collection_serialization.js";
|
|
12
|
+
import { GLTF_MICRON_ID_FIELD } from "./GLTF_MICRON_ID_FIELD.js";
|
|
13
13
|
|
|
14
14
|
export const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
|
|
15
15
|
|
|
@@ -35,6 +35,25 @@ function max_polycount(object) {
|
|
|
35
35
|
return r;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {THREE.Object3D} object
|
|
41
|
+
*/
|
|
42
|
+
function ensureProxy(object) {
|
|
43
|
+
if (object.isMicronMesh) {
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @type {MicronGeometry}
|
|
47
|
+
*/
|
|
48
|
+
const micron_geo = object.geometry;
|
|
49
|
+
|
|
50
|
+
if (micron_geo.proxy === null) {
|
|
51
|
+
// proxy geometry doesn't exist, build one
|
|
52
|
+
micron_geo.buildProxy();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
38
57
|
export class GLTFAssetTransformer extends AssetTransformer {
|
|
39
58
|
/**
|
|
40
59
|
*
|
|
@@ -66,10 +85,10 @@ export class GLTFAssetTransformer extends AssetTransformer {
|
|
|
66
85
|
|
|
67
86
|
/**
|
|
68
87
|
*
|
|
69
|
-
* @type {
|
|
88
|
+
* @type {MicronGeometry[]}
|
|
70
89
|
* @private
|
|
71
90
|
*/
|
|
72
|
-
this.
|
|
91
|
+
this.__active_mesh_micron_cache = [];
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
/**
|
|
@@ -97,23 +116,52 @@ export class GLTFAssetTransformer extends AssetTransformer {
|
|
|
97
116
|
*/
|
|
98
117
|
const geometry = object.geometry;
|
|
99
118
|
|
|
100
|
-
const
|
|
119
|
+
const micron_geometry_index = geometry.userData[GLTF_MICRON_ID_FIELD];
|
|
101
120
|
|
|
102
|
-
if (typeof
|
|
121
|
+
if (typeof micron_geometry_index !== "number") {
|
|
103
122
|
return;
|
|
104
123
|
}
|
|
105
124
|
|
|
125
|
+
const micron_geometry = this.__active_mesh_micron_cache[micron_geometry_index];
|
|
106
126
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
if (micron_geometry === undefined) {
|
|
128
|
+
console.error(`Micron geometry '${micron_geometry_index}' not found`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// set proxy for raycasting
|
|
133
|
+
micron_geometry.proxy = geometry;
|
|
134
|
+
|
|
135
|
+
geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
* @param {{userData:{}}} gltf
|
|
142
|
+
* @param {AssetDescription} ad
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
async __load_mesh_micron_data(gltf, ad) {
|
|
146
|
+
// clear active cache
|
|
147
|
+
this.__active_mesh_micron_cache = [];
|
|
148
|
+
|
|
149
|
+
const micron_metadata = gltf.userData.micron;
|
|
150
|
+
|
|
151
|
+
if (micron_metadata === undefined) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const uri = micron_metadata.geometry_data_uri;
|
|
156
|
+
if (uri === undefined) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
111
159
|
|
|
112
160
|
const base = computePathDirectory(ad.path);
|
|
113
161
|
|
|
114
162
|
let micron_data;
|
|
115
163
|
|
|
116
|
-
const micron_path = `${base}/${
|
|
164
|
+
const micron_path = `${base}/${uri}`;
|
|
117
165
|
|
|
118
166
|
try {
|
|
119
167
|
micron_data = await this.__am.promise(micron_path, ASSET_TYPE_ARRAY_BUFFER);
|
|
@@ -124,14 +172,8 @@ export class GLTFAssetTransformer extends AssetTransformer {
|
|
|
124
172
|
|
|
125
173
|
// deserialize micron data
|
|
126
174
|
const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
|
|
127
|
-
const micron_geometry = new MicronGeometry();
|
|
128
|
-
|
|
129
|
-
this.__serde.deserialize(buffer, micron_geometry);
|
|
130
175
|
|
|
131
|
-
|
|
132
|
-
micron_geometry.proxy = geometry;
|
|
133
|
-
|
|
134
|
-
geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
|
|
176
|
+
deserialize_geometry_collection(this.__active_mesh_micron_cache, buffer);
|
|
135
177
|
}
|
|
136
178
|
|
|
137
179
|
|
|
@@ -171,6 +213,8 @@ export class GLTFAssetTransformer extends AssetTransformer {
|
|
|
171
213
|
|
|
172
214
|
source.override_mesh = micron_root;
|
|
173
215
|
|
|
216
|
+
traverseThreeObject(micron_root, ensureProxy);
|
|
217
|
+
|
|
174
218
|
return source;
|
|
175
219
|
}
|
|
176
220
|
}
|