@woosh/meep-engine 2.34.44 → 2.34.48
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/BitSet.js +4 -2
- package/core/bvh2/BinaryNode.js +53 -25
- 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/aabb/aabb3_estimate_projected_area2.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/engine/ecs/foliage/ecs/Foliage2System.js +22 -5
- package/engine/graphics/compute_geometry_polycount.js +21 -0
- package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +64 -9
- 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/MicronGeometry.js +1 -3
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +176 -0
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +1 -135
- package/engine/graphics/micron/prototypeVirtualGeometry.js +13 -8
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +10 -43
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +2 -8
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +123 -0
- 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/binary/BitSet.js
CHANGED
|
@@ -533,12 +533,14 @@ BitSet.prototype.shift = function (distance, start_index, end_index) {
|
|
|
533
533
|
* Sets all of the bits in this BitSet to false.
|
|
534
534
|
*/
|
|
535
535
|
BitSet.prototype.reset = function () {
|
|
536
|
-
|
|
536
|
+
const current_length = this.__length;
|
|
537
|
+
|
|
538
|
+
if (current_length <= 0) {
|
|
537
539
|
// no action required
|
|
538
540
|
return;
|
|
539
541
|
}
|
|
540
542
|
|
|
541
|
-
this.__data_uint32.fill(0, 0, Math.ceil(
|
|
543
|
+
this.__data_uint32.fill(0, 0, Math.ceil(current_length / 32));
|
|
542
544
|
this.__length = 0;
|
|
543
545
|
};
|
|
544
546
|
|
package/core/bvh2/BinaryNode.js
CHANGED
|
@@ -211,44 +211,62 @@ export class BinaryNode extends Node {
|
|
|
211
211
|
*/
|
|
212
212
|
__insertion_findSiblingFor(box) {
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
let
|
|
214
|
+
let node = this;
|
|
215
|
+
let cost_left = 0;
|
|
216
|
+
let cost_right = 0;
|
|
216
217
|
|
|
217
|
-
|
|
218
|
-
|
|
218
|
+
while (node.isBinaryNode) {
|
|
219
|
+
const left = node.left;
|
|
220
|
+
const right = node.right;
|
|
219
221
|
|
|
220
|
-
|
|
221
|
-
const node = open_set[--cursor];
|
|
222
|
+
const area = aabb3_box_surface_area_2(node);
|
|
222
223
|
|
|
223
|
-
const
|
|
224
|
+
const combined_area = combined_surface_area(node, box);
|
|
224
225
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
best_node = node;
|
|
228
|
-
}
|
|
226
|
+
//cost of creating a new parent for this node and the new leaf
|
|
227
|
+
const cost = combined_area;
|
|
229
228
|
|
|
230
|
-
|
|
229
|
+
// minimum cost of pushing the leaf further down the tree
|
|
230
|
+
const inheritance_cost = combined_area - area;
|
|
231
231
|
|
|
232
|
-
|
|
232
|
+
// cost of descending left
|
|
233
|
+
if (left !== null) {
|
|
234
|
+
if (left.isLeafNode) {
|
|
235
|
+
cost_left = combined_surface_area(left, box) + inheritance_cost;
|
|
236
|
+
} else {
|
|
237
|
+
cost_left = combined_surface_area(left, box) - aabb3_box_surface_area_2(left) + inheritance_cost;
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
cost_left = Infinity;
|
|
241
|
+
}
|
|
233
242
|
|
|
234
|
-
|
|
235
|
-
|
|
243
|
+
// cost of descending right
|
|
244
|
+
if (right !== null) {
|
|
236
245
|
|
|
237
|
-
if (
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
if (node.right !== null) {
|
|
243
|
-
open_set[cursor++] = node.right
|
|
244
|
-
}
|
|
246
|
+
if (right.isLeafNode) {
|
|
247
|
+
cost_right = combined_surface_area(right, box) + inheritance_cost;
|
|
248
|
+
} else {
|
|
249
|
+
cost_right = combined_surface_area(right, box) - aabb3_box_surface_area_2(right) + inheritance_cost;
|
|
245
250
|
}
|
|
251
|
+
} else {
|
|
252
|
+
cost_right = Infinity;
|
|
246
253
|
}
|
|
247
254
|
|
|
255
|
+
if (cost < cost_left && cost < cost_right) {
|
|
256
|
+
// descending either branch is too expensive
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
248
259
|
|
|
260
|
+
if (cost_left < cost_right && left !== null) {
|
|
261
|
+
node = left;
|
|
262
|
+
} else if (right !== null) {
|
|
263
|
+
node = right;
|
|
264
|
+
} else {
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
249
267
|
}
|
|
250
268
|
|
|
251
|
-
return
|
|
269
|
+
return node;
|
|
252
270
|
}
|
|
253
271
|
|
|
254
272
|
/**
|
|
@@ -1134,6 +1152,16 @@ BinaryNode.prototype.isBinaryNode = true;
|
|
|
1134
1152
|
* @returns {number}
|
|
1135
1153
|
*/
|
|
1136
1154
|
function inclusion_surface_area_heuristic(node, addition) {
|
|
1155
|
+
return combined_surface_area(node, addition) - aabb3_box_surface_area_2(node);
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
*
|
|
1160
|
+
* @param {AABB3} node
|
|
1161
|
+
* @param {AABB3} addition
|
|
1162
|
+
* @returns {number}
|
|
1163
|
+
*/
|
|
1164
|
+
function combined_surface_area(node, addition) {
|
|
1137
1165
|
const x0 = min2(node.x0, addition.x0);
|
|
1138
1166
|
const y0 = min2(node.y0, addition.y0);
|
|
1139
1167
|
const z0 = min2(node.z0, addition.z0);
|
|
@@ -1142,7 +1170,7 @@ function inclusion_surface_area_heuristic(node, addition) {
|
|
|
1142
1170
|
const y1 = max2(node.y1, addition.y1);
|
|
1143
1171
|
const z1 = max2(node.z1, addition.z1);
|
|
1144
1172
|
|
|
1145
|
-
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1)
|
|
1173
|
+
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
|
|
1146
1174
|
}
|
|
1147
1175
|
|
|
1148
1176
|
/**
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const stack = [];
|
|
2
|
+
let stackPointer = 0;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {BinaryNode} root
|
|
7
|
+
* @param {function(BinaryNode|LeafNode):*} visitor
|
|
8
|
+
* @param {*} [thisArg]
|
|
9
|
+
* @return {number}
|
|
10
|
+
*/
|
|
11
|
+
export function bvh_traverse_pre_order_using_stack(root, visitor, thisArg) {
|
|
12
|
+
let visitCount = 0;
|
|
13
|
+
|
|
14
|
+
const stackOffset = stackPointer;
|
|
15
|
+
|
|
16
|
+
stack[stackPointer++] = root;
|
|
17
|
+
|
|
18
|
+
let n;
|
|
19
|
+
|
|
20
|
+
while (stackPointer-- > stackOffset) {
|
|
21
|
+
|
|
22
|
+
visitCount++;
|
|
23
|
+
|
|
24
|
+
n = stack[stackPointer];
|
|
25
|
+
|
|
26
|
+
visitor.call(thisArg, n);
|
|
27
|
+
|
|
28
|
+
if (!n.isLeafNode) {
|
|
29
|
+
//a binary node
|
|
30
|
+
if (n.right !== null) {
|
|
31
|
+
stack[stackPointer++] = n.right;
|
|
32
|
+
}
|
|
33
|
+
if (n.left !== null) {
|
|
34
|
+
stack[stackPointer++] = n.left;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// drop stack frame
|
|
40
|
+
stackPointer = stackOffset;
|
|
41
|
+
|
|
42
|
+
return visitCount;
|
|
43
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { convertGraphToDotString } from "../../graph/convertGraphToDotString.js";
|
|
2
|
+
import { bvh_traverse_pre_order_using_stack } from "../traversal/bvh_traverse_pre_order_using_stack.js";
|
|
3
|
+
import { Graph } from "../../graph/v2/Graph.js";
|
|
4
|
+
import { Edge, EdgeDirectionType } from "../../graph/Edge.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {BinaryNode} bvh
|
|
9
|
+
* @returns {Graph}
|
|
10
|
+
*/
|
|
11
|
+
export function bvh_to_graph(bvh) {
|
|
12
|
+
//traverse twice, first collect all nodes, second time introduce edges
|
|
13
|
+
const graph = new Graph();
|
|
14
|
+
|
|
15
|
+
bvh_traverse_pre_order_using_stack(bvh, node => {
|
|
16
|
+
graph.addNode(node);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
bvh_traverse_pre_order_using_stack(bvh, node => {
|
|
20
|
+
if (node.isBinaryNode) {
|
|
21
|
+
|
|
22
|
+
if (node.left !== null) {
|
|
23
|
+
const edge = new Edge(node, node.left);
|
|
24
|
+
|
|
25
|
+
edge.direction = EdgeDirectionType.Forward;
|
|
26
|
+
|
|
27
|
+
graph.addEdge(edge);
|
|
28
|
+
}
|
|
29
|
+
if (node.right !== null) {
|
|
30
|
+
const edge = new Edge(node, node.right);
|
|
31
|
+
|
|
32
|
+
edge.direction = EdgeDirectionType.Forward;
|
|
33
|
+
|
|
34
|
+
graph.addEdge(edge);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return graph;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build a Graphviz DOT representation of the graph
|
|
44
|
+
* @param {BinaryNode} bvh
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export function convert_bvh_to_dot_format_string(bvh) {
|
|
48
|
+
const graph = bvh_to_graph(bvh);
|
|
49
|
+
return convertGraphToDotString(graph);
|
|
50
|
+
}
|
|
@@ -31,14 +31,6 @@ export class TopoMesh {
|
|
|
31
31
|
this.__faces = new Set();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
get edges() {
|
|
35
|
-
throw new Error('Deprecated accessor, use getEdges instead');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get faces() {
|
|
39
|
-
throw new Error('Deprecated accessor, use getEdges instead');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
34
|
/**
|
|
43
35
|
*
|
|
44
36
|
* @returns {Set<TopoEdge>}
|
|
@@ -241,24 +241,25 @@ export class TopoVertex {
|
|
|
241
241
|
const faces = victim.faces;
|
|
242
242
|
const face_count = faces.length;
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
let i = 0;
|
|
245
|
+
|
|
246
|
+
for (; i < face_count; i++) {
|
|
245
247
|
// take over the victim's faces
|
|
246
248
|
const face = faces[i];
|
|
247
249
|
|
|
248
|
-
|
|
249
|
-
face.computeNormal();
|
|
250
|
+
|
|
251
|
+
// face.computeNormal(); // DEBUG
|
|
250
252
|
face.replaceVertex(victim, this);
|
|
251
253
|
|
|
252
254
|
this.addUniqueFace(face);
|
|
253
255
|
|
|
254
|
-
// DEBUG
|
|
255
|
-
face.computeNormal();
|
|
256
|
+
// face.computeNormal(); // DEBUG
|
|
256
257
|
}
|
|
257
258
|
|
|
258
259
|
const edges = victim.edges;
|
|
259
260
|
const edge_count = edges.length;
|
|
260
261
|
|
|
261
|
-
for (
|
|
262
|
+
for (i = 0; i < edge_count; i++) {
|
|
262
263
|
// take over the victim's edges
|
|
263
264
|
const edge = edges[i];
|
|
264
265
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { v3_dot } from "../../../../v3_dot.js";
|
|
2
|
+
import { fabsf } from "../../../../../math/fabsf.js";
|
|
3
|
+
import { EPSILON } from "../../../../../math/MathUtils.js";
|
|
4
|
+
import { vec3 } from "gl-matrix";
|
|
2
5
|
|
|
3
6
|
export class Quadratic3 {
|
|
4
7
|
constructor() {
|
|
@@ -21,6 +24,74 @@ export class Quadratic3 {
|
|
|
21
24
|
this.d2 = 0;
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @param {ArrayLike<number>|number[]|Float32Array} result
|
|
30
|
+
*/
|
|
31
|
+
toVector3(result) {
|
|
32
|
+
result[0] = this.ad;
|
|
33
|
+
result[1] = this.bd;
|
|
34
|
+
result[2] = this.cd;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param {ArrayLike<number>|number[]|Float32Array} m3
|
|
40
|
+
*/
|
|
41
|
+
toTensorM3(m3) {
|
|
42
|
+
m3[0] = this.a2;
|
|
43
|
+
m3[1] = this.ab;
|
|
44
|
+
m3[2] = this.ac;
|
|
45
|
+
|
|
46
|
+
m3[3] = this.ab;
|
|
47
|
+
m3[4] = this.b2;
|
|
48
|
+
m3[5] = this.bc;
|
|
49
|
+
|
|
50
|
+
m3[6] = this.ac;
|
|
51
|
+
m3[7] = this.bc;
|
|
52
|
+
m3[8] = this.c2;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Equivalent to taking a tensor followed by matrix inversion
|
|
57
|
+
* @param {ArrayLike<number>|number[]|Float32Array} m3
|
|
58
|
+
* @param {number} epsilon
|
|
59
|
+
* @returns {boolean} whether operation was successful or not
|
|
60
|
+
*/
|
|
61
|
+
toTensorM3Inverse(m3, epsilon) {
|
|
62
|
+
const a2 = this.a2;
|
|
63
|
+
const b2 = this.b2;
|
|
64
|
+
const c2 = this.c2;
|
|
65
|
+
const bc = this.bc;
|
|
66
|
+
const ab = this.ab;
|
|
67
|
+
const ac = this.ac;
|
|
68
|
+
|
|
69
|
+
const det = a2 * (b2 * c2 - bc * bc) -
|
|
70
|
+
ab * (ab * c2 - ac * bc) +
|
|
71
|
+
ac * (ab * bc - ac * b2);
|
|
72
|
+
|
|
73
|
+
if (fabsf(det) > epsilon) {
|
|
74
|
+
|
|
75
|
+
const invdet = 1.0 / det;
|
|
76
|
+
|
|
77
|
+
m3[0] = (b2 * c2 - bc * bc) * invdet;
|
|
78
|
+
m3[3] = (bc * ac - ab * c2) * invdet;
|
|
79
|
+
m3[6] = (ab * bc - b2 * ac) * invdet;
|
|
80
|
+
|
|
81
|
+
m3[1] = (ac * bc - ab * c2) * invdet;
|
|
82
|
+
m3[4] = (a2 * c2 - ac * ac) * invdet;
|
|
83
|
+
m3[7] = (ab * ac - a2 * bc) * invdet;
|
|
84
|
+
|
|
85
|
+
m3[2] = (ab * bc - ac * b2) * invdet;
|
|
86
|
+
m3[5] = (ac * ab - a2 * bc) * invdet;
|
|
87
|
+
m3[8] = (a2 * b2 - ab * ab) * invdet;
|
|
88
|
+
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
24
95
|
/**
|
|
25
96
|
* Set from plane expressed as a 4 component vector
|
|
26
97
|
* @param {number} x plane normal
|
|
@@ -78,18 +149,35 @@ export class Quadratic3 {
|
|
|
78
149
|
evaluate(x, y, z) {
|
|
79
150
|
// Evaluate vAv + 2bv + c
|
|
80
151
|
|
|
81
|
-
return x * x * this.a2 + 2 * x * y * this.ab + 2 * x * z * this.ac + 2 * x * this.ad
|
|
82
|
-
+ y * y * this.b2 + 2 * y * z * this.bc + 2 * y * this.bd
|
|
83
|
-
+ z * z * this.c2 + 2 * z * this.cd
|
|
84
|
-
+ this.d2;
|
|
152
|
+
return (x * x * this.a2) + (2 * x * y * this.ab) + (2 * x * z * this.ac) + (2 * x * this.ad) // A
|
|
153
|
+
+ (y * y * this.b2) + (2 * y * z * this.bc) + (2 * y * this.bd) // B
|
|
154
|
+
+ (z * z * this.c2) + (2 * z * this.cd) // C
|
|
155
|
+
+ this.d2; // D
|
|
85
156
|
}
|
|
86
157
|
|
|
87
158
|
/**
|
|
159
|
+
* Find optimal vertex position based on the quadratic
|
|
160
|
+
*
|
|
161
|
+
* Based on Bleder's implementation: https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/blenlib/intern/quadric.c
|
|
88
162
|
*
|
|
89
163
|
* @param {number[]} out
|
|
164
|
+
* @returns {boolean}
|
|
90
165
|
*/
|
|
91
166
|
optimize(out) {
|
|
92
|
-
|
|
167
|
+
const m = new Float32Array(9);
|
|
168
|
+
|
|
169
|
+
if (this.toTensorM3Inverse(m, EPSILON)) {
|
|
170
|
+
|
|
171
|
+
this.toVector3(out);
|
|
172
|
+
|
|
173
|
+
vec3.transformMat3(out, out, m);
|
|
174
|
+
vec3.negate(out, out);
|
|
175
|
+
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return false;
|
|
180
|
+
|
|
93
181
|
}
|
|
94
182
|
|
|
95
183
|
/**
|
|
@@ -31,7 +31,10 @@ export function build_vertex_quadratics(mesh, quadratics) {
|
|
|
31
31
|
const mesh_vertices = mesh.vertices;
|
|
32
32
|
const mesh_vertex_count = mesh_vertices.length;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
|
|
35
|
+
let i, face;
|
|
36
|
+
|
|
37
|
+
for (i = 0; i < mesh_vertex_count; i++) {
|
|
35
38
|
const mesh_vertex = mesh_vertices[i];
|
|
36
39
|
|
|
37
40
|
const vertex_quadratic = new Quadratic3();
|
|
@@ -44,15 +47,15 @@ export function build_vertex_quadratics(mesh, quadratics) {
|
|
|
44
47
|
|
|
45
48
|
const faces = mesh.getFaces();
|
|
46
49
|
|
|
47
|
-
for (
|
|
50
|
+
for (face of faces) {
|
|
48
51
|
|
|
49
52
|
q.setFromFace(face);
|
|
50
53
|
|
|
51
54
|
const face_vertices = face.vertices;
|
|
52
55
|
const face_vertex_count = face_vertices.length;
|
|
53
56
|
|
|
54
|
-
for (
|
|
55
|
-
const face_vertex = face_vertices[
|
|
57
|
+
for (i = 0; i < face_vertex_count; i++) {
|
|
58
|
+
const face_vertex = face_vertices[i];
|
|
56
59
|
|
|
57
60
|
// accumulate to adjacent vertex
|
|
58
61
|
const face_vertex_quadratic = quadratics.get(face_vertex.index);
|
|
@@ -18,5 +18,11 @@ export function compute_edge_collapse_cost_quadratic(
|
|
|
18
18
|
const q_v0 = q0.evaluate(target.x, target.y, target.z);
|
|
19
19
|
const q_v1 = q1.evaluate(target.x, target.y, target.z);
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* 'cost' shouldn't be negative but happens sometimes with small values.
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
const cost = Math.abs(q_v0 + q_v1);
|
|
26
|
+
|
|
27
|
+
return cost;
|
|
22
28
|
}
|
|
@@ -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) {
|
|
@@ -111,13 +111,26 @@ export class Foliage2System extends System {
|
|
|
111
111
|
|
|
112
112
|
this.renderLayer = graphics.layers.create('instanced-mesh-system');
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
/**
|
|
115
|
+
*
|
|
116
|
+
* @type {CameraViewManager}
|
|
117
|
+
*/
|
|
118
|
+
const views = graphics.views;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
*
|
|
122
|
+
* @type {List<CameraView>}
|
|
123
|
+
*/
|
|
124
|
+
const view_list = views.elements;
|
|
125
|
+
|
|
126
|
+
view_list.forEach(this.__handle_view_added, this);
|
|
115
127
|
|
|
116
|
-
|
|
117
|
-
|
|
128
|
+
view_list.on.added.add(this.__handle_view_added, this);
|
|
129
|
+
view_list.on.removed.add(this.__handle_view_removed, this);
|
|
118
130
|
|
|
119
|
-
this.renderLayer.buildVisibleSet = (
|
|
131
|
+
this.renderLayer.buildVisibleSet = (destination, destination_offset, view) => {
|
|
120
132
|
const data = this.data;
|
|
133
|
+
let additions = 0;
|
|
121
134
|
|
|
122
135
|
for (let entity in data) {
|
|
123
136
|
|
|
@@ -147,11 +160,15 @@ export class Foliage2System extends System {
|
|
|
147
160
|
}
|
|
148
161
|
|
|
149
162
|
const mesh = group.mesh;
|
|
150
|
-
|
|
163
|
+
|
|
164
|
+
destination[additions + destination_offset] = mesh;
|
|
165
|
+
additions++;
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
}
|
|
154
169
|
}
|
|
170
|
+
|
|
171
|
+
return additions;
|
|
155
172
|
};
|
|
156
173
|
|
|
157
174
|
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
|
+
}
|