@woosh/meep-engine 2.122.2 → 2.122.3

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 CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.122.2",
8
+ "version": "2.122.3",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -1051,6 +1051,8 @@ export class BVH {
1051
1051
  * @param {number} child_2
1052
1052
  */
1053
1053
  node_assign_children(parent, child_1, child_2) {
1054
+ this.node_set_combined_aabb(parent, child_1, child_2);
1055
+
1054
1056
  this.node_set_child1(parent, child_1);
1055
1057
  this.node_set_child2(parent, child_2);
1056
1058
 
@@ -1058,13 +1060,11 @@ export class BVH {
1058
1060
  this.node_set_parent(child_2, parent);
1059
1061
 
1060
1062
  this.node_set_height(parent,
1061
- Math.max(
1063
+ 1+ Math.max(
1062
1064
  this.node_get_height(child_1),
1063
1065
  this.node_get_height(child_2),
1064
- ) + 1
1066
+ )
1065
1067
  );
1066
-
1067
- this.node_set_combined_aabb(parent, child_1, child_2);
1068
1068
  }
1069
1069
 
1070
1070
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ebvh_build_for_geometry_morton.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,oDAPW,GAAG,eACH,MAAM,EAAE,GAAC,WAAW,GAAC,WAAW,kBAChC,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,WAAW,WACX,KAAK,YACL,MAAM,QAiIhB;sBAlJqB,6BAA6B"}
1
+ {"version":3,"file":"ebvh_build_for_geometry_morton.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH,oDAPW,GAAG,eACH,MAAM,EAAE,GAAC,WAAW,GAAC,WAAW,kBAChC,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,WAAW,WACX,KAAK,YACL,MAAM,QAsHhB;sBAvIqB,6BAA6B"}
@@ -131,18 +131,7 @@ export function ebvh_build_for_geometry_morton(
131
131
 
132
132
  typed_array_copy(nodes, unprocessed_nodes);
133
133
 
134
- // do long-distance swaps, starting high and coming down
135
- for (let power = 5; power > Math.max(5 - quality, 1); power--) {
136
-
137
- ebvh_nodes_sort_sah_local4(
138
- bvh,
139
- unprocessed_nodes,
140
- 0,
141
- 1 << power,
142
- tri_count
143
- );
144
134
 
145
- }
146
135
 
147
136
 
148
137
  // assign root
@@ -1 +1 @@
1
- {"version":3,"file":"ebvh_build_hierarchy.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_hierarchy.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,0CATW,GAAG,qBACH,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,aACN,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,2BACN,MAAM,0BACN,MAAM,GACJ,MAAM,CAmFlB"}
1
+ {"version":3,"file":"ebvh_build_hierarchy.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_hierarchy.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,0CATW,GAAG,qBACH,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,aACN,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,2BACN,MAAM,0BACN,MAAM,GACJ,MAAM,CAmFlB"}
@@ -1,5 +1,4 @@
1
1
  import { assert } from "../../assert.js";
2
- import { max2 } from "../../math/max2.js";
3
2
  import { NULL_NODE } from "./BVH.js";
4
3
  import { ebvh_nodes_sort_sah_local4 } from "./ebvh_nodes_sort_sah_local4.js";
5
4
 
@@ -40,6 +39,19 @@ export function ebvh_build_hierarchy(
40
39
 
41
40
  const sah_optimization_cycle_count = Math.floor(sah_optimization_level + sah_optimization_bias * current_construction_depth);
42
41
 
42
+ // do long-distance swaps, starting high and coming down
43
+ for (let power = 5; power > Math.max(5 - sah_optimization_cycle_count, 1); power--) {
44
+
45
+ ebvh_nodes_sort_sah_local4(
46
+ bvh,
47
+ unprocessed_nodes,
48
+ 0,
49
+ 1 << power,
50
+ unprocessed_node_count
51
+ );
52
+
53
+ }
54
+
43
55
  for (let i = 0; i < sah_optimization_cycle_count; i++) {
44
56
 
45
57
  // Sort intermediate nodes using small locality and SAH metric
@@ -65,20 +77,7 @@ export function ebvh_build_hierarchy(
65
77
 
66
78
  const parent = node_pool[used_index++];
67
79
 
68
- bvh.node_set_combined_aabb(parent, child_1, child_2);
69
-
70
- bvh.node_set_parent(child_1, parent);
71
- bvh.node_set_parent(child_2, parent);
72
-
73
- bvh.node_set_child1(parent, child_1);
74
- bvh.node_set_child2(parent, child_2);
75
-
76
- bvh.node_set_height(parent,
77
- 1 + max2(
78
- bvh.node_get_height(child_1),
79
- bvh.node_get_height(child_2)
80
- )
81
- );
80
+ bvh.node_assign_children(parent, child_1, child_2);
82
81
 
83
82
  unprocessed_nodes[added_nodes++] = parent;
84
83
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * DO NOT USE, currently broken
3
+ * @param {BVH} bvh
4
+ * @param {number[]|Uint32Array} leaf_nodes
5
+ * @param {number[]} sorted_morton_codes
6
+ * @param {number} leaf_count
7
+ * @param {number[]} internal_nodes
8
+ * @returns {number} new root
9
+ */
10
+ export function ebvh_build_hierarchy_radix(bvh: BVH, leaf_nodes: number[] | Uint32Array, sorted_morton_codes: number[], leaf_count: number, internal_nodes: number[]): number;
11
+ //# sourceMappingURL=ebvh_build_hierarchy_radix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ebvh_build_hierarchy_radix.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_hierarchy_radix.js"],"names":[],"mappings":"AA0MA;;;;;;;;GAQG;AACH,gDAPW,GAAG,cACH,MAAM,EAAE,GAAC,WAAW,uBACpB,MAAM,EAAE,cACR,MAAM,kBACN,MAAM,EAAE,GACN,MAAM,CAiElB"}
@@ -0,0 +1,275 @@
1
+ import { assert } from "../../assert.js";
2
+ import { clz32 } from "../../binary/clz32.js";
3
+ import { clamp } from "../../math/clamp.js";
4
+ import { NULL_NODE } from "./BVH.js";
5
+
6
+ /**
7
+ *
8
+ * @see "Thinking Parallel, Part III: Tree Construction on the GPU", 2012 by Tero Karras
9
+ *
10
+ * @param {number[]|Uint32Array} sortedMortonCodes
11
+ * @param {number} first
12
+ * @param {number} last
13
+ * @return {number}
14
+ */
15
+ function find_split(
16
+ sortedMortonCodes,
17
+ first,
18
+ last
19
+ ) {
20
+ // Identical Morton codes => split the range in the middle.
21
+
22
+ const firstCode = sortedMortonCodes[first];
23
+ const lastCode = sortedMortonCodes[last];
24
+
25
+ if (firstCode === lastCode) {
26
+ return (first + last) >>> 1;
27
+ }
28
+
29
+ // Calculate the number of highest bits that are the same
30
+ // for all objects, using the count-leading-zeros intrinsic.
31
+
32
+ const commonPrefix = clz32(firstCode ^ lastCode);
33
+
34
+ // Use binary search to find where the next bit differs.
35
+ // Specifically, we are looking for the highest object that
36
+ // shares more than commonPrefix bits with the first one.
37
+
38
+ let split = first; // initial guess
39
+ let step = last - first;
40
+
41
+ do {
42
+ step = (step + 1) >>> 1; // exponential decrease
43
+ const newSplit = split + step; // proposed new position
44
+
45
+ if (newSplit < last) {
46
+ const splitCode = sortedMortonCodes[newSplit];
47
+ const splitPrefix = clz32(firstCode ^ splitCode);
48
+ if (splitPrefix > commonPrefix) {
49
+ split = newSplit; // accept proposal
50
+ }
51
+ }
52
+ }
53
+ while (step > 1);
54
+
55
+ return split;
56
+ }
57
+
58
+ /**
59
+ *
60
+ * @param indexA
61
+ * @param indexB
62
+ * @param elementCount
63
+ * @param mortonCodes
64
+ * @return {number}
65
+ * @see https://github.com/turanszkij/WickedEngine/blob/506749de321c2ab66fd33fbe41efb95afbbb7ff8/WickedEngine/shaders/bvh_hierarchyCS.hlsl#L28C1-L48C2
66
+ */
67
+ function GetLongestCommonPrefix(indexA, indexB, elementCount, mortonCodes) {
68
+ assert.isNonNegativeInteger(indexA, 'indexA');
69
+ assert.isNonNegativeInteger(indexB, 'indexB');
70
+
71
+ if (indexA >= elementCount || indexB >= elementCount) {
72
+ return -1;
73
+ } else {
74
+ const mortonCodeA = mortonCodes[indexA];
75
+ const mortonCodeB = mortonCodes[indexB];
76
+ if (mortonCodeA !== mortonCodeB) {
77
+ return clz32(mortonCodeA ^ mortonCodeB);
78
+ } else {
79
+ // TODO: Technically this should be primitive ID
80
+ return clz32(indexA ^ indexB) + 31;
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * @see https://github.com/turanszkij/WickedEngine/blob/506749de321c2ab66fd33fbe41efb95afbbb7ff8/WickedEngine/shaders/bvh_hierarchyCS.hlsl#L28C1-L48C2
87
+ * @param {number[]|Uint32Array} output
88
+ * @param {number[]} sortedMortonCodes
89
+ * @param {number} numTriangles
90
+ * @param {number} idx
91
+ */
92
+ function determineRangeW(output, sortedMortonCodes, numTriangles, idx) {
93
+ if (idx === 0) {
94
+ // root
95
+ output[0] = 0;
96
+ output[1] = numTriangles - 1;
97
+ return;
98
+ }
99
+
100
+ let d = GetLongestCommonPrefix(idx, idx + 1, numTriangles, sortedMortonCodes) - GetLongestCommonPrefix(idx, idx - 1, numTriangles, sortedMortonCodes);
101
+ d = clamp(d, -1, 1);
102
+
103
+ let minPrefix = GetLongestCommonPrefix(idx, idx - d, numTriangles, sortedMortonCodes);
104
+
105
+ // TODO: Consider starting this at a higher number
106
+ let maxLength = 2;
107
+ while (GetLongestCommonPrefix(idx, idx + maxLength * d, numTriangles, sortedMortonCodes) > minPrefix) {
108
+ maxLength <<= 2;
109
+ }
110
+
111
+ let length = 0;
112
+ for (let t = maxLength >>> 1; t > 0; t >>>= 1) {
113
+ if (GetLongestCommonPrefix(idx, idx + (length + t) * d, numTriangles, sortedMortonCodes) > minPrefix) {
114
+ length = length + t;
115
+ }
116
+ }
117
+
118
+ let j = idx + length * d;
119
+
120
+ output[0] = Math.min(idx, j);
121
+ output[1] = Math.max(idx, j);
122
+
123
+ }
124
+
125
+ /**
126
+ * @see https://github.com/mbartling/cuda-bvh/blob/7f2f98d9d29956c3559632e59104ba66f31f80b8/kernels/bvh.cu#L276C1-L352C2
127
+ * @param {number[]|Uint32Array} output
128
+ * @param {number[]} sortedMortonCodes
129
+ * @param {number} numTriangles
130
+ * @param {number} idx
131
+ */
132
+ function determineRange(output, sortedMortonCodes, numTriangles, idx) {
133
+
134
+ //determine the range of keys covered by each internal node (as well as its children)
135
+ //direction is found by looking at the neighboring keys ki-1 , ki , ki+1
136
+ //the index is either the beginning of the range or the end of the range
137
+ let direction = 0;
138
+ let common_prefix_with_left = 0;
139
+ let common_prefix_with_right = 0;
140
+
141
+ common_prefix_with_right = clz32(sortedMortonCodes[idx] ^ sortedMortonCodes[idx + 1]);
142
+
143
+ if (idx === 0) {
144
+ common_prefix_with_left = -1;
145
+ } else {
146
+ common_prefix_with_left = clz32(sortedMortonCodes[idx] ^ sortedMortonCodes[idx - 1]);
147
+
148
+ }
149
+
150
+ direction = ((common_prefix_with_right - common_prefix_with_left) > 0) ? 1 : -1;
151
+
152
+ let min_prefix_range = 0;
153
+
154
+ if (idx === 0) {
155
+ min_prefix_range = -1;
156
+
157
+ } else {
158
+ min_prefix_range = clz32(sortedMortonCodes[idx] ^ sortedMortonCodes[idx - direction]);
159
+ }
160
+
161
+ let lmax = 2;
162
+ let next_key = idx + lmax * direction;
163
+
164
+ while ((next_key >= 0) && (next_key < numTriangles) && (clz32(sortedMortonCodes[idx] ^ sortedMortonCodes[next_key]) > min_prefix_range)) {
165
+ lmax *= 2;
166
+ next_key = idx + lmax * direction;
167
+ }
168
+ //find the other end using binary search
169
+ let l = 0;
170
+
171
+ do {
172
+ lmax = (lmax + 1) >> 1; // exponential decrease
173
+ const new_val = idx + (l + lmax) * direction;
174
+
175
+ if (new_val >= 0 && new_val < numTriangles) {
176
+ const Code = sortedMortonCodes[new_val];
177
+ const Prefix = clz32(sortedMortonCodes[idx] ^ Code);
178
+ if (Prefix > min_prefix_range) {
179
+ l = l + lmax;
180
+ }
181
+ }
182
+ } while (lmax > 1);
183
+
184
+ const j = idx + l * direction;
185
+
186
+ let left = 0;
187
+ let right = 0;
188
+
189
+ if (idx < j) {
190
+ left = idx;
191
+ right = j;
192
+ } else {
193
+ left = j;
194
+ right = idx;
195
+ }
196
+
197
+ // printf("idx : (%d) returning range (%d, %d) \n" , idx , left, right);
198
+
199
+ output[0] = left
200
+ output[1] = right;
201
+ }
202
+
203
+ /**
204
+ * DO NOT USE, currently broken
205
+ * @param {BVH} bvh
206
+ * @param {number[]|Uint32Array} leaf_nodes
207
+ * @param {number[]} sorted_morton_codes
208
+ * @param {number} leaf_count
209
+ * @param {number[]} internal_nodes
210
+ * @returns {number} new root
211
+ */
212
+ export function ebvh_build_hierarchy_radix(
213
+ bvh,
214
+ leaf_nodes,
215
+ sorted_morton_codes,
216
+ leaf_count,
217
+ internal_nodes,
218
+ ) {
219
+ console.warn("IMPLEMENTATION IS INCOMPLETE, DO NOT USE")
220
+
221
+ assert.isNonNegativeInteger(leaf_count, 'leaf_count');
222
+
223
+ // Construct leaf nodes.
224
+ // Note: This step can be avoided by storing
225
+ // the tree in a slightly different way.
226
+
227
+ const range = new Uint32Array(2);
228
+
229
+ // Construct internal nodes.
230
+ for (let idx = 0; idx < leaf_count - 1; idx++) // in parallel
231
+ {
232
+ // Find out which range of objects the node corresponds to.
233
+ // (This is where the magic happens!)
234
+
235
+ determineRange(range, sorted_morton_codes, leaf_count, idx);
236
+
237
+ const first = range[0];
238
+ const last = range[1];
239
+
240
+ // Determine where to split the range.
241
+
242
+ const split = find_split(sorted_morton_codes, first, last);
243
+ assert.isNonNegativeInteger(split, 'split');
244
+
245
+ // Select childA.
246
+
247
+ let childA;
248
+ if (split === first) {
249
+ childA = leaf_nodes[split];
250
+ } else {
251
+ childA = internal_nodes[split];
252
+ }
253
+
254
+ // Select childB.
255
+
256
+ let childB;
257
+ if (split + 1 === last) {
258
+ childB = leaf_nodes[split + 1];
259
+ } else {
260
+ childB = internal_nodes[split + 1];
261
+ }
262
+
263
+ // Record parent-child relationships.
264
+ const parent = internal_nodes[idx];
265
+
266
+ bvh.node_assign_children(parent, childA, childB);
267
+ }
268
+
269
+ // Node 0 is the root.
270
+ const root = internal_nodes[0];
271
+
272
+ bvh.node_set_parent(root, NULL_NODE);
273
+
274
+ return root;
275
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ebvh_optimize_treelet.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_optimize_treelet.js"],"names":[],"mappings":"AAuNA;;;;;;;GAOG;AACH,2CAJW,GAAG,SACH,MAAM,iBACN,MAAM,QA8IhB"}
1
+ {"version":3,"file":"ebvh_optimize_treelet.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_optimize_treelet.js"],"names":[],"mappings":"AAuNA;;;;;;;GAOG;AACH,2CAJW,GAAG,SACH,MAAM,iBACN,MAAM,QA+IhB"}
@@ -256,6 +256,7 @@ export function ebvh_optimize_treelet(
256
256
 
257
257
  const min_height = Math.ceil(Math.log2(treelet_size));
258
258
 
259
+ // do a stackless traversal
259
260
  while (true) {
260
261
 
261
262