@woosh/meep-engine 2.43.16 → 2.43.18
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/assert.js +3 -1
- package/core/bvh2/aabb3/aabb3_intersects_ray.js +14 -9
- package/core/bvh2/aabb3/aabb3_intersects_ray_branchless.js +52 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.d.ts +2 -0
- package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +214 -5
- package/core/bvh2/bvh3/bvh_query_leaves_ray.js +32 -29
- package/core/collection/array/typed/typed_array_copy.js +2 -2
- package/core/geom/3d/aabb/compute_aabb_from_points.js +4 -3
- package/core/geom/3d/compute_triangle_normal.js +76 -0
- package/core/geom/3d/topology/samples/sampleFloodFill.js +1 -1
- package/core/geom/3d/topology/simplify/compute_face_normal_change_dot_product.js +1 -1
- package/core/geom/3d/topology/simplify/quadratic/Quadratic3.js +1 -1
- package/core/geom/3d/topology/struct/TopoTriangle.js +1 -57
- package/core/geom/3d/topology/tm_face_normal.js +1 -1
- package/core/geom/3d/topology/tm_vertex_compute_normal.js +1 -1
- package/core/geom/3d/triangle/computeTriangleRayIntersection.js +195 -27
- package/core/geom/Vector3.js +12 -12
- package/core/math/physics/brdf/D_GGX.js +13 -0
- package/editor/tools/v2/prototypeTransformControls.js +14 -2
- package/engine/ecs/parent/EntityNode.js +80 -7
- package/engine/ecs/parent/EntityNodeFlags.js +8 -0
- package/engine/ecs/terrain/tiles/TerrainTile.js +7 -9
- package/engine/graphics/ecs/path/PathDisplaySystem.d.ts +3 -0
- package/engine/graphics/ecs/path/PathDisplaySystem.js +10 -0
- package/engine/graphics/geometry/AttributeSpec.js +18 -3
- package/engine/graphics/geometry/VertexDataSpec.js +53 -3
- package/engine/graphics/micron/format/VirtualGeometry.js +7 -0
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +1 -1
- package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +5 -2
- package/engine/graphics/particles/particular/engine/parameter/sample/RGBA_LUT_HEATMAP_IR.js +11 -0
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -9
- package/engine/graphics/sh3/README.md +1 -0
- package/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +324 -0
- package/engine/graphics/sh3/path_tracer/PathTracedMesh.js +85 -0
- package/engine/graphics/sh3/path_tracer/PathTracer.js +469 -0
- package/engine/graphics/sh3/path_tracer/apply_texture_clamping_to_coordinate.js +22 -0
- package/engine/graphics/sh3/path_tracer/compute_triangle_group_aabb3.js +36 -0
- package/engine/graphics/sh3/path_tracer/getBiasedNormalSample.js +55 -0
- package/engine/graphics/sh3/path_tracer/make_sky_hosek.js +44 -0
- package/engine/graphics/sh3/path_tracer/make_sky_rtiw.js +15 -0
- package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +619 -0
- package/engine/graphics/sh3/path_tracer/random_in_hemisphere.js +39 -0
- package/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +42 -0
- package/engine/graphics/sh3/path_tracer/ray_reflect.js +27 -0
- package/engine/graphics/sh3/path_tracer/sample_triangle_attribute.js +35 -0
- package/engine/graphics/sh3/path_tracer/vec3_uint8_to_float.js +12 -0
- package/engine/graphics/sh3/sky/hosek/README.md +4 -0
- package/engine/graphics/sh3/sky/hosek/prototype_hosek.js +71 -0
- package/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +4171 -0
- package/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +2 -0
- package/package.json +1 -1
- package/view/elements/progress/SmoothProgressBar.js +1 -1
- package/view/task/TaskProgressView.js +6 -8
package/core/assert.js
CHANGED
|
@@ -380,7 +380,9 @@ assert.notNaN = function (value, name = "value") {
|
|
|
380
380
|
* @param {string} name
|
|
381
381
|
*/
|
|
382
382
|
assert.isFiniteNumber = function (value, name = "value") {
|
|
383
|
-
|
|
383
|
+
if (!Number.isFinite(value)) {
|
|
384
|
+
throw new Error(`${name} must be a finite number, instead was ${value}`);
|
|
385
|
+
}
|
|
384
386
|
};
|
|
385
387
|
|
|
386
388
|
export {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fabsf } from "../../math/fabsf.js";
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
/**
|
|
4
5
|
* NOTES:
|
|
5
6
|
* https://web.archive.org/web/20090803054252/http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c
|
|
@@ -20,41 +21,46 @@ import { fabsf } from "../../math/fabsf.js";
|
|
|
20
21
|
* @param {number} dirZ
|
|
21
22
|
* @returns {boolean}
|
|
22
23
|
*/
|
|
23
|
-
function aabb3_intersects_ray(
|
|
24
|
+
export function aabb3_intersects_ray(
|
|
25
|
+
x0, y0, z0,
|
|
26
|
+
x1, y1, z1,
|
|
27
|
+
oX, oY, oZ,
|
|
28
|
+
dirX, dirY, dirZ
|
|
29
|
+
) {
|
|
24
30
|
|
|
25
31
|
// Z Projection
|
|
26
|
-
const boxExtentsX = (x1 - x0)
|
|
32
|
+
const boxExtentsX = (x1 - x0) * 0.5;
|
|
27
33
|
|
|
28
34
|
const centerX = x0 + boxExtentsX;
|
|
29
35
|
|
|
30
36
|
const diffX = oX - centerX;
|
|
31
37
|
|
|
32
38
|
|
|
33
|
-
if (
|
|
39
|
+
if (diffX * dirX >= 0.0 && fabsf(diffX) > boxExtentsX) {
|
|
34
40
|
return false;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
// Y projection
|
|
38
|
-
const boxExtentsY = (y1 - y0)
|
|
44
|
+
const boxExtentsY = (y1 - y0) * 0.5;
|
|
39
45
|
|
|
40
46
|
const centerY = y0 + boxExtentsY;
|
|
41
47
|
|
|
42
48
|
const diffY = oY - centerY;
|
|
43
49
|
|
|
44
50
|
|
|
45
|
-
if (
|
|
51
|
+
if (diffY * dirY >= 0.0 && fabsf(diffY) > boxExtentsY) {
|
|
46
52
|
return false;
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
// Z projection
|
|
50
|
-
const boxExtentsZ = (z1 - z0)
|
|
56
|
+
const boxExtentsZ = (z1 - z0) * 0.5;
|
|
51
57
|
|
|
52
58
|
const centerZ = z0 + boxExtentsZ;
|
|
53
59
|
|
|
54
60
|
const diffZ = oZ - centerZ;
|
|
55
61
|
|
|
56
62
|
|
|
57
|
-
if (
|
|
63
|
+
if (diffZ * dirZ >= 0.0 && fabsf(diffZ) > boxExtentsZ) {
|
|
58
64
|
return false;
|
|
59
65
|
}
|
|
60
66
|
|
|
@@ -64,9 +70,9 @@ function aabb3_intersects_ray(x0, y0, z0, x1, y1, z1, oX, oY, oZ, dirX, dirY, di
|
|
|
64
70
|
//b = fabsf(Dir.y);
|
|
65
71
|
//if(fabsf(Diff.y)>BoxExtents.y + b) return false;
|
|
66
72
|
|
|
67
|
-
const a = fabsf(dirX);
|
|
68
73
|
const b = fabsf(dirY);
|
|
69
74
|
const c = fabsf(dirZ);
|
|
75
|
+
const a = fabsf(dirX);
|
|
70
76
|
|
|
71
77
|
const f0 = dirY * diffZ - dirZ * diffY;
|
|
72
78
|
|
|
@@ -89,4 +95,3 @@ function aabb3_intersects_ray(x0, y0, z0, x1, y1, z1, oX, oY, oZ, dirX, dirY, di
|
|
|
89
95
|
return true;
|
|
90
96
|
}
|
|
91
97
|
|
|
92
|
-
export { aabb3_intersects_ray };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { min2 } from "../../math/min2.js";
|
|
2
|
+
import { max2 } from "../../math/max2.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SLOW, don't use in production
|
|
6
|
+
* It is branchless on systems where min/max instructions exist.
|
|
7
|
+
* Unfortunately in JS that's not the case, so this is just a curiosity
|
|
8
|
+
* @see https://tavianator.com/2011/ray_box.html
|
|
9
|
+
* @param {number} x0
|
|
10
|
+
* @param {number} y0
|
|
11
|
+
* @param {number} z0
|
|
12
|
+
* @param {number} x1
|
|
13
|
+
* @param {number} y1
|
|
14
|
+
* @param {number} z1
|
|
15
|
+
* @param {number} oX
|
|
16
|
+
* @param {number} oY
|
|
17
|
+
* @param {number} oZ
|
|
18
|
+
* @param {number} dirX
|
|
19
|
+
* @param {number} dirY
|
|
20
|
+
* @param {number} dirZ
|
|
21
|
+
* @returns {boolean}
|
|
22
|
+
*/
|
|
23
|
+
export function aabb3_intersects_ray_branchless(
|
|
24
|
+
x0, y0, z0,
|
|
25
|
+
x1, y1, z1,
|
|
26
|
+
oX, oY, oZ,
|
|
27
|
+
dirX, dirY, dirZ
|
|
28
|
+
) {
|
|
29
|
+
const inv_dir_x = 1 / dirX;
|
|
30
|
+
const inv_dir_y = 1 / dirY;
|
|
31
|
+
const inv_dir_z = 1 / dirZ;
|
|
32
|
+
|
|
33
|
+
const tx1 = (x0 - oX) * inv_dir_x;
|
|
34
|
+
const tx2 = (x1 - oX) * inv_dir_x;
|
|
35
|
+
|
|
36
|
+
let tmin = min2(tx1, tx2);
|
|
37
|
+
let tmax = max2(tx1, tx2);
|
|
38
|
+
|
|
39
|
+
const ty1 = (y0 - oY) * inv_dir_y;
|
|
40
|
+
const ty2 = (y1 - oY) * inv_dir_y;
|
|
41
|
+
|
|
42
|
+
tmin = max2(tmin, min2(ty1, ty2));
|
|
43
|
+
tmax = min2(tmax, max2(ty1, ty2));
|
|
44
|
+
|
|
45
|
+
const tz1 = (z0 - oZ) * inv_dir_z;
|
|
46
|
+
const tz2 = (z1 - oZ) * inv_dir_z;
|
|
47
|
+
|
|
48
|
+
tmin = max2(tmin, min2(tz1, tz2));
|
|
49
|
+
tmax = min2(tmax, max2(tz1, tz2));
|
|
50
|
+
|
|
51
|
+
return tmax >= tmin;
|
|
52
|
+
}
|
|
@@ -2,10 +2,12 @@ import { aabb3_compute_surface_area } from "../aabb3/aabb3_compute_surface_area.
|
|
|
2
2
|
import { min2 } from "../../math/min2.js";
|
|
3
3
|
import { max2 } from "../../math/max2.js";
|
|
4
4
|
import { assert } from "../../assert.js";
|
|
5
|
+
import { typed_array_copy } from "../../collection/array/typed/typed_array_copy.js";
|
|
6
|
+
import { array_copy } from "../../collection/array/copyArray.js";
|
|
5
7
|
|
|
6
8
|
const COLUMN_PARENT = 6;
|
|
7
|
-
const COLUMN_CHILD_1 = 7;
|
|
8
|
-
const COLUMN_CHILD_2 = 8;
|
|
9
|
+
export const COLUMN_CHILD_1 = 7;
|
|
10
|
+
export const COLUMN_CHILD_2 = 8;
|
|
9
11
|
const COLUMN_HEIGHT = 9;
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -40,7 +42,7 @@ const CAPACITY_GROW_MIN_STEP = 64;
|
|
|
40
42
|
* @readonly
|
|
41
43
|
* @type {number}
|
|
42
44
|
*/
|
|
43
|
-
const ELEMENT_WORD_COUNT = 10;
|
|
45
|
+
export const ELEMENT_WORD_COUNT = 10;
|
|
44
46
|
|
|
45
47
|
/**
|
|
46
48
|
* How many nodes can be stored in the newly constructed tree before allocation needs to take place
|
|
@@ -134,6 +136,16 @@ export class ExplicitBinaryBoundingVolumeHierarchy {
|
|
|
134
136
|
this.__capacity + CAPACITY_GROW_MIN_STEP
|
|
135
137
|
));
|
|
136
138
|
|
|
139
|
+
this.__set_capacity(new_capacity);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
*
|
|
144
|
+
* @param {number} new_capacity
|
|
145
|
+
* @private
|
|
146
|
+
*/
|
|
147
|
+
__set_capacity(new_capacity) {
|
|
148
|
+
|
|
137
149
|
const old_data_uint32 = this.__data_uint32;
|
|
138
150
|
|
|
139
151
|
const new_data_buffer = new ArrayBuffer(new_capacity * ELEMENT_WORD_COUNT * 4);
|
|
@@ -144,11 +156,20 @@ export class ExplicitBinaryBoundingVolumeHierarchy {
|
|
|
144
156
|
this.__data_uint32 = new Uint32Array(new_data_buffer);
|
|
145
157
|
|
|
146
158
|
// copy old data into new buffer
|
|
147
|
-
this.__data_uint32
|
|
159
|
+
typed_array_copy(old_data_uint32, this.__data_uint32);
|
|
148
160
|
|
|
149
161
|
this.__capacity = new_capacity;
|
|
150
162
|
}
|
|
151
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Trim allocated memory region to only contain allocated nodes
|
|
166
|
+
*/
|
|
167
|
+
trim() {
|
|
168
|
+
if (this.__capacity > this.__size) {
|
|
169
|
+
this.__set_capacity(this.__size);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
152
173
|
/**
|
|
153
174
|
*
|
|
154
175
|
* @returns {number}
|
|
@@ -945,11 +966,199 @@ export class ExplicitBinaryBoundingVolumeHierarchy {
|
|
|
945
966
|
return i - destination_offset;
|
|
946
967
|
}
|
|
947
968
|
|
|
969
|
+
/**
|
|
970
|
+
* Update parent and child links of a given node to point to a new location, useful for re-locating nodes
|
|
971
|
+
* @param {number} node node to update
|
|
972
|
+
* @param {number} destination Where updated links should point to
|
|
973
|
+
* @private
|
|
974
|
+
*/
|
|
975
|
+
__move_node_links(node, destination) {
|
|
976
|
+
|
|
977
|
+
const uint32 = this.__data_uint32;
|
|
978
|
+
|
|
979
|
+
const source_address = node * ELEMENT_WORD_COUNT;
|
|
980
|
+
|
|
981
|
+
// update children of a
|
|
982
|
+
const child1 = uint32[source_address + COLUMN_CHILD_1];
|
|
983
|
+
const child2 = uint32[source_address + COLUMN_CHILD_2];
|
|
984
|
+
|
|
985
|
+
if (child1 !== NULL_NODE) {
|
|
986
|
+
|
|
987
|
+
uint32[child1 * ELEMENT_WORD_COUNT + COLUMN_PARENT] = destination;
|
|
988
|
+
uint32[child2 * ELEMENT_WORD_COUNT + COLUMN_PARENT] = destination;
|
|
989
|
+
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// update parent of a
|
|
993
|
+
const parent = uint32[source_address + COLUMN_PARENT];
|
|
994
|
+
|
|
995
|
+
if (parent !== NULL_NODE) {
|
|
996
|
+
const parent_child1 = uint32[parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1];
|
|
997
|
+
|
|
998
|
+
if (parent_child1 === node) {
|
|
999
|
+
uint32[parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] = destination;
|
|
1000
|
+
} else {
|
|
1001
|
+
uint32[parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_2] = destination;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Swap two nodes in memory
|
|
1008
|
+
* @param {number} a
|
|
1009
|
+
* @param {number} b
|
|
1010
|
+
* @returns {boolean}
|
|
1011
|
+
*/
|
|
1012
|
+
swap_nodes(a, b) {
|
|
1013
|
+
// console.log(`swap ${a} - ${b}`)
|
|
1014
|
+
|
|
1015
|
+
const uint32 = this.__data_uint32;
|
|
1016
|
+
|
|
1017
|
+
const address_a = a * ELEMENT_WORD_COUNT;
|
|
1018
|
+
const address_b = b * ELEMENT_WORD_COUNT;
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
if (uint32[address_a + COLUMN_PARENT] === b) {
|
|
1022
|
+
// attempting to swap direct parent/child, this is unsupported
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
if (uint32[address_b + COLUMN_PARENT] === a) {
|
|
1026
|
+
// attempting to swap direct parent/child, this is unsupported
|
|
1027
|
+
return false;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
this.__move_node_links(a, b);
|
|
1031
|
+
this.__move_node_links(b, a);
|
|
1032
|
+
|
|
1033
|
+
// copy A to temp buffer
|
|
1034
|
+
array_copy(uint32, address_a, this.__free, this.__free_pointer, ELEMENT_WORD_COUNT);
|
|
1035
|
+
|
|
1036
|
+
// write data
|
|
1037
|
+
array_copy(uint32, address_b, uint32, address_a, ELEMENT_WORD_COUNT);
|
|
1038
|
+
array_copy(this.__free, this.__free_pointer, uint32, address_b, ELEMENT_WORD_COUNT);
|
|
1039
|
+
|
|
1040
|
+
// update root as necessary
|
|
1041
|
+
if (this.__root === a) {
|
|
1042
|
+
this.__root = b;
|
|
1043
|
+
} else if (this.__root === b) {
|
|
1044
|
+
this.__root = a;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
return true;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
|
|
948
1051
|
/**
|
|
949
1052
|
* Sort live nodes in the traversal order.
|
|
950
1053
|
* This makes most queries have linear access, resulting in near-optimal cache usage
|
|
1054
|
+
* NOTE: assumes that there are no free nodes
|
|
951
1055
|
*/
|
|
952
1056
|
sort_for_traversal_depth_first() {
|
|
953
|
-
|
|
1057
|
+
const stack = [];
|
|
1058
|
+
|
|
1059
|
+
stack[0] = 0;
|
|
1060
|
+
stack[1] = this.__size - 1;
|
|
1061
|
+
|
|
1062
|
+
let stack_pointer = 2;
|
|
1063
|
+
let i, j;
|
|
1064
|
+
|
|
1065
|
+
const uint32 = this.__data_uint32;
|
|
1066
|
+
const float32 = this.__data_float32;
|
|
1067
|
+
|
|
1068
|
+
while (stack_pointer > 0) {
|
|
1069
|
+
stack_pointer -= 2;
|
|
1070
|
+
|
|
1071
|
+
const right = stack[stack_pointer + 1];
|
|
1072
|
+
const left = stack[stack_pointer];
|
|
1073
|
+
|
|
1074
|
+
i = left;
|
|
1075
|
+
j = right;
|
|
1076
|
+
|
|
1077
|
+
const pivotIndex = (left + right) >> 1;
|
|
1078
|
+
|
|
1079
|
+
/* partition */
|
|
1080
|
+
while (i <= j) {
|
|
1081
|
+
|
|
1082
|
+
while (traversal_sort_compare_nodes(uint32, float32, i, pivotIndex) > 0) {
|
|
1083
|
+
i++;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
while (traversal_sort_compare_nodes(uint32, float32, j, pivotIndex) < 0) {
|
|
1087
|
+
j--;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (i <= j) {
|
|
1091
|
+
|
|
1092
|
+
if (i !== j) {
|
|
1093
|
+
//do swap
|
|
1094
|
+
this.swap_nodes(i, j);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
i++;
|
|
1098
|
+
j--;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/* recursion */
|
|
1103
|
+
if (left < j) {
|
|
1104
|
+
stack[stack_pointer++] = left;
|
|
1105
|
+
stack[stack_pointer++] = j;
|
|
1106
|
+
}
|
|
1107
|
+
if (i < right) {
|
|
1108
|
+
stack[stack_pointer++] = i;
|
|
1109
|
+
stack[stack_pointer++] = right;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
954
1112
|
}
|
|
955
1113
|
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
*
|
|
1117
|
+
* @param {Uint32Array} uint32
|
|
1118
|
+
* @param {number} node_index
|
|
1119
|
+
* @return {number}
|
|
1120
|
+
*/
|
|
1121
|
+
function compute_traversal_index_upper_bound(uint32, node_index) {
|
|
1122
|
+
let n = node_index;
|
|
1123
|
+
|
|
1124
|
+
let parent = uint32[node_index * ELEMENT_WORD_COUNT + COLUMN_PARENT];
|
|
1125
|
+
|
|
1126
|
+
let result = 0;
|
|
1127
|
+
let x = 0;
|
|
1128
|
+
|
|
1129
|
+
while (parent !== NULL_NODE) {
|
|
1130
|
+
|
|
1131
|
+
if (uint32[parent * ELEMENT_WORD_COUNT + COLUMN_CHILD_1] === n) {
|
|
1132
|
+
result += Math.pow(2, x);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
x++;
|
|
1136
|
+
|
|
1137
|
+
n = parent;
|
|
1138
|
+
parent = uint32[n * ELEMENT_WORD_COUNT + COLUMN_PARENT];
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
return result;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
/**
|
|
1145
|
+
*
|
|
1146
|
+
* @param {Uint32Array} uint32
|
|
1147
|
+
* @param {Float32Array} float32
|
|
1148
|
+
* @param {number} a
|
|
1149
|
+
* @param {number} b
|
|
1150
|
+
* @returns {number}
|
|
1151
|
+
*/
|
|
1152
|
+
function traversal_sort_compare_nodes(uint32, float32, a, b) {
|
|
1153
|
+
const a_height = uint32[a * ELEMENT_WORD_COUNT + COLUMN_HEIGHT];
|
|
1154
|
+
const b_height = uint32[b * ELEMENT_WORD_COUNT + COLUMN_HEIGHT];
|
|
1155
|
+
|
|
1156
|
+
const height_delta = a_height - b_height;
|
|
1157
|
+
|
|
1158
|
+
if (height_delta !== 0) {
|
|
1159
|
+
return height_delta;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
return compute_traversal_index_upper_bound(uint32, a) - compute_traversal_index_upper_bound(uint32, b);
|
|
1163
|
+
|
|
1164
|
+
}
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
import { aabb3_intersects_ray } from "../aabb3/aabb3_intersects_ray.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
COLUMN_CHILD_1,
|
|
4
|
+
COLUMN_CHILD_2,
|
|
5
|
+
ELEMENT_WORD_COUNT,
|
|
6
|
+
NULL_NODE
|
|
7
|
+
} from "./ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
*
|
|
6
11
|
* @type {number[]}
|
|
7
12
|
*/
|
|
8
|
-
const traversal_stack =
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* @type {number[]}
|
|
13
|
-
*/
|
|
14
|
-
const scratch_aabb = [];
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @type {number}
|
|
19
|
-
*/
|
|
20
|
-
let traversal_cursor = 0;
|
|
13
|
+
const traversal_stack = new Uint32Array(2048);
|
|
21
14
|
|
|
22
15
|
|
|
23
16
|
/**
|
|
@@ -39,19 +32,29 @@ export function bvh_query_leaves_ray(
|
|
|
39
32
|
origin_x, origin_y, origin_z,
|
|
40
33
|
direction_x, direction_y, direction_z
|
|
41
34
|
) {
|
|
42
|
-
const stack_frame_address = traversal_cursor;
|
|
43
|
-
|
|
44
35
|
const root = bvh.root;
|
|
45
36
|
|
|
46
37
|
if (root === NULL_NODE) {
|
|
47
38
|
return 0;
|
|
48
39
|
}
|
|
49
40
|
|
|
50
|
-
traversal_stack[traversal_cursor++] = root;
|
|
51
41
|
|
|
52
|
-
|
|
42
|
+
traversal_stack[0] = root;
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
let result_cursor = result_offset;
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @type {number}
|
|
48
|
+
*/
|
|
49
|
+
let traversal_cursor = 1;
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
For performance, we bind data directly to avoid extra copies required to read out AABB
|
|
53
|
+
*/
|
|
54
|
+
const float32 = bvh.__data_float32;
|
|
55
|
+
const uint32 = bvh.__data_uint32;
|
|
56
|
+
|
|
57
|
+
do {
|
|
55
58
|
traversal_cursor--;
|
|
56
59
|
|
|
57
60
|
/**
|
|
@@ -60,12 +63,12 @@ export function bvh_query_leaves_ray(
|
|
|
60
63
|
*/
|
|
61
64
|
const node = traversal_stack[traversal_cursor];
|
|
62
65
|
|
|
63
|
-
|
|
66
|
+
const address = node * ELEMENT_WORD_COUNT;
|
|
64
67
|
|
|
65
68
|
// test node against the ray
|
|
66
69
|
const intersects = aabb3_intersects_ray(
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
float32[address], float32[address + 1], float32[address + 2],
|
|
71
|
+
float32[address + 3], float32[address + 4], float32[address + 5],
|
|
69
72
|
origin_x, origin_y, origin_z,
|
|
70
73
|
direction_x, direction_y, direction_z
|
|
71
74
|
);
|
|
@@ -74,22 +77,22 @@ export function bvh_query_leaves_ray(
|
|
|
74
77
|
continue;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
// get fist child to check if this is a leaf node or not
|
|
81
|
+
const child_1 = uint32[address + COLUMN_CHILD_1];
|
|
78
82
|
|
|
79
|
-
if (
|
|
83
|
+
if (child_1 !== NULL_NODE) {
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
traversal_stack[traversal_cursor++] =
|
|
85
|
+
// this is not a leaf node, push children onto traversal stack
|
|
86
|
+
traversal_stack[traversal_cursor++] = child_1;
|
|
87
|
+
traversal_stack[traversal_cursor++] = uint32[address + COLUMN_CHILD_2];
|
|
83
88
|
|
|
84
89
|
} else {
|
|
85
90
|
// leaf node
|
|
86
91
|
|
|
87
92
|
result[result_cursor++] = node;
|
|
88
93
|
}
|
|
89
|
-
}
|
|
94
|
+
} while (traversal_cursor > 0);
|
|
90
95
|
|
|
91
96
|
// drop stack frame
|
|
92
|
-
traversal_cursor = stack_frame_address;
|
|
93
|
-
|
|
94
97
|
return result_cursor - result_offset;
|
|
95
98
|
}
|
|
@@ -3,8 +3,8 @@ import { array_copy } from "../copyArray.js";
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Assumes arrays have the same type
|
|
6
|
-
* @param {TypedArray|Float32Array|Uint8Array} source
|
|
7
|
-
* @param {TypedArray|Float32Array|Uint8Array} destination
|
|
6
|
+
* @param {TypedArray|Float32Array|Uint8Array|Uint32Array} source
|
|
7
|
+
* @param {TypedArray|Float32Array|Uint8Array|Uint32Array} destination
|
|
8
8
|
*/
|
|
9
9
|
export function typed_array_copy(source, destination) {
|
|
10
10
|
const destination_size = destination.length;
|
|
@@ -4,11 +4,12 @@ import { max2 } from "../../../math/max2.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Multidimensional axis-aligned bounding box calculation
|
|
6
6
|
* @param {number[]} result
|
|
7
|
-
* @param {number[]} input
|
|
7
|
+
* @param {number[]|ArrayLike<number>} input
|
|
8
|
+
* @param {number} input_offset
|
|
8
9
|
* @param {number} input_count
|
|
9
10
|
* @param {number} d number of dimensions
|
|
10
11
|
*/
|
|
11
|
-
export function compute_aabb_from_points(result, input, input_count, d) {
|
|
12
|
+
export function compute_aabb_from_points(result, input, input_offset, input_count, d) {
|
|
12
13
|
let i = 0;
|
|
13
14
|
let j = 0;
|
|
14
15
|
|
|
@@ -19,7 +20,7 @@ export function compute_aabb_from_points(result, input, input_count, d) {
|
|
|
19
20
|
|
|
20
21
|
for (i = 0; i < input_count; i++) {
|
|
21
22
|
for (j = 0; j < d; j++) {
|
|
22
|
-
const v = input[i*d + j];
|
|
23
|
+
const v = input[input_count + i * d + j];
|
|
23
24
|
|
|
24
25
|
result[j] = min2(result[j], v);
|
|
25
26
|
result[j + d] = max2(result[j + d], v);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { v3_length_sqr } from "../v3_length_sqr.js";
|
|
2
|
+
import { vec3 } from "gl-matrix";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param {number[]} result
|
|
7
|
+
* @param {number} result_offset
|
|
8
|
+
* @param {number} vAx
|
|
9
|
+
* @param {number} vAy
|
|
10
|
+
* @param {number} vAz
|
|
11
|
+
* @param {number} vBx
|
|
12
|
+
* @param {number} vBy
|
|
13
|
+
* @param {number} vBz
|
|
14
|
+
* @param {number} vCx
|
|
15
|
+
* @param {number} vCy
|
|
16
|
+
* @param {number} vCz
|
|
17
|
+
*/
|
|
18
|
+
export function v3_compute_triangle_normal(result, result_offset, vAx, vAy, vAz, vBx, vBy, vBz, vCx, vCy, vCz) {
|
|
19
|
+
//compute CB and AB vectors
|
|
20
|
+
const vCBx = vCx - vBx;
|
|
21
|
+
const vCBy = vCy - vBy;
|
|
22
|
+
const vCBz = vCz - vBz;
|
|
23
|
+
|
|
24
|
+
const vABx = vAx - vBx;
|
|
25
|
+
const vABy = vAy - vBy;
|
|
26
|
+
const vABz = vAz - vBz;
|
|
27
|
+
|
|
28
|
+
//compute triangle normal
|
|
29
|
+
const crossX = vCBy * vABz - vCBz * vABy;
|
|
30
|
+
const crossY = vCBz * vABx - vCBx * vABz;
|
|
31
|
+
const crossZ = vCBx * vABy - vCBy * vABx;
|
|
32
|
+
|
|
33
|
+
const l_sqr = v3_length_sqr(crossX, crossY, crossZ);
|
|
34
|
+
|
|
35
|
+
if (l_sqr === 0) {
|
|
36
|
+
// degenerate triangle, provide arbitrary invalid result
|
|
37
|
+
result[result_offset] = 0;
|
|
38
|
+
result[result_offset + 1] = 1;
|
|
39
|
+
result[result_offset + 2] = 0;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const l_inv = 1 / Math.sqrt(l_sqr);
|
|
44
|
+
|
|
45
|
+
const x = crossX * l_inv;
|
|
46
|
+
const y = crossY * l_inv;
|
|
47
|
+
const z = crossZ * l_inv;
|
|
48
|
+
|
|
49
|
+
result[result_offset] = x;
|
|
50
|
+
result[result_offset + 1] = y;
|
|
51
|
+
result[result_offset + 2] = z;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @param {number[]|vec3} result
|
|
57
|
+
* @param {number[]} vA
|
|
58
|
+
* @param {number[]} vB
|
|
59
|
+
* @param {number[]} vC
|
|
60
|
+
*/
|
|
61
|
+
export function compute_triangle_normal(result, vA, vB, vC) {
|
|
62
|
+
|
|
63
|
+
const vAx = vA[0];
|
|
64
|
+
const vAy = vA[1];
|
|
65
|
+
const vAz = vA[2];
|
|
66
|
+
|
|
67
|
+
const vBx = vB[0];
|
|
68
|
+
const vBy = vB[1];
|
|
69
|
+
const vBz = vB[2];
|
|
70
|
+
|
|
71
|
+
const vCx = vC[0];
|
|
72
|
+
const vCy = vC[1];
|
|
73
|
+
const vCz = vC[2];
|
|
74
|
+
|
|
75
|
+
v3_compute_triangle_normal(result, 0, vAx, vAy, vAz, vBx, vBy, vBz, vCx, vCy, vCz);
|
|
76
|
+
}
|
|
@@ -211,7 +211,7 @@ async function main(engine) {
|
|
|
211
211
|
|
|
212
212
|
const aabb_array = [];
|
|
213
213
|
const position_attribute = geometry.getAttribute('position');
|
|
214
|
-
compute_aabb_from_points(aabb_array, position_attribute.array, position_attribute.count, 3);
|
|
214
|
+
compute_aabb_from_points(aabb_array, position_attribute.array, 0, position_attribute.count, 3);
|
|
215
215
|
const aabb3 = new AABB3(...aabb_array);
|
|
216
216
|
//
|
|
217
217
|
// weld_duplicate_vertices(topo, aabb3);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { v3_dot } from "../../../../v3_dot.js";
|
|
2
2
|
import { fabsf } from "../../../../../math/fabsf.js";
|
|
3
3
|
import { vec3 } from "gl-matrix";
|
|
4
|
-
import { compute_triangle_normal } from "../../struct/TopoTriangle.js";
|
|
5
4
|
import { EPSILON } from "../../../../../math/EPSILON.js";
|
|
5
|
+
import { compute_triangle_normal } from "../../../compute_triangle_normal.js";
|
|
6
6
|
|
|
7
7
|
const scratch_v3 = new Float32Array(3);
|
|
8
8
|
|