@woosh/meep-engine 2.48.20 → 2.48.22
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/package.json +1 -1
- package/src/{engine/graphics/micron/build/clustering → core/geom/3d/topology/util}/compute_face_connection_weight.js +40 -35
- package/src/core/graph/build_face_graph_from_mesh.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/sample/load_gltf.js +0 -3
- package/src/engine/graphics/micron/MICRON_GEOMETRY_FIELD.js +0 -1
- package/src/engine/graphics/micron/MICRON_URI_FIELD.js +0 -1
- package/src/engine/graphics/micron/build/MICRON_PATCH_SIZE_MAX.js +0 -5
- package/src/engine/graphics/micron/build/PatchRepresentation.js +0 -424
- package/src/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +0 -311
- package/src/engine/graphics/micron/build/build_geometry_info.js +0 -21
- package/src/engine/graphics/micron/build/clustering/assignInitialPatchNeighbours.js +0 -63
- package/src/engine/graphics/micron/build/clustering/assign_patch_neighbours_from_topology.js +0 -46
- package/src/engine/graphics/micron/build/clustering/build_clustering_2.js +0 -37
- package/src/engine/graphics/micron/build/clustering/build_leaf_patches.js +0 -326
- package/src/engine/graphics/micron/build/clustering/build_leaf_patches_metis.js +0 -76
- package/src/engine/graphics/micron/build/clustering/computeBorderLengthChange.js +0 -59
- package/src/engine/graphics/micron/build/clustering/computeFaceCurvatureScore.js +0 -57
- package/src/engine/graphics/micron/build/clustering/computeOpenFaceFreedom.js +0 -35
- package/src/engine/graphics/micron/build/clustering/populateOpenFaceNeighboursForPatch.js +0 -56
- package/src/engine/graphics/micron/build/clustering/validate_leaf_patch_connectivity.js +0 -44
- package/src/engine/graphics/micron/build/compute_micron_buffer_array_constructor.js +0 -24
- package/src/engine/graphics/micron/build/compute_vertex_remap_cost.js +0 -29
- package/src/engine/graphics/micron/build/debug/build_clustering_info.js +0 -58
- package/src/engine/graphics/micron/build/debug/build_graph_info.js +0 -59
- package/src/engine/graphics/micron/build/fill_patch_geometry_data.js +0 -270
- package/src/engine/graphics/micron/build/hierarchy/buildAbstractPatchHierarchy.js +0 -196
- package/src/engine/graphics/micron/build/hierarchy/build_intermediate_patch_topology.js +0 -162
- package/src/engine/graphics/micron/build/hierarchy/build_merge_graph.js +0 -89
- package/src/engine/graphics/micron/build/hierarchy/computePatchMergeScore.js +0 -146
- package/src/engine/graphics/micron/build/hierarchy/compute_patches_shared_vertex_count.js +0 -32
- package/src/engine/graphics/micron/build/hierarchy/compute_patches_shared_vertices.js +0 -34
- package/src/engine/graphics/micron/build/hierarchy/merge_patches.js +0 -581
- package/src/engine/graphics/micron/build/hierarchy/metis_cluster_clusters.js +0 -53
- package/src/engine/graphics/micron/build/hierarchy/optimize_graph_partitioning_balance.js +0 -515
- package/src/engine/graphics/micron/build/hierarchy/patch_combine.js +0 -180
- package/src/engine/graphics/micron/build/hierarchy/patch_fill_holes_by_uncollapse.js +0 -60
- package/src/engine/graphics/micron/build/hierarchy/patch_stitch_parent_border.js +0 -320
- package/src/engine/graphics/micron/build/hierarchy/qvdr_build_simplified_clusters.js +0 -547
- package/src/engine/graphics/micron/build/hierarchy/qvdr_build_tree.js +0 -140
- package/src/engine/graphics/micron/buildPatchwork.js +0 -68
- package/src/engine/graphics/micron/convert_three_object_to_micron.js +0 -179
- package/src/engine/graphics/micron/debug/VirtualGeometryStats.js +0 -42
- package/src/engine/graphics/micron/format/MICRON_GEOMETRY_PROPERTY_NAME.js +0 -1
- package/src/engine/graphics/micron/format/MicronGeometry.d.ts +0 -21
- package/src/engine/graphics/micron/format/MicronGeometry.js +0 -334
- package/src/engine/graphics/micron/format/MicronGeometryPatch.d.ts +0 -3
- package/src/engine/graphics/micron/format/MicronGeometryPatch.js +0 -205
- package/src/engine/graphics/micron/format/MicronGeometryPatchOccurance.js +0 -50
- package/src/engine/graphics/micron/format/ThreeMicronMesh.d.ts +0 -10
- package/src/engine/graphics/micron/format/ThreeMicronMesh.js +0 -45
- package/src/engine/graphics/micron/format/VirtualGeometry.js +0 -158
- package/src/engine/graphics/micron/format/micron_build_proxy_geometry.js +0 -205
- package/src/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.js +0 -123
- package/src/engine/graphics/micron/format/serialization/MicronGeometryBinarySerializationAdapter.spec.js +0 -63
- package/src/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.js +0 -83
- package/src/engine/graphics/micron/format/serialization/collection/geometry_collection_serialization.spec.js +0 -51
- package/src/engine/graphics/micron/format/serialization/deserialize_attribute_spec.js +0 -25
- package/src/engine/graphics/micron/format/serialization/deserialize_patch.js +0 -106
- package/src/engine/graphics/micron/format/serialization/serialize_attribute_spec.js +0 -18
- package/src/engine/graphics/micron/format/serialization/serialize_patch.js +0 -84
- package/src/engine/graphics/micron/format/validate_patch_bounds.js +0 -69
- package/src/engine/graphics/micron/plugin/GLTFAssetTransformer.js +0 -265
- package/src/engine/graphics/micron/plugin/GLTF_MICRON_ID_FIELD.js +0 -5
- package/src/engine/graphics/micron/plugin/MicronRenderPlugin.d.ts +0 -8
- package/src/engine/graphics/micron/plugin/MicronRenderPlugin.js +0 -150
- package/src/engine/graphics/micron/plugin/serialization/BufferGeometrySerializationAdapter.js +0 -176
- package/src/engine/graphics/micron/plugin/shaded_geometry/MicronShadedGeometryRenderAdapter.js +0 -216
- package/src/engine/graphics/micron/prototypeMicronProxyBuild.js +0 -227
- package/src/engine/graphics/micron/prototypeVirtualGeometry.js +0 -911
- package/src/engine/graphics/micron/render/PatchCacheKey.js +0 -79
- package/src/engine/graphics/micron/render/VIRTUAL_MESH_FLAG.d.ts +0 -1
- package/src/engine/graphics/micron/render/VIRTUAL_MESH_FLAG.js +0 -1
- package/src/engine/graphics/micron/render/VirtualGeometryBuilder.js +0 -207
- package/src/engine/graphics/micron/render/approximateTriangleArea.js +0 -25
- package/src/engine/graphics/micron/render/culling/PatchCullingSystem.js +0 -129
- package/src/engine/graphics/micron/render/instanced/PatchDataTextures.js +0 -329
- package/src/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +0 -175
- package/src/engine/graphics/micron/render/instanced/shader/constants.js +0 -3
- package/src/engine/graphics/micron/render/instanced/shader/gen_micron_vertex_attribute_texture_name.js +0 -8
- package/src/engine/graphics/micron/render/instanced/shader/shader_rewrite_standard.js +0 -250
- package/src/engine/graphics/micron/render/makeThreeMeshFromVirtualGeometry.js +0 -37
- package/src/engine/graphics/micron/render/refinement/ActivePatchFlags.js +0 -8
- package/src/engine/graphics/micron/render/refinement/ActivePatchList.js +0 -241
- package/src/engine/graphics/micron/render/refinement/ActivePatchRecord.js +0 -154
- package/src/engine/graphics/micron/render/refinement/RefinementSpec.js +0 -84
- package/src/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +0 -133
- package/src/engine/graphics/micron/render/refinement/is_patch_facing_back.js +0 -43
- package/src/engine/graphics/micron/render/refinement/is_patch_visible.js +0 -37
- package/src/engine/graphics/micron/render/v1/MaterialContext.js +0 -150
- package/src/engine/graphics/micron/render/v1/MaterialVertexSpec.js +0 -115
- package/src/engine/graphics/micron/render/v1/MicronRenderContext.js +0 -145
- package/src/engine/graphics/micron/render/v1/ThreeVirtualGeometryAdapter.js +0 -255
- package/src/engine/graphics/micron/render/v1/VGThreeRenderer.js +0 -142
- package/src/engine/graphics/micron/render/v1/getTransformedPositionsCached.js +0 -54
- package/src/engine/graphics/micron/simplifyGeometry.js +0 -26
- package/src/engine/graphics/micron/util/patchToBufferGeometry.js +0 -19
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
compute_face_normal_change_dot_product
|
|
3
|
-
} from "../../../../core/geom/3d/topology/simplify/compute_face_normal_change_dot_product.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {TopoVertex} from
|
|
8
|
-
* @param {TopoVertex} to
|
|
9
|
-
*
|
|
10
|
-
* @returns {number}
|
|
11
|
-
*/
|
|
12
|
-
export function computeVertexRemapCost(from, to) {
|
|
13
|
-
let result = 0;
|
|
14
|
-
|
|
15
|
-
const faces = from.faces;
|
|
16
|
-
const face_count = faces.length;
|
|
17
|
-
|
|
18
|
-
for (let i = 0; i < face_count; i++) {
|
|
19
|
-
const face = faces[i];
|
|
20
|
-
|
|
21
|
-
const normal_dot = compute_face_normal_change_dot_product(face, from, to);
|
|
22
|
-
|
|
23
|
-
const normal_cost = 1 - normal_dot;
|
|
24
|
-
|
|
25
|
-
result += normal_cost;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { computeStatisticalMedian } from "../../../../../core/math/statistics/computeStatisticalMedian.js";
|
|
2
|
-
import { max2 } from "../../../../../core/math/max2.js";
|
|
3
|
-
import { MICRON_PATCH_SIZE_MAX } from "../MICRON_PATCH_SIZE_MAX.js";
|
|
4
|
-
import { computeStatisticalMean } from "../../../../../core/math/statistics/computeStatisticalMean.js";
|
|
5
|
-
import { formatNumberByThousands, prettyPrint } from "../../../../../core/NumberFormat.js";
|
|
6
|
-
import { computeStatisticalPercentile } from "../../../../../core/math/statistics/computeStatisticalPercentile.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param {PatchRepresentation[]} patches
|
|
11
|
-
*/
|
|
12
|
-
export function build_clustering_info(patches) {
|
|
13
|
-
|
|
14
|
-
const patch_count = patches.length;
|
|
15
|
-
|
|
16
|
-
const patch_face_counts = patches.map(p => p.topology_snapshot.getFaces().size);
|
|
17
|
-
const total_patch_faces = patch_face_counts.reduce((previousValue, x) => previousValue + x, 0);
|
|
18
|
-
|
|
19
|
-
const patch_size_median = computeStatisticalMedian(patch_face_counts);
|
|
20
|
-
const undeflow_face_count = patch_face_counts.reduce((acc, c) => {
|
|
21
|
-
const local_underflow = max2(0, MICRON_PATCH_SIZE_MAX - c);
|
|
22
|
-
return acc + local_underflow;
|
|
23
|
-
}, 0);
|
|
24
|
-
const overflow_face_count = patch_face_counts.reduce((acc, c) => {
|
|
25
|
-
const local_overflow = max2(0, c - MICRON_PATCH_SIZE_MAX);
|
|
26
|
-
return acc + local_overflow;
|
|
27
|
-
}, 0);
|
|
28
|
-
|
|
29
|
-
const patch_size_mean = computeStatisticalMean(patch_face_counts);
|
|
30
|
-
|
|
31
|
-
const connection_count = patches.reduce((acc, p) => acc + p.neighbours.length, 0);
|
|
32
|
-
|
|
33
|
-
// compute perimeter lengths
|
|
34
|
-
const total_perimeter = patches.reduce((acc, p) => acc + p.computePerimeterLength(), 0);
|
|
35
|
-
|
|
36
|
-
const underflow_patch_count = patch_face_counts.filter(p => p < MICRON_PATCH_SIZE_MAX).length;
|
|
37
|
-
|
|
38
|
-
return `Leaf Stats:
|
|
39
|
-
Total faces: ${formatNumberByThousands(total_patch_faces)}
|
|
40
|
-
Patch count: ${formatNumberByThousands(patch_count)}
|
|
41
|
-
|
|
42
|
-
patch size(median): ${patch_size_median}
|
|
43
|
-
patch size(mean): ${patch_size_mean.toFixed(2)}
|
|
44
|
-
patch size(10th %): ${computeStatisticalPercentile(patch_face_counts, .1, 0.1)}
|
|
45
|
-
patch size(25th %): ${computeStatisticalPercentile(patch_face_counts, .25, 0.25)}
|
|
46
|
-
patch size(90th %) : ${computeStatisticalPercentile(patch_face_counts, .9, 0.9)}
|
|
47
|
-
|
|
48
|
-
Total undeflow patches: ${formatNumberByThousands(underflow_patch_count)} (${(underflow_patch_count * 100 / patch_count).toPrecision(3)}%)
|
|
49
|
-
Total undeflow faces: ${formatNumberByThousands(undeflow_face_count)} (${(undeflow_face_count * 100 / total_patch_faces).toPrecision(3)}%)
|
|
50
|
-
Total overflow faces: ${formatNumberByThousands(overflow_face_count)}
|
|
51
|
-
|
|
52
|
-
Total connections: ${formatNumberByThousands(connection_count)}
|
|
53
|
-
Average connectedness : ${(connection_count / patch_count).toPrecision(4)} neighbours/patch
|
|
54
|
-
|
|
55
|
-
Total perimeter: ${prettyPrint(total_perimeter)}
|
|
56
|
-
Average patch perimeter: ${(total_perimeter / patch_count).toPrecision(4)}
|
|
57
|
-
`
|
|
58
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
import { prettyPrint } from "../../../../../core/NumberFormat.js";
|
|
4
|
-
import { MICRON_PATCH_SIZE_MAX } from "../MICRON_PATCH_SIZE_MAX.js";
|
|
5
|
-
import { max2 } from "../../../../../core/math/max2.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @param {PatchRepresentation} root
|
|
10
|
-
* @returns {string}
|
|
11
|
-
*/
|
|
12
|
-
export function build_graph_info(root) {
|
|
13
|
-
// ingest all patches into a flat hierarchy
|
|
14
|
-
const all_nodes = [];
|
|
15
|
-
const leaf_nodes = [];
|
|
16
|
-
const intermediate_nodes = [];
|
|
17
|
-
|
|
18
|
-
root.traverse(n => {
|
|
19
|
-
all_nodes.push(n);
|
|
20
|
-
|
|
21
|
-
if (n.lod === 0) {
|
|
22
|
-
leaf_nodes.push(n);
|
|
23
|
-
} else {
|
|
24
|
-
intermediate_nodes.push(n);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const intermediate_face_count = intermediate_nodes.reduce((acc, p) => {
|
|
29
|
-
return acc + p.topology_snapshot.getFaces().size;
|
|
30
|
-
}, 0);
|
|
31
|
-
|
|
32
|
-
const leaf_face_count = leaf_nodes.reduce((acc, p) => {
|
|
33
|
-
return acc + p.topology_snapshot.getFaces().size;
|
|
34
|
-
}, 0);
|
|
35
|
-
|
|
36
|
-
const intermediate_node_count = all_nodes.length - leaf_nodes.length;
|
|
37
|
-
const balance_quality = (leaf_nodes.length - 1) / intermediate_node_count;
|
|
38
|
-
|
|
39
|
-
const intermediate_overflow_patch_count = intermediate_nodes.filter(p => p.topology_snapshot.getFaces().size > MICRON_PATCH_SIZE_MAX).length;
|
|
40
|
-
|
|
41
|
-
const intermediate_overflow_face_count = intermediate_nodes
|
|
42
|
-
.map(n => n.topology_snapshot.getFaces().size)
|
|
43
|
-
.reduce((acc, c) => {
|
|
44
|
-
const local_overflow = max2(0, c - MICRON_PATCH_SIZE_MAX);
|
|
45
|
-
return acc + local_overflow;
|
|
46
|
-
}, 0);
|
|
47
|
-
|
|
48
|
-
return `Graph Stats:
|
|
49
|
-
Total nodes: ${prettyPrint(all_nodes.length)}
|
|
50
|
-
Total intermediate nodes: ${prettyPrint(intermediate_node_count)}
|
|
51
|
-
Depth: ${prettyPrint(root.lod)}
|
|
52
|
-
Balance quality: ${(balance_quality * 100).toPrecision(3)}%
|
|
53
|
-
|
|
54
|
-
Intermediate face count: ${prettyPrint(intermediate_face_count)} (${(intermediate_face_count * 100 / leaf_face_count).toPrecision(3)}% of original)
|
|
55
|
-
Intermediate overflow faces: ${prettyPrint(intermediate_overflow_face_count)} (${(intermediate_overflow_face_count * 100 / intermediate_face_count).toPrecision(3)}%)
|
|
56
|
-
|
|
57
|
-
Intermediate overflow patches: ${prettyPrint(intermediate_overflow_patch_count)} (${(intermediate_overflow_patch_count * 100 / intermediate_node_count).toPrecision(3)}%)
|
|
58
|
-
`;
|
|
59
|
-
}
|
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
import { BinaryDataType } from "../../../../core/binary/type/BinaryDataType.js";
|
|
2
|
-
import { passThrough } from "../../../../core/function/Functions.js";
|
|
3
|
-
import { to_half_float_uint16 } from "../../../../core/binary/to_half_float_uint16.js";
|
|
4
|
-
import { compute_micron_buffer_array_constructor } from "./compute_micron_buffer_array_constructor.js";
|
|
5
|
-
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
6
|
-
import { dataTypeByteSize } from "../../../../core/binary/type/DataTypeByteSizes.js";
|
|
7
|
-
import { UintArrayForCount } from "../../../../core/collection/array/typed/uint_array_for_count.js";
|
|
8
|
-
import { clamp01 } from "../../../../core/math/clamp01.js";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @param {number} vertex_count
|
|
12
|
-
* @param {Map<number, number>} index_map_backward
|
|
13
|
-
* @param {number} itemSize
|
|
14
|
-
* @param {ArrayLike<number>} attribute_array
|
|
15
|
-
* @param {number[]} vertex_data_buffer_accessor
|
|
16
|
-
* @param {function} transformer_method
|
|
17
|
-
* @param {*} [transformer_context]
|
|
18
|
-
*/
|
|
19
|
-
function transform_attribute_data(
|
|
20
|
-
vertex_count,
|
|
21
|
-
index_map_backward,
|
|
22
|
-
itemSize,
|
|
23
|
-
attribute_array,
|
|
24
|
-
vertex_data_buffer_accessor,
|
|
25
|
-
transformer_method,
|
|
26
|
-
transformer_context
|
|
27
|
-
) {
|
|
28
|
-
let j, k;
|
|
29
|
-
|
|
30
|
-
for (j = 0; j < vertex_count; j++) {
|
|
31
|
-
// map patch vertex index to original geometry's vertex index
|
|
32
|
-
const source_vertex_index = index_map_backward.get(j);
|
|
33
|
-
|
|
34
|
-
const source_vertex_offset = source_vertex_index * itemSize;
|
|
35
|
-
const target_vertex_offset = j * itemSize;
|
|
36
|
-
|
|
37
|
-
for (k = 0; k < itemSize; k++) {
|
|
38
|
-
|
|
39
|
-
// get item value
|
|
40
|
-
const value = attribute_array[source_vertex_offset + k];
|
|
41
|
-
|
|
42
|
-
// transform
|
|
43
|
-
const transformed_value = transformer_method.call(transformer_context, value);
|
|
44
|
-
|
|
45
|
-
// write into buffer
|
|
46
|
-
vertex_data_buffer_accessor[target_vertex_offset + k] = transformed_value;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @param {number} vertex_count
|
|
53
|
-
* @param {Map<number, number>} index_map_backward
|
|
54
|
-
* @param {number} itemSize
|
|
55
|
-
* @param {ArrayLike<number>} attribute_array
|
|
56
|
-
* @param {number[]} vertex_data_buffer_accessor
|
|
57
|
-
*/
|
|
58
|
-
function copy_attribute_data(vertex_count, index_map_backward, itemSize, attribute_array, vertex_data_buffer_accessor) {
|
|
59
|
-
let j, k;
|
|
60
|
-
|
|
61
|
-
for (j = 0; j < vertex_count; j++) {
|
|
62
|
-
// map patch vertex index to original geometry's vertex index
|
|
63
|
-
const source_vertex_index = index_map_backward.get(j);
|
|
64
|
-
|
|
65
|
-
const source_vertex_offset = source_vertex_index * itemSize;
|
|
66
|
-
const target_vertex_offset = j * itemSize;
|
|
67
|
-
|
|
68
|
-
for (k = 0; k < itemSize; k++) {
|
|
69
|
-
|
|
70
|
-
// get item value
|
|
71
|
-
const value = attribute_array[source_vertex_offset + k];
|
|
72
|
-
|
|
73
|
-
// write into buffer
|
|
74
|
-
vertex_data_buffer_accessor[target_vertex_offset + k] = value;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
*
|
|
81
|
-
* @param {number} value
|
|
82
|
-
* @returns {number}
|
|
83
|
-
*/
|
|
84
|
-
function resample_normalized_uint16_to_uint8(value) {
|
|
85
|
-
const normalized = clamp01(value / 65535);
|
|
86
|
-
|
|
87
|
-
return Math.round(normalized * 255);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
*
|
|
92
|
-
* @param {number} value
|
|
93
|
-
* @return {number}
|
|
94
|
-
*/
|
|
95
|
-
function normalize_to_int8(value) {
|
|
96
|
-
return Math.round(value * 127);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
* @param {number} value
|
|
102
|
-
* @return {number}
|
|
103
|
-
*/
|
|
104
|
-
function normalize_to_uint8(value) {
|
|
105
|
-
return Math.round(value * 255);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @enum {function(number):number}
|
|
110
|
-
*/
|
|
111
|
-
const DataConverterType = {
|
|
112
|
-
None: passThrough,
|
|
113
|
-
Number2HalfFloat: to_half_float_uint16,
|
|
114
|
-
Normalize2Int8: normalize_to_int8,
|
|
115
|
-
Normalize2Uint8: normalize_to_uint8,
|
|
116
|
-
ResampleNormalized_Uint16_to_Uint8: resample_normalized_uint16_to_uint8
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* How to convert data from source three.js buffer attribute to what we store in the patch description based on the supplied micron spec
|
|
121
|
-
* @param {AttributeSpec} spec
|
|
122
|
-
* @param {THREE.BufferAttribute} source
|
|
123
|
-
* @returns {DataConverterType}
|
|
124
|
-
*/
|
|
125
|
-
function compute_attribute_data_converter(source, spec) {
|
|
126
|
-
const target_type = spec.type;
|
|
127
|
-
if (target_type === BinaryDataType.Float16) {
|
|
128
|
-
return DataConverterType.Number2HalfFloat;
|
|
129
|
-
} else if (spec.normalized && !source.normalized) {
|
|
130
|
-
// source data can be normalized but isn't
|
|
131
|
-
if (target_type === BinaryDataType.Int8) {
|
|
132
|
-
return DataConverterType.Normalize2Int8;
|
|
133
|
-
} else if (target_type === BinaryDataType.Uint8) {
|
|
134
|
-
return DataConverterType.Normalize2Uint8;
|
|
135
|
-
} else {
|
|
136
|
-
throw new Error(`Unsupported normalized type '${target_type}'`);
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
const source_array = source.array;
|
|
140
|
-
|
|
141
|
-
const source_type = typedArrayToDataType(source_array);
|
|
142
|
-
|
|
143
|
-
const target_byte_size = dataTypeByteSize(target_type);
|
|
144
|
-
const source_byte_size = dataTypeByteSize(source_type)
|
|
145
|
-
|
|
146
|
-
if (target_byte_size !== source_byte_size) {
|
|
147
|
-
// wrong data size
|
|
148
|
-
|
|
149
|
-
if (target_type === BinaryDataType.Uint8 && source_type === BinaryDataType.Uint16) {
|
|
150
|
-
return DataConverterType.ResampleNormalized_Uint16_to_Uint8;
|
|
151
|
-
} else {
|
|
152
|
-
throw new Error(`Unsupported conversion ${source_type} -> ${target_type}`);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
} else {
|
|
156
|
-
return DataConverterType.None;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
*
|
|
163
|
-
* @param {MicronGeometryPatch} result
|
|
164
|
-
* @param {THREE.BufferGeometry} buffer_geometry
|
|
165
|
-
* @param {TopoMesh} topo
|
|
166
|
-
* @param {VertexDataSpec} vertex_data_spec
|
|
167
|
-
*/
|
|
168
|
-
export function fill_patch_geometry_data(result, buffer_geometry, topo, vertex_data_spec) {
|
|
169
|
-
/**
|
|
170
|
-
*
|
|
171
|
-
* @type {Map<number, number>}
|
|
172
|
-
*/
|
|
173
|
-
const index_map_forward = new Map();
|
|
174
|
-
/**
|
|
175
|
-
*
|
|
176
|
-
* @type {Map<number, number>}
|
|
177
|
-
*/
|
|
178
|
-
const index_map_backward = new Map();
|
|
179
|
-
|
|
180
|
-
let vertex_count = 0;
|
|
181
|
-
|
|
182
|
-
// remap vertices
|
|
183
|
-
const faces = topo.getFaces();
|
|
184
|
-
const face_count = faces.size;
|
|
185
|
-
const polygon_buffer_size = face_count * 3;
|
|
186
|
-
|
|
187
|
-
// pick container just large enough to point to all vertices
|
|
188
|
-
const FaceArrayConstructor = UintArrayForCount(topo.vertices.length);
|
|
189
|
-
|
|
190
|
-
result.face_indices = new FaceArrayConstructor(polygon_buffer_size);
|
|
191
|
-
result.polygon_count = face_count;
|
|
192
|
-
|
|
193
|
-
let i3 = 0;
|
|
194
|
-
for (const topo_face of faces) {
|
|
195
|
-
|
|
196
|
-
for (let j = 0; j < 3; j++) {
|
|
197
|
-
// get vertices
|
|
198
|
-
const topo_vertex = topo_face.vertices[j];
|
|
199
|
-
|
|
200
|
-
const index = topo_vertex.index;
|
|
201
|
-
|
|
202
|
-
if (!index_map_forward.has(index)) {
|
|
203
|
-
index_map_forward.set(index, vertex_count);
|
|
204
|
-
index_map_backward.set(vertex_count, index);
|
|
205
|
-
|
|
206
|
-
vertex_count++;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// write index into patch
|
|
210
|
-
result.face_indices[i3 + j] = index_map_forward.get(index);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
i3 += 3;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// write vertices
|
|
217
|
-
result.vertex_count = vertex_count;
|
|
218
|
-
|
|
219
|
-
// collect metadata about vertices
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
// compute byte size of each vertex
|
|
223
|
-
const source_attributes = buffer_geometry.attributes;
|
|
224
|
-
|
|
225
|
-
let vertex_buffer_attribute_address = 0;
|
|
226
|
-
|
|
227
|
-
const micron_attributes = vertex_data_spec.attributes;
|
|
228
|
-
const attribute_count = micron_attributes.length;
|
|
229
|
-
|
|
230
|
-
//TODO create a single ArrayBuffer for all attributes to get better cache coherence for rendering
|
|
231
|
-
|
|
232
|
-
for (let i = 0; i < attribute_count; i++) {
|
|
233
|
-
const attribute_spec = micron_attributes[i];
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
*
|
|
237
|
-
* @type {THREE.BufferAttribute | THREE.InterleavedBufferAttribute}
|
|
238
|
-
*/
|
|
239
|
-
const attribute = source_attributes[attribute_spec.name];
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (attribute.isInterleavedBufferAttribute) {
|
|
243
|
-
throw new Error('Interleaved buffers are not supported');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const attribute_array = attribute.array;
|
|
247
|
-
|
|
248
|
-
const itemSize = attribute.itemSize;
|
|
249
|
-
|
|
250
|
-
const TypedArrayConstructor = compute_micron_buffer_array_constructor(attribute_spec.type);
|
|
251
|
-
|
|
252
|
-
const vertex_data_buffer_accessor = new TypedArrayConstructor(
|
|
253
|
-
vertex_count * itemSize
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
const converter = compute_attribute_data_converter(attribute, attribute_spec);
|
|
257
|
-
|
|
258
|
-
if (converter === DataConverterType.None) {
|
|
259
|
-
copy_attribute_data(vertex_count, index_map_backward, itemSize, attribute_array, vertex_data_buffer_accessor);
|
|
260
|
-
|
|
261
|
-
} else {
|
|
262
|
-
transform_attribute_data(vertex_count, index_map_backward, itemSize, attribute_array, vertex_data_buffer_accessor, converter);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
vertex_buffer_attribute_address += attribute_spec.getByteSize() * vertex_count;
|
|
266
|
-
|
|
267
|
-
result.vertex_attribute_arrays[i] = vertex_data_buffer_accessor;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { merge_patches } from "./merge_patches.js";
|
|
2
|
-
import { coarsen_graph } from "../../../../../core/graph/coarsen_graph.js";
|
|
3
|
-
import { build_merge_graph } from "./build_merge_graph.js";
|
|
4
|
-
import { assign_patch_neighbours_from_topology } from "../clustering/assign_patch_neighbours_from_topology.js";
|
|
5
|
-
import { assert } from "../../../../../core/assert.js";
|
|
6
|
-
import { graph_create_off_mesh_links } from "../../../../../core/graph/build_face_graph_from_mesh.js";
|
|
7
|
-
import {
|
|
8
|
-
build_vertex_quadratics
|
|
9
|
-
} from "../../../../../core/geom/3d/topology/simplify/quadratic/build_vertex_quadratics.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* @param {Graph<MultiNode<PatchRepresentation>>} graph
|
|
14
|
-
* @param {number} n
|
|
15
|
-
*/
|
|
16
|
-
function merge_graph_level(graph, n) {
|
|
17
|
-
assert.isFiniteNumber(n, 'n');
|
|
18
|
-
assert.isNonNegativeInteger(n, 'n');
|
|
19
|
-
|
|
20
|
-
for (let i = 2; i <= n; i *= 2) {
|
|
21
|
-
|
|
22
|
-
if (graph.getNodeCount() <= 1) {
|
|
23
|
-
// fully merged, no further merge possible
|
|
24
|
-
break;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
coarsen_graph(graph, i);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
*
|
|
34
|
-
* @type {number}
|
|
35
|
-
*/
|
|
36
|
-
const DEFAULT_MERGE_COUNT = 4;
|
|
37
|
-
/**
|
|
38
|
-
* Maximum number of patches that can be merged together
|
|
39
|
-
* @type {number}
|
|
40
|
-
*/
|
|
41
|
-
const LIMIT_MERGE_COUNT = 64;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
*
|
|
45
|
-
* @param {PatchRepresentation[]} nodes
|
|
46
|
-
* @returns {PatchRepresentation}
|
|
47
|
-
*/
|
|
48
|
-
async function assemble_graph(nodes) {
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* @type {PatchRepresentation[]}
|
|
52
|
-
* @private
|
|
53
|
-
*/
|
|
54
|
-
let __nodes = nodes.slice();
|
|
55
|
-
|
|
56
|
-
const initial_node_count = __nodes.length;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
*
|
|
60
|
-
* @type {{value: number}}
|
|
61
|
-
* @private
|
|
62
|
-
*/
|
|
63
|
-
const __node_count = {
|
|
64
|
-
value: initial_node_count
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
let level = 0;
|
|
68
|
-
let merge_count = DEFAULT_MERGE_COUNT;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
*
|
|
73
|
-
* @type {Map<number, Quadratic3>}
|
|
74
|
-
*/
|
|
75
|
-
const vertex_quadratics = new Map();
|
|
76
|
-
|
|
77
|
-
/*
|
|
78
|
-
build initial quadratic errors for each vertex
|
|
79
|
-
To keep track of error throughout simplification levels
|
|
80
|
-
*/
|
|
81
|
-
for (let i = 0; i < __node_count.value; i++) {
|
|
82
|
-
const patch = __nodes[i];
|
|
83
|
-
|
|
84
|
-
build_vertex_quadratics({ mesh: patch.topology_snapshot, quadratics: vertex_quadratics });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
while (__node_count.value > 1) {
|
|
88
|
-
|
|
89
|
-
// assemble nodes into a graph
|
|
90
|
-
const leaf_cluster_weight_graph = build_merge_graph(__nodes);
|
|
91
|
-
|
|
92
|
-
if (__node_count.value <= 4 || merge_count >= 16) {
|
|
93
|
-
// graph is quite small now, it's possible that some patches are disconnected, force connections to allow for collapse
|
|
94
|
-
graph_create_off_mesh_links(leaf_cluster_weight_graph);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// merge graph nodes up to X nodes per cluster
|
|
98
|
-
merge_graph_level(leaf_cluster_weight_graph, merge_count);
|
|
99
|
-
|
|
100
|
-
// assemble multi-nodes
|
|
101
|
-
const graph_nodes = leaf_cluster_weight_graph.getNodes();
|
|
102
|
-
|
|
103
|
-
const old_node_count = __node_count.value;
|
|
104
|
-
|
|
105
|
-
__nodes = [];
|
|
106
|
-
__node_count.value = 0;
|
|
107
|
-
|
|
108
|
-
const __promises = [];
|
|
109
|
-
|
|
110
|
-
for (const multi_node of graph_nodes) {
|
|
111
|
-
const patches_to_merge = multi_node.source_nodes;
|
|
112
|
-
|
|
113
|
-
const promise = merge_patches(__nodes, __node_count, patches_to_merge, vertex_quadratics);
|
|
114
|
-
__promises.push(promise);
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
await Promise.all(__promises);
|
|
119
|
-
|
|
120
|
-
if (__node_count.value >= old_node_count) {
|
|
121
|
-
// new graph has the same number of nodes as the old one
|
|
122
|
-
|
|
123
|
-
if (leaf_cluster_weight_graph.getNodeCount() <= 1) {
|
|
124
|
-
// graph is already merged to the maximum level
|
|
125
|
-
throw new Error(`Simplification failed, graph already at maximum coarseness`);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (merge_count >= LIMIT_MERGE_COUNT) {
|
|
129
|
-
throw new Error(`Exceeded merge limit(=${LIMIT_MERGE_COUNT}), attempting to merge too many patches together`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (old_node_count <= merge_count) {
|
|
133
|
-
throw new Error(`Already allowing to merge all of the nodes, yet merge still fails. Allowed patch count = ${merge_count}, Actual patches = ${old_node_count})`);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// failed to do any merging, increase merge scope
|
|
137
|
-
merge_count *= 2;
|
|
138
|
-
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// clear existing neighbours for this level
|
|
143
|
-
for (let i = 0; i < __node_count.value; i++) {
|
|
144
|
-
const node = __nodes[i];
|
|
145
|
-
|
|
146
|
-
const neighbours = node.neighbours;
|
|
147
|
-
neighbours.splice(0, neighbours.length);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// write neighbours
|
|
151
|
-
assign_patch_neighbours_from_topology(__nodes);
|
|
152
|
-
|
|
153
|
-
level++;
|
|
154
|
-
|
|
155
|
-
merge_count = DEFAULT_MERGE_COUNT;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// return root
|
|
159
|
-
const root = __nodes[0];
|
|
160
|
-
|
|
161
|
-
if (initial_node_count === 1) {
|
|
162
|
-
// there are no children, whole hierarchy is just one node, set group bounds to equal node bounds
|
|
163
|
-
root.group_bounding_sphere.set(root.bounding_sphere);
|
|
164
|
-
root.group_aabb.copy(root.bounding_box);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
return root;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* @param {TopoMesh} t
|
|
174
|
-
*/
|
|
175
|
-
function cleanup_disconnected_edges(t) {
|
|
176
|
-
|
|
177
|
-
const edges = t.getEdges();
|
|
178
|
-
|
|
179
|
-
for (let edge of edges) {
|
|
180
|
-
|
|
181
|
-
if (edge.faces.length === 0) {
|
|
182
|
-
// cut
|
|
183
|
-
edges.delete(edge);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* @param {PatchRepresentation[]} leaves
|
|
190
|
-
* @returns {PatchRepresentation} new root
|
|
191
|
-
*/
|
|
192
|
-
export async function buildAbstractPatchHierarchy(leaves) {
|
|
193
|
-
const root = await assemble_graph(leaves);
|
|
194
|
-
|
|
195
|
-
return root;
|
|
196
|
-
}
|