@woosh/meep-engine 2.119.117 → 2.119.119

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.119.117",
8
+ "version": "2.119.119",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -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,CAoFlB"}
1
+ {"version":3,"file":"ebvh_build_hierarchy.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_build_hierarchy.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AACH,0CATW,GAAG,qBACH,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,aACN,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,2BACN,MAAM,0BACN,MAAM,GACJ,MAAM,CAgGlB"}
@@ -3,6 +3,12 @@ import { max2 } from "../../math/max2.js";
3
3
  import { NULL_NODE } from "./BVH.js";
4
4
  import { ebvh_nodes_sort_sah_local4 } from "./ebvh_nodes_sort_sah_local4.js";
5
5
 
6
+ /**
7
+ * Somewhat arbitrary, pulled from various papers
8
+ * @type {number}
9
+ */
10
+ const SAH_MERGE_FRACTION = 0.93;
11
+
6
12
  /**
7
13
  * Given a set of leaves, build intermediate node hierarchy on top, all the way up to the root
8
14
  * Assumes nodes are spatially sorted, if not - no guarantees can be made about quality
@@ -36,33 +42,43 @@ export function ebvh_build_hierarchy(
36
42
 
37
43
  let current_construction_depth = 0;
38
44
 
45
+ const primitive_counts = new Uint32Array(input_node_count);
46
+ primitive_counts.fill(1);
47
+
39
48
  while (unprocessed_node_count > 1) {
40
49
 
41
- const sah_optimization_cycle_count = sah_optimization_level + sah_optimization_bias * current_construction_depth;
50
+ const sah_optimization_cycle_count = Math.floor(sah_optimization_level + sah_optimization_bias * current_construction_depth);
42
51
 
43
52
  for (let i = 0; i < sah_optimization_cycle_count; i++) {
44
53
 
45
54
  // sort intermediate nodes using small locality and SAH metric
46
- const swap_count = ebvh_nodes_sort_sah_local4(
55
+ const swap_distance = (sah_optimization_cycle_count - i) * 2;
56
+
57
+ ebvh_nodes_sort_sah_local4(
47
58
  bvh,
48
59
  unprocessed_nodes,
60
+ primitive_counts,
49
61
  0,
50
- (sah_optimization_cycle_count - i)*2,
62
+ swap_distance,
51
63
  unprocessed_node_count
52
64
  );
53
65
 
54
- if (swap_count === 0) {
55
- break;
56
- }
57
-
58
66
  }
59
67
 
60
68
  let added_nodes = 0;
61
69
  let cursor = 0;
62
70
 
63
- while (cursor + 1 < unprocessed_node_count) {
64
- const child_2 = unprocessed_nodes[cursor++];
65
- const child_1 = unprocessed_nodes[cursor++];
71
+ let merge_limit = unprocessed_node_count;
72
+ if (sah_optimization_cycle_count > 0) {
73
+ merge_limit = Math.ceil(unprocessed_node_count * SAH_MERGE_FRACTION);
74
+ }
75
+
76
+ while (cursor + 1 < merge_limit) {
77
+ const child_2_index = cursor++;
78
+ const child_1_index = cursor++;
79
+
80
+ const child_2 = unprocessed_nodes[child_2_index];
81
+ const child_1 = unprocessed_nodes[child_1_index];
66
82
 
67
83
  const parent = node_pool[used_index++];
68
84
 
@@ -81,7 +97,9 @@ export function ebvh_build_hierarchy(
81
97
  )
82
98
  );
83
99
 
84
- unprocessed_nodes[added_nodes++] = parent;
100
+ const parent_index = added_nodes++;
101
+ unprocessed_nodes[parent_index] = parent;
102
+ primitive_counts[parent_index] = primitive_counts[child_1_index] + primitive_counts[child_2_index];
85
103
  }
86
104
 
87
105
  while (cursor < unprocessed_node_count) {
@@ -3,9 +3,10 @@
3
3
  * Useful for optimizing topology for traversal.
4
4
  * @param {BVH} bvh
5
5
  * @param {number[]|Uint32Array} nodes
6
+ * @param {number[]|Uint32Array} primitive_counts
6
7
  * @param {number} offset
7
8
  * @param {number} distance
8
9
  * @param {number} count
9
10
  */
10
- export function ebvh_nodes_sort_sah_local4(bvh: BVH, nodes: number[] | Uint32Array, offset: number, distance: number, count: number): number;
11
+ export function ebvh_nodes_sort_sah_local4(bvh: BVH, nodes: number[] | Uint32Array, primitive_counts: number[] | Uint32Array, offset: number, distance: number, count: number): number;
11
12
  //# sourceMappingURL=ebvh_nodes_sort_sah_local4.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ebvh_nodes_sort_sah_local4.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_nodes_sort_sah_local4.js"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,gDANW,GAAG,SACH,MAAM,EAAE,GAAC,WAAW,UACpB,MAAM,YACN,MAAM,SACN,MAAM,UAgDhB"}
1
+ {"version":3,"file":"ebvh_nodes_sort_sah_local4.d.ts","sourceRoot":"","sources":["../../../../../src/core/bvh2/bvh3/ebvh_nodes_sort_sah_local4.js"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,gDAPW,GAAG,SACH,MAAM,EAAE,GAAC,WAAW,oBACpB,MAAM,EAAE,GAAC,WAAW,UACpB,MAAM,YACN,MAAM,SACN,MAAM,UAqGhB"}
@@ -1,27 +1,47 @@
1
+ import { array_swap } from "../../collection/array/array_swap.js";
2
+
3
+
1
4
  /**
2
5
  * Sort consequent 4 nodes to reduce SAH among each consequent pair.
3
6
  * Useful for optimizing topology for traversal.
4
7
  * @param {BVH} bvh
5
8
  * @param {number[]|Uint32Array} nodes
9
+ * @param {number[]|Uint32Array} primitive_counts
6
10
  * @param {number} offset
7
11
  * @param {number} distance
8
12
  * @param {number} count
9
13
  */
10
- export function ebvh_nodes_sort_sah_local4(bvh, nodes, offset, distance, count) {
14
+ export function ebvh_nodes_sort_sah_local4(
15
+ bvh,
16
+ nodes,
17
+ primitive_counts,
18
+ offset,
19
+ distance,
20
+ count
21
+ ) {
11
22
 
12
23
  const swap_pair_limit = Math.floor((count - (distance + 2)) / 2);
13
24
  const end = offset + swap_pair_limit * 2;
14
25
 
15
26
  let swap_count = 0;
16
27
 
17
- for (let i = offset; i < end; i += 2) {
18
- const j = i + distance;
28
+ for (let index_a = offset; index_a < end; index_a += 2) {
29
+ const index_c = index_a + distance;
30
+
31
+ const index_b = index_a + 1;
32
+ const index_d = index_c + 1;
33
+
34
+ const node_a = nodes[index_a];
35
+ const node_b = nodes[index_b];
36
+
37
+ const node_c = nodes[index_c];
38
+ const node_d = nodes[index_d];
19
39
 
20
- const a = nodes[i];
21
- const b = nodes[i + 1];
40
+ const count_a = primitive_counts[index_a];
41
+ const count_b = primitive_counts[index_b];
22
42
 
23
- const c = nodes[j];
24
- const d = nodes[j + 1];
43
+ const count_c = primitive_counts[index_c];
44
+ const count_d = primitive_counts[index_d];
25
45
 
26
46
  /*
27
47
  possible combinations:
@@ -31,25 +51,62 @@ export function ebvh_nodes_sort_sah_local4(bvh, nodes, offset, distance, count)
31
51
 
32
52
  Other combinations are not of interest as order among each pair is irrelevant for traversal performance
33
53
  */
34
- const cost0 = bvh.node_get_combined_surface_area(a, b) + bvh.node_get_combined_surface_area(c, d);
35
- const cost1 = bvh.node_get_combined_surface_area(a, c) + bvh.node_get_combined_surface_area(b, d);
36
- const cost2 = bvh.node_get_combined_surface_area(a, d) + bvh.node_get_combined_surface_area(c, b);
54
+
55
+ const area_ab = bvh.node_get_combined_surface_area(node_a, node_b);
56
+ const area_cd = bvh.node_get_combined_surface_area(node_c, node_d);
57
+
58
+ const area_ac = bvh.node_get_combined_surface_area(node_a, node_c);
59
+ const area_bd = bvh.node_get_combined_surface_area(node_b, node_d);
60
+
61
+ const area_ad = bvh.node_get_combined_surface_area(node_a, node_d);
62
+ const area_cb = bvh.node_get_combined_surface_area(node_c, node_b);
63
+
64
+ const cost_ab = area_ab * (count_a + count_b);
65
+ const cost_cd = area_cd * (count_c + count_d);
66
+
67
+ const cost_ac = area_ac * (count_a + count_c);
68
+ const cost_bd = area_bd * (count_b + count_d);
69
+
70
+ const cost_ad = area_ad * (count_a + count_d);
71
+ const cost_cb = area_cb * (count_c + count_b);
72
+
73
+ const cost0 = cost_ab + cost_cd;
74
+ const cost1 = cost_ac + cost_bd;
75
+ const cost2 = cost_ad + cost_cb;
76
+
77
+ let post_swap = false;
37
78
 
38
79
  if (cost0 <= cost1 && cost0 <= cost2) {
39
80
  // no change
40
- continue;
81
+ post_swap = cost_cd < cost_ab;
82
+
41
83
  } else if (cost1 <= cost2) {
42
84
  // swap C and B
43
- nodes[i + 1] = c;
44
- nodes[j] = b;
85
+ nodes[index_b] = node_c;
86
+ nodes[index_c] = node_b;
87
+
88
+ primitive_counts[index_b] = count_c;
89
+ primitive_counts[index_c] = count_b;
45
90
 
91
+ swap_count++;
92
+
93
+ post_swap = cost_bd < cost_ac;
46
94
  } else {
47
95
  // swap B and D
48
- nodes[i + 1] = d;
49
- nodes[j + 1] = b;
96
+ nodes[index_b] = node_d;
97
+ nodes[index_d] = node_b;
98
+
99
+ primitive_counts[index_b] = count_d;
100
+ primitive_counts[index_d] = count_b;
101
+
102
+ swap_count++;
103
+
104
+ post_swap = cost_cb < cost_ad;
50
105
  }
51
106
 
52
- swap_count++;
107
+ // put node pairs in their cost order
108
+ array_swap(nodes, index_a, nodes, index_c, 2);
109
+ array_swap(primitive_counts, index_a, primitive_counts, index_c, 2);
53
110
  }
54
111
 
55
112
  return swap_count;
@@ -1 +1 @@
1
- {"version":3,"file":"PathTracedScene.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/path_tracer/PathTracedScene.js"],"names":[],"mappings":"AAmDA;IAGI;;;OAGG;IACH,eAFU,GAAG,CAEa;IAG1B;;;OAGG;IACH,QAFU,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAElB;IAEnB;;;OAGG;IACH,UAFU,aAAa,EAAE,CAEX;IAEd;;;OAGG;IACH,WAFU,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAElC;IAmBtB;;;;OAIG;IACH,6BAA6C;IAkF7C,iBAOC;IAED;;;;OAIG;IACH,uBAHW,KAAK,CAAC,cAAc,GACnB,mBAAmB,CAmB9B;IAED;;;OAGG;IACH,gBAFW,aAAa,QAMvB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACZ,OAAO,CAInB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACZ,OAAO,CAiCnB;IAED;;;;OAIG;IACH,iBAHW,cAAc,GACZ,OAAO,CAgBnB;IAED;;;;OAIG;IACH,yBAHW,KAAK,CAAC,QAAQ,GACZ,gBAAgB,CAI5B;IAED;;;;;OAKG;IACH,qBAJW,KAAK,CAAC,cAAc,YACpB,KAAK,CAAC,QAAQ,aACd,IAAI,GAAC,MAAM,EAAE,QAavB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,EAAE,OACR,MAAM,EAAE,gBACR,IAAI,QA0Cd;IAED;;;;OAIG;IACH,cAHW,IAAI,GACF,OAAO,CAsCnB;IAED;;;;;OAKG;IACH,WAJW,MAAM,EAAE,OACR,MAAM,EAAE,GAAC,IAAI,GACZ,MAAM,CA+CjB;IAED;;;;;;OAMG;IACH,uBALW,MAAM,EAAE,cACR,MAAM,aACN,MAAM,EAAE,oBACR,MAAM,QAIhB;IAED;;;;;OAKG;IACH,mBAJW,MAAM,EAAE,cACR,MAAM,OACN,MAAM,EAAE,QAwHlB;;CACJ;oBAzlB8B,mCAAmC;+BAqBnC,qBAAqB;8BAJtB,kDAAkD;oCAC5C,0BAA0B;qBAPzC,kCAAkC"}
1
+ {"version":3,"file":"PathTracedScene.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/path_tracer/PathTracedScene.js"],"names":[],"mappings":"AAoDA;IAGI;;;OAGG;IACH,eAFU,GAAG,CAEa;IAG1B;;;OAGG;IACH,QAFU,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAElB;IAEnB;;;OAGG;IACH,UAFU,aAAa,EAAE,CAEX;IAEd;;;OAGG;IACH,WAFU,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAElC;IAmBtB;;;;OAIG;IACH,6BAA6C;IAqF7C,iBAOC;IAED;;;;OAIG;IACH,uBAHW,KAAK,CAAC,cAAc,GACnB,mBAAmB,CAmB9B;IAED;;;OAGG;IACH,gBAFW,aAAa,QAMvB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACZ,OAAO,CAInB;IAED;;;;OAIG;IACH,cAHW,cAAc,GACZ,OAAO,CAiCnB;IAED;;;;OAIG;IACH,iBAHW,cAAc,GACZ,OAAO,CAgBnB;IAED;;;;OAIG;IACH,yBAHW,KAAK,CAAC,QAAQ,GACZ,gBAAgB,CAI5B;IAED;;;;;OAKG;IACH,qBAJW,KAAK,CAAC,cAAc,YACpB,KAAK,CAAC,QAAQ,aACd,IAAI,GAAC,MAAM,EAAE,QAavB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,EAAE,OACR,MAAM,EAAE,gBACR,IAAI,QA0Cd;IAED;;;;OAIG;IACH,cAHW,IAAI,GACF,OAAO,CAsCnB;IAED;;;;;OAKG;IACH,WAJW,MAAM,EAAE,OACR,MAAM,EAAE,GAAC,IAAI,GACZ,MAAM,CA+CjB;IAED;;;;;;OAMG;IACH,uBALW,MAAM,EAAE,cACR,MAAM,aACN,MAAM,EAAE,oBACR,MAAM,QAIhB;IAED;;;;;OAKG;IACH,mBAJW,MAAM,EAAE,cACR,MAAM,OACN,MAAM,EAAE,QAwHlB;;CACJ;oBA7lB8B,mCAAmC;+BAqBnC,qBAAqB;8BAJtB,kDAAkD;oCAC5C,0BAA0B;qBAPzC,kCAAkC"}
@@ -23,22 +23,23 @@ import { MaterialConverter } from "./material/MaterialConverter.js";
23
23
  import { PathTracedMesh } from "./PathTracedMesh.js";
24
24
  import { sample_material } from "./texture/sample_material.js";
25
25
 
26
- function light_getDistanceAttenuation( distance, cutoff_distance, decay_exponent){
26
+ function light_getDistanceAttenuation(distance, cutoff_distance, decay_exponent) {
27
27
 
28
- let distanceFalloff = 1.0 / Math.max( Math.pow( distance, decay_exponent ), 0.01 );
28
+ let distanceFalloff = 1.0 / Math.max(Math.pow(distance, decay_exponent), 0.01);
29
29
 
30
- if ( cutoff_distance > 0.0 ) {
30
+ if (cutoff_distance > 0.0) {
31
31
  const b = distance / cutoff_distance;
32
- const b2 = b*b;
33
- const b4 = b2*b2;
32
+ const b2 = b * b;
33
+ const b4 = b2 * b2;
34
34
 
35
- const c= saturate( 1.0 - b4 );
35
+ const c = saturate(1.0 - b4);
36
36
 
37
- distanceFalloff *= c*c;
37
+ distanceFalloff *= c * c;
38
38
  }
39
39
 
40
40
  return distanceFalloff;
41
41
  }
42
+
42
43
  /**
43
44
  *
44
45
  * @type {number[]|Uint32Array}
@@ -170,7 +171,10 @@ export class PathTracedScene {
170
171
  bvh.node_set_height(node, 0);
171
172
 
172
173
  }
173
- ebvh_nodes_sort_sah_local4(bvh, nodes, 0, 2,node_leaf_count);
174
+ const primitive_counts = new Uint32Array(node_leaf_count);
175
+ primitive_counts.fill(1);
176
+
177
+ ebvh_nodes_sort_sah_local4(bvh, nodes, primitive_counts, 0, 2, node_leaf_count);
174
178
 
175
179
  // record newly generated nodes as "unprocessed"
176
180
  const unprocessed_nodes = new Uint32Array(node_leaf_count);
@@ -589,9 +593,9 @@ export class PathTracedScene {
589
593
  continue;
590
594
  }
591
595
 
592
- const attenuation = light_getDistanceAttenuation(distance_to_light,radius,2);
596
+ const attenuation = light_getDistanceAttenuation(distance_to_light, radius, 2);
593
597
 
594
- const intensity = dotNL * light.intensity.getValue()*attenuation;
598
+ const intensity = dotNL * light.intensity.getValue() * attenuation;
595
599
  const light_color = light.color;
596
600
 
597
601
  out[out_offset] += light_color.r * intensity;