@woosh/meep-engine 3.61.1 → 3.61.2
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 +1 -1
- package/src/engine/network/sim/SimActionExecutor.d.ts +4 -0
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +4 -0
- package/src/generation/foliage/material/foliage_atlas_cutout.d.ts.map +1 -1
- package/src/generation/foliage/material/foliage_atlas_cutout.js +21 -5
- package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts +8 -0
- package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts.map +1 -1
- package/src/generation/foliage/mesh/tree_cluster_representatives.js +178 -78
- package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
- package/src/generation/foliage/mesh/tree_mesh_build_bark.js +178 -97
- package/src/generation/foliage/skeleton/ShootLightField.d.ts +1 -0
- package/src/generation/foliage/skeleton/ShootLightField.d.ts.map +1 -1
- package/src/generation/foliage/skeleton/ShootLightField.js +88 -17
- package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +5 -2
- package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
- package/src/generation/foliage/skeleton/ShootWoodHash.js +191 -25
- package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap/main.js +4 -0
- package/src/shade/playground/probe_clipmap_box/README.md +55 -0
- package/src/shade/playground/probe_clipmap_box/index.html +185 -0
- package/src/shade/playground/probe_clipmap_box/main.d.ts +8 -0
- package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -0
- package/src/shade/playground/probe_clipmap_box/main.js +323 -0
- package/src/shade/playground/probe_clipmap_box/scene.d.ts +93 -0
- package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -0
- package/src/shade/playground/probe_clipmap_box/scene.js +256 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +6 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts +12 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.js +49 -24
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts +12 -0
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.js +50 -19
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.js +6 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +5 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +7 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +6 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +10 -9
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +12 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +14 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +17 -22
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +53 -65
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts +2 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +9 -20
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +2 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +14 -19
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +8 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.js +13 -18
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.js +4 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.js +4 -6
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.js +4 -7
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +4 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +14 -13
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +3 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +7 -15
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -1
- package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +5 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +26 -8
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +170 -142
- package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.js +5 -8
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +15 -4
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +33 -7
- package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts +40 -0
- package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.js +75 -0
- package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.js +3 -1
- package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts +28 -0
- package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.js +41 -0
- package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts +12 -0
- package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.js +24 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +3 -2
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +4 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +2 -5
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +3 -20
- package/src/shade/renderer/water/chunk_water_gi.d.ts +1 -1
- package/src/shade/renderer/water/chunk_water_gi.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_gi.js +6 -8
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +76 -32
- package/src/core/math/hash/squirrel3.d.ts +0 -17
- package/src/core/math/hash/squirrel3.d.ts.map +0 -1
- package/src/core/math/hash/squirrel3.js +0 -30
- package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts +0 -12
- package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts.map +0 -1
- package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.js +0 -30
|
@@ -72,9 +72,55 @@ const RING = {
|
|
|
72
72
|
/** @type {import("../config/BranchGeneratorConfig.js").BranchGeneratorConfig|null} */
|
|
73
73
|
lvl_cfg: null,
|
|
74
74
|
collars: [],
|
|
75
|
-
knots: []
|
|
75
|
+
knots: [],
|
|
76
|
+
active_collars: [],
|
|
77
|
+
active_collar_theta: [],
|
|
78
|
+
active_knots: [],
|
|
79
|
+
active_knot_theta: [],
|
|
80
|
+
is_circle: false
|
|
76
81
|
};
|
|
77
82
|
|
|
83
|
+
function ring_prepare(ring) {
|
|
84
|
+
const ac = ring.active_collars;
|
|
85
|
+
const act = ring.active_collar_theta;
|
|
86
|
+
ac.length = 0;
|
|
87
|
+
act.length = 0;
|
|
88
|
+
const rx = ring.rx, ry = ring.ry, rz = ring.rz;
|
|
89
|
+
const sx = ring.sx, sy = ring.sy, sz = ring.sz;
|
|
90
|
+
const t_norm = ring.t_norm;
|
|
91
|
+
if (ring.collar_amp > 1e-4) {
|
|
92
|
+
const collars = ring.collars;
|
|
93
|
+
for (let i = 0; i < collars.length; i++) {
|
|
94
|
+
const cc = collars[i];
|
|
95
|
+
if (Math.abs(t_norm - cc.t_c) < 3.2 * cc.sigma_t) {
|
|
96
|
+
ac.push(cc);
|
|
97
|
+
act.push(Math.atan2(
|
|
98
|
+
cc.tx_c * sx + cc.ty_c * sy + cc.tz_c * sz,
|
|
99
|
+
cc.tx_c * rx + cc.ty_c * ry + cc.tz_c * rz
|
|
100
|
+
));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const ak = ring.active_knots;
|
|
105
|
+
const akt = ring.active_knot_theta;
|
|
106
|
+
ak.length = 0;
|
|
107
|
+
akt.length = 0;
|
|
108
|
+
if (ring.knot_scale > 0.05) {
|
|
109
|
+
const knots = ring.knots;
|
|
110
|
+
for (let i = 0; i < knots.length; i++) {
|
|
111
|
+
const kn = knots[i];
|
|
112
|
+
if (Math.abs(t_norm - kn.t_k) < 3.2 * kn.sigma_t) {
|
|
113
|
+
ak.push(kn);
|
|
114
|
+
akt.push(Math.atan2(
|
|
115
|
+
kn.tx_k * sx + kn.ty_k * sy + kn.tz_k * sz,
|
|
116
|
+
kn.tx_k * rx + kn.ty_k * ry + kn.tz_k * rz
|
|
117
|
+
));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
ring.is_circle = !(ring.flare_env > 0.0) && !(ring.flute_env > 1e-5) && !(ring.oval_ecc > 1e-4) && ac.length === 0 && ak.length === 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
78
124
|
/**
|
|
79
125
|
* The collars of the branches `b` carries, where each joins it: a boss on its bark, and the grain flowing round it.
|
|
80
126
|
*
|
|
@@ -160,6 +206,14 @@ function circle_sides(r, tolerance) {
|
|
|
160
206
|
* @type {number}
|
|
161
207
|
*/
|
|
162
208
|
const BARK_REFERENCE_SIDES = 64;
|
|
209
|
+
const REF_THETA = new Float64Array(BARK_REFERENCE_SIDES);
|
|
210
|
+
const REF_COS = new Float64Array(BARK_REFERENCE_SIDES);
|
|
211
|
+
const REF_SIN = new Float64Array(BARK_REFERENCE_SIDES);
|
|
212
|
+
for (let j = 0; j < BARK_REFERENCE_SIDES; j++) {
|
|
213
|
+
REF_THETA[j] = PI2 * j / BARK_REFERENCE_SIDES;
|
|
214
|
+
REF_COS[j] = Math.cos(REF_THETA[j]);
|
|
215
|
+
REF_SIN[j] = Math.sin(REF_THETA[j]);
|
|
216
|
+
}
|
|
163
217
|
|
|
164
218
|
/**
|
|
165
219
|
* Fills {@link RING} for the candidate ring `c` of a plan's arrays.
|
|
@@ -183,19 +237,18 @@ function plan_fill_ring(plan, c, lvl_cfg, collars, knots) {
|
|
|
183
237
|
RING.lvl_cfg = lvl_cfg;
|
|
184
238
|
RING.collars = collars;
|
|
185
239
|
RING.knots = knots;
|
|
240
|
+
ring_prepare(RING);
|
|
186
241
|
}
|
|
187
242
|
|
|
188
243
|
/**
|
|
189
244
|
* Point of candidate ring `c` at angle `theta`, into `out` at `o`: its spine point plus its shaped radius along the
|
|
190
245
|
* ring's radial direction. {@link RING} must hold the ring.
|
|
191
246
|
*/
|
|
192
|
-
function plan_ring_point(out, o, plan, c, theta) {
|
|
193
|
-
bark_ring_shape(SCRATCH_SHAPE, theta, RING);
|
|
247
|
+
function plan_ring_point(out, o, plan, c, theta, cos_t = Math.cos(theta), sin_t = Math.sin(theta)) {
|
|
248
|
+
bark_ring_shape(SCRATCH_SHAPE, theta, RING, cos_t, sin_t);
|
|
194
249
|
// the weld's symmetric flare on the rings after the first
|
|
195
250
|
const r_mult = SCRATCH_SHAPE[0] + (c > 0 ? plan.weld[c] * 0.18 : 0.0);
|
|
196
251
|
const r = plan.radius[c] * Math.max(0.25, r_mult);
|
|
197
|
-
const cos_t = Math.cos(theta);
|
|
198
|
-
const sin_t = Math.sin(theta);
|
|
199
252
|
out[o] = plan.points[c * 3] + r * (cos_t * RING.rx + sin_t * RING.sx);
|
|
200
253
|
out[o + 1] = plan.points[c * 3 + 1] + r * (cos_t * RING.ry + sin_t * RING.sy);
|
|
201
254
|
out[o + 2] = plan.points[c * 3 + 2] + r * (cos_t * RING.rz + sin_t * RING.sz);
|
|
@@ -209,7 +262,8 @@ function point_segment_distance(p, po, a, ao, b, bo) {
|
|
|
209
262
|
const apx = p[po] - a[ao], apy = p[po + 1] - a[ao + 1], apz = p[po + 2] - a[ao + 2];
|
|
210
263
|
const len2 = abx * abx + aby * aby + abz * abz;
|
|
211
264
|
const t = len2 > 0 ? clamp((apx * abx + apy * aby + apz * abz) / len2, 0, 1) : 0;
|
|
212
|
-
|
|
265
|
+
const dx = apx - t * abx, dy = apy - t * aby, dz = apz - t * abz;
|
|
266
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
213
267
|
}
|
|
214
268
|
|
|
215
269
|
/**
|
|
@@ -370,8 +424,26 @@ function bark_plan_rings(skeleton, b, lvl_cfg, nodes, edges, collars, knots, wel
|
|
|
370
424
|
const measured = new Float64Array(C * M * 3);
|
|
371
425
|
for (let c = 0; c < C; c++) {
|
|
372
426
|
plan_fill_ring(plan, c, lvl_cfg, collars, knots);
|
|
373
|
-
|
|
374
|
-
|
|
427
|
+
if (M === BARK_REFERENCE_SIDES && RING.is_circle) {
|
|
428
|
+
const r = plan.radius[c] * Math.max(0.25, 1.0 + (c > 0 ? plan.weld[c] * 0.18 : 0.0));
|
|
429
|
+
const px = plan.points[c * 3], py = plan.points[c * 3 + 1], pz = plan.points[c * 3 + 2];
|
|
430
|
+
const rx = RING.rx, ry = RING.ry, rz = RING.rz, sx = RING.sx, sy = RING.sy, sz = RING.sz;
|
|
431
|
+
const base = c * M * 3;
|
|
432
|
+
for (let j = 0; j < M; j++) {
|
|
433
|
+
const cos_t = REF_COS[j], sin_t = REF_SIN[j];
|
|
434
|
+
const o = base + j * 3;
|
|
435
|
+
measured[o] = px + r * (cos_t * rx + sin_t * sx);
|
|
436
|
+
measured[o + 1] = py + r * (cos_t * ry + sin_t * sy);
|
|
437
|
+
measured[o + 2] = pz + r * (cos_t * rz + sin_t * sz);
|
|
438
|
+
}
|
|
439
|
+
} else if (M === BARK_REFERENCE_SIDES) {
|
|
440
|
+
for (let j = 0; j < M; j++) {
|
|
441
|
+
plan_ring_point(measured, (c * M + j) * 3, plan, c, REF_THETA[j], REF_COS[j], REF_SIN[j]);
|
|
442
|
+
}
|
|
443
|
+
} else {
|
|
444
|
+
for (let j = 0; j < M; j++) {
|
|
445
|
+
plan_ring_point(measured, (c * M + j) * 3, plan, c, PI2 * j / M);
|
|
446
|
+
}
|
|
375
447
|
}
|
|
376
448
|
}
|
|
377
449
|
|
|
@@ -411,18 +483,27 @@ function bark_plan_rings(skeleton, b, lvl_cfg, nodes, edges, collars, knots, wel
|
|
|
411
483
|
for (let c = 0; c < C; c++) {
|
|
412
484
|
if (!keep[c]) continue;
|
|
413
485
|
plan_fill_ring(plan, c, lvl_cfg, collars, knots);
|
|
486
|
+
polygon[0] = measured[c * M * 3];
|
|
487
|
+
polygon[1] = measured[c * M * 3 + 1];
|
|
488
|
+
polygon[2] = measured[c * M * 3 + 2];
|
|
414
489
|
let sides = 3;
|
|
415
490
|
for (; sides < M; sides++) {
|
|
416
|
-
|
|
417
|
-
|
|
491
|
+
plan_ring_point(polygon, 3, plan, c, PI2 / sides);
|
|
492
|
+
plan_ring_point(SCRATCH_PLAN_MID, 0, plan, c, PI2 * 0.5 / sides);
|
|
493
|
+
if (point_segment_distance(SCRATCH_PLAN_MID, 0, polygon, 0, polygon, 3) > tolerance) continue;
|
|
494
|
+
for (let k = 2; k < sides; k++) {
|
|
495
|
+
plan_ring_point(polygon, k * 3, plan, c, PI2 * k / sides);
|
|
418
496
|
}
|
|
497
|
+
polygon[sides * 3] = polygon[0];
|
|
498
|
+
polygon[sides * 3 + 1] = polygon[1];
|
|
499
|
+
polygon[sides * 3 + 2] = polygon[2];
|
|
419
500
|
let within = true;
|
|
420
501
|
for (let j = 0; j < M && within; j++) {
|
|
421
502
|
const k = Math.floor(j * sides / M);
|
|
422
503
|
within = point_segment_distance(measured, (c * M + j) * 3, polygon, k * 3, polygon, (k + 1) * 3) <= tolerance;
|
|
423
504
|
}
|
|
424
505
|
// a chord strays furthest from the wood at its middle
|
|
425
|
-
for (let k =
|
|
506
|
+
for (let k = 1; k < sides && within; k++) {
|
|
426
507
|
plan_ring_point(SCRATCH_PLAN_MID, 0, plan, c, PI2 * (k + 0.5) / sides);
|
|
427
508
|
within = point_segment_distance(SCRATCH_PLAN_MID, 0, polygon, k * 3, polygon, (k + 1) * 3) <= tolerance;
|
|
428
509
|
}
|
|
@@ -445,14 +526,19 @@ function bark_plan_rings(skeleton, b, lvl_cfg, nodes, edges, collars, knots, wel
|
|
|
445
526
|
* @param {number} theta
|
|
446
527
|
* @param {RING} ring
|
|
447
528
|
*/
|
|
448
|
-
function bark_ring_shape(out, theta, ring) {
|
|
529
|
+
function bark_ring_shape(out, theta, ring, cos_t = Math.cos(theta), sin_t = Math.sin(theta)) {
|
|
530
|
+
if (ring.is_circle) {
|
|
531
|
+
out[0] = 1.0;
|
|
532
|
+
out[1] = 0.0;
|
|
533
|
+
out[2] = 0.0;
|
|
534
|
+
out[3] = 1.0;
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
449
537
|
const lvl_cfg = ring.lvl_cfg;
|
|
450
|
-
const
|
|
451
|
-
const
|
|
538
|
+
const ry = ring.ry;
|
|
539
|
+
const sy = ring.sy;
|
|
452
540
|
const t_norm = ring.t_norm;
|
|
453
541
|
const unwelded = ring.unwelded;
|
|
454
|
-
const cos_t = Math.cos(theta);
|
|
455
|
-
const sin_t = Math.sin(theta);
|
|
456
542
|
const n_rad_y = cos_t * ry + sin_t * sy;
|
|
457
543
|
const tan_theta_y = -sin_t * ry + cos_t * sy;
|
|
458
544
|
|
|
@@ -490,64 +576,52 @@ function bark_ring_shape(out, theta, ring) {
|
|
|
490
576
|
}
|
|
491
577
|
|
|
492
578
|
// 3. Parent-stem branch collar swelling bosses & UV grain streamline deflection around child branches
|
|
493
|
-
const collars = ring.
|
|
579
|
+
const collars = ring.active_collars;
|
|
580
|
+
const collar_thetas = ring.active_collar_theta;
|
|
494
581
|
const parent_collar_amp = ring.collar_amp;
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
const b_amp = parent_collar_amp * (0.55 + 0.75 * cc.r_ratio);
|
|
512
|
-
r_mult += b_amp * gauss;
|
|
513
|
-
d_rmult_dtheta += -b_amp * gauss * (u_th / cc.sigma_theta);
|
|
514
|
-
const r_uv2 = dist2 + 0.85;
|
|
515
|
-
u_warp += 0.008 * unwelded * (u_th / r_uv2) * Math.exp(-0.35 * dist2);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
582
|
+
for (let c_idx = 0; c_idx < collars.length; c_idx++) {
|
|
583
|
+
const cc = collars[c_idx];
|
|
584
|
+
const dt = t_norm - cc.t_c;
|
|
585
|
+
const theta_c = collar_thetas[c_idx];
|
|
586
|
+
const dtheta = Math.atan2(Math.sin(theta - theta_c), Math.cos(theta - theta_c));
|
|
587
|
+
const sig_t = dt < 0.0 ? cc.sigma_t * 1.25 : cc.sigma_t * 0.90;
|
|
588
|
+
const u_t = dt / sig_t;
|
|
589
|
+
const u_th = dtheta / cc.sigma_theta;
|
|
590
|
+
const dist2 = u_t * u_t + u_th * u_th;
|
|
591
|
+
if (dist2 < 9.0) {
|
|
592
|
+
const gauss = Math.exp(-0.5 * dist2);
|
|
593
|
+
const b_amp = parent_collar_amp * (0.55 + 0.75 * cc.r_ratio);
|
|
594
|
+
r_mult += b_amp * gauss;
|
|
595
|
+
d_rmult_dtheta += -b_amp * gauss * (u_th / cc.sigma_theta);
|
|
596
|
+
const r_uv2 = dist2 + 0.85;
|
|
597
|
+
u_warp += 0.008 * unwelded * (u_th / r_uv2) * Math.exp(-0.35 * dist2);
|
|
518
598
|
}
|
|
519
599
|
}
|
|
520
600
|
|
|
521
601
|
// 4. Branch scars: volcanic callus rims + UV grain streamline deflection
|
|
522
|
-
const knots = ring.
|
|
602
|
+
const knots = ring.active_knots;
|
|
603
|
+
const knot_thetas = ring.active_knot_theta;
|
|
523
604
|
const knot_scale = ring.knot_scale;
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
const dw_drho2 = (1.90 - 0.85 * (0.30 + 1.90 * rho2)) * exp_r;
|
|
542
|
-
r_mult += k_amp * w_rim;
|
|
543
|
-
d_rmult_dtheta += k_amp * dw_drho2 * (2.0 * u_th / kn.sigma_theta);
|
|
544
|
-
if (rho2 < 0.65) {
|
|
545
|
-
vert_ao *= (0.72 + 0.28 * (rho2 / 0.65));
|
|
546
|
-
}
|
|
547
|
-
const r_uv2 = rho2 + 0.85;
|
|
548
|
-
u_warp += 0.009 * unwelded * (u_th / r_uv2) * Math.exp(-0.35 * rho2);
|
|
549
|
-
}
|
|
605
|
+
for (let k_idx = 0; k_idx < knots.length; k_idx++) {
|
|
606
|
+
const kn = knots[k_idx];
|
|
607
|
+
const dt = t_norm - kn.t_k;
|
|
608
|
+
const theta_k = knot_thetas[k_idx];
|
|
609
|
+
const dtheta = Math.atan2(Math.sin(theta - theta_k), Math.cos(theta - theta_k));
|
|
610
|
+
const u_t = dt / kn.sigma_t;
|
|
611
|
+
const u_th = dtheta / kn.sigma_theta;
|
|
612
|
+
const rho2 = u_t * u_t + u_th * u_th;
|
|
613
|
+
if (rho2 < 9.0) {
|
|
614
|
+
const k_amp = kn.amp_k * knot_scale;
|
|
615
|
+
const exp_r = Math.exp(-0.85 * rho2);
|
|
616
|
+
const w_rim = (0.30 + 1.90 * rho2) * exp_r;
|
|
617
|
+
const dw_drho2 = (1.90 - 0.85 * (0.30 + 1.90 * rho2)) * exp_r;
|
|
618
|
+
r_mult += k_amp * w_rim;
|
|
619
|
+
d_rmult_dtheta += k_amp * dw_drho2 * (2.0 * u_th / kn.sigma_theta);
|
|
620
|
+
if (rho2 < 0.65) {
|
|
621
|
+
vert_ao *= (0.72 + 0.28 * (rho2 / 0.65));
|
|
550
622
|
}
|
|
623
|
+
const r_uv2 = rho2 + 0.85;
|
|
624
|
+
u_warp += 0.009 * unwelded * (u_th / r_uv2) * Math.exp(-0.35 * rho2);
|
|
551
625
|
}
|
|
552
626
|
}
|
|
553
627
|
|
|
@@ -704,13 +778,13 @@ export function tree_mesh_build_bark(
|
|
|
704
778
|
}
|
|
705
779
|
|
|
706
780
|
const positions = geometry_obtain_attribute(out, StandardAttributes.Position, 3, total_vertices);
|
|
707
|
-
const normals = geometry_obtain_attribute(out, StandardAttributes.Normal, 3, total_vertices);
|
|
708
|
-
const uv0 = geometry_obtain_attribute(out, StandardAttributes.TextureCoordinates0, 2, total_vertices);
|
|
709
|
-
const uv1 = geometry_obtain_attribute(out, StandardAttributes.TextureCoordinates1, 2, total_vertices);
|
|
710
|
-
const colors = geometry_obtain_attribute(out, StandardAttributes.Color, 3, total_vertices);
|
|
711
|
-
const joints = geometry_obtain_joints_attribute(out, total_vertices);
|
|
712
|
-
const weights = geometry_obtain_attribute(out, StandardAttributes.SkinningWeights, 4, total_vertices);
|
|
713
|
-
const indices = geometry_obtain_index(out, total_indices);
|
|
781
|
+
const normals = only_rings ? null : geometry_obtain_attribute(out, StandardAttributes.Normal, 3, total_vertices);
|
|
782
|
+
const uv0 = only_rings ? null : geometry_obtain_attribute(out, StandardAttributes.TextureCoordinates0, 2, total_vertices);
|
|
783
|
+
const uv1 = only_rings ? null : geometry_obtain_attribute(out, StandardAttributes.TextureCoordinates1, 2, total_vertices);
|
|
784
|
+
const colors = only_rings ? null : geometry_obtain_attribute(out, StandardAttributes.Color, 3, total_vertices);
|
|
785
|
+
const joints = only_rings ? null : geometry_obtain_joints_attribute(out, total_vertices);
|
|
786
|
+
const weights = only_rings ? null : geometry_obtain_attribute(out, StandardAttributes.SkinningWeights, 4, total_vertices);
|
|
787
|
+
const indices = only_rings ? null : geometry_obtain_index(out, total_indices);
|
|
714
788
|
|
|
715
789
|
if (is_empty_fallback) {
|
|
716
790
|
// Populate valid non-degenerate fallback quad so ensureTangents() and MeshoptClusterizer always succeed
|
|
@@ -1057,6 +1131,7 @@ export function tree_mesh_build_bark(
|
|
|
1057
1131
|
RING.lvl_cfg = lvl_cfg;
|
|
1058
1132
|
RING.collars = child_collars;
|
|
1059
1133
|
RING.knots = branch_knots;
|
|
1134
|
+
ring_prepare(RING);
|
|
1060
1135
|
|
|
1061
1136
|
for (let j = 0; j <= m_i; j++) {
|
|
1062
1137
|
// Ensure exact periodic closure between j=0 and j=m_i
|
|
@@ -1076,7 +1151,7 @@ export function tree_mesh_build_bark(
|
|
|
1076
1151
|
const tan_theta_z = -sin_t * rz + cos_t * sz;
|
|
1077
1152
|
|
|
1078
1153
|
// The ring's smooth shape at theta (lobes, flutes, ovalization, collar bosses, knots), then its bark relief
|
|
1079
|
-
bark_ring_shape(SCRATCH_SHAPE, theta, RING);
|
|
1154
|
+
bark_ring_shape(SCRATCH_SHAPE, theta, RING, cos_t, sin_t);
|
|
1080
1155
|
let r_mult = SCRATCH_SHAPE[0];
|
|
1081
1156
|
let d_rmult_dtheta = SCRATCH_SHAPE[1];
|
|
1082
1157
|
let u_warp = SCRATCH_SHAPE[2];
|
|
@@ -1163,36 +1238,38 @@ export function tree_mesh_build_bark(
|
|
|
1163
1238
|
}
|
|
1164
1239
|
|
|
1165
1240
|
const v3 = v_cursor * 3;
|
|
1166
|
-
const v2 = v_cursor * 2;
|
|
1167
|
-
const v4 = v_cursor * 4;
|
|
1168
|
-
|
|
1169
1241
|
positions[v3] = vx;
|
|
1170
1242
|
positions[v3 + 1] = vy;
|
|
1171
1243
|
positions[v3 + 2] = vz;
|
|
1172
1244
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1245
|
+
if (!only_rings) {
|
|
1246
|
+
const v2 = v_cursor * 2;
|
|
1247
|
+
const v4 = v_cursor * 4;
|
|
1248
|
+
|
|
1249
|
+
normals[v3] = vnx;
|
|
1250
|
+
normals[v3 + 1] = vny;
|
|
1251
|
+
normals[v3 + 2] = vnz;
|
|
1176
1252
|
|
|
1177
|
-
|
|
1178
|
-
|
|
1253
|
+
uv0[v2] = k_wrap * (j / m_i) + twist_uv * arc_s + u_warp;
|
|
1254
|
+
uv0[v2 + 1] = v_base;
|
|
1179
1255
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1256
|
+
uv1[v2] = wind_sway;
|
|
1257
|
+
uv1[v2 + 1] = wind_phase;
|
|
1182
1258
|
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1259
|
+
colors[v3] = vert_ao;
|
|
1260
|
+
colors[v3 + 1] = vert_ao;
|
|
1261
|
+
colors[v3 + 2] = vert_ao;
|
|
1186
1262
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1263
|
+
joints[v4] = ring_j0;
|
|
1264
|
+
joints[v4 + 1] = ring_j1;
|
|
1265
|
+
joints[v4 + 2] = ring_j2;
|
|
1266
|
+
joints[v4 + 3] = ring_j3;
|
|
1191
1267
|
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1268
|
+
weights[v4] = ring_w0;
|
|
1269
|
+
weights[v4 + 1] = ring_w1;
|
|
1270
|
+
weights[v4 + 2] = ring_w2;
|
|
1271
|
+
weights[v4 + 3] = ring_w3;
|
|
1272
|
+
}
|
|
1196
1273
|
|
|
1197
1274
|
v_cursor++;
|
|
1198
1275
|
}
|
|
@@ -1253,7 +1330,7 @@ export function tree_mesh_build_bark(
|
|
|
1253
1330
|
w3: ring_w3
|
|
1254
1331
|
});
|
|
1255
1332
|
|
|
1256
|
-
if (prev_ring_start >= 0) {
|
|
1333
|
+
if (!only_rings && prev_ring_start >= 0) {
|
|
1257
1334
|
i_cursor = branch_ring_triangulate(
|
|
1258
1335
|
indices,
|
|
1259
1336
|
i_cursor,
|
|
@@ -1302,6 +1379,10 @@ export function tree_mesh_build_bark(
|
|
|
1302
1379
|
// living branch, a flat break on a dead stub
|
|
1303
1380
|
const apex_start = v_cursor;
|
|
1304
1381
|
const m_tip = prev_m;
|
|
1382
|
+
if (only_rings) {
|
|
1383
|
+
v_cursor += m_tip;
|
|
1384
|
+
continue;
|
|
1385
|
+
}
|
|
1305
1386
|
const apex_height = skeleton.branch_dead[b] ? 0.0 : SHOOT_BUD_HEIGHT;
|
|
1306
1387
|
const cap_ext = tip_r * apex_height;
|
|
1307
1388
|
const cap_arc_s = tip_arc_s + cap_ext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShootLightField.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/skeleton/ShootLightField.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ShootLightField.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/skeleton/ShootLightField.js"],"names":[],"mappings":"AAiEA;;;;;;GAMG;AACH;IAQI;;;;OAIG;IACH,iBAJW,UAAU,MAAM,CAAC,OACjB,UAAU,MAAM,CAAC,QACjB,MAAM,EAqBhB;IAjBG,aAAgB;IAChB,kBAAiC;IACjC,WAA0D;IAC1D,WAA0D;IAC1D,WAA0D;IAE1D;;;OAGG;IACH,WAFU,YAAY,CAEc;IACpC;;;OAGG;IACH,YAFU,YAAY,CAEuB;IAC7C,4BAAwC;IAG5C;;OAEG;IACH,cAeC;IAED;;;;;;OAMG;IACH,SALW,MAAM,KACN,MAAM,KACN,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;OAMG;IACH,WALW,MAAM,KACN,MAAM,KACN,MAAM,QACN,MAAM,QAgBhB;IAED;;;;;OAKG;IACH,mBAJW,UAAU,MAAM,CAAC,KACjB,UAAU,MAAM,CAAC,QACjB,MAAM,QAUhB;IAED;;;;OAIG;IACH,gBAFW,MAAM,QAuEhB;IAED;;;;;;;OAOG;IACH,iBALW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,KAClC,MAAM,KACN,MAAM,KACN,MAAM,QAiBhB;IAED;;;;;;OAMG;IACH,iBALW,MAAM,KACN,MAAM,KACN,MAAM,GACJ,MAAM,CAKlB;;CACJ"}
|
|
@@ -61,6 +61,8 @@ const SKY_WEIGHTS = (() => {
|
|
|
61
61
|
return w;
|
|
62
62
|
})();
|
|
63
63
|
|
|
64
|
+
const OPEN_SKY = SKY_WEIGHTS.reduce((s, w) => s + w, 0);
|
|
65
|
+
|
|
64
66
|
/**
|
|
65
67
|
* Light inside a crown from its own leaves: leaf area deposited in a voxel grid, and the relative irradiance each
|
|
66
68
|
* voxel receives from a standard overcast sky through the leaf area between it and the sky, by Beer-Lambert,
|
|
@@ -69,6 +71,13 @@ const SKY_WEIGHTS = (() => {
|
|
|
69
71
|
* The cost of {@link solve} is the grid's cells times its 17 sky directions, whatever the leaf count.
|
|
70
72
|
*/
|
|
71
73
|
export class ShootLightField {
|
|
74
|
+
#min_i = Infinity;
|
|
75
|
+
#max_i = -1;
|
|
76
|
+
#min_j = Infinity;
|
|
77
|
+
#max_j = -1;
|
|
78
|
+
#min_k = Infinity;
|
|
79
|
+
#max_k = -1;
|
|
80
|
+
|
|
72
81
|
/**
|
|
73
82
|
* @param {ArrayLike<number>} min world corner of the grid
|
|
74
83
|
* @param {ArrayLike<number>} max opposite corner
|
|
@@ -99,7 +108,20 @@ export class ShootLightField {
|
|
|
99
108
|
* Removes all leaf area.
|
|
100
109
|
*/
|
|
101
110
|
clear() {
|
|
102
|
-
this
|
|
111
|
+
if (this.#max_j < 0) return;
|
|
112
|
+
const { nx, nz, leaf_area } = this;
|
|
113
|
+
for (let j = this.#min_j; j <= this.#max_j; j++) {
|
|
114
|
+
for (let k = this.#min_k; k <= this.#max_k; k++) {
|
|
115
|
+
const row = (j * nz + k) * nx;
|
|
116
|
+
leaf_area.fill(0, row + this.#min_i, row + this.#max_i + 1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
this.#min_i = Infinity;
|
|
120
|
+
this.#max_i = -1;
|
|
121
|
+
this.#min_j = Infinity;
|
|
122
|
+
this.#max_j = -1;
|
|
123
|
+
this.#min_k = Infinity;
|
|
124
|
+
this.#max_k = -1;
|
|
103
125
|
}
|
|
104
126
|
|
|
105
127
|
/**
|
|
@@ -125,8 +147,19 @@ export class ShootLightField {
|
|
|
125
147
|
* @param {number} area
|
|
126
148
|
*/
|
|
127
149
|
deposit(x, y, z, area) {
|
|
128
|
-
const
|
|
129
|
-
|
|
150
|
+
const i = Math.floor((x - this.min[0]) / this.cell);
|
|
151
|
+
const j = Math.floor((y - this.min[1]) / this.cell);
|
|
152
|
+
const k = Math.floor((z - this.min[2]) / this.cell);
|
|
153
|
+
if (i < 0 || j < 0 || k < 0 || i >= this.nx || j >= this.ny || k >= this.nz) return;
|
|
154
|
+
this.leaf_area[(j * this.nz + k) * this.nx + i] += area;
|
|
155
|
+
if (area > 0) {
|
|
156
|
+
if (i < this.#min_i) this.#min_i = i;
|
|
157
|
+
if (i > this.#max_i) this.#max_i = i;
|
|
158
|
+
if (j < this.#min_j) this.#min_j = j;
|
|
159
|
+
if (j > this.#max_j) this.#max_j = j;
|
|
160
|
+
if (k < this.#min_k) this.#min_k = k;
|
|
161
|
+
if (k > this.#max_k) this.#max_k = k;
|
|
162
|
+
}
|
|
130
163
|
}
|
|
131
164
|
|
|
132
165
|
/**
|
|
@@ -151,33 +184,71 @@ export class ShootLightField {
|
|
|
151
184
|
* @param {number} clumping
|
|
152
185
|
*/
|
|
153
186
|
solve(clumping) {
|
|
154
|
-
const { nx,
|
|
155
|
-
const k_ext = SPHERICAL_LEAF_PROJECTION * clamp(clumping, 0, 1);
|
|
156
|
-
const volume = cell * cell * cell;
|
|
187
|
+
const { nx, nz, cell } = this;
|
|
157
188
|
const irradiance = this.irradiance;
|
|
158
189
|
const transmittance = this.transmittance;
|
|
159
190
|
const leaf_area = this.leaf_area;
|
|
160
|
-
|
|
191
|
+
const max_j = this.#max_j;
|
|
192
|
+
irradiance.fill(OPEN_SKY);
|
|
193
|
+
if (max_j < 0) return;
|
|
194
|
+
|
|
195
|
+
const min_i = this.#min_i, max_i = this.#max_i;
|
|
196
|
+
const min_k = this.#min_k, max_k = this.#max_k;
|
|
197
|
+
for (let j = max_j; j >= 0; j--) {
|
|
198
|
+
const fall = max_j - j;
|
|
199
|
+
const k0 = Math.max(0, min_k - 2 * fall), k1 = Math.min(nz - 1, max_k + 2 * fall);
|
|
200
|
+
const i0 = Math.max(0, min_i - 2 * fall), i1 = Math.min(nx - 1, max_i + 2 * fall);
|
|
201
|
+
for (let k = k0; k <= k1; k++) {
|
|
202
|
+
const row = (j * nz + k) * nx;
|
|
203
|
+
irradiance.fill(0, row + i0, row + i1 + 1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const k_ext = SPHERICAL_LEAF_PROJECTION * clamp(clumping, 0, 1);
|
|
208
|
+
const volume = cell * cell * cell;
|
|
161
209
|
for (let d = 0; d < SKY_DIRECTIONS.length; d++) {
|
|
162
210
|
const [dx, dy, dz] = SKY_DIRECTIONS[d];
|
|
163
211
|
const step = Math.hypot(dx, dy, dz) * cell;
|
|
164
212
|
const w = SKY_WEIGHTS[d];
|
|
165
213
|
// a voxel sees the sky through the voxel one step towards it, which was swept the row before
|
|
166
|
-
for (let j =
|
|
214
|
+
for (let j = max_j; j >= 0; j--) {
|
|
215
|
+
const fall = max_j - j;
|
|
216
|
+
const k0 = Math.max(0, min_k - 2 * fall), k1 = Math.min(nz - 1, max_k + 2 * fall);
|
|
217
|
+
const i0 = Math.max(0, min_i - 2 * fall), i1 = Math.min(nx - 1, max_i + 2 * fall);
|
|
218
|
+
const dk0 = dz < 0 ? min_k : Math.max(0, min_k - dz * fall);
|
|
219
|
+
const dk1 = dz > 0 ? max_k : Math.min(nz - 1, max_k - dz * fall);
|
|
220
|
+
const di0 = dx < 0 ? min_i : Math.max(0, min_i - dx * fall);
|
|
221
|
+
const di1 = dx > 0 ? max_i : Math.min(nx - 1, max_i - dx * fall);
|
|
222
|
+
const up_fall = fall - 1;
|
|
223
|
+
const uk0 = up_fall >= 0 ? (dz < 0 ? min_k : Math.max(0, min_k - dz * up_fall)) : nz;
|
|
224
|
+
const uk1 = up_fall >= 0 ? (dz > 0 ? max_k : Math.min(nz - 1, max_k - dz * up_fall)) : -1;
|
|
225
|
+
const ui0 = up_fall >= 0 ? (dx < 0 ? min_i : Math.max(0, min_i - dx * up_fall)) : nx;
|
|
226
|
+
const ui1 = up_fall >= 0 ? (dx > 0 ? max_i : Math.min(nx - 1, max_i - dx * up_fall)) : -1;
|
|
167
227
|
const j1 = j + dy;
|
|
168
|
-
for (let k =
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
228
|
+
for (let k = k0; k <= k1; k++) {
|
|
229
|
+
const row = (j * nz + k) * nx;
|
|
230
|
+
if (k < dk0 || k > dk1) {
|
|
231
|
+
for (let i = i0; i <= i1; i++) irradiance[row + i] += w;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
for (let i = i0; i < di0; i++) irradiance[row + i] += w;
|
|
235
|
+
const k1_idx = k + dz;
|
|
236
|
+
const k_in = k1_idx >= uk0 && k1_idx <= uk1;
|
|
237
|
+
const u_row = (j1 * nz + k1_idx) * nx;
|
|
238
|
+
for (let i = di0; i <= di1; i++) {
|
|
239
|
+
const i1_idx = i + dx;
|
|
240
|
+
const v = row + i;
|
|
173
241
|
let t = 1.0;
|
|
174
|
-
if (
|
|
175
|
-
const u =
|
|
176
|
-
|
|
242
|
+
if (k_in && i1_idx >= ui0 && i1_idx <= ui1) {
|
|
243
|
+
const u = u_row + i1_idx;
|
|
244
|
+
const lu = leaf_area[u];
|
|
245
|
+
t = lu > 0 ? transmittance[u] * Math.exp(-k_ext * (lu / volume) * step) : transmittance[u];
|
|
177
246
|
}
|
|
178
247
|
transmittance[v] = t;
|
|
179
|
-
|
|
248
|
+
const lv = leaf_area[v];
|
|
249
|
+
irradiance[v] += lv > 0 ? w * t * Math.exp(-k_ext * (lv / volume) * step * 0.5) : w * t;
|
|
180
250
|
}
|
|
251
|
+
for (let i = di1 + 1; i <= i1; i++) irradiance[row + i] += w;
|
|
181
252
|
}
|
|
182
253
|
}
|
|
183
254
|
}
|
|
@@ -26,8 +26,10 @@ export class ShootWoodHash {
|
|
|
26
26
|
radii: number[];
|
|
27
27
|
units: number[];
|
|
28
28
|
}>);
|
|
29
|
-
/** @type {Map<number, number[]>} */
|
|
30
|
-
cells: Map<number, number[]
|
|
29
|
+
/** @type {Map<number, number[] & {max?: number}>} */
|
|
30
|
+
cells: Map<number, number[] & {
|
|
31
|
+
max?: number;
|
|
32
|
+
}>;
|
|
31
33
|
/**
|
|
32
34
|
* Thickest living unit (m) in each cell as of the last {@link refresh}, a unit added since counting as infinitely
|
|
33
35
|
* thick, so a query that wants only wood at least so thick can pass a cell by.
|
|
@@ -86,5 +88,6 @@ export class ShootWoodHash {
|
|
|
86
88
|
* @returns {number}
|
|
87
89
|
*/
|
|
88
90
|
hits(a: ArrayLike<number>, b: ArrayLike<number>, radius: number, min_radius: number, skip: (arg0: number, arg1: number, arg2: number, arg3: number) => boolean): number;
|
|
91
|
+
#private;
|
|
89
92
|
}
|
|
90
93
|
//# sourceMappingURL=ShootWoodHash.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShootWoodHash.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/skeleton/ShootWoodHash.js"],"names":[],"mappings":"AAiCA;;;;;;GAMG;AACH;
|
|
1
|
+
{"version":3,"file":"ShootWoodHash.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/skeleton/ShootWoodHash.js"],"names":[],"mappings":"AAiCA;;;;;;GAMG;AACH;IA0LI;;;;;;OAMG;IACH,uBALW;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAC,KAClC,MAAM,KACN,MAAM,GACJ,MAAM,CAMlB;IAvHD;;OAEG;IACH,kBAFW,MAAM;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAC,CAAC,EAIrF;IAlFD,qDAAqD;IACrD,OADW,IAAI,MAAM,EAAE,MAAM,EAAE,GAAG;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAC/B;IAElB;;;;OAIG;IACH,UAFU,IAAI,MAAM,EAAE,MAAM,CAAC,CAER;IAErB;;;OAGG;IACH,YAFU,MAAM,CAED;IAEf;;;OAGG;IACH,WAFU,MAAM,EAAE,CAEH;IAEf;;;OAGG;IACH,YAFU,MAAM,EAAE,CAEF;IAEhB;;;OAGG;IACH,MAFU,MAAM,EAAE,CAER;IAEV,cAAU;IA+CN;eAHqB,OAAO;gBAAU,MAAM,EAAE;eAAS,MAAM,EAAE;eAAS,MAAM,EAAE;QAGhE;IAGpB;;;;OAIG;IACH,OAHW,MAAM,KACN,MAAM,QA8ChB;IAED;;;;OAIG;IACH,gBA2CC;IAeD;;;;;;;;;;;OAWG;IACH,QAPW,UAAU,MAAM,CAAC,KACjB,UAAU,MAAM,CAAC,UACjB,MAAM,cACN,MAAM,eACG,MAAM,QAAE,MAAM,QAAE,MAAM,QAAE,MAAM,KAAG,OAAO,GAC/C,MAAM,CAqIlB;;CACJ"}
|