@woosh/meep-engine 2.34.38 → 2.34.39

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.
@@ -34,7 +34,7 @@ let stackPointer = 0;
34
34
  */
35
35
  const stack = [];
36
36
 
37
- export class BinaryNode extends Node{
37
+ export class BinaryNode extends Node {
38
38
  constructor() {
39
39
  super();
40
40
 
@@ -58,10 +58,17 @@ export class BinaryNode extends Node{
58
58
 
59
59
  /**
60
60
  * Number of leaf nodes in the hierarchy
61
+ * @deprecated
61
62
  * @type {number}
62
63
  * @private
63
64
  */
64
65
  this.leafNodeCount = 0;
66
+
67
+ /**
68
+ * Leaf node will have height 0, root node will have height equal to maximum depth of the tree
69
+ * @type {number}
70
+ */
71
+ this.height = 0;
65
72
  }
66
73
 
67
74
  /**
@@ -107,38 +114,38 @@ export class BinaryNode extends Node{
107
114
  * @param {*} [thisArg]
108
115
  */
109
116
  traverseLeavesPreOrderUsingStack(visitor, thisArg) {
110
- let visitCount = 0;
117
+ let visitCount = 0;
111
118
 
112
- const stackOffset = stackPointer;
119
+ const stackOffset = stackPointer;
113
120
 
114
- stack[stackPointer++] = this;
121
+ stack[stackPointer++] = this;
115
122
 
116
- let n;
123
+ let n;
117
124
 
118
- while (stackPointer-- > stackOffset) {
125
+ while (stackPointer-- > stackOffset) {
119
126
 
120
- visitCount++;
127
+ visitCount++;
121
128
 
122
- n = stack[stackPointer];
129
+ n = stack[stackPointer];
123
130
 
124
- if (n.isLeafNode) {
125
- visitor.call(thisArg, n);
126
- } else {
127
- //a binary node
128
- if (n.right !== null) {
129
- stack[stackPointer++] = n.right;
130
- }
131
- if (n.left !== null) {
132
- stack[stackPointer++] = n.left;
133
- }
131
+ if (n.isLeafNode) {
132
+ visitor.call(thisArg, n);
133
+ } else {
134
+ //a binary node
135
+ if (n.right !== null) {
136
+ stack[stackPointer++] = n.right;
137
+ }
138
+ if (n.left !== null) {
139
+ stack[stackPointer++] = n.left;
134
140
  }
135
141
  }
142
+ }
136
143
 
137
144
  // drop stack frame
138
145
  stackPointer = stackOffset;
139
146
 
140
- return visitCount;
141
- }
147
+ return visitCount;
148
+ }
142
149
 
143
150
 
144
151
  /**
@@ -154,6 +161,7 @@ export class BinaryNode extends Node{
154
161
  this.right = null;
155
162
 
156
163
  this.leafNodeCount = 0;
164
+ this.height = 0;
157
165
 
158
166
  this.setNegativelyInfiniteBounds();
159
167
  }
@@ -167,10 +175,6 @@ export class BinaryNode extends Node{
167
175
  this.left = left;
168
176
  this.right = right;
169
177
 
170
- this.updateLeafNodeCount()
171
-
172
- this.refitFor2();
173
-
174
178
  left.parentNode = this;
175
179
  right.parentNode = this;
176
180
  }
@@ -183,11 +187,6 @@ export class BinaryNode extends Node{
183
187
  assert.isNull(this.left, 'left');
184
188
 
185
189
  this.left = child;
186
-
187
- this.updateLeafNodeCount();
188
-
189
- this.refit();
190
-
191
190
  child.parentNode = this;
192
191
  }
193
192
 
@@ -199,16 +198,12 @@ export class BinaryNode extends Node{
199
198
  assert.isNull(this.right, 'right');
200
199
 
201
200
  this.right = child;
202
-
203
- this.updateLeafNodeCount();
204
-
205
- this.refit();
206
-
207
201
  child.parentNode = this;
208
202
  }
209
203
 
210
204
  /**
211
205
  * For incremental insertion, a sibling needs to be found, newly inserted node will be parented together with this sibling
206
+ * @see https://github.com/erincatto/box2d/blob/9dc24a6fd4f32442c4bcf80791de47a0a7d25afb/src/collision/b2_dynamic_tree.cpp#L197
212
207
  * @param {AABB3} box
213
208
  * @returns {BinaryNode|LeafNode}
214
209
  */
@@ -503,6 +498,35 @@ export class BinaryNode extends Node{
503
498
  return surfaceAreaHeuristic(thisArea, leftArea, rightArea, leftLeaves, rightLeaves);
504
499
  }
505
500
 
501
+ updateHeight() {
502
+ let node = this;
503
+ let n = 0;
504
+
505
+ while (node !== null) {
506
+ n = 0;
507
+
508
+ const right = node.right;
509
+
510
+ if (right !== null) {
511
+ n = right.height;
512
+ }
513
+
514
+ const left = this.left;
515
+
516
+ if (left !== null) {
517
+ n = max2(n, left.height);
518
+ }
519
+
520
+ node.height = n + 1;
521
+
522
+ // propagate update up the tree
523
+ node = node.parentNode;
524
+ }
525
+ }
526
+
527
+ /**
528
+ * @deprecated
529
+ */
506
530
  updateLeafNodeCount() {
507
531
  let node = this;
508
532
 
@@ -568,6 +592,7 @@ export class BinaryNode extends Node{
568
592
  r.right = rL;
569
593
 
570
594
  r.updateLeafNodeCount();
595
+ r.updateHeight();
571
596
 
572
597
  r.bubbleRefit();
573
598
  }
@@ -575,25 +600,26 @@ export class BinaryNode extends Node{
575
600
  rotateRight() {
576
601
  const r = this.right;
577
602
 
578
- const l = this.left;
603
+ const left = this.left;
579
604
 
580
- const lL = l.left;
581
- const lR = l.right;
605
+ const lL = left.left;
606
+ const lR = left.right;
582
607
 
583
608
  if (lL !== null) {
584
609
  lL.parentNode = this;
585
610
  }
586
611
 
587
- l.right = r;
612
+ left.right = r;
588
613
  if (r !== null) {
589
- r.parentNode = l;
614
+ r.parentNode = left;
590
615
  }
591
616
 
592
- l.left = lR;
617
+ left.left = lR;
593
618
 
594
- l.updateLeafNodeCount();
619
+ left.updateLeafNodeCount();
620
+ left.updateHeight();
595
621
 
596
- l.bubbleRefit();
622
+ left.bubbleRefit();
597
623
  }
598
624
 
599
625
  /**
@@ -624,8 +650,14 @@ export class BinaryNode extends Node{
624
650
  for (i = 0; i < remaining_nodes - 1; i += 2) {
625
651
  const a = nodes[i];
626
652
  const b = nodes[i + 1];
653
+
627
654
  n = new BinaryNode();
655
+
628
656
  n.setChildren(a, b);
657
+
658
+ n.updateHeight();
659
+ n.refitFor2();
660
+
629
661
  nodes[i >> 1] = n;
630
662
  }
631
663
 
@@ -994,15 +1026,19 @@ export class BinaryNode extends Node{
994
1026
  const sibling = this.__insertion_findSiblingFor(child);
995
1027
 
996
1028
  const sibling_parent = sibling.parentNode;
1029
+ let parent = sibling_parent;
1030
+
997
1031
  if (sibling_parent === null) {
998
- // root node
1032
+ // "sibling" is the root node
1033
+
1034
+ parent = sibling;
999
1035
 
1000
1036
  if (sibling.left === null) {
1001
1037
  sibling.setChildLeft(child);
1002
1038
  } else if (sibling.right === null) {
1003
1039
  sibling.setChildRight(child);
1004
1040
  } else {
1005
- const parent = new BinaryNode();
1041
+ parent = new BinaryNode();
1006
1042
 
1007
1043
  parent.setChildren(sibling.right, child);
1008
1044
  sibling.right = parent;
@@ -1025,12 +1061,23 @@ export class BinaryNode extends Node{
1025
1061
 
1026
1062
  } else {
1027
1063
 
1028
- transplantNewCommonParent(sibling, child)
1064
+ parent = transplantNewCommonParent(sibling, child)
1029
1065
 
1030
1066
  }
1031
1067
 
1032
- sibling_parent.bubbleRefit();
1068
+ }
1069
+
1070
+ // walk back up the tree fixing heights and bounds
1071
+ while (parent !== null) {
1072
+ // parent = this.balance();
1073
+
1074
+ const left = parent.left;
1075
+ const right = parent.right;
1033
1076
 
1077
+ parent.height = 1 + max2(left !== null ? left.height : 0, right !== null ? right.height : 0);
1078
+ parent.refit();
1079
+
1080
+ parent = parent.parentNode;
1034
1081
  }
1035
1082
  }
1036
1083
 
@@ -1116,38 +1163,6 @@ function inclusion_cost_lower_bound(node, addition) {
1116
1163
  }
1117
1164
 
1118
1165
 
1119
- /**
1120
- *
1121
- * @param {Node} n0
1122
- * @param {Node} n1
1123
- * @return {number}
1124
- */
1125
- function sortMortonCodes(n0, n1) {
1126
- return n0._mortonCode - n1._mortonCode;
1127
- }
1128
-
1129
-
1130
- /**
1131
- *
1132
- * @param node
1133
- */
1134
- function countLeaves(node) {
1135
- if (isLeaf(node)) {
1136
- return 1;
1137
- }
1138
-
1139
- let result = 0;
1140
-
1141
- node.traversePreOrderUsingStack(function (node) {
1142
- if (isLeaf(node)) {
1143
- result++;
1144
- }
1145
- });
1146
-
1147
- return result;
1148
- }
1149
-
1150
-
1151
1166
  /**
1152
1167
  * @private
1153
1168
  * Used in intersection traversal methods. Should be invoked via Function.apply and Function.call only and not be called directly
@@ -1179,10 +1194,6 @@ function transplantNewCommonParent(node, child) {
1179
1194
  bNode.setChildren(node, child);
1180
1195
  bNode.parentNode = parent;
1181
1196
 
1182
- parent.bubbleExpandToFit(bNode);
1183
-
1184
- parent.updateLeafNodeCount();
1185
-
1186
1197
  return bNode;
1187
1198
  }
1188
1199
 
@@ -39,17 +39,6 @@ export class LeafNode extends Node {
39
39
  this.y1 = y1;
40
40
  this.z1 = z1;
41
41
 
42
- /**
43
- *
44
- * @type {boolean}
45
- */
46
- this.isLeafNode = true;
47
- /**
48
- * Useful shortcut, to avoid having to distinguish between leaf and intermediate nodes
49
- * @readonly
50
- * @type {number}
51
- */
52
- this.leafNodeCount = 1;
53
42
  }
54
43
 
55
44
  /**
@@ -105,6 +94,26 @@ export class LeafNode extends Node {
105
94
  }
106
95
  }
107
96
 
97
+ /**
98
+ *
99
+ * @type {boolean}
100
+ */
101
+ LeafNode.prototype.isLeafNode = true;
102
+
103
+ /**
104
+ * Leaf node will have height 0, root node will have height equal to maximum depth of the tree
105
+ * @type {number}
106
+ */
107
+ LeafNode.prototype.height = 0;
108
+
109
+ /**
110
+ * Useful shortcut, to avoid having to distinguish between leaf and intermediate nodes
111
+ * @readonly
112
+ * @deprecated
113
+ * @type {number}
114
+ */
115
+ LeafNode.prototype.leafNodeCount = 1;
116
+
108
117
  /**
109
118
  *
110
119
  * @param {BinaryBuffer} buffer
package/core/bvh2/Node.js CHANGED
@@ -132,6 +132,7 @@ export class Node extends AABB3 {
132
132
  }
133
133
 
134
134
  node.updateLeafNodeCount();
135
+ node.updateHeight();
135
136
  }
136
137
 
137
138
  /**
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "productName": "Meep",
6
6
  "description": "production-ready JavaScript game engine based on Entity Component System Architecture",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.34.38",
8
+ "version": "2.34.39",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",