@woosh/meep-engine 2.48.20 → 2.48.21
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/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/compute_face_connection_weight.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,581 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
import { TopoMesh } from "../../../../../core/geom/3d/topology/struct/TopoMesh.js";
|
|
4
|
-
import { MICRON_PATCH_SIZE_MAX } from "../MICRON_PATCH_SIZE_MAX.js";
|
|
5
|
-
import { compute_set_of_shared_vertices } from "./build_intermediate_patch_topology.js";
|
|
6
|
-
import { max2 } from "../../../../../core/math/max2.js";
|
|
7
|
-
import {
|
|
8
|
-
collapse_all_degenerate_edges
|
|
9
|
-
} from "../../../../../core/geom/3d/topology/simplify/collapse_all_degenerate_edges.js";
|
|
10
|
-
import {
|
|
11
|
-
deep_copy_vertex_quadratics
|
|
12
|
-
} from "../../../../../core/geom/3d/topology/simplify/quadratic/build_vertex_quadratics.js";
|
|
13
|
-
import { SquareMatrix } from "../../../../../core/graph/SquareMatrix.js";
|
|
14
|
-
import { BinaryDataType } from "../../../../../core/binary/type/BinaryDataType.js";
|
|
15
|
-
import { matrix_eigenvalues_in_place } from "../../../../../core/graph/eigen/eigen.js";
|
|
16
|
-
import { min2 } from "../../../../../core/math/min2.js";
|
|
17
|
-
import { PatchRepresentation } from "../PatchRepresentation.js";
|
|
18
|
-
import {
|
|
19
|
-
build_face_graph_from_mesh,
|
|
20
|
-
graph_create_off_mesh_links
|
|
21
|
-
} from "../../../../../core/graph/build_face_graph_from_mesh.js";
|
|
22
|
-
import { optimize_graph_partitioning_balance_detailed } from "./optimize_graph_partitioning_balance.js";
|
|
23
|
-
import { patch_build_parent } from "./patch_combine.js";
|
|
24
|
-
import { array_copy } from "../../../../../core/collection/array/copyArray.js";
|
|
25
|
-
import { ceilPowerOfTwo } from "../../../../../core/binary/operations/ceilPowerOfTwo.js";
|
|
26
|
-
import { isPowerOfTwo } from "../../../../../core/math/isPowerOrTwo.js";
|
|
27
|
-
import {
|
|
28
|
-
computeTopoMeshBoundiningBox
|
|
29
|
-
} from "../../../../../core/geom/3d/topology/bounds/computeTopoMeshBoundiningBox.js";
|
|
30
|
-
import { AABB3 } from "../../../../../core/bvh2/aabb3/AABB3.js";
|
|
31
|
-
import {
|
|
32
|
-
computeTopoMeshBoundingSphere
|
|
33
|
-
} from "../../../../../core/geom/3d/topology/bounds/computeTopoMeshBoundingSphere.js";
|
|
34
|
-
import { Uint32Heap } from "../../../../../core/collection/heap/Uint32Heap.js";
|
|
35
|
-
import {
|
|
36
|
-
edge_collapse_populate_heap,
|
|
37
|
-
edge_collapse_reduce_face_count
|
|
38
|
-
} from "../../../../../core/geom/3d/topology/simplify/simplifyTopoMesh2.js";
|
|
39
|
-
import { cluster_mesh_metis } from "../../../../../core/graph/cluster_mesh_metis.js";
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
* @param {SquareMatrix} result
|
|
44
|
-
* @param {Iterable<TopoTriangle>} faces
|
|
45
|
-
* @param {Map<TopoTriangle,number>} face_index_map
|
|
46
|
-
*/
|
|
47
|
-
function build_face_degree_matrix(result, faces, face_index_map) {
|
|
48
|
-
for (const face of faces) {
|
|
49
|
-
const face_index = face_index_map.get(face);
|
|
50
|
-
|
|
51
|
-
const edges = face.edges;
|
|
52
|
-
|
|
53
|
-
const edge_count = edges.length;
|
|
54
|
-
|
|
55
|
-
let degree = 0;
|
|
56
|
-
|
|
57
|
-
for (let i = 0; i < edge_count; i++) {
|
|
58
|
-
const edge = edges[i];
|
|
59
|
-
|
|
60
|
-
degree += edge.faces.length - 1;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
result.setCellValue(face_index, face_index, degree);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {SquareMatrix} result
|
|
70
|
-
* @param {TopoMesh} mesh
|
|
71
|
-
* @param {Map<TopoTriangle,number>} face_index_map
|
|
72
|
-
*/
|
|
73
|
-
function build_face_adjacency_matrix(result, mesh, face_index_map) {
|
|
74
|
-
const edges = mesh.getEdges();
|
|
75
|
-
|
|
76
|
-
for (const edge of edges) {
|
|
77
|
-
const faces = edge.faces;
|
|
78
|
-
|
|
79
|
-
const n = faces.length;
|
|
80
|
-
|
|
81
|
-
for (let i = 0; i < n; i++) {
|
|
82
|
-
const f0 = faces[i];
|
|
83
|
-
|
|
84
|
-
const f0_index = face_index_map.get(f0);
|
|
85
|
-
|
|
86
|
-
for (let j = i + 1; j < n; j++) {
|
|
87
|
-
const f1 = faces[j];
|
|
88
|
-
|
|
89
|
-
const f1_index = face_index_map.get(f1);
|
|
90
|
-
|
|
91
|
-
result.setCellValue(f0_index, f1_index, 1);
|
|
92
|
-
result.setCellValue(f1_index, f0_index, 1);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
*
|
|
100
|
-
* @param {TopoMesh} mesh
|
|
101
|
-
* @returns {Map<TopoTriangle, number>}
|
|
102
|
-
*/
|
|
103
|
-
function build_face_index_map(mesh) {
|
|
104
|
-
let face_index = 0;
|
|
105
|
-
const face_set = mesh.getFaces();
|
|
106
|
-
|
|
107
|
-
const face_index_map = new Map();
|
|
108
|
-
|
|
109
|
-
for (const face of face_set) {
|
|
110
|
-
face_index_map.set(face, face_index++);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return face_index_map;
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
*
|
|
119
|
-
* @param {TopoMesh} mesh
|
|
120
|
-
* @param {number} k number of clusters to make
|
|
121
|
-
* @returns {TopoTriangle[][]}
|
|
122
|
-
*/
|
|
123
|
-
function cluster_mesh(mesh, k,) {
|
|
124
|
-
|
|
125
|
-
const face_index_map = new Map();
|
|
126
|
-
const face_set = mesh.getFaces();
|
|
127
|
-
const face_array = Array.from(face_set);
|
|
128
|
-
|
|
129
|
-
for (let i = 0; i < face_array.length; i++) {
|
|
130
|
-
const face = face_array[i];
|
|
131
|
-
face_index_map.set(face, i);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// build laplacian of the face graph
|
|
135
|
-
|
|
136
|
-
const face_count = face_set.size;
|
|
137
|
-
|
|
138
|
-
// build laplacian matrix
|
|
139
|
-
const m_adjacency = new SquareMatrix(face_count, BinaryDataType.Uint8);
|
|
140
|
-
const m_degree = new SquareMatrix(face_count, BinaryDataType.Uint8);
|
|
141
|
-
|
|
142
|
-
build_face_adjacency_matrix(m_adjacency, mesh, face_index_map);
|
|
143
|
-
build_face_degree_matrix(m_degree, face_set, face_index_map);
|
|
144
|
-
|
|
145
|
-
const mat_laplace = new SquareMatrix(face_count, BinaryDataType.Float64);
|
|
146
|
-
|
|
147
|
-
mat_laplace.subtractMatrices(m_degree, m_adjacency);
|
|
148
|
-
|
|
149
|
-
// compute eigen values
|
|
150
|
-
const eigen_values = matrix_eigenvalues_in_place(mat_laplace);
|
|
151
|
-
|
|
152
|
-
const mapped_eigen_values = Array.from(eigen_values).map((v, i) => {
|
|
153
|
-
return {
|
|
154
|
-
v, i
|
|
155
|
-
};
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
mapped_eigen_values.sort((a, b) => a.v - b.v);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// eigenvalues are a projection of closeness of nodes
|
|
162
|
-
const result = [];
|
|
163
|
-
|
|
164
|
-
let face_cursor = 0;
|
|
165
|
-
const step_size = Math.ceil(face_count / k);
|
|
166
|
-
for (let i = 0; i < k; i++) {
|
|
167
|
-
const end_index = min2(face_count, face_cursor + step_size);
|
|
168
|
-
|
|
169
|
-
const cluster = [];
|
|
170
|
-
|
|
171
|
-
for (let j = face_cursor; j < end_index; j++) {
|
|
172
|
-
const face_index = mapped_eigen_values[j].i;
|
|
173
|
-
|
|
174
|
-
const face = face_array[face_index];
|
|
175
|
-
|
|
176
|
-
cluster.push(face);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
face_cursor = end_index;
|
|
180
|
-
|
|
181
|
-
result.push(cluster);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return result;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* @template N
|
|
189
|
-
* @param {Graph<N>} graph
|
|
190
|
-
* @returns {Map<N, number>}
|
|
191
|
-
*/
|
|
192
|
-
function build_graph_node_index_map(graph) {
|
|
193
|
-
const r = new Map();
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const nodes = graph.getNodes();
|
|
197
|
-
|
|
198
|
-
let i = 0;
|
|
199
|
-
for (const node of nodes) {
|
|
200
|
-
r.set(node, i);
|
|
201
|
-
|
|
202
|
-
i++;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return r;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
*
|
|
210
|
-
* @param {TopoMesh} mesh
|
|
211
|
-
* @param {number} k
|
|
212
|
-
* @param {number} per_cluster_triangle_limit
|
|
213
|
-
* @returns {TopoMesh[]}
|
|
214
|
-
*/
|
|
215
|
-
async function recursive_split_mesh_partition(mesh, k, per_cluster_triangle_limit) {
|
|
216
|
-
if (!isPowerOfTwo(k)) {
|
|
217
|
-
throw new Error(`k must be power of two, instead was '${k}'`);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const levels = Math.log2(k);
|
|
221
|
-
|
|
222
|
-
let meshes = [mesh];
|
|
223
|
-
|
|
224
|
-
for (let i = 0; i < levels; i++) {
|
|
225
|
-
const merge_target = per_cluster_triangle_limit * Math.pow(2, levels - i)
|
|
226
|
-
const output_meshes = [];
|
|
227
|
-
for (let j = 0; j < meshes.length; j++) {
|
|
228
|
-
const topoMesh = meshes[j];
|
|
229
|
-
|
|
230
|
-
const split = await partition_mesh(topoMesh, 2, merge_target);
|
|
231
|
-
|
|
232
|
-
Array.prototype.push.apply(output_meshes, split);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
meshes = output_meshes;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return meshes;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
*
|
|
243
|
-
* @param {TopoMesh} mesh
|
|
244
|
-
* @param {number} k
|
|
245
|
-
* @param {number} per_cluster_triangle_limit
|
|
246
|
-
* @returns {TopoMesh[]}
|
|
247
|
-
*/
|
|
248
|
-
async function partition_mesh_advanced(mesh, k, per_cluster_triangle_limit) {
|
|
249
|
-
const metis_result = await partition_mesh_metis(mesh, k, per_cluster_triangle_limit);
|
|
250
|
-
|
|
251
|
-
if (metis_result !== undefined) {
|
|
252
|
-
return metis_result;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// fallback
|
|
256
|
-
return recursive_split_mesh_partition(mesh, k, per_cluster_triangle_limit);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
*
|
|
261
|
-
* @param {TopoMesh} mesh
|
|
262
|
-
* @param {number} k
|
|
263
|
-
* @param {number} per_cluster_triangle_limit
|
|
264
|
-
* @returns {TopoMesh[]|undefined} Either returns the desired partitioning, or undefined in case of failure
|
|
265
|
-
*/
|
|
266
|
-
async function partition_mesh_metis(mesh, k, per_cluster_triangle_limit) {
|
|
267
|
-
|
|
268
|
-
const input_face_count = mesh.getFaces().size;
|
|
269
|
-
const face_array = Array.from(mesh.getFaces());
|
|
270
|
-
|
|
271
|
-
const partitioning = new Uint32Array(input_face_count);
|
|
272
|
-
|
|
273
|
-
const cluster_count = await cluster_mesh_metis(partitioning, mesh, per_cluster_triangle_limit);
|
|
274
|
-
|
|
275
|
-
if (cluster_count !== k) {
|
|
276
|
-
return undefined;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const result = [];
|
|
281
|
-
const vertexMaps = [];
|
|
282
|
-
|
|
283
|
-
for (let i = 0; i < cluster_count; i++) {
|
|
284
|
-
result[i] = new TopoMesh();
|
|
285
|
-
vertexMaps[i] = new Map();
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
for (let i = 0; i < input_face_count; i++) {
|
|
289
|
-
|
|
290
|
-
const triangle = face_array[i];
|
|
291
|
-
|
|
292
|
-
const partition_index = partitioning[i];
|
|
293
|
-
|
|
294
|
-
const patition_mesh = result[partition_index];
|
|
295
|
-
const vertexMap = vertexMaps[partition_index];
|
|
296
|
-
|
|
297
|
-
patition_mesh.addFaceCopy(triangle, vertexMap)
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return result;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
*
|
|
306
|
-
* @param {TopoMesh} mesh
|
|
307
|
-
* @param {number} k
|
|
308
|
-
* @param {number} per_cluster_triangle_limit
|
|
309
|
-
* @returns {TopoMesh[]}
|
|
310
|
-
*/
|
|
311
|
-
function partition_mesh(mesh, k, per_cluster_triangle_limit) {
|
|
312
|
-
if (k === 1) {
|
|
313
|
-
// special case, no partitioning required
|
|
314
|
-
return [mesh];
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const graph = build_face_graph_from_mesh(mesh);
|
|
318
|
-
|
|
319
|
-
graph_create_off_mesh_links(graph);
|
|
320
|
-
|
|
321
|
-
const node_array = Array.from(graph.getNodes());
|
|
322
|
-
const clusters = optimize_graph_partitioning_balance_detailed(node_array, k, graph);
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
*
|
|
326
|
-
* @type {TopoMesh[]}
|
|
327
|
-
*/
|
|
328
|
-
const result = [];
|
|
329
|
-
|
|
330
|
-
for (let i = 0; i < k; i++) {
|
|
331
|
-
const cluster = clusters[i];
|
|
332
|
-
|
|
333
|
-
const cluster_size = cluster.length;
|
|
334
|
-
|
|
335
|
-
const mesh = new TopoMesh();
|
|
336
|
-
|
|
337
|
-
const vertexMap = new Map();
|
|
338
|
-
|
|
339
|
-
for (let j = 0; j < cluster_size; j++) {
|
|
340
|
-
const node_index = cluster[j];
|
|
341
|
-
|
|
342
|
-
const node = node_array[node_index];
|
|
343
|
-
|
|
344
|
-
const triangle = node.source_nodes[0];
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
mesh.addFaceCopy(triangle, vertexMap)
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
result[i] = mesh;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return result;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function partition_mesh_spectral(merged_mesh, up_count, nodes, output, output_offset) {
|
|
357
|
-
const face_clusters = cluster_mesh(merged_mesh, up_count);
|
|
358
|
-
|
|
359
|
-
const cluster_count = face_clusters.length;
|
|
360
|
-
|
|
361
|
-
for (let i = 0; i < cluster_count; i++) {
|
|
362
|
-
const rep = new PatchRepresentation();
|
|
363
|
-
|
|
364
|
-
const cluster = face_clusters[i];
|
|
365
|
-
|
|
366
|
-
const cluster_mesh = new TopoMesh();
|
|
367
|
-
|
|
368
|
-
for (let j = 0; j < cluster.length; j++) {
|
|
369
|
-
const face = cluster[j];
|
|
370
|
-
|
|
371
|
-
cluster_mesh.injectFace(face);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
rep.topology_snapshot = cluster_mesh;
|
|
375
|
-
|
|
376
|
-
Array.prototype.push.apply(rep.children, nodes);
|
|
377
|
-
|
|
378
|
-
output[output_offset + i] = rep;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
return cluster_count;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
*
|
|
386
|
-
* @param {PatchRepresentation[]} output
|
|
387
|
-
* @param {{value:number}} output_offset
|
|
388
|
-
* @param {PatchRepresentation[]} nodes
|
|
389
|
-
* @param {number} up_count
|
|
390
|
-
* @param {Map<number, Quadratic3>} quadratics accumulated quadratic errors for each vertex
|
|
391
|
-
* @returns {number} number of patches added to output
|
|
392
|
-
*/
|
|
393
|
-
async function many_to_many_merge(
|
|
394
|
-
output,
|
|
395
|
-
output_offset,
|
|
396
|
-
nodes,
|
|
397
|
-
up_count,
|
|
398
|
-
quadratics
|
|
399
|
-
) {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
// create a topology from source nodes
|
|
403
|
-
const merged_mesh = new TopoMesh();
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
*
|
|
407
|
-
* @type {Map<number, TopoVertex>}
|
|
408
|
-
*/
|
|
409
|
-
const vertex_map = new Map();
|
|
410
|
-
|
|
411
|
-
const input_node_count = nodes.length;
|
|
412
|
-
|
|
413
|
-
for (let i = 0; i < input_node_count; i++) {
|
|
414
|
-
const child = nodes[i];
|
|
415
|
-
merged_mesh._addWithVertexMap(child.topology_snapshot, vertex_map);
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
*
|
|
420
|
-
* @type {Set<number>}
|
|
421
|
-
*/
|
|
422
|
-
const restricted_vertices = new Set();
|
|
423
|
-
|
|
424
|
-
compute_set_of_shared_vertices(restricted_vertices, merged_mesh, nodes);
|
|
425
|
-
|
|
426
|
-
const target_face_count = up_count * MICRON_PATCH_SIZE_MAX;
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const source_mesh_face_count = merged_mesh.getFaces().size;
|
|
430
|
-
|
|
431
|
-
const num_desired_faces_to_remove = max2(0, source_mesh_face_count - target_face_count);
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
*
|
|
435
|
-
* @type {Map<number, Quadratic3>}
|
|
436
|
-
*/
|
|
437
|
-
const vertex_quadratics = new Map();
|
|
438
|
-
|
|
439
|
-
/*
|
|
440
|
-
make a copy of relevant quadratics, simplification might be rejected if objectives are not met (face count too high)
|
|
441
|
-
So to keep simplification speculative, we make a copy of quadratics and apply any changes once the simplification is validated
|
|
442
|
-
*/
|
|
443
|
-
deep_copy_vertex_quadratics(vertex_quadratics, quadratics, merged_mesh);
|
|
444
|
-
|
|
445
|
-
let actual_up_count = up_count;
|
|
446
|
-
|
|
447
|
-
// simplify topology
|
|
448
|
-
if (num_desired_faces_to_remove > 0) {
|
|
449
|
-
|
|
450
|
-
const heap = new Uint32Heap(merged_mesh.getEdges().size);
|
|
451
|
-
const edge_lookup = new Map();
|
|
452
|
-
|
|
453
|
-
// debugValidateMesh(merged_mesh);
|
|
454
|
-
|
|
455
|
-
edge_collapse_populate_heap(merged_mesh.getEdges(), restricted_vertices, heap, vertex_quadratics, edge_lookup);
|
|
456
|
-
edge_collapse_reduce_face_count(merged_mesh, num_desired_faces_to_remove, heap, edge_lookup, restricted_vertices, vertex_quadratics);
|
|
457
|
-
|
|
458
|
-
// debugValidateMesh(merged_mesh);
|
|
459
|
-
|
|
460
|
-
collapse_all_degenerate_edges(merged_mesh.getEdges(), merged_mesh);
|
|
461
|
-
|
|
462
|
-
// debugValidateMesh(merged_mesh);
|
|
463
|
-
|
|
464
|
-
const merged_mesh_face_count = merged_mesh.getFaces().size;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (merged_mesh_face_count > target_face_count) {
|
|
468
|
-
// simplification failed, reject
|
|
469
|
-
const t = output_offset.value;
|
|
470
|
-
output_offset.value += input_node_count;
|
|
471
|
-
array_copy(nodes, 0, output, t, input_node_count);
|
|
472
|
-
return input_node_count;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// update source quadratics
|
|
477
|
-
const merged_mesh_vertices = merged_mesh.vertices;
|
|
478
|
-
const merged_mesh_vertex_count = merged_mesh_vertices.length;
|
|
479
|
-
|
|
480
|
-
let largest_squared_error = 0;
|
|
481
|
-
|
|
482
|
-
for (let i = 0; i < merged_mesh_vertex_count; i++) {
|
|
483
|
-
const vertex = merged_mesh_vertices[i];
|
|
484
|
-
|
|
485
|
-
const vertex_index = vertex.index;
|
|
486
|
-
|
|
487
|
-
const vertex_quadratic = vertex_quadratics.get(vertex_index);
|
|
488
|
-
//
|
|
489
|
-
const vertex_error_sqr = vertex_quadratic.evaluate(vertex.x, vertex.y, vertex.z);
|
|
490
|
-
|
|
491
|
-
if (vertex_error_sqr > largest_squared_error) {
|
|
492
|
-
largest_squared_error = vertex_error_sqr;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// copy back to the source
|
|
496
|
-
quadratics.set(vertex_index, vertex_quadratic);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const group_aabb = new AABB3();
|
|
500
|
-
computeTopoMeshBoundiningBox(group_aabb, merged_mesh);
|
|
501
|
-
|
|
502
|
-
const group_bounding_sphere = new Float32Array(4);
|
|
503
|
-
computeTopoMeshBoundingSphere(group_bounding_sphere, merged_mesh);
|
|
504
|
-
|
|
505
|
-
const group_inverse_polycount = 1 / merged_mesh.getFaces().size;
|
|
506
|
-
|
|
507
|
-
const group_bounding_sphere_radius = group_bounding_sphere[3];
|
|
508
|
-
const group_bounding_sphere_section_area = group_bounding_sphere_radius * group_bounding_sphere_radius;
|
|
509
|
-
|
|
510
|
-
const area_based_qem_error = largest_squared_error / group_bounding_sphere_section_area;
|
|
511
|
-
|
|
512
|
-
// const group_per_pixel_error = min2(
|
|
513
|
-
// group_inverse_polycount,
|
|
514
|
-
// area_based_qem_error
|
|
515
|
-
// );
|
|
516
|
-
|
|
517
|
-
const group_per_pixel_error = group_inverse_polycount;
|
|
518
|
-
// const group_per_pixel_error = Math.sqrt(largest_squared_error);
|
|
519
|
-
|
|
520
|
-
// split topology into desired number of pieces
|
|
521
|
-
const pieces = await partition_mesh_advanced(merged_mesh, actual_up_count, MICRON_PATCH_SIZE_MAX);
|
|
522
|
-
|
|
523
|
-
for (let i = 0; i < actual_up_count; i++) {
|
|
524
|
-
const rep = patch_build_parent(nodes);
|
|
525
|
-
|
|
526
|
-
const piece_mesh = pieces[i];
|
|
527
|
-
|
|
528
|
-
rep.topology_snapshot = piece_mesh;
|
|
529
|
-
|
|
530
|
-
rep.group_aabb.copy(group_aabb);
|
|
531
|
-
rep.group_bounding_sphere.set(group_bounding_sphere);
|
|
532
|
-
|
|
533
|
-
rep.computeBounds();
|
|
534
|
-
|
|
535
|
-
rep.group_error = group_per_pixel_error;
|
|
536
|
-
|
|
537
|
-
//
|
|
538
|
-
// if (piece_mesh.getFaces().size > MICRON_PATCH_SIZE_MAX) {
|
|
539
|
-
// debugger;
|
|
540
|
-
// }
|
|
541
|
-
|
|
542
|
-
output[output_offset.value++] = rep;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
return actual_up_count;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
*
|
|
550
|
-
* @param {PatchRepresentation[]} output
|
|
551
|
-
* @param {{value:number}} output_offset
|
|
552
|
-
* @param {PatchRepresentation[]} nodes
|
|
553
|
-
* @param {Map<number, Quadratic3>} quadratics Vertex quadratic error set
|
|
554
|
-
* @returns {number} number of patches added to output
|
|
555
|
-
*/
|
|
556
|
-
export async function merge_patches(
|
|
557
|
-
output,
|
|
558
|
-
output_offset,
|
|
559
|
-
nodes,
|
|
560
|
-
quadratics
|
|
561
|
-
) {
|
|
562
|
-
const node_count = nodes.length;
|
|
563
|
-
|
|
564
|
-
if (node_count === 0) {
|
|
565
|
-
// empty input
|
|
566
|
-
return 0;
|
|
567
|
-
} else if (node_count === 1) {
|
|
568
|
-
// only 1 patch, no merge opportunity, forward it to output directly
|
|
569
|
-
const node = nodes[0];
|
|
570
|
-
|
|
571
|
-
output[output_offset.value++] = node;
|
|
572
|
-
return 1;
|
|
573
|
-
} else {
|
|
574
|
-
|
|
575
|
-
const target_node_count = max2(1, Math.ceil(nodes.length / 2));
|
|
576
|
-
|
|
577
|
-
const clipped_node_count = ceilPowerOfTwo(target_node_count);
|
|
578
|
-
|
|
579
|
-
return await many_to_many_merge(output, output_offset, nodes, clipped_node_count, quadratics);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
import { metis_cluster_bs } from "../../../../../core/graph/cluster_mesh_metis.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {Uint32Array|Uint16Array|Uint8Array|number[]} result
|
|
8
|
-
* @param {PatchRepresentation[]} clusters
|
|
9
|
-
* @param {number} cluster_size
|
|
10
|
-
*/
|
|
11
|
-
export async function metis_cluster_clusters(result, clusters, cluster_size) {
|
|
12
|
-
|
|
13
|
-
const node_count = clusters.length;
|
|
14
|
-
|
|
15
|
-
const edge_addresses = new Uint32Array(node_count + 1);
|
|
16
|
-
const adjacency = [];
|
|
17
|
-
const edge_weights = [];
|
|
18
|
-
|
|
19
|
-
// build node-to-index map
|
|
20
|
-
const node_index_map = new Map();
|
|
21
|
-
for (let i = 0; i < node_count; i++) {
|
|
22
|
-
const node = clusters[i];
|
|
23
|
-
node_index_map.set(node, i);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
let offset = 0;
|
|
27
|
-
edge_addresses[0] = 0;
|
|
28
|
-
|
|
29
|
-
for (let i = 0; i < node_count; i++) {
|
|
30
|
-
const cluster = clusters[i];
|
|
31
|
-
|
|
32
|
-
const neighbours = cluster.neighbours;
|
|
33
|
-
|
|
34
|
-
const neighbour_count = neighbours.length;
|
|
35
|
-
|
|
36
|
-
for (let j = 0; j < neighbour_count; j++) {
|
|
37
|
-
const neighbour = neighbours[j];
|
|
38
|
-
|
|
39
|
-
adjacency[offset] = node_index_map.get(neighbour);
|
|
40
|
-
edge_weights[offset] = 1;
|
|
41
|
-
|
|
42
|
-
offset++;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
edge_addresses[i + 1] = offset;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const adjecency_uint32 = new Uint32Array(adjacency);
|
|
49
|
-
const edge_weights_uint32 = new Uint32Array(edge_weights);
|
|
50
|
-
|
|
51
|
-
return await metis_cluster_bs(result, node_count, edge_addresses, adjecency_uint32, edge_weights_uint32, cluster_size);
|
|
52
|
-
|
|
53
|
-
}
|