@woosh/meep-engine 2.43.17 → 2.43.19

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/assert.js +3 -1
  2. package/core/bvh2/aabb3/aabb3_intersects_ray.js +14 -9
  3. package/core/bvh2/aabb3/aabb3_intersects_ray_branchless.js +52 -0
  4. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.d.ts +2 -0
  5. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +162 -10
  6. package/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.js +34 -0
  7. package/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +175 -0
  8. package/core/bvh2/bvh3/ebvh_sort_for_traversal_depth_first.js +122 -0
  9. package/core/bvh2/bvh3/{bvh_collect_user_data.js → query/bvh_collect_user_data.js} +1 -1
  10. package/core/bvh2/bvh3/{bvh_query_leaves_generic.js → query/bvh_query_leaves_generic.js} +1 -1
  11. package/core/bvh2/bvh3/query/bvh_query_leaves_ray.js +97 -0
  12. package/core/bvh2/bvh3/{bvh_query_user_data_generic.js → query/bvh_query_user_data_generic.js} +1 -1
  13. package/core/bvh2/bvh3/{bvh_query_user_data_nearest_to_point.js → query/bvh_query_user_data_nearest_to_point.js} +3 -3
  14. package/core/bvh2/bvh3/{bvh_query_user_data_nearest_to_point.spec.js → query/bvh_query_user_data_nearest_to_point.spec.js} +1 -1
  15. package/core/bvh2/bvh3/{bvh_query_user_data_overlaps_frustum.js → query/bvh_query_user_data_overlaps_frustum.js} +2 -2
  16. package/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +1 -1
  17. package/core/collection/array/arrayQuickSort.js +1 -1
  18. package/core/collection/array/typed/typed_array_copy.js +2 -2
  19. package/core/geom/3d/aabb/compute_aabb_from_points.js +4 -3
  20. package/core/geom/3d/compute_triangle_normal.js +76 -0
  21. package/core/geom/3d/topology/samples/sampleFloodFill.js +1 -1
  22. package/core/geom/3d/topology/simplify/compute_face_normal_change_dot_product.js +1 -1
  23. package/core/geom/3d/topology/simplify/quadratic/Quadratic3.js +1 -1
  24. package/core/geom/3d/topology/struct/TopoTriangle.js +1 -57
  25. package/core/geom/3d/topology/tm_face_normal.js +1 -1
  26. package/core/geom/3d/topology/tm_vertex_compute_normal.js +1 -1
  27. package/core/geom/3d/triangle/computeTriangleRayIntersection.js +195 -27
  28. package/core/geom/Vector3.js +12 -12
  29. package/core/math/physics/brdf/D_GGX.js +13 -0
  30. package/editor/tools/v2/prototypeTransformControls.js +14 -2
  31. package/engine/ecs/parent/EntityNode.js +80 -7
  32. package/engine/ecs/parent/EntityNodeFlags.js +8 -0
  33. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
  34. package/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +9 -1
  35. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +1 -1
  36. package/engine/graphics/geometry/AttributeSpec.js +18 -3
  37. package/engine/graphics/geometry/VertexDataSpec.js +53 -3
  38. package/engine/graphics/micron/format/VirtualGeometry.js +7 -0
  39. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +1 -1
  40. package/engine/graphics/micron/render/refinement/get_geometry_patch_cut.js +5 -2
  41. package/engine/graphics/particles/particular/engine/parameter/sample/RGBA_LUT_HEATMAP_IR.js +11 -0
  42. package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +2 -9
  43. package/engine/graphics/render/forward_plus/model/DirectionalLight.js +40 -0
  44. package/engine/graphics/sh3/README.md +1 -0
  45. package/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +265 -0
  46. package/engine/graphics/sh3/path_tracer/PathTracedMesh.js +85 -0
  47. package/engine/graphics/sh3/path_tracer/PathTracer.js +534 -0
  48. package/engine/graphics/sh3/path_tracer/apply_texture_clamping_to_coordinate.js +22 -0
  49. package/engine/graphics/sh3/path_tracer/compute_triangle_group_aabb3.js +36 -0
  50. package/engine/graphics/sh3/path_tracer/getBiasedNormalSample.js +55 -0
  51. package/engine/graphics/sh3/path_tracer/make_one_vector3.js +7 -0
  52. package/engine/graphics/sh3/path_tracer/make_sky_hosek.js +44 -0
  53. package/engine/graphics/sh3/path_tracer/make_sky_rtiw.js +17 -0
  54. package/engine/graphics/sh3/path_tracer/make_zero_vector3.js +7 -0
  55. package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +631 -0
  56. package/engine/graphics/sh3/path_tracer/random_in_hemisphere.js +39 -0
  57. package/engine/graphics/sh3/path_tracer/ray_hit_apply_transform.js +42 -0
  58. package/engine/graphics/sh3/path_tracer/ray_reflect.js +27 -0
  59. package/engine/graphics/sh3/path_tracer/sample_triangle_attribute.js +35 -0
  60. package/engine/graphics/sh3/path_tracer/vec3_uint8_to_float.js +12 -0
  61. package/engine/graphics/sh3/sky/hosek/README.md +4 -0
  62. package/engine/graphics/sh3/sky/hosek/prototype_hosek.js +71 -0
  63. package/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +4171 -0
  64. package/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +2 -0
  65. package/package.json +1 -1
  66. package/view/elements/progress/SmoothProgressBar.js +1 -1
  67. package/view/task/TaskProgressView.js +6 -8
  68. package/core/bvh2/bvh3/bvh_query_leaves_ray.js +0 -95
@@ -1,6 +1,6 @@
1
1
  //
2
2
 
3
- import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
3
+ import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.d.ts";
4
4
 
5
5
  const traversal_stack = [];
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
1
+ import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
2
2
 
3
3
  /**
4
4
  *
@@ -0,0 +1,97 @@
1
+ import { aabb3_intersects_ray } from "../../aabb3/aabb3_intersects_ray.js";
2
+ import {
3
+ COLUMN_CHILD_1,
4
+ COLUMN_CHILD_2,
5
+ ELEMENT_WORD_COUNT,
6
+ NULL_NODE
7
+ } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
8
+
9
+ /**
10
+ *
11
+ * @type {number[]}
12
+ */
13
+ const traversal_stack = new Uint32Array(2048);
14
+
15
+
16
+ /**
17
+ *
18
+ * @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
19
+ * @param {number[]} result
20
+ * @param {number} result_offset
21
+ * @param {number} origin_x
22
+ * @param {number} origin_y
23
+ * @param {number} origin_z
24
+ * @param {number} direction_x
25
+ * @param {number} direction_y
26
+ * @param {number} direction_z
27
+ * @returns {number}
28
+ */
29
+ export function bvh_query_leaves_ray(
30
+ bvh,
31
+ result, result_offset,
32
+ origin_x, origin_y, origin_z,
33
+ direction_x, direction_y, direction_z
34
+ ) {
35
+ const root = bvh.root;
36
+
37
+ if (root === NULL_NODE) {
38
+ return 0;
39
+ }
40
+
41
+
42
+ traversal_stack[0] = root;
43
+
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 {
58
+ traversal_cursor--;
59
+
60
+ /**
61
+ *
62
+ * @type {number}
63
+ */
64
+ const node = traversal_stack[traversal_cursor];
65
+
66
+ const address = node * ELEMENT_WORD_COUNT;
67
+
68
+ // test node against the ray
69
+ const intersects = aabb3_intersects_ray(
70
+ float32[address], float32[address + 1], float32[address + 2],
71
+ float32[address + 3], float32[address + 4], float32[address + 5],
72
+ origin_x, origin_y, origin_z,
73
+ direction_x, direction_y, direction_z
74
+ );
75
+
76
+ if (!intersects) {
77
+ continue;
78
+ }
79
+
80
+ // get fist child to check if this is a leaf node or not
81
+ const child_1 = uint32[address + COLUMN_CHILD_1];
82
+
83
+ if (child_1 !== NULL_NODE) {
84
+
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];
88
+
89
+ } else {
90
+ // leaf node
91
+
92
+ result[result_cursor++] = node;
93
+ }
94
+ } while (traversal_cursor > 0);
95
+
96
+ return result_cursor - result_offset;
97
+ }
@@ -1,4 +1,4 @@
1
- import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
1
+ import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
2
2
 
3
3
  /**
4
4
  *
@@ -1,6 +1,6 @@
1
- import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
2
- import { aabb3_signed_distance_sqr_to_point } from "../aabb3/aabb3_signed_distance_sqr_to_point.js";
3
- import { max2 } from "../../math/max2.js";
1
+ import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
2
+ import { aabb3_signed_distance_sqr_to_point } from "../../aabb3/aabb3_signed_distance_sqr_to_point.js";
3
+ import { max2 } from "../../../math/max2.js";
4
4
 
5
5
  /**
6
6
  *
@@ -1,4 +1,4 @@
1
- import { ExplicitBinaryBoundingVolumeHierarchy } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
1
+ import { ExplicitBinaryBoundingVolumeHierarchy } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
2
2
  import { bvh_query_user_data_nearest_to_point } from "./bvh_query_user_data_nearest_to_point.js";
3
3
 
4
4
  /**
@@ -1,6 +1,6 @@
1
1
  //
2
- import { NULL_NODE } from "./ExplicitBinaryBoundingVolumeHierarchy.js";
3
- import { aabb3_array_intersects_frustum_degree } from "../aabb3/aabb3_array_intersects_frustum_degree.js";
2
+ import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
3
+ import { aabb3_array_intersects_frustum_degree } from "../../aabb3/aabb3_array_intersects_frustum_degree.js";
4
4
  import { bvh_collect_user_data } from "./bvh_collect_user_data.js";
5
5
 
6
6
  const traversal_stack = [];
@@ -4,7 +4,7 @@
4
4
  import { array_copy } from "../../../collection/array/copyArray.js";
5
5
  import { NULL_NODE } from "../ExplicitBinaryBoundingVolumeHierarchy.js";
6
6
  import { aabb3_array_intersects_frustum_degree } from "../../aabb3/aabb3_array_intersects_frustum_degree.js";
7
- import { bvh_collect_user_data } from "../bvh_collect_user_data.js";
7
+ import { bvh_collect_user_data } from "./bvh_collect_user_data.js";
8
8
  import { v3_distance_above_plane } from "../../../geom/v3_distance_above_plane.js";
9
9
 
10
10
  const traversal_stack = [];
@@ -4,7 +4,7 @@ const stack = [];
4
4
 
5
5
  /**
6
6
  * @template T
7
- * @param {T[]} data
7
+ * @param {T[]|ArrayLike<number>|Uint32Array} data
8
8
  * @param {function(T):number} score_function
9
9
  * @param {*} score_function_context
10
10
  * @param {number} start
@@ -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,5 +1,5 @@
1
1
  import { v3_dot } from "../../../v3_dot.js";
2
- import { compute_triangle_normal } from "../struct/TopoTriangle.js";
2
+ import { compute_triangle_normal } from "../../compute_triangle_normal.js";
3
3
 
4
4
  const scratch_normal = new Float32Array(3);
5
5
 
@@ -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
 
@@ -3,63 +3,7 @@ import { array_push_if_unique } from "../../../../collection/array/array_push_if
3
3
  import { assert } from "../../../../assert.js";
4
4
  import { array_remove_first } from "../../../../collection/array/array_remove_first.js";
5
5
  import { vec3 } from "gl-matrix";
6
- import { v3_length_sqr } from "../../../v3_length_sqr.js";
7
-
8
- /**
9
- *
10
- * @param {number[]|vec3} result
11
- * @param {Vector3|Vector3Like|TopoVertex|{x:number,y:number,z:number}} vA
12
- * @param {Vector3|Vector3Like|TopoVertex|{x:number,y:number,z:number}} vB
13
- * @param {Vector3|Vector3Like|TopoVertex|{x:number,y:number,z:number}} vC
14
- */
15
- export function compute_triangle_normal(result, vA, vB, vC) {
16
-
17
- const vAx = vA.x
18
- const vAy = vA.y
19
- const vAz = vA.z
20
-
21
- const vBx = vB.x
22
- const vBy = vB.y
23
- const vBz = vB.z
24
-
25
- const vCx = vC.x
26
- const vCy = vC.y
27
- const vCz = vC.z
28
-
29
- //compute CB and AB vectors
30
- const vCBx = vCx - vBx;
31
- const vCBy = vCy - vBy;
32
- const vCBz = vCz - vBz;
33
-
34
- const vABx = vAx - vBx;
35
- const vABy = vAy - vBy;
36
- const vABz = vAz - vBz;
37
-
38
- //compute triangle normal
39
- const crossX = vCBy * vABz - vCBz * vABy;
40
- const crossY = vCBz * vABx - vCBx * vABz;
41
- const crossZ = vCBx * vABy - vCBy * vABx;
42
-
43
- const l_sqr = v3_length_sqr(crossX, crossY, crossZ);
44
-
45
- if (l_sqr === 0) {
46
- // degenerate triangle, provide arbitrary invalid result
47
- vec3.set(result, 0, 0, 0);
48
- return;
49
- }
50
-
51
- const l_inv = 1 / Math.sqrt(l_sqr);
52
-
53
- const x = crossX * l_inv;
54
- const y = crossY * l_inv;
55
- const z = crossZ * l_inv;
56
-
57
-
58
- vec3.set(
59
- result,
60
- x, y, z
61
- );
62
- }
6
+ import { compute_triangle_normal } from "../../compute_triangle_normal.js";
63
7
 
64
8
  let index_counter = 0;
65
9
 
@@ -1,4 +1,4 @@
1
- import { compute_triangle_normal } from "./struct/TopoTriangle.js";
1
+ import { compute_triangle_normal } from "../compute_triangle_normal.js";
2
2
 
3
3
  /**
4
4
  *
@@ -1,4 +1,4 @@
1
- import { compute_triangle_normal } from "./struct/TopoTriangle.js";
1
+ import { compute_triangle_normal } from "../compute_triangle_normal.js";
2
2
  //
3
3
 
4
4
 
@@ -30,43 +30,43 @@ export function computeTriangleRayIntersection(
30
30
  bx, by, bz,
31
31
  cx, cy, cz
32
32
  ) {
33
- assert.isNumber(ax,'ax');
34
- assert.isNumber(ay,'ay');
35
- assert.isNumber(az,'az');
33
+ assert.isNumber(ax, 'ax');
34
+ assert.isNumber(ay, 'ay');
35
+ assert.isNumber(az, 'az');
36
36
 
37
- assert.isNumber(bx,'bx');
38
- assert.isNumber(by,'by');
39
- assert.isNumber(bz,'bz');
37
+ assert.isNumber(bx, 'bx');
38
+ assert.isNumber(by, 'by');
39
+ assert.isNumber(bz, 'bz');
40
40
 
41
- assert.isNumber(cx,'cx');
42
- assert.isNumber(cy,'cy');
43
- assert.isNumber(cz,'cz');
41
+ assert.isNumber(cx, 'cx');
42
+ assert.isNumber(cy, 'cy');
43
+ assert.isNumber(cz, 'cz');
44
44
 
45
45
  // nan checks
46
- assert.notNaN(ax,'ax');
47
- assert.notNaN(ay,'ay');
48
- assert.notNaN(az,'az');
46
+ assert.notNaN(ax, 'ax');
47
+ assert.notNaN(ay, 'ay');
48
+ assert.notNaN(az, 'az');
49
49
 
50
- assert.notNaN(bx,'bx');
51
- assert.notNaN(by,'by');
52
- assert.notNaN(bz,'bz');
50
+ assert.notNaN(bx, 'bx');
51
+ assert.notNaN(by, 'by');
52
+ assert.notNaN(bz, 'bz');
53
53
 
54
- assert.notNaN(cx,'cx');
55
- assert.notNaN(cy,'cy');
56
- assert.notNaN(cz,'cz');
54
+ assert.notNaN(cx, 'cx');
55
+ assert.notNaN(cy, 'cy');
56
+ assert.notNaN(cz, 'cz');
57
57
 
58
58
  // finate number check
59
- assert.isFiniteNumber(ax,'ax');
60
- assert.isFiniteNumber(ay,'ay');
61
- assert.isFiniteNumber(az,'az');
59
+ assert.isFiniteNumber(ax, 'ax');
60
+ assert.isFiniteNumber(ay, 'ay');
61
+ assert.isFiniteNumber(az, 'az');
62
62
 
63
- assert.isFiniteNumber(bx,'bx');
64
- assert.isFiniteNumber(by,'by');
65
- assert.isFiniteNumber(bz,'bz');
63
+ assert.isFiniteNumber(bx, 'bx');
64
+ assert.isFiniteNumber(by, 'by');
65
+ assert.isFiniteNumber(bz, 'bz');
66
66
 
67
- assert.isFiniteNumber(cx,'cx');
68
- assert.isFiniteNumber(cy,'cy');
69
- assert.isFiniteNumber(cz,'cz');
67
+ assert.isFiniteNumber(cx, 'cx');
68
+ assert.isFiniteNumber(cy, 'cy');
69
+ assert.isFiniteNumber(cz, 'cz');
70
70
 
71
71
 
72
72
  // edge1 = a - b
@@ -157,3 +157,171 @@ export function computeTriangleRayIntersection(
157
157
 
158
158
  return true;
159
159
  }
160
+
161
+ /**
162
+ * Compute barycentric coordinates for triangle intersection
163
+ * Operates on edges, this is optimized for raytracing, as same edges are required to reconstruct various attributes later on
164
+ * NOTE: most of the code is inlined for speed to avoid allocation and function calls
165
+ * @see https://github.com/erich666/jgt-code/blob/master/Volume_02/Number_1/Moller1997a/raytri.c
166
+ * @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2,‎ 1997, p. 21–28)
167
+ * @param {number[]} result
168
+ * @param {number} origin_x
169
+ * @param {number} origin_y
170
+ * @param {number} origin_z
171
+ * @param {number} direction_x
172
+ * @param {number} direction_y
173
+ * @param {number} direction_z
174
+ * @param {number} ax
175
+ * @param {number} ay
176
+ * @param {number} az
177
+ * @param {number} edge1_x
178
+ * @param {number} edge1_y
179
+ * @param {number} edge1_z
180
+ * @param {number} edge2_x
181
+ * @param {number} edge2_y
182
+ * @param {number} edge2_z
183
+ * @return {boolean}
184
+ */
185
+ export function computeTriangleRayIntersectionBarycentricEdge(result, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, ax, ay, az, edge1_x, edge1_y, edge1_z, edge2_x, edge2_y, edge2_z) {
186
+ // begin calculating determinant - also used to calculate U parameter
187
+
188
+ // CROSS(pvec, dir, edge2)
189
+ const pvec_x = direction_y * edge2_z - direction_z * edge2_y;
190
+ const pvec_y = direction_z * edge2_x - direction_x * edge2_z;
191
+ const pvec_z = direction_x * edge2_y - direction_y * edge2_x;
192
+
193
+ //if determinant is near zero, ray lies in plane of triangle
194
+ const det = v3_dot(edge1_x, edge1_y, edge1_z, pvec_x, pvec_y, pvec_z);
195
+
196
+ if (det <= 0) {
197
+ // back-face culling
198
+ return false;
199
+ }
200
+
201
+ // calculate distance from vert0 to ray origin (not really, but okay)
202
+ const tvec_x = origin_x - ax;
203
+ const tvec_y = origin_y - ay;
204
+ const tvec_z = origin_z - az;
205
+
206
+ // calculate u
207
+ let u = v3_dot(tvec_x, tvec_y, tvec_z, pvec_x, pvec_y, pvec_z);
208
+
209
+ if (u < 0 || u > det) {
210
+ // outside of bounds of the triangle
211
+ return false;
212
+ }
213
+
214
+ // prepare to test V parameter
215
+ // CROSS(qvec, tvec, edge1)
216
+ const qvec_x = tvec_y * edge1_z - tvec_z * edge1_y;
217
+ const qvec_y = tvec_z * edge1_x - tvec_x * edge1_z;
218
+ const qvec_z = tvec_x * edge1_y - tvec_y * edge1_x;
219
+
220
+ // calculate V parameter
221
+ let v = v3_dot(direction_x, direction_y, direction_z, qvec_x, qvec_y, qvec_z);
222
+
223
+ if (v < 0 || u + v > det) {
224
+ // out of bounds
225
+ return false;
226
+ }
227
+
228
+
229
+ const inv_det = 1 / det;
230
+
231
+ // calculate t, scale parameter, ray intersects triangle
232
+ const t = v3_dot(edge2_x, edge2_y, edge2_z, qvec_x, qvec_y, qvec_z) * inv_det;
233
+
234
+ u *= inv_det;
235
+ v *= inv_det;
236
+
237
+ result[0] = t;
238
+ result[1] = u;
239
+ result[2] = v;
240
+
241
+ return true;
242
+ }
243
+
244
+ /**
245
+ * Compute barycentric coordinates for triangle intersection
246
+ * NOTE: most of the code is inlined for speed to avoid allocation and function calls
247
+ * @see https://github.com/erich666/jgt-code/blob/master/Volume_02/Number_1/Moller1997a/raytri.c
248
+ * @source https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm (Möller and Trumbore, « Fast, Minimum Storage Ray-Triangle Intersection », Journal of Graphics Tools, vol. 2,‎ 1997, p. 21–28)
249
+ * @param {number[]} result [t,u,v, normal_x, normal_y, normal_z] will be written here
250
+ * @param {number} origin_x
251
+ * @param {number} origin_y
252
+ * @param {number} origin_z
253
+ * @param {number} direction_x
254
+ * @param {number} direction_y
255
+ * @param {number} direction_z
256
+ * @param {number} ax
257
+ * @param {number} ay
258
+ * @param {number} az
259
+ * @param {number} bx
260
+ * @param {number} by
261
+ * @param {number} bz
262
+ * @param {number} cx
263
+ * @param {number} cy
264
+ * @param {number} cz
265
+ * @returns {boolean}
266
+ */
267
+ export function computeTriangleRayIntersectionBarycentric(
268
+ result,
269
+ origin_x, origin_y, origin_z,
270
+ direction_x, direction_y, direction_z,
271
+ ax, ay, az,
272
+ bx, by, bz,
273
+ cx, cy, cz
274
+ ) {
275
+ assert.isNumber(ax, 'ax');
276
+ assert.isNumber(ay, 'ay');
277
+ assert.isNumber(az, 'az');
278
+
279
+ assert.isNumber(bx, 'bx');
280
+ assert.isNumber(by, 'by');
281
+ assert.isNumber(bz, 'bz');
282
+
283
+ assert.isNumber(cx, 'cx');
284
+ assert.isNumber(cy, 'cy');
285
+ assert.isNumber(cz, 'cz');
286
+
287
+ // nan checks
288
+ assert.notNaN(ax, 'ax');
289
+ assert.notNaN(ay, 'ay');
290
+ assert.notNaN(az, 'az');
291
+
292
+ assert.notNaN(bx, 'bx');
293
+ assert.notNaN(by, 'by');
294
+ assert.notNaN(bz, 'bz');
295
+
296
+ assert.notNaN(cx, 'cx');
297
+ assert.notNaN(cy, 'cy');
298
+ assert.notNaN(cz, 'cz');
299
+
300
+ // finate number check
301
+ assert.isFiniteNumber(ax, 'ax');
302
+ assert.isFiniteNumber(ay, 'ay');
303
+ assert.isFiniteNumber(az, 'az');
304
+
305
+ assert.isFiniteNumber(bx, 'bx');
306
+ assert.isFiniteNumber(by, 'by');
307
+ assert.isFiniteNumber(bz, 'bz');
308
+
309
+ assert.isFiniteNumber(cx, 'cx');
310
+ assert.isFiniteNumber(cy, 'cy');
311
+ assert.isFiniteNumber(cz, 'cz');
312
+
313
+
314
+ // find vectors for two edges sharing vert
315
+
316
+ // edge1 = a - b
317
+ const edge1_x = bx - ax;
318
+ const edge1_y = by - ay;
319
+ const edge1_z = bz - az;
320
+
321
+ // edge2 = c - a
322
+ const edge2_x = cx - ax;
323
+ const edge2_y = cy - ay;
324
+ const edge2_z = cz - az;
325
+
326
+ return computeTriangleRayIntersectionBarycentricEdge(result, origin_x, origin_y, origin_z, direction_x, direction_y, direction_z, ax, ay, az, edge1_x, edge1_y, edge1_z, edge2_x, edge2_y, edge2_z);
327
+ }
@@ -305,6 +305,18 @@ class Vector3 {
305
305
  return this;
306
306
  }
307
307
 
308
+ /**
309
+ *
310
+ * @param {Vector3} first
311
+ * @param {Vector3} second
312
+ */
313
+ crossVectors(first, second) {
314
+ const ax = first.x, ay = first.y, az = first.z;
315
+ const bx = second.x, by = second.y, bz = second.z;
316
+
317
+ this._crossVectors(ax, ay, az, bx, by, bz);
318
+ }
319
+
308
320
  /**
309
321
  *
310
322
  * @param {number} ax
@@ -322,18 +334,6 @@ class Vector3 {
322
334
  this.set(x, y, z);
323
335
  }
324
336
 
325
- /**
326
- *
327
- * @param {Vector3} first
328
- * @param {Vector3} second
329
- */
330
- crossVectors(first, second) {
331
- const ax = first.x, ay = first.y, az = first.z;
332
- const bx = second.x, by = second.y, bz = second.z;
333
-
334
- this._crossVectors(ax, ay, az, bx, by, bz);
335
- }
336
-
337
337
  /**
338
338
  * Sets all components of the vector to absolute value (positive)
339
339
  * @returns {Vector3}