@woosh/meep-engine 2.34.43 → 2.34.47

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.
Files changed (68) hide show
  1. package/core/bvh2/BinaryNode.js +62 -32
  2. package/core/bvh2/LeafNode.js +2 -1
  3. package/core/bvh2/aabb3/AABB3.js +879 -1059
  4. package/core/bvh2/aabb3/AABB3.spec.js +5 -7
  5. package/core/bvh2/aabb3/aabb3_array_intersects_ray.js +2 -2
  6. package/core/bvh2/aabb3/aabb3_box_surface_area_2.js +10 -0
  7. package/core/bvh2/aabb3/aabb3_compute_half_surface_area.js +16 -0
  8. package/core/bvh2/aabb3/aabb3_compute_surface_area.js +18 -0
  9. package/core/bvh2/aabb3/aabb3_expand_array.js +15 -0
  10. package/core/bvh2/aabb3/aabb3_intersect_aabb3.js +28 -0
  11. package/core/bvh2/aabb3/aabb3_intersect_ray_slab.js +73 -0
  12. package/core/bvh2/aabb3/{aabb3_intersects_frustum.js → aabb3_intersects_frustum_array.js} +16 -1
  13. package/core/bvh2/aabb3/aabb3_intersects_line_segment.js +79 -0
  14. package/core/bvh2/aabb3/aabb3_intersects_ray.js +92 -0
  15. package/core/bvh2/aabb3/{AABB3Math.spec.js → aabb3_intersects_ray.spec.js} +3 -3
  16. package/core/bvh2/aabb3/aabb3_intersects_ray_fast.js +176 -0
  17. package/core/bvh2/aabb3/aabb3_score_boxes_SAH.js +43 -0
  18. package/core/bvh2/aabb3/aabb_score_boxes_SAH_delta.js +37 -0
  19. package/core/bvh2/aabb3/deserializeAABB3.js +17 -0
  20. package/core/bvh2/aabb3/deserializeAABB3Encoded_v0.js +73 -0
  21. package/core/bvh2/aabb3/deserializeAABB3Quantized16Uint.js +36 -0
  22. package/core/bvh2/aabb3/serializeAABB3.js +13 -0
  23. package/core/bvh2/aabb3/serializeAABB3Quantized16Uint.js +33 -0
  24. package/core/bvh2/binary/2/BinaryUint32BVH.js +3 -3
  25. package/core/bvh2/binary/BinaryBVH.js +2 -2
  26. package/core/bvh2/binary/RayLeafIntersectionVisitor.js +2 -2
  27. package/core/bvh2/serialization/deserializeBinaryNode.js +1 -1
  28. package/core/bvh2/serialization/deserializeBinaryNodeFromBinaryBuffer.js +2 -1
  29. package/core/bvh2/serialization/serializeBinaryNode.js +1 -1
  30. package/core/bvh2/serialization/serializeBinaryNodeToBinaryBuffer.js +2 -1
  31. package/core/bvh2/transform/BottomUpOptimizingRebuilder.js +6 -5
  32. package/core/bvh2/transform/tryRotateSingleNode.js +2 -1
  33. package/core/bvh2/traversal/bvh_traverse_pre_order_using_stack.js +43 -0
  34. package/core/bvh2/visual/convert_bvh_to_dot_format_string.js +50 -0
  35. package/core/geom/3d/frustum/{array_setFromProjectionMatrix.js → frustum_from_projection_matrix_array.js} +1 -1
  36. package/core/geom/3d/topology/TopoMesh.js +0 -8
  37. package/core/geom/3d/topology/TopoVertex.js +7 -6
  38. package/core/geom/3d/topology/simplify/quadratic/Quadratic3.js +93 -5
  39. package/core/geom/3d/topology/simplify/quadratic/build_vertex_quadratics.js +7 -4
  40. package/core/geom/3d/topology/simplify/quadratic/compute_edge_collapse_cost_quadratic.js +7 -1
  41. package/core/geom/3d/topology/simplify/simplifyTopoMesh.js +1 -14
  42. package/core/graph/convertGraphToDotString.js +4 -4
  43. package/core/graph/v2/Graph.js +4 -0
  44. package/core/math/fabsf.js +8 -0
  45. package/engine/development/performance/MetricCollection.js +6 -0
  46. package/engine/ecs/foliage/ecs/Foliage2System.js +7 -2
  47. package/engine/graphics/compute_geometry_polycount.js +21 -0
  48. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
  49. package/engine/graphics/ecs/mesh-v2/sample/prototypeShadedGeometry.js +66 -9
  50. package/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +2 -2
  51. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +4 -0
  52. package/engine/graphics/micron/build/hierarchy/merge_patches.js +1 -1
  53. package/engine/graphics/micron/convert_three_object_to_micron.js +2 -0
  54. package/engine/graphics/micron/format/MicronGeometryPatchOccurance.js +3 -2
  55. package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +176 -0
  56. package/engine/graphics/micron/plugin/MicronRenderPlugin.js +1 -135
  57. package/engine/graphics/micron/prototypeVirtualGeometry.js +12 -7
  58. package/engine/graphics/micron/render/PatchCacheKey.js +1 -1
  59. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +16 -43
  60. package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +5 -1
  61. package/engine/graphics/micron/render/refinement/ActivePatchList.js +4 -10
  62. package/engine/graphics/micron/render/refinement/RefinementSpec.js +16 -20
  63. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +316 -11
  64. package/engine/graphics/render/layers/RenderLayer.js +22 -14
  65. package/engine/graphics/render/visibility/IncrementalDeltaSet.js +18 -5
  66. package/engine/graphics/render/visibility/VisibilityComputer.js +11 -15
  67. package/package.json +1 -1
  68. package/core/bvh2/aabb3/AABB3Math.js +0 -579
@@ -0,0 +1,17 @@
1
+ /**
2
+ *
3
+ * @param {BinaryBuffer} buffer
4
+ * @param {AABB3} box
5
+ */
6
+ function deserializeAABB3(buffer, box) {
7
+ const x0 = buffer.readFloat64();
8
+ const y0 = buffer.readFloat64();
9
+ const z0 = buffer.readFloat64();
10
+ const x1 = buffer.readFloat64();
11
+ const y1 = buffer.readFloat64();
12
+ const z1 = buffer.readFloat64();
13
+
14
+ box.setBounds(x0, y0, z0, x1, y1, z1);
15
+ }
16
+
17
+ export { deserializeAABB3 };
@@ -0,0 +1,73 @@
1
+ /**
2
+ *
3
+ * @param {BinaryBuffer} buffer
4
+ * @param {AABB3} box
5
+ * @param {number} x0
6
+ * @param {number} y0
7
+ * @param {number} z0
8
+ * @param {number} x1
9
+ * @param {number} y1
10
+ * @param {number} z1
11
+ */
12
+ export function deserializeAABB3Encoded_v0(buffer, box, x0, y0, z0, x1, y1, z1) {
13
+ const header = buffer.readUint8();
14
+
15
+ //compute value ranges
16
+ const xD = x1 - x0;
17
+ const yD = y1 - y0;
18
+ const zD = z1 - z0;
19
+
20
+
21
+ let qx0;
22
+ let qx1;
23
+
24
+ let qy0;
25
+ let qy1;
26
+
27
+ let qz0;
28
+ let qz1;
29
+
30
+ if ((header & 1) === 0) {
31
+ const _x0 = buffer.readUint16();
32
+ qx0 = (_x0 / 65535) * xD + x0;
33
+ } else {
34
+ qx0 = x0;
35
+ }
36
+
37
+ if ((header & 2) === 0) {
38
+ const _x1 = buffer.readUint16();
39
+ qx1 = (_x1 / 65535) * xD + x0;
40
+ } else {
41
+ qx1 = x1;
42
+ }
43
+
44
+ if ((header & 4) === 0) {
45
+ const _y0 = buffer.readUint16();
46
+ qy0 = (_y0 / 65535) * yD + y0;
47
+ } else {
48
+ qy0 = y0;
49
+ }
50
+
51
+ if ((header & 8) === 0) {
52
+ const _y1 = buffer.readUint16();
53
+ qy1 = (_y1 / 65535) * yD + y0;
54
+ } else {
55
+ qy1 = y1;
56
+ }
57
+
58
+ if ((header & 16) === 0) {
59
+ const _z0 = buffer.readUint16();
60
+ qz0 = (_z0 / 65535) * zD + z0;
61
+ } else {
62
+ qz0 = z0;
63
+ }
64
+
65
+ if ((header & 32) === 0) {
66
+ const _z1 = buffer.readUint16();
67
+ qz1 = (_z1 / 65535) * zD + z0;
68
+ } else {
69
+ qz1 = z1;
70
+ }
71
+
72
+ box.setBounds(qx0, qy0, qz0, qx1, qy1, qz1);
73
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ *
3
+ * @param {BinaryBuffer} buffer
4
+ * @param {AABB3} box
5
+ * @param {number} x0
6
+ * @param {number} y0
7
+ * @param {number} z0
8
+ * @param {number} x1
9
+ * @param {number} y1
10
+ * @param {number} z1
11
+ */
12
+ export function deserializeAABB3Quantized16Uint(buffer, box, x0, y0, z0, x1, y1, z1) {
13
+ //compute value ranges
14
+ const xD = x1 - x0;
15
+ const yD = y1 - y0;
16
+ const zD = z1 - z0;
17
+
18
+ //read values
19
+ const _x0 = buffer.readUint16();
20
+ const _y0 = buffer.readUint16();
21
+ const _z0 = buffer.readUint16();
22
+ const _x1 = buffer.readUint16();
23
+ const _y1 = buffer.readUint16();
24
+ const _z1 = buffer.readUint16();
25
+
26
+ //quantize all values
27
+ const qx0 = (_x0 / 65535) * xD + x0;
28
+ const qy0 = (_y0 / 65535) * yD + y0;
29
+ const qz0 = (_z0 / 65535) * zD + z0;
30
+
31
+ const qx1 = (_x1 / 65535) * xD + x0;
32
+ const qy1 = (_y1 / 65535) * yD + y0;
33
+ const qz1 = (_z1 / 65535) * zD + z0;
34
+
35
+ box.setBounds(qx0, qy0, qz0, qx1, qy1, qz1);
36
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ *
3
+ * @param {BinaryBuffer} buffer
4
+ * @param {AABB3} box
5
+ */
6
+ export function serializeAABB3(buffer, box) {
7
+ buffer.writeFloat64(box.x0);
8
+ buffer.writeFloat64(box.y0);
9
+ buffer.writeFloat64(box.z0);
10
+ buffer.writeFloat64(box.x1);
11
+ buffer.writeFloat64(box.y1);
12
+ buffer.writeFloat64(box.z1);
13
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ *
3
+ * @param {BinaryBuffer} buffer
4
+ * @param {AABB3} box
5
+ * @param {number} x0
6
+ * @param {number} y0
7
+ * @param {number} z0
8
+ * @param {number} x1
9
+ * @param {number} y1
10
+ * @param {number} z1
11
+ */
12
+ export function serializeAABB3Quantized16Uint(buffer, box, x0, y0, z0, x1, y1, z1) {
13
+ //compute value ranges
14
+ const xD = x1 - x0;
15
+ const yD = y1 - y0;
16
+ const zD = z1 - z0;
17
+
18
+ //quantize all values
19
+ const _x0 = (((box.x0 - x0) / xD) * 65535) | 0;
20
+ const _y0 = (((box.y0 - y0) / yD) * 65535) | 0;
21
+ const _z0 = (((box.z0 - z0) / zD) * 65535) | 0;
22
+
23
+ const _x1 = (((box.x1 - x0) / xD) * 65535) | 0;
24
+ const _y1 = (((box.y1 - y0) / yD) * 65535) | 0;
25
+ const _z1 = (((box.z1 - z0) / zD) * 65535) | 0;
26
+
27
+ buffer.writeUint16(_x0);
28
+ buffer.writeUint16(_y0);
29
+ buffer.writeUint16(_z0);
30
+ buffer.writeUint16(_x1);
31
+ buffer.writeUint16(_y1);
32
+ buffer.writeUint16(_z1);
33
+ }
@@ -3,10 +3,10 @@ import { min2 } from "../../../math/min2.js";
3
3
  import { max2 } from "../../../math/max2.js";
4
4
  import { ceilPowerOfTwo } from "../../../binary/operations/ceilPowerOfTwo.js";
5
5
  import { array_swap } from "../../../collection/array/array_swap.js";
6
- import { _boxSurfaceArea2 } from "../../aabb3/AABB3Math.js";
7
6
  import { mortonEncode_magicbits } from "../../../geom/3d/morton/mortonEncode_magicbits.js";
8
7
  import { min3 } from "../../../math/min3.js";
9
8
  import { max3 } from "../../../math/max3.js";
9
+ import { aabb3_compute_half_surface_area } from "../../aabb3/aabb3_compute_half_surface_area.js";
10
10
 
11
11
  /**
12
12
  * @readonly
@@ -272,7 +272,7 @@ export class BinaryUint32BVH {
272
272
  }
273
273
 
274
274
  this.readBounds(address, box, 0);
275
- result += _boxSurfaceArea2(box[0], box[1], box[2], box[3], box[4], box[5]);
275
+ result += aabb3_compute_half_surface_area(box[0], box[1], box[2], box[3], box[4], box[5]);
276
276
  }
277
277
 
278
278
  return result;
@@ -299,7 +299,7 @@ export class BinaryUint32BVH {
299
299
  const y1 = max3(scratch_box_0[4], scratch_box_1[4], scratch_box_2[4]);
300
300
  const z1 = max3(scratch_box_0[5], scratch_box_1[5], scratch_box_2[5]);
301
301
 
302
- return _boxSurfaceArea2(x0, y0, z0, x1, y1, z1);
302
+ return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
303
303
  }
304
304
 
305
305
  /**
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import PrimitiveType from "../../binary/type/PrimitiveTypes.js";
5
5
  import BinaryStructure from "../../binary/type/Type.js";
6
- import { intersectRay } from "../aabb3/AABB3Math.js";
6
+ import { aabb3_intersects_ray } from "../aabb3/aabb3_intersects_ray.js";
7
7
 
8
8
  const NodeType = {
9
9
  LEAF: 0,
@@ -262,7 +262,7 @@ BinaryBVH.prototype.traverseRayLeafIntersections = function (startX, startY, sta
262
262
  const y1 = daNode.read_y1(dataView, address);
263
263
  const z1 = daNode.read_z1(dataView, address);
264
264
 
265
- let b = intersectRay(x0, y0, z0, x1, y1, z1, startX, startY, startZ, directionX, directionY, directionZ);
265
+ let b = aabb3_intersects_ray(x0, y0, z0, x1, y1, z1, startX, startY, startZ, directionX, directionY, directionZ);
266
266
 
267
267
  if (!b) {
268
268
  return false;
@@ -1,7 +1,7 @@
1
1
  import { noop } from "../../function/Functions.js";
2
- import { intersectRay } from "../aabb3/AABB3Math.js";
3
2
  import { IndexedBinaryBVHVisitor } from "./IndexedBinaryBVHVisitor.js";
4
3
  import { NodeType } from "./NodeType.js";
4
+ import { aabb3_intersects_ray } from "../aabb3/aabb3_intersects_ray.js";
5
5
 
6
6
  export class RayLeafIntersectionVisitor extends IndexedBinaryBVHVisitor {
7
7
  constructor() {
@@ -37,7 +37,7 @@ export class RayLeafIntersectionVisitor extends IndexedBinaryBVHVisitor {
37
37
  const y1 = data[address + 4];
38
38
  const z1 = data[address + 5];
39
39
 
40
- const intersectionFound = intersectRay(x0, y0, z0, x1, y1, z1,
40
+ const intersectionFound = aabb3_intersects_ray(x0, y0, z0, x1, y1, z1,
41
41
  this.originX, this.originY, this.originZ,
42
42
  this.directionX, this.directionY, this.directionZ
43
43
  );
@@ -1,6 +1,6 @@
1
- import { deserializeAABB3 } from "../aabb3/AABB3.js";
2
1
  import { BinaryNode } from "../BinaryNode.js";
3
2
  import { deserializeLeafNode, LeafNode } from "../LeafNode.js";
3
+ import { deserializeAABB3 } from "../aabb3/deserializeAABB3.js";
4
4
 
5
5
  /**
6
6
  *
@@ -1,6 +1,7 @@
1
- import { deserializeAABB3, deserializeAABB3Encoded_v0 } from "../aabb3/AABB3.js";
2
1
  import { BinaryNode } from "../BinaryNode.js";
3
2
  import { LeafNode } from "../LeafNode.js";
3
+ import { deserializeAABB3Encoded_v0 } from "../aabb3/deserializeAABB3Encoded_v0.js";
4
+ import { deserializeAABB3 } from "../aabb3/deserializeAABB3.js";
4
5
 
5
6
  /**
6
7
  *
@@ -1,5 +1,5 @@
1
- import { serializeAABB3 } from "../aabb3/AABB3.js";
2
1
  import { isLeaf, serializeLeafNode } from "../LeafNode.js";
2
+ import { serializeAABB3 } from "../aabb3/serializeAABB3.js";
3
3
 
4
4
  /**
5
5
  *
@@ -1,4 +1,5 @@
1
- import { serializeAABB3, serializeAABB3Encoded_v0 } from "../aabb3/AABB3.js";
1
+ import { serializeAABB3Encoded_v0 } from "../aabb3/AABB3.js";
2
+ import { serializeAABB3 } from "../aabb3/serializeAABB3.js";
2
3
 
3
4
  /**
4
5
  *
@@ -1,7 +1,8 @@
1
- import { boxSurfaceArea2, scoreBoxesSAH } from "../aabb3/AABB3Math.js";
2
1
  import { BinaryNode } from "../BinaryNode.js";
3
2
  import { isLeaf } from "../LeafNode.js";
4
3
  import { surfaceAreaHeuristic } from "../sah/surfaceAreaHeuristic.js";
4
+ import { aabb3_score_boxes_SAH } from "../aabb3/aabb3_score_boxes_SAH.js";
5
+ import { aabb3_box_surface_area_2 } from "../aabb3/aabb3_box_surface_area_2.js";
5
6
 
6
7
  function BottomUpOptimizingRebuilder() {
7
8
  this.root = null;
@@ -9,7 +10,7 @@ function BottomUpOptimizingRebuilder() {
9
10
  /**
10
11
  * @type {function(left:NodeDescription, right:NodeDescription):number} heuristic Cost function of pairing two nodes, lower value means better pairing
11
12
  */
12
- this.heuristic = scoreBoxesSAH;
13
+ this.heuristic = aabb3_score_boxes_SAH;
13
14
  }
14
15
 
15
16
  /**
@@ -128,13 +129,13 @@ function leaves(node) {
128
129
  }
129
130
 
130
131
  function sah(left, right) {
131
- const leftArea = boxSurfaceArea2(left);
132
- const rightArea = boxSurfaceArea2(right);
132
+ const leftArea = aabb3_box_surface_area_2(left);
133
+ const rightArea = aabb3_box_surface_area_2(right);
133
134
 
134
135
  const leftLeaves = leaves(left);
135
136
  const rightLeaves = leaves(right);
136
137
 
137
- const commonArea = scoreBoxesSAH(left, right);
138
+ const commonArea = aabb3_score_boxes_SAH(left, right);
138
139
 
139
140
  return surfaceAreaHeuristic(commonArea, leftArea, rightArea, leftLeaves, rightLeaves);
140
141
  }
@@ -1,6 +1,7 @@
1
- import { boxSurfaceArea2 as computeArea, scoreBoxesSAH as computeAreaFor2 } from "../aabb3/AABB3Math.js";
2
1
  import { surfaceAreaHeuristic as sah } from "../sah/surfaceAreaHeuristic.js";
3
2
  import { isLeaf } from "../LeafNode.js";
3
+ import { aabb3_score_boxes_SAH as computeAreaFor2 } from "../aabb3/aabb3_score_boxes_SAH.js";
4
+ import { aabb3_box_surface_area_2 as computeArea } from "../aabb3/aabb3_box_surface_area_2.js";
4
5
 
5
6
  /**
6
7
  *
@@ -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
+ }
@@ -25,7 +25,7 @@ function array_set_plane_normalized(destination, destination_offset, x, y, z, w)
25
25
  * @param {number[]|Float32Array} frustum_planes
26
26
  * @param {number[]} me
27
27
  */
28
- export function array_setFromProjectionMatrix(frustum_planes, me) {
28
+ export function frustum_from_projection_matrix_array(frustum_planes, me) {
29
29
 
30
30
  const me0 = me[0];
31
31
  const me3 = me[3];
@@ -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
- for (let i = 0; i < face_count; i++) {
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
- // DEBUG
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 (let i = 0; i < edge_count; i++) {
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
- throw new Error('Not Implemented');
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
- for (let i = 0; i < mesh_vertex_count; i++) {
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 (let face of faces) {
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 (let j = 0; j < face_vertex_count; j++) {
55
- const face_vertex = face_vertices[j];
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
- return q_v0 + q_v1;
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
  }