@woosh/meep-engine 2.163.2 → 2.163.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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.d.ts +12 -0
  3. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.d.ts.map +1 -0
  4. package/src/core/geom/3d/equirectangular/equirectangular_direction_to_uv.js +18 -0
  5. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.d.ts +14 -0
  6. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.d.ts.map +1 -0
  7. package/src/core/geom/3d/equirectangular/equirectangular_uv_to_direction.js +24 -0
  8. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.d.ts.map +1 -1
  9. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_island_erode.js +368 -290
  10. package/src/core/geom/vec3/v3_uniform_sample_cone.d.ts +11 -0
  11. package/src/core/geom/vec3/v3_uniform_sample_cone.d.ts.map +1 -0
  12. package/src/core/geom/vec3/v3_uniform_sample_cone.js +21 -0
  13. package/src/core/math/physics/brdf/cone_cosine_from_roughness.d.ts +13 -0
  14. package/src/core/math/physics/brdf/cone_cosine_from_roughness.d.ts.map +1 -0
  15. package/src/core/math/physics/brdf/cone_cosine_from_roughness.js +28 -0
  16. package/src/core/math/physics/brdf/reflection_sample_weight.d.ts +18 -0
  17. package/src/core/math/physics/brdf/reflection_sample_weight.d.ts.map +1 -0
  18. package/src/core/math/physics/brdf/reflection_sample_weight.js +48 -0
  19. package/src/engine/graphics/GraphicsEngine.d.ts.map +1 -1
  20. package/src/engine/graphics/GraphicsEngine.js +52 -0
  21. package/src/engine/graphics/sh3/sky/hosek/make_environment_sky_hosek.d.ts +26 -0
  22. package/src/engine/graphics/sh3/sky/hosek/make_environment_sky_hosek.d.ts.map +1 -0
  23. package/src/engine/graphics/sh3/sky/hosek/make_environment_sky_hosek.js +49 -0
  24. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.d.ts +26 -0
  25. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.d.ts.map +1 -0
  26. package/src/engine/graphics/sh3/sky/hosek/render_hosek_sky_to_equirectangular.js +70 -0
  27. package/src/engine/graphics/sh3/sky/hosek/setup_environment_sky_from_ecd.d.ts +24 -0
  28. package/src/engine/graphics/sh3/sky/hosek/setup_environment_sky_from_ecd.d.ts.map +1 -0
  29. package/src/engine/graphics/sh3/sky/hosek/setup_environment_sky_from_ecd.js +51 -0
  30. package/src/engine/graphics/texture/EnvironmentTextureProjection.d.ts +9 -0
  31. package/src/engine/graphics/texture/EnvironmentTextureProjection.d.ts.map +1 -0
  32. package/src/engine/graphics/texture/EnvironmentTextureProjection.js +15 -0
  33. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.d.ts +44 -0
  34. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.d.ts.map +1 -0
  35. package/src/engine/graphics/texture/reflection/convolve_equirectangular_reflection.js +189 -0
  36. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.d.ts +25 -0
  37. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.d.ts.map +1 -0
  38. package/src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js +51 -0
  39. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.d.ts +15 -0
  40. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.d.ts.map +1 -0
  41. package/src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js +63 -0
  42. package/src/engine/navigation/mesh/build/bt_mesh_carve_height_clearance.d.ts +27 -0
  43. package/src/engine/navigation/mesh/build/bt_mesh_carve_height_clearance.d.ts.map +1 -0
  44. package/src/engine/navigation/mesh/build/bt_mesh_carve_height_clearance.js +323 -0
  45. package/src/engine/navigation/mesh/build/navmesh_build_topology.d.ts.map +1 -1
  46. package/src/engine/navigation/mesh/build/navmesh_build_topology.js +223 -226
  47. package/src/engine/.fuse_hidden0000001500000001 +0 -581
@@ -0,0 +1,189 @@
1
+ import { hammersley_sequence_2d } from "../../../../core/math/statistics/hammersley_sequence_2d.js";
2
+ import { v3_orthonormal_matrix_from_normal } from "../../../../core/geom/vec3/v3_orthonormal_matrix_from_normal.js";
3
+ import { v3_uniform_sample_cone } from "../../../../core/geom/vec3/v3_uniform_sample_cone.js";
4
+ import { reflection_sample_weight } from "../../../../core/math/physics/brdf/reflection_sample_weight.js";
5
+ import { cone_cosine_from_roughness } from "../../../../core/math/physics/brdf/cone_cosine_from_roughness.js";
6
+ import { equirectangular_uv_to_direction } from "../../../../core/geom/3d/equirectangular/equirectangular_uv_to_direction.js";
7
+ import { sampler2d_sample_equirectangular_direction } from "../sampler/sampler2d_sample_equirectangular_direction.js";
8
+ import { Sampler2D } from "../sampler/Sampler2D.js";
9
+ import {
10
+ equirectangular_reflection_lod_to_roughness,
11
+ roughness_from_relative_mip
12
+ } from "./equirectangular_reflection_roughness.js";
13
+
14
+ /**
15
+ * Below this we treat the surface as a perfect mirror.
16
+ * @type {number}
17
+ */
18
+ const BSDF_ROUGHNESS_MINIMUM = 0.02;
19
+
20
+ // scratch state (single-threaded, non-reentrant)
21
+ const _basis = new Float32Array(9);
22
+ const _rand = [0, 0];
23
+ const _local = [0, 0, 0];
24
+ const _radiance = [0, 0, 0, 0];
25
+
26
+ /**
27
+ * Convolve an equirectangular radiance map for a single output direction,
28
+ * importance-sampling a cone around it with a spherical-gaussian GGX weight.
29
+ * This is the per-texel core of the prefilter (extracted for testing).
30
+ *
31
+ * @param {Sampler2D} input equirectangular radiance (the previous, sharper mip)
32
+ * @param {number} out_x output (reflection) direction, unit length, +Y up
33
+ * @param {number} out_y
34
+ * @param {number} out_z
35
+ * @param {number} roughness perceptual roughness for this convolution step
36
+ * @param {number} sample_count number of cone samples
37
+ * @param {number[]|Float32Array} result
38
+ * @param {number} [result_offset=0]
39
+ */
40
+ export function convolve_equirectangular_reflection_direction(
41
+ input,
42
+ out_x, out_y, out_z,
43
+ roughness,
44
+ sample_count,
45
+ result,
46
+ result_offset = 0
47
+ ) {
48
+ const cone_cos = cone_cosine_from_roughness(roughness);
49
+
50
+ v3_orthonormal_matrix_from_normal(_basis, 0, out_x, out_y, out_z);
51
+
52
+ const t_x = _basis[0], t_y = _basis[1], t_z = _basis[2];
53
+ const b_x = _basis[3], b_y = _basis[4], b_z = _basis[5];
54
+ const n_x = _basis[6], n_y = _basis[7], n_z = _basis[8];
55
+
56
+ const itemSize = input.itemSize;
57
+
58
+ let weight_accum = 0;
59
+ let r0 = 0, r1 = 0, r2 = 0, r3 = 0;
60
+
61
+ for (let i = 0; i < sample_count; i++) {
62
+ hammersley_sequence_2d(_rand, 0, i, sample_count);
63
+
64
+ v3_uniform_sample_cone(_local, 0, _rand[0], _rand[1], cone_cos);
65
+
66
+ const lx = _local[0], ly = _local[1], lz = _local[2];
67
+
68
+ // world direction = lx * T + ly * B + lz * N
69
+ let in_x = lx * t_x + ly * b_x + lz * n_x;
70
+ let in_y = lx * t_y + ly * b_y + lz * n_y;
71
+ let in_z = lx * t_z + ly * b_z + lz * n_z;
72
+
73
+ const len = Math.sqrt(in_x * in_x + in_y * in_y + in_z * in_z);
74
+ if (len > 0) {
75
+ const inv_len = 1.0 / len;
76
+ in_x *= inv_len;
77
+ in_y *= inv_len;
78
+ in_z *= inv_len;
79
+ }
80
+
81
+ sampler2d_sample_equirectangular_direction(input, in_x, in_y, in_z, _radiance, 0);
82
+
83
+ const weight = reflection_sample_weight(out_x, out_y, out_z, in_x, in_y, in_z, roughness);
84
+
85
+ r0 += _radiance[0] * weight;
86
+ r1 += _radiance[1] * weight;
87
+ r2 += _radiance[2] * weight;
88
+ if (itemSize > 3) {
89
+ r3 += _radiance[3] * weight;
90
+ }
91
+
92
+ weight_accum += weight;
93
+ }
94
+
95
+ const inv = weight_accum === 0 ? 0 : 1.0 / weight_accum;
96
+
97
+ result[result_offset] = r0 * inv;
98
+ result[result_offset + 1] = r1 * inv;
99
+ result[result_offset + 2] = r2 * inv;
100
+ if (itemSize > 3) {
101
+ result[result_offset + 3] = r3 * inv;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Convolve a whole equirectangular level into `output`.
107
+ *
108
+ * @param {Sampler2D} input source radiance (previous mip)
109
+ * @param {Sampler2D} output destination (this mip)
110
+ * @param {number} roughness convolution roughness for this step
111
+ * @param {number} sample_count
112
+ */
113
+ export function convolve_equirectangular_reflection_level(input, output, roughness, sample_count) {
114
+ const width = output.width;
115
+ const height = output.height;
116
+
117
+ const direction = [0, 0, 0];
118
+ const texel = new Float32Array(output.itemSize);
119
+
120
+ for (let j = 0; j < height; j++) {
121
+ const v = (j + 0.5) / height;
122
+
123
+ for (let i = 0; i < width; i++) {
124
+ const u = (i + 0.5) / width;
125
+
126
+ equirectangular_uv_to_direction(u, v, direction, 0);
127
+
128
+ convolve_equirectangular_reflection_direction(
129
+ input,
130
+ direction[0], direction[1], direction[2],
131
+ roughness,
132
+ sample_count,
133
+ texel,
134
+ 0
135
+ );
136
+
137
+ output.write(i, j, texel);
138
+ }
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Build a prefiltered reflection mip chain from a base equirectangular radiance
144
+ * map. Mip 0 is the (sharp) base; each subsequent mip is half resolution and
145
+ * convolved from the previous one, so roughness increases with mip level. This
146
+ * is the CPU replacement for THREE's PMREMGenerator, decoupled from three.js.
147
+ *
148
+ * @param {Sampler2D} base equirectangular RGBA radiance (mip 0)
149
+ * @param {object} [options]
150
+ * @param {number} [options.sample_count=32] cone samples per texel (the sky is low frequency)
151
+ * @param {number} [options.mip_levels] number of levels; defaults to the full chain
152
+ * @param {number} [options.max_roughness=0.7] roughness reached at the last mip
153
+ * @returns {Sampler2D[]} mip chain, index 0 = base
154
+ */
155
+ export function build_equirectangular_reflection_mip_chain(base, options = {}) {
156
+ const {
157
+ sample_count = 32,
158
+ mip_levels,
159
+ max_roughness = 0.7
160
+ } = options;
161
+
162
+ const full_levels = Math.floor(Math.log2(Math.max(1, Math.min(base.width, base.height)))) + 1;
163
+ const levels = mip_levels !== undefined ? Math.min(mip_levels, full_levels) : full_levels;
164
+
165
+ const mips = [base];
166
+
167
+ for (let i = 1; i < levels; i++) {
168
+ const previous = mips[i - 1];
169
+
170
+ const width = Math.max(1, previous.width >> 1);
171
+ const height = Math.max(1, previous.height >> 1);
172
+
173
+ const level = Sampler2D.float32(base.itemSize, width, height);
174
+
175
+ const prev_roughness = equirectangular_reflection_lod_to_roughness(i - 1, levels, max_roughness);
176
+ const curr_roughness = equirectangular_reflection_lod_to_roughness(i, levels, max_roughness);
177
+
178
+ const step_roughness = Math.max(
179
+ BSDF_ROUGHNESS_MINIMUM,
180
+ roughness_from_relative_mip(prev_roughness, curr_roughness)
181
+ );
182
+
183
+ convolve_equirectangular_reflection_level(previous, level, step_roughness, sample_count);
184
+
185
+ mips.push(level);
186
+ }
187
+
188
+ return mips;
189
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Roughness schedule for a prefiltered reflection mip chain, ported from the
3
+ * EEVEE "sphere probe" convolution (generalised to an arbitrary mip count).
4
+ */
5
+ /**
6
+ * Map a mip level to the perceptual roughness it represents.
7
+ *
8
+ * @param {number} lod mip level, 0 = sharpest
9
+ * @param {number} mip_levels total number of mip levels
10
+ * @param {number} [max_roughness=0.7] roughness reached at the last mip
11
+ * @returns {number}
12
+ */
13
+ export function equirectangular_reflection_lod_to_roughness(lod: number, mip_levels: number, max_roughness?: number): number;
14
+ /**
15
+ * Given that the previous mip is already convolved to `prev_mip_roughness`,
16
+ * derive the additional roughness to apply when convolving it into the current
17
+ * mip, so the result matches `curr_mip_roughness`. Uses the gaussian
18
+ * convolution composition rule G(a) x G(b) = G(a+b).
19
+ *
20
+ * @param {number} prev_mip_roughness
21
+ * @param {number} curr_mip_roughness
22
+ * @returns {number}
23
+ */
24
+ export function roughness_from_relative_mip(prev_mip_roughness: number, curr_mip_roughness: number): number;
25
+ //# sourceMappingURL=equirectangular_reflection_roughness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equirectangular_reflection_roughness.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/texture/reflection/equirectangular_reflection_roughness.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,iEALW,MAAM,cACN,MAAM,kBACN,MAAM,GACJ,MAAM,CAiBlB;AAED;;;;;;;;;GASG;AACH,gEAJW,MAAM,sBACN,MAAM,GACJ,MAAM,CAYlB"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Roughness schedule for a prefiltered reflection mip chain, ported from the
3
+ * EEVEE "sphere probe" convolution (generalised to an arbitrary mip count).
4
+ */
5
+
6
+ /**
7
+ * Map a mip level to the perceptual roughness it represents.
8
+ *
9
+ * @param {number} lod mip level, 0 = sharpest
10
+ * @param {number} mip_levels total number of mip levels
11
+ * @param {number} [max_roughness=0.7] roughness reached at the last mip
12
+ * @returns {number}
13
+ */
14
+ export function equirectangular_reflection_lod_to_roughness(lod, mip_levels, max_roughness = 0.7) {
15
+ const mip_ratio = mip_levels > 1 ? lod / (mip_levels - 1) : 0;
16
+
17
+ const a = mip_ratio;
18
+ const b = 0.6; // factor of ratio
19
+ const c = 0.4; // factor of ratio_sqrt
20
+
21
+ const b2 = b * b;
22
+ const c2 = c * c;
23
+ const c4 = c2 * c2;
24
+
25
+ // inverse of the roughness->lod mapping (a quadratic)
26
+ const ratio = (-Math.sqrt(4.0 * a * b * c2 + c4) + 2.0 * a * b + c2) / (2.0 * b2);
27
+
28
+ return ratio * max_roughness;
29
+ }
30
+
31
+ /**
32
+ * Given that the previous mip is already convolved to `prev_mip_roughness`,
33
+ * derive the additional roughness to apply when convolving it into the current
34
+ * mip, so the result matches `curr_mip_roughness`. Uses the gaussian
35
+ * convolution composition rule G(a) x G(b) = G(a+b).
36
+ *
37
+ * @param {number} prev_mip_roughness
38
+ * @param {number} curr_mip_roughness
39
+ * @returns {number}
40
+ */
41
+ export function roughness_from_relative_mip(prev_mip_roughness, curr_mip_roughness) {
42
+ // the exponent should be 2 but 3 is a bit less blurry than expected in practice
43
+ const exponent = 3.0;
44
+
45
+ const m_prev = Math.pow(prev_mip_roughness, exponent);
46
+ const m_curr = Math.pow(curr_mip_roughness, exponent);
47
+
48
+ const m_target = Math.max(0.0, m_curr - m_prev);
49
+
50
+ return Math.pow(m_target, 1.0 / exponent);
51
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Bilinearly sample a Sampler2D that holds an equirectangular image, by world
3
+ * direction (+Y up). The longitude axis (U) wraps and the latitude axis (V) is
4
+ * clamped, so there is no seam at longitude +/-pi (unlike Sampler2D's own
5
+ * bilinear sampling, which clamps both axes).
6
+ *
7
+ * @param {Sampler2D} sampler equirectangular source
8
+ * @param {number} dir_x
9
+ * @param {number} dir_y
10
+ * @param {number} dir_z
11
+ * @param {number[]|Float32Array} result
12
+ * @param {number} [result_offset=0]
13
+ */
14
+ export function sampler2d_sample_equirectangular_direction(sampler: Sampler2D, dir_x: number, dir_y: number, dir_z: number, result: number[] | Float32Array, result_offset?: number): void;
15
+ //# sourceMappingURL=sampler2d_sample_equirectangular_direction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sampler2d_sample_equirectangular_direction.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/texture/sampler/sampler2d_sample_equirectangular_direction.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,sFANW,MAAM,SACN,MAAM,SACN,MAAM,UACN,MAAM,EAAE,GAAC,YAAY,kBACrB,MAAM,QA+ChB"}
@@ -0,0 +1,63 @@
1
+ import { equirectangular_direction_to_uv } from "../../../../core/geom/3d/equirectangular/equirectangular_direction_to_uv.js";
2
+
3
+ const _uv = [0, 0];
4
+
5
+ /**
6
+ * Bilinearly sample a Sampler2D that holds an equirectangular image, by world
7
+ * direction (+Y up). The longitude axis (U) wraps and the latitude axis (V) is
8
+ * clamped, so there is no seam at longitude +/-pi (unlike Sampler2D's own
9
+ * bilinear sampling, which clamps both axes).
10
+ *
11
+ * @param {Sampler2D} sampler equirectangular source
12
+ * @param {number} dir_x
13
+ * @param {number} dir_y
14
+ * @param {number} dir_z
15
+ * @param {number[]|Float32Array} result
16
+ * @param {number} [result_offset=0]
17
+ */
18
+ export function sampler2d_sample_equirectangular_direction(sampler, dir_x, dir_y, dir_z, result, result_offset = 0) {
19
+ equirectangular_direction_to_uv(dir_x, dir_y, dir_z, _uv, 0);
20
+
21
+ const width = sampler.width;
22
+ const height = sampler.height;
23
+ const itemSize = sampler.itemSize;
24
+ const data = sampler.data;
25
+
26
+ // texel-space coordinates with texel centers at integer + 0.5
27
+ const fx = _uv[0] * width - 0.5;
28
+ const fy = _uv[1] * height - 0.5;
29
+
30
+ const x0i = Math.floor(fx);
31
+ const y0i = Math.floor(fy);
32
+
33
+ const tx = fx - x0i;
34
+ const ty = fy - y0i;
35
+
36
+ // longitude wraps, latitude clamps
37
+ const x0 = ((x0i % width) + width) % width;
38
+ const x1 = ((x0i + 1) % width + width) % width;
39
+ const y0 = y0i < 0 ? 0 : (y0i >= height ? height - 1 : y0i);
40
+ const y1i = y0i + 1;
41
+ const y1 = y1i < 0 ? 0 : (y1i >= height ? height - 1 : y1i);
42
+
43
+ const w00 = (1 - tx) * (1 - ty);
44
+ const w10 = tx * (1 - ty);
45
+ const w01 = (1 - tx) * ty;
46
+ const w11 = tx * ty;
47
+
48
+ const row0 = y0 * width;
49
+ const row1 = y1 * width;
50
+
51
+ const o00 = (row0 + x0) * itemSize;
52
+ const o10 = (row0 + x1) * itemSize;
53
+ const o01 = (row1 + x0) * itemSize;
54
+ const o11 = (row1 + x1) * itemSize;
55
+
56
+ for (let c = 0; c < itemSize; c++) {
57
+ result[result_offset + c] =
58
+ data[o00 + c] * w00 +
59
+ data[o10 + c] * w10 +
60
+ data[o01 + c] * w01 +
61
+ data[o11 + c] * w11;
62
+ }
63
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Carve holes into a (welded, connected) walkable topology wherever an agent of the given height
3
+ * would not fit under overhead geometry.
4
+ *
5
+ * Operates on the topology rather than a triangle soup so that all subdivision is conformal:
6
+ * {@link bt_edge_split} re-triangulates every face around a split edge, so neighbouring faces can
7
+ * never disagree on a shared edge (no cracks / T-junctions). Refinement is adaptive - only faces whose
8
+ * column actually contains an overhang are subdivided, and only down to `resolution` - so clear areas
9
+ * stay coarse and the subdivision hugs the obstacle contour instead of tessellating whole triangles.
10
+ *
11
+ * @param {object} params
12
+ * @param {BinaryTopology} params.mesh walkable topology to carve (modified in place)
13
+ * @param {BinaryTopology} params.source original source mesh (walkable + overhead geometry)
14
+ * @param {BVH} params.source_bvh BVH over `source` (leaves carry source face IDs)
15
+ * @param {number} params.agent_height
16
+ * @param {number} params.agent_radius
17
+ * @param {Vector3} params.up world up direction
18
+ */
19
+ export function bt_mesh_carve_height_clearance({ mesh, source, source_bvh, agent_height, agent_radius, up, }: {
20
+ mesh: BinaryTopology;
21
+ source: BinaryTopology;
22
+ source_bvh: BVH;
23
+ agent_height: number;
24
+ agent_radius: number;
25
+ up: Vector3;
26
+ }): void;
27
+ //# sourceMappingURL=bt_mesh_carve_height_clearance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bt_mesh_carve_height_clearance.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/navigation/mesh/build/bt_mesh_carve_height_clearance.js"],"names":[],"mappings":"AA2LA;;;;;;;;;;;;;;;;;GAiBG;AACH;IAPkC,IAAI;IACJ,MAAM;IACjB,UAAU;IACP,YAAY,EAA3B,MAAM;IACS,YAAY,EAA3B,MAAM;IACU,EAAE;SAuH5B"}