@woosh/meep-engine 2.34.42 → 2.34.46
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/BinaryNode.js +60 -32
- package/core/bvh2/LeafNode.js +2 -1
- package/core/bvh2/aabb3/AABB3.js +879 -1059
- package/core/bvh2/aabb3/AABB3.spec.js +5 -7
- package/core/bvh2/aabb3/aabb3_array_intersects_ray.js +2 -2
- package/core/bvh2/aabb3/aabb3_box_surface_area_2.js +10 -0
- package/core/bvh2/aabb3/aabb3_compute_half_surface_area.js +16 -0
- package/core/bvh2/aabb3/aabb3_compute_surface_area.js +18 -0
- package/core/bvh2/aabb3/aabb3_expand_array.js +15 -0
- package/core/bvh2/aabb3/aabb3_intersect_aabb3.js +28 -0
- package/core/bvh2/aabb3/aabb3_intersect_ray_slab.js +73 -0
- package/core/bvh2/aabb3/{aabb3_intersects_frustum.js → aabb3_intersects_frustum_array.js} +16 -1
- package/core/bvh2/aabb3/aabb3_intersects_line_segment.js +79 -0
- package/core/bvh2/aabb3/aabb3_intersects_ray.js +92 -0
- package/core/bvh2/aabb3/{AABB3Math.spec.js → aabb3_intersects_ray.spec.js} +3 -3
- package/core/bvh2/aabb3/aabb3_intersects_ray_fast.js +176 -0
- package/core/bvh2/aabb3/aabb3_score_boxes_SAH.js +43 -0
- package/core/bvh2/aabb3/aabb_score_boxes_SAH_delta.js +37 -0
- package/core/bvh2/aabb3/deserializeAABB3.js +17 -0
- package/core/bvh2/aabb3/deserializeAABB3Encoded_v0.js +73 -0
- package/core/bvh2/aabb3/deserializeAABB3Quantized16Uint.js +36 -0
- package/core/bvh2/aabb3/serializeAABB3.js +13 -0
- package/core/bvh2/aabb3/serializeAABB3Quantized16Uint.js +33 -0
- package/core/bvh2/binary/2/BinaryUint32BVH.js +3 -3
- package/core/bvh2/binary/BinaryBVH.js +2 -2
- package/core/bvh2/binary/RayLeafIntersectionVisitor.js +2 -2
- package/core/bvh2/serialization/deserializeBinaryNode.js +1 -1
- package/core/bvh2/serialization/deserializeBinaryNodeFromBinaryBuffer.js +2 -1
- package/core/bvh2/serialization/serializeBinaryNode.js +1 -1
- package/core/bvh2/serialization/serializeBinaryNodeToBinaryBuffer.js +2 -1
- package/core/bvh2/transform/BottomUpOptimizingRebuilder.js +6 -5
- package/core/bvh2/transform/tryRotateSingleNode.js +2 -1
- package/core/bvh2/traversal/bvh_traverse_pre_order_using_stack.js +43 -0
- package/core/bvh2/visual/convert_bvh_to_dot_format_string.js +50 -0
- package/core/geom/3d/frustum/{array_setFromProjectionMatrix.js → frustum_from_projection_matrix_array.js} +1 -1
- package/core/geom/3d/topology/TopoMesh.js +0 -8
- package/core/geom/3d/topology/TopoVertex.js +7 -6
- package/core/geom/3d/topology/simplify/quadratic/Quadratic3.js +93 -5
- package/core/geom/3d/topology/simplify/quadratic/build_vertex_quadratics.js +7 -4
- package/core/geom/3d/topology/simplify/quadratic/compute_edge_collapse_cost_quadratic.js +7 -1
- package/core/geom/3d/topology/simplify/simplifyTopoMesh.js +1 -14
- package/core/graph/convertGraphToDotString.js +4 -4
- package/core/graph/v2/Graph.js +4 -0
- package/core/math/fabsf.js +8 -0
- package/engine/development/performance/MetricCollection.js +6 -0
- package/engine/ecs/foliage/ecs/Foliage2System.js +6 -2
- package/engine/graphics/compute_geometry_polycount.js +21 -0
- package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +77 -7
- package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +2 -2
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +4 -0
- package/engine/graphics/micron/build/hierarchy/merge_patches.js +1 -1
- package/engine/graphics/micron/convert_three_object_to_micron.js +2 -0
- package/engine/graphics/micron/format/MicronGeometryPatchOccurance.js +3 -2
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +176 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +1 -135
- package/engine/graphics/micron/prototypeVirtualGeometry.js +12 -7
- package/engine/graphics/micron/render/PatchCacheKey.js +1 -1
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +16 -43
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +5 -1
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +4 -10
- package/engine/graphics/micron/render/refinement/RefinementSpec.js +16 -20
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +316 -11
- package/engine/graphics/render/layers/RenderLayer.js +22 -14
- package/engine/graphics/render/visibility/IncrementalDeltaSet.js +18 -5
- package/engine/graphics/render/visibility/VisibilityComputer.js +11 -15
- package/package.json +1 -1
- package/core/bvh2/aabb3/AABB3Math.js +0 -579
|
@@ -23,7 +23,6 @@ export function extract_edge_cost(edge) {
|
|
|
23
23
|
/**
|
|
24
24
|
* @param {number} number_faces_to_remove minimum number of faces to removed
|
|
25
25
|
* @param {BinaryHeap<EdgeCollapseCandidate>} heap
|
|
26
|
-
* @param {EdgeCollapseCandidate[]} removed_edges
|
|
27
26
|
* @param {TopoMesh} mesh
|
|
28
27
|
* @param {Map<TopoEdge, EdgeCollapseCandidate>} edge_to_collapse_map
|
|
29
28
|
* @param {Map<number, Quadratic3>} vertex_quadratics
|
|
@@ -32,7 +31,6 @@ export function extract_edge_cost(edge) {
|
|
|
32
31
|
export function collapse_edges(
|
|
33
32
|
number_faces_to_remove,
|
|
34
33
|
heap,
|
|
35
|
-
removed_edges,
|
|
36
34
|
mesh,
|
|
37
35
|
edge_to_collapse_map,
|
|
38
36
|
vertex_quadratics,
|
|
@@ -64,8 +62,6 @@ export function collapse_edges(
|
|
|
64
62
|
// continue;
|
|
65
63
|
// }
|
|
66
64
|
|
|
67
|
-
removed_edges.push(collapse_candidate);
|
|
68
|
-
|
|
69
65
|
// find edges that need to be updated
|
|
70
66
|
const victim_vertex = collapse_candidate.victim_vertex;
|
|
71
67
|
|
|
@@ -208,21 +204,15 @@ export function collapse_edges(
|
|
|
208
204
|
* @param {TopoMesh} mesh
|
|
209
205
|
* @param {number} num_faces_to_remove desired number of faces to remove
|
|
210
206
|
* @param {Set<number>} [restricted_vertices] vertices that are not allowed to be removed
|
|
211
|
-
* @returns {EdgeCollapseCandidate[]} collapsed edges
|
|
212
207
|
*/
|
|
213
208
|
export function simplifyTopoMesh(mesh, num_faces_to_remove, restricted_vertices = new Set()) {
|
|
214
|
-
/**
|
|
215
|
-
*
|
|
216
|
-
* @type {EdgeCollapseCandidate[]}
|
|
217
|
-
*/
|
|
218
|
-
const removed_edges = [];
|
|
219
209
|
|
|
220
210
|
const faces = mesh.getFaces();
|
|
221
211
|
const face_count = faces.size;
|
|
222
212
|
|
|
223
213
|
if (num_faces_to_remove <= 0 || face_count <= 0) {
|
|
224
214
|
// we're already at the target
|
|
225
|
-
return
|
|
215
|
+
return ;
|
|
226
216
|
}
|
|
227
217
|
|
|
228
218
|
|
|
@@ -258,7 +248,6 @@ export function simplifyTopoMesh(mesh, num_faces_to_remove, restricted_vertices
|
|
|
258
248
|
collapse_edges(
|
|
259
249
|
num_faces_to_remove,
|
|
260
250
|
open_set,
|
|
261
|
-
removed_edges,
|
|
262
251
|
mesh,
|
|
263
252
|
edge_to_collapse_map,
|
|
264
253
|
vertex_quadratics,
|
|
@@ -270,6 +259,4 @@ export function simplifyTopoMesh(mesh, num_faces_to_remove, restricted_vertices
|
|
|
270
259
|
collapse_all_degenerate_edges(mesh.getEdges(), mesh);
|
|
271
260
|
|
|
272
261
|
// debugValidateMesh(mesh);
|
|
273
|
-
|
|
274
|
-
return removed_edges;
|
|
275
262
|
}
|
|
@@ -2,7 +2,7 @@ import LineBuilder from "../codegen/LineBuilder.js";
|
|
|
2
2
|
import { EdgeDirectionType } from "./Edge.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Build a DOT representation of the graph
|
|
5
|
+
* Build a Graphviz DOT representation of the graph
|
|
6
6
|
* @param {Graph} graph
|
|
7
7
|
* @returns {string}
|
|
8
8
|
*/
|
|
@@ -13,7 +13,7 @@ export function convertGraphToDotString(graph) {
|
|
|
13
13
|
|
|
14
14
|
lb.indent();
|
|
15
15
|
|
|
16
|
-
const nodes = graph.
|
|
16
|
+
const nodes = Array.from(graph.getNodes());
|
|
17
17
|
const nodeCount = nodes.length;
|
|
18
18
|
|
|
19
19
|
function nodeId(index) {
|
|
@@ -33,9 +33,9 @@ export function convertGraphToDotString(graph) {
|
|
|
33
33
|
|
|
34
34
|
const node = nodes[i];
|
|
35
35
|
|
|
36
|
-
const attachedEdges =
|
|
36
|
+
const attachedEdges = [];
|
|
37
37
|
|
|
38
|
-
const nAttachedEdges = attachedEdges
|
|
38
|
+
const nAttachedEdges = graph.getAttachedEdges(attachedEdges, node);
|
|
39
39
|
|
|
40
40
|
for (let j = 0; j < nAttachedEdges; j++) {
|
|
41
41
|
const edge = attachedEdges[j];
|
package/core/graph/v2/Graph.js
CHANGED
|
@@ -335,6 +335,10 @@ export class Graph {
|
|
|
335
335
|
* @returns {number}
|
|
336
336
|
*/
|
|
337
337
|
getAttachedEdges(result, node) {
|
|
338
|
+
assert.defined(result, 'result');
|
|
339
|
+
assert.isArray(result, 'result');
|
|
340
|
+
assert.defined(node, 'node');
|
|
341
|
+
|
|
338
342
|
const context = this.__nodes.get(node);
|
|
339
343
|
|
|
340
344
|
if (context === undefined) {
|
|
@@ -116,8 +116,9 @@ export class Foliage2System extends System {
|
|
|
116
116
|
graphics.views.elements.on.added.add(this.__handle_view_added, this);
|
|
117
117
|
graphics.views.elements.on.removed.add(this.__handle_view_removed, this);
|
|
118
118
|
|
|
119
|
-
this.renderLayer.buildVisibleSet = (
|
|
119
|
+
this.renderLayer.buildVisibleSet = (destination, destination_offset, view) => {
|
|
120
120
|
const data = this.data;
|
|
121
|
+
let additions = 0;
|
|
121
122
|
|
|
122
123
|
for (let entity in data) {
|
|
123
124
|
|
|
@@ -147,11 +148,14 @@ export class Foliage2System extends System {
|
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
const mesh = group.mesh;
|
|
150
|
-
|
|
151
|
+
|
|
152
|
+
destination[additions + destination_offset] = mesh;
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
}
|
|
154
156
|
}
|
|
157
|
+
|
|
158
|
+
return additions;
|
|
155
159
|
};
|
|
156
160
|
|
|
157
161
|
readyCallback();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {THREE.BufferGeometry} geometry
|
|
4
|
+
* @returns {number}
|
|
5
|
+
*/
|
|
6
|
+
export function compute_geometry_polycount(geometry) {
|
|
7
|
+
const index = geometry.getIndex();
|
|
8
|
+
|
|
9
|
+
if (index !== null) {
|
|
10
|
+
return index.count / 3;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const position_attribute = geometry.getAttribute('position');
|
|
14
|
+
|
|
15
|
+
if (position_attribute !== undefined) {
|
|
16
|
+
return position_attribute.count / 3;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// no valid way to discern polycount, assume 0
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
@@ -58,7 +58,7 @@ function scene_object_filter(object3D) {
|
|
|
58
58
|
/**
|
|
59
59
|
* @type {THREE.Material|null|undefined}
|
|
60
60
|
*/
|
|
61
|
-
const material = (object3D.customDepthMaterial
|
|
61
|
+
const material = (object3D.customDepthMaterial ? object3D.customDepthMaterial : object3D.material);
|
|
62
62
|
|
|
63
63
|
if (material && material.visible === false) {
|
|
64
64
|
//material's main
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ShadedGeometry } from "./ShadedGeometry.js";
|
|
2
2
|
import { Transform } from "../../../ecs/transform/Transform.js";
|
|
3
3
|
import { System } from "../../../ecs/System.js";
|
|
4
|
-
import { intersectRay } from "../../../../core/bvh2/aabb3/AABB3Math.js";
|
|
5
4
|
import { GeometrySpatialQueryAccelerator } from "../../geometry/buffered/query/GeometrySpatialQueryAccelerator.js";
|
|
6
5
|
import { SurfacePoint3 } from "../../../../core/geom/3d/SurfacePoint3.js";
|
|
7
6
|
import { v3_distance_sqr } from "../../../../core/geom/v3_distance_sqr.js";
|
|
8
7
|
import { mat4 } from "gl-matrix";
|
|
9
8
|
import { returnTrue } from "../../../../core/function/Functions.js";
|
|
9
|
+
import { aabb3_intersects_ray } from "../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
*
|
|
@@ -142,7 +142,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
142
142
|
const node = traversal_stack[traversal_cursor];
|
|
143
143
|
|
|
144
144
|
// test node against the ray
|
|
145
|
-
const intersects =
|
|
145
|
+
const intersects = aabb3_intersects_ray(
|
|
146
146
|
node.x0, node.y0, node.z0,
|
|
147
147
|
node.x1, node.y1, node.z1,
|
|
148
148
|
origin_x, origin_y, origin_z,
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { EngineHarness } from "../../../../EngineHarness.js";
|
|
2
|
-
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.
|
|
3
|
-
import EntityBuilder from "../../../../ecs/EntityBuilder.
|
|
4
|
-
import { Transform } from "../../../../ecs/transform/Transform.
|
|
5
|
-
import { ShadedGeometry } from "../ShadedGeometry.
|
|
2
|
+
import { ShadedGeometrySystem } from "../ShadedGeometrySystem.js";
|
|
3
|
+
import EntityBuilder from "../../../../ecs/EntityBuilder.js";
|
|
4
|
+
import { Transform } from "../../../../ecs/transform/Transform.js";
|
|
5
|
+
import { ShadedGeometry } from "../ShadedGeometry.js";
|
|
6
6
|
import { BoxBufferGeometry, MeshBasicMaterial } from "three";
|
|
7
|
+
import { randomFloatBetween } from "../../../../../core/math/random/randomFloatBetween.js";
|
|
8
|
+
import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
|
|
9
|
+
import ViewportPosition from "../../../../ecs/gui/position/ViewportPosition.js";
|
|
10
|
+
import GUIElement from "../../../../ecs/gui/GUIElement.js";
|
|
11
|
+
import ButtonView from "../../../../../view/elements/button/ButtonView.js";
|
|
12
|
+
import { downloadAsFile } from "../../../../../core/binary/ByteArrayTools.js";
|
|
13
|
+
import { convert_bvh_to_dot_format_string } from "../../../../../core/bvh2/visual/convert_bvh_to_dot_format_string.js";
|
|
14
|
+
import ViewportPositionSystem from "../../../../ecs/gui/position/ViewportPositionSystem.js";
|
|
15
|
+
import GUIElementSystem from "../../../../ecs/gui/GUIElementSystem.js";
|
|
7
16
|
|
|
8
17
|
const eh = new EngineHarness();
|
|
9
18
|
|
|
@@ -22,10 +31,71 @@ async function main(engine) {
|
|
|
22
31
|
|
|
23
32
|
const ecd = em.dataset;
|
|
24
33
|
|
|
34
|
+
const material = new MeshBasicMaterial({
|
|
35
|
+
color: 0xFFFFFF
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// material.visible = false;
|
|
39
|
+
|
|
40
|
+
window.material = material;
|
|
41
|
+
|
|
42
|
+
const geometry = new BoxBufferGeometry();
|
|
43
|
+
|
|
44
|
+
const random = seededRandom(0);
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < 100000; i++) {
|
|
47
|
+
|
|
48
|
+
new EntityBuilder()
|
|
49
|
+
.add(Transform.fromJSON({
|
|
50
|
+
position: {
|
|
51
|
+
x: randomFloatBetween(random, -50, 50),
|
|
52
|
+
y: randomFloatBetween(random, 0, 10),
|
|
53
|
+
z: randomFloatBetween(random, -50, 50)
|
|
54
|
+
},
|
|
55
|
+
scale: 0.01
|
|
56
|
+
}))
|
|
57
|
+
.add(ShadedGeometry.from(geometry, material))
|
|
58
|
+
.build(ecd);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
debug_button(engine, () => {
|
|
62
|
+
const dot = convert_bvh_to_dot_format_string(engine.graphics.layers.getLayerByName('shaded-geometry').bvh);
|
|
63
|
+
downloadAsFile(dot, 'bvh.dot', 'text');
|
|
64
|
+
|
|
65
|
+
}, 'save dot file');
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
const entityManager = engine.entityManager;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
*
|
|
74
|
+
* @param {Engine} engine
|
|
75
|
+
* @param {function} action
|
|
76
|
+
* @param {string} [name]
|
|
77
|
+
* @param {EntityComponentDataset} ecd
|
|
78
|
+
*/
|
|
79
|
+
function debug_button(engine, action, name = "Button", ecd = entityManager.dataset) {
|
|
80
|
+
if (entityManager.getSystem(ViewportPositionSystem) === null) {
|
|
81
|
+
entityManager.addSystem(new ViewportPositionSystem(engine.graphics.viewport.size));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (entityManager.getSystem(GUIElementSystem) === null) {
|
|
85
|
+
entityManager.addSystem(new GUIElementSystem(engine.gui.view, engine));
|
|
86
|
+
}
|
|
87
|
+
|
|
25
88
|
new EntityBuilder()
|
|
26
|
-
.add(
|
|
27
|
-
.add(
|
|
28
|
-
|
|
89
|
+
.add(ViewportPosition.fromJSON({}))
|
|
90
|
+
.add(GUIElement.fromView(new ButtonView({
|
|
91
|
+
action,
|
|
92
|
+
name,
|
|
93
|
+
css: {
|
|
94
|
+
background: 'rgba(255,255,255,0.8)',
|
|
95
|
+
border: '1px solid black',
|
|
96
|
+
borderRadius: '4px',
|
|
97
|
+
padding: '2px',
|
|
98
|
+
}
|
|
29
99
|
})))
|
|
30
100
|
.build(ecd);
|
|
31
101
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { SurfacePoint3 } from "../../../../../core/geom/3d/SurfacePoint3.js";
|
|
2
2
|
import { NodeType } from "../../../../../core/bvh2/binary/NodeType.js";
|
|
3
|
-
import { intersectRay } from "../../../../../core/bvh2/aabb3/AABB3Math.js";
|
|
4
3
|
import Vector3 from "../../../../../core/geom/Vector3.js";
|
|
5
4
|
import { computeTriangleRayIntersection } from "../../../../../core/geom/3d/triangle/computeTriangleRayIntersection.js";
|
|
6
5
|
import { GeometrySpatialAcceleratorVisitor } from "./GeometryVisitor.js";
|
|
6
|
+
import { aabb3_intersects_ray } from "../../../../../core/bvh2/aabb3/aabb3_intersects_ray.js";
|
|
7
7
|
|
|
8
8
|
export class RaycastNearestHitComputingVisitor extends GeometrySpatialAcceleratorVisitor {
|
|
9
9
|
constructor() {
|
|
@@ -158,7 +158,7 @@ export class RaycastNearestHitComputingVisitor extends GeometrySpatialAccelerato
|
|
|
158
158
|
const y1 = data[address + 4];
|
|
159
159
|
const z1 = data[address + 5];
|
|
160
160
|
|
|
161
|
-
return
|
|
161
|
+
return aabb3_intersects_ray(
|
|
162
162
|
x0, y0, z0,
|
|
163
163
|
x1, y1, z1,
|
|
164
164
|
|
|
@@ -15,6 +15,7 @@ import { compute_buffer_geometry_byte_size } from "../../geometry/buffered/compu
|
|
|
15
15
|
import { deinterleaveBufferGeometry } from "../../geometry/buffered/deinterleaveBufferGeometry.js";
|
|
16
16
|
import { AABB3 } from "../../../../core/bvh2/aabb3/AABB3.js";
|
|
17
17
|
import { aabb3_from_v3_array } from "../../../../core/bvh2/aabb3/aabb3_from_v3_array.js";
|
|
18
|
+
import { update_topo_face_normals } from "../../../../core/geom/3d/topology/update_topo_face_normals.js";
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Returns current time in milliseconds
|
|
@@ -142,6 +143,9 @@ export async function buildMicronGeometryFromBufferGeometry(input) {
|
|
|
142
143
|
|
|
143
144
|
expandConnectivityByLocality(topoMesh, geometry_aabb);
|
|
144
145
|
|
|
146
|
+
// ensure faces have normals for mesh simplification
|
|
147
|
+
update_topo_face_normals(Array.from(topoMesh.getFaces()), topoMesh.getFaces().size);
|
|
148
|
+
|
|
145
149
|
/**
|
|
146
150
|
* Used to generate neighbourhood assignment
|
|
147
151
|
* @type {Map<number, PatchRepresentation>}
|
|
@@ -399,7 +399,6 @@ async function many_to_many_merge(
|
|
|
399
399
|
collapse_edges(
|
|
400
400
|
num_desired_faces_to_remove,
|
|
401
401
|
open_set,
|
|
402
|
-
[],
|
|
403
402
|
merged_mesh,
|
|
404
403
|
edge_to_collapse_map,
|
|
405
404
|
vertex_quadratics,
|
|
@@ -462,6 +461,7 @@ async function many_to_many_merge(
|
|
|
462
461
|
// );
|
|
463
462
|
|
|
464
463
|
const group_per_pixel_error = group_inverse_polycount;
|
|
464
|
+
// const group_per_pixel_error = Math.sqrt(largest_squared_error);
|
|
465
465
|
|
|
466
466
|
// split topology into desired number of pieces
|
|
467
467
|
const pieces = recursive_split_mesh_partition(merged_mesh, actual_up_count, MICRON_PATCH_SIZE_MAX);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { squirrel3 } from "../../../../core/math/hash/squirrel3.js";
|
|
2
|
+
import { isArrayEqualStrict } from "../../../../core/collection/array/isArrayEqualStrict.js";
|
|
2
3
|
|
|
3
4
|
export class MicronGeometryPatchOccurrence {
|
|
4
5
|
constructor() {
|
|
@@ -21,7 +22,7 @@ export class MicronGeometryPatchOccurrence {
|
|
|
21
22
|
this.patch = null;
|
|
22
23
|
/**
|
|
23
24
|
*
|
|
24
|
-
* @type {
|
|
25
|
+
* @type {number[]|Float32Array|null}
|
|
25
26
|
*/
|
|
26
27
|
this.transform = null;
|
|
27
28
|
}
|
|
@@ -41,7 +42,7 @@ export class MicronGeometryPatchOccurrence {
|
|
|
41
42
|
return this.geometry_id === other.geometry_id
|
|
42
43
|
&& this.instance_id === other.instance_id
|
|
43
44
|
&& this.patch.id === other.patch.id
|
|
44
|
-
&& this.transform
|
|
45
|
+
&& isArrayEqualStrict(this.transform, other.transform)
|
|
45
46
|
;
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -0,0 +1,176 @@
|
|
|
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
|
+
import { computePathDirectory } from "../../../../core/FilePath.js";
|
|
5
|
+
import { BinaryBuffer } from "../../../../core/binary/BinaryBuffer.js";
|
|
6
|
+
import { MicronGeometry } from "../format/MicronGeometry.js";
|
|
7
|
+
import { MICRON_GEOMETRY_FIELD } from "../MICRON_GEOMETRY_FIELD.js";
|
|
8
|
+
import { async_traverse_three_object } from "../../../asset/loaders/async_traverse_three_object.js";
|
|
9
|
+
import { convert_three_object_to_micron } from "../convert_three_object_to_micron.js";
|
|
10
|
+
import { compute_geometry_polycount } from "../../compute_geometry_polycount.js";
|
|
11
|
+
import { traverseThreeObject } from "../../ecs/highlight/renderer/traverseThreeObject.js";
|
|
12
|
+
import { max2 } from "../../../../core/math/max2.js";
|
|
13
|
+
|
|
14
|
+
export const ASSET_TYPE_ARRAY_BUFFER = "arraybuffer";
|
|
15
|
+
|
|
16
|
+
const DEFAULT_THRESHOLD_POLYCOUNT = 1024;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param {THREE.Object3D} object
|
|
21
|
+
* @return {number}
|
|
22
|
+
*/
|
|
23
|
+
function max_polycount(object) {
|
|
24
|
+
let r = 0;
|
|
25
|
+
|
|
26
|
+
traverseThreeObject(object, (m) => {
|
|
27
|
+
if (m.isMesh) {
|
|
28
|
+
const geo = m.geometry;
|
|
29
|
+
if (geo !== null) {
|
|
30
|
+
r = max2(r, compute_geometry_polycount(geo))
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return r;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class GLTFAssetTransformer extends AssetTransformer {
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>} cache
|
|
42
|
+
*/
|
|
43
|
+
constructor(cache) {
|
|
44
|
+
super();
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
*
|
|
48
|
+
* @type {AbstractAsyncMap<THREE.BufferGeometry, MicronGeometry>}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
this.__cache = cache;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @type {AssetManager|null}
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
this.__am = null;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Minimum number of polygons required for micron to be used
|
|
62
|
+
* @type {number}
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
this.__threshold_polycount = DEFAULT_THRESHOLD_POLYCOUNT;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* @type {MicronGeometryBinarySerializationAdapter}
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
this.__serde = new MicronGeometryBinarySerializationAdapter();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param {AssetManager|null} am
|
|
78
|
+
*/
|
|
79
|
+
set assetManager(am) {
|
|
80
|
+
this.__am = am;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {THREE.Object3D} object
|
|
86
|
+
* @param {{asset:AssetDescription}} ctx
|
|
87
|
+
* @return {Promise<void>}
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
async __visitObjectToLoadMicron(object, ctx) {
|
|
91
|
+
if (!object.isMesh) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @type {THREE.BufferGeometry}
|
|
97
|
+
*/
|
|
98
|
+
const geometry = object.geometry;
|
|
99
|
+
|
|
100
|
+
const micron_uri = geometry.userData[MICRON_URI_FIELD];
|
|
101
|
+
|
|
102
|
+
if (typeof micron_uri !== "string") {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @type {AssetDescription}
|
|
109
|
+
*/
|
|
110
|
+
const ad = ctx.asset;
|
|
111
|
+
|
|
112
|
+
const base = computePathDirectory(ad.path);
|
|
113
|
+
|
|
114
|
+
let micron_data;
|
|
115
|
+
|
|
116
|
+
const micron_path = `${base}/${micron_uri}`;
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
micron_data = await this.__am.promise(micron_path, ASSET_TYPE_ARRAY_BUFFER);
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.error(`Failed to load micron geometry '${micron_path}' referenced in GLTF (will skip): ${e}`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// deserialize micron data
|
|
126
|
+
const buffer = BinaryBuffer.fromArrayBuffer(micron_data.create());
|
|
127
|
+
const micron_geometry = new MicronGeometry();
|
|
128
|
+
|
|
129
|
+
this.__serde.deserialize(buffer, micron_geometry);
|
|
130
|
+
|
|
131
|
+
// set proxy for raycasting
|
|
132
|
+
micron_geometry.proxy = geometry;
|
|
133
|
+
|
|
134
|
+
geometry[MICRON_GEOMETRY_FIELD] = micron_geometry;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
*
|
|
140
|
+
* @param {Asset} source
|
|
141
|
+
* @param {AssetDescription} asset_description
|
|
142
|
+
* @return {Promise<Asset>}
|
|
143
|
+
*/
|
|
144
|
+
async transform(source, asset_description) {
|
|
145
|
+
const animationClips = source.animations;
|
|
146
|
+
|
|
147
|
+
if (animationClips !== undefined && animationClips.length > 0) {
|
|
148
|
+
// animations might cause trouble
|
|
149
|
+
console.warn(`model '${asset_description.path}' contains animations, these animations might not works as intended with micron.`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @type {THREE.Object3D}
|
|
154
|
+
*/
|
|
155
|
+
const root = source.create();
|
|
156
|
+
|
|
157
|
+
const gltf_max_polycount = max_polycount(root);
|
|
158
|
+
|
|
159
|
+
if (gltf_max_polycount < this.__threshold_polycount) {
|
|
160
|
+
// no change, geometries are too small
|
|
161
|
+
return source;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// attempt to load existing micron geometries
|
|
165
|
+
await async_traverse_three_object(root, this.__visitObjectToLoadMicron, this, {
|
|
166
|
+
asset: asset_description
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const micron_root = await convert_three_object_to_micron(root.clone(), this.__cache);
|
|
170
|
+
micron_root.boundingSphere = root.boundingSphere;
|
|
171
|
+
|
|
172
|
+
source.override_mesh = micron_root;
|
|
173
|
+
|
|
174
|
+
return source;
|
|
175
|
+
}
|
|
176
|
+
}
|