@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.
Files changed (114) hide show
  1. package/package.json +1 -1
  2. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -0
  3. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  4. package/src/engine/network/sim/SimActionExecutor.js +4 -0
  5. package/src/generation/foliage/material/foliage_atlas_cutout.d.ts.map +1 -1
  6. package/src/generation/foliage/material/foliage_atlas_cutout.js +21 -5
  7. package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts +8 -0
  8. package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts.map +1 -1
  9. package/src/generation/foliage/mesh/tree_cluster_representatives.js +178 -78
  10. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
  11. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +178 -97
  12. package/src/generation/foliage/skeleton/ShootLightField.d.ts +1 -0
  13. package/src/generation/foliage/skeleton/ShootLightField.d.ts.map +1 -1
  14. package/src/generation/foliage/skeleton/ShootLightField.js +88 -17
  15. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +5 -2
  16. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
  17. package/src/generation/foliage/skeleton/ShootWoodHash.js +191 -25
  18. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  19. package/src/shade/playground/probe_clipmap/main.js +4 -0
  20. package/src/shade/playground/probe_clipmap_box/README.md +55 -0
  21. package/src/shade/playground/probe_clipmap_box/index.html +185 -0
  22. package/src/shade/playground/probe_clipmap_box/main.d.ts +8 -0
  23. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -0
  24. package/src/shade/playground/probe_clipmap_box/main.js +323 -0
  25. package/src/shade/playground/probe_clipmap_box/scene.d.ts +93 -0
  26. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -0
  27. package/src/shade/playground/probe_clipmap_box/scene.js +256 -0
  28. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  29. package/src/shade/renderer/Renderer.js +6 -1
  30. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts +12 -0
  31. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts.map +1 -1
  32. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.js +49 -24
  33. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts +12 -0
  34. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts.map +1 -1
  35. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.js +50 -19
  36. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.d.ts.map +1 -1
  37. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.js +6 -2
  38. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +5 -1
  39. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  40. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +7 -3
  41. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +6 -4
  42. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  43. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +10 -9
  44. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +12 -0
  45. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  46. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +14 -0
  47. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +17 -22
  48. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  49. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +53 -65
  50. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts +2 -3
  51. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts.map +1 -1
  52. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +9 -20
  53. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +2 -2
  54. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  55. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +14 -19
  56. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +1 -1
  57. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  58. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +8 -4
  59. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +1 -1
  60. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts +2 -1
  61. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts.map +1 -1
  62. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.js +13 -18
  63. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts +1 -1
  64. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts.map +1 -1
  65. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.js +4 -2
  66. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.d.ts.map +1 -1
  67. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.js +4 -6
  68. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts.map +1 -1
  69. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.js +4 -7
  70. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +4 -3
  71. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  72. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +14 -13
  73. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +3 -4
  74. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  75. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +7 -15
  76. package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -1
  77. package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +5 -1
  78. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +26 -8
  79. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  80. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +170 -142
  81. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts +1 -1
  82. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts.map +1 -1
  83. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.js +5 -8
  84. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +15 -4
  85. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -1
  86. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +33 -7
  87. package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts +40 -0
  88. package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts.map +1 -0
  89. package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.js +75 -0
  90. package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.d.ts.map +1 -1
  91. package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.js +3 -1
  92. package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts +28 -0
  93. package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts.map +1 -0
  94. package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.js +41 -0
  95. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts +12 -0
  96. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts.map +1 -0
  97. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.js +24 -0
  98. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +3 -2
  99. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -1
  100. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +4 -0
  101. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +2 -5
  102. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -1
  103. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +3 -20
  104. package/src/shade/renderer/water/chunk_water_gi.d.ts +1 -1
  105. package/src/shade/renderer/water/chunk_water_gi.d.ts.map +1 -1
  106. package/src/shade/renderer/water/chunk_water_gi.js +6 -8
  107. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  108. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +76 -32
  109. package/src/core/math/hash/squirrel3.d.ts +0 -17
  110. package/src/core/math/hash/squirrel3.d.ts.map +0 -1
  111. package/src/core/math/hash/squirrel3.js +0 -30
  112. package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts +0 -12
  113. package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts.map +0 -1
  114. package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.js +0 -30
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Advanced 3D game engine",
7
7
  "type": "module",
8
8
  "author": "Alexander Goldring",
9
- "version": "3.61.1",
9
+ "version": "3.61.2",
10
10
  "exports": {
11
11
  "./build/*": "./build/*",
12
12
  "./src/*": "./src/*",
@@ -224,6 +224,10 @@ export class SimActionExecutor {
224
224
  /**
225
225
  * Execute an action: capture prior state of affected components, apply, log.
226
226
  *
227
+ * Not re-entrant: calling `execute` or {@link record} from inside `affected_components`,
228
+ * {@link authorize}, `apply`, `announce` or {@link on_component_written} is illegal (the
229
+ * executor is passed to actions for `slot_table` / `current_sender_id` reads only).
230
+ *
227
231
  * @param {SimAction} action
228
232
  * @param {number} [sender_id] peer that originated this action.
229
233
  * Defaults to {@link SENDER_LOCAL} for locally-originated actions.
@@ -1 +1 @@
1
- {"version":3,"file":"SimActionExecutor.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/sim/SimActionExecutor.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,2BAFU,MAAM,CAEiB;AAEjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,6BAFU,MAAM,CAEmB;AAEnC;;;;;;;;;;GAUG;AACH,8BAFU,MAAM,CAEoB;AAEpC;;;;;;;;;;;;GAYG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;GAMG;AACH,0BAFU,MAAM,CAEgB;AAEhC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IA2EI;;;;;;;;;OASG;IACH,sGATW;QACV,KAAS,yBAAyB;QAClC,UAAc,YAAY;QAC1B,eAAmB,oBAAoB;QACvC,kBAAsB,8BAA8B;QACpD,UAAc,uBAAuB;QACrC,gBAAoB,CAAC,mBAAmB;KACrC,EAyFH;IAjKD;;;;;;;;;OASG;IACH,gBAFU,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEP;IAEtB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,KAAK,OAAO,CAAC,GAAG,IAAI,CAEtE;IAEjB;;;;;;;;;;;;;;;OAeG;IACH,UAFU,OAAO,CAEA;IAEjB;;;;;;;OAOG;IACH,sBAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAE7C;IAaxB;;OAEG;IACH,8BAAkB;IAElB;;OAEG;IACH,sBAA4B;IAE5B;;OAEG;IACH,mCAAsC;IAEtC;;OAEG;IACH,gDAA4C;IAE5C;;;;OAIG;IACH,iCAA4B;IAE5B;;;;;;;;;;;OAWG;IACH,kBAFU,mBAAiB,IAAI,CAES;IA4BxC;;;;;;;OAOG;IACH,mBAFU,MAAM,CAEqB;IAErC;;;;;;;OAOG;IACH,kBAFU,MAAM,CAEoB;IAGxC;;;;;;;;;;OAUG;IACH,uCAPW,MAAM,GAGJ,OAAO,CA0KnB;IAkCD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gCAwCC;IAED;;;;;;;;;;;;;OAaG;IACH,4BAFW,MAAM,QAqChB;IAED;;;;;;;;OAQG;IACH,sBAJW,UAAU,UACV,MAAM,UACN,MAAM,QAchB;;CACJ;mBA7mBkB,uCAAuC"}
1
+ {"version":3,"file":"SimActionExecutor.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/sim/SimActionExecutor.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,2BAFU,MAAM,CAEiB;AAEjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,6BAFU,MAAM,CAEmB;AAEnC;;;;;;;;;;GAUG;AACH,8BAFU,MAAM,CAEoB;AAEpC;;;;;;;;;;;;GAYG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;GAMG;AACH,0BAFU,MAAM,CAEgB;AAEhC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IA2EI;;;;;;;;;OASG;IACH,sGATW;QACV,KAAS,yBAAyB;QAClC,UAAc,YAAY;QAC1B,eAAmB,oBAAoB;QACvC,kBAAsB,8BAA8B;QACpD,UAAc,uBAAuB;QACrC,gBAAoB,CAAC,mBAAmB;KACrC,EAyFH;IAjKD;;;;;;;;;OASG;IACH,gBAFU,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEP;IAEtB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,KAAK,OAAO,CAAC,GAAG,IAAI,CAEtE;IAEjB;;;;;;;;;;;;;;;OAeG;IACH,UAFU,OAAO,CAEA;IAEjB;;;;;;;OAOG;IACH,sBAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAE7C;IAaxB;;OAEG;IACH,8BAAkB;IAElB;;OAEG;IACH,sBAA4B;IAE5B;;OAEG;IACH,mCAAsC;IAEtC;;OAEG;IACH,gDAA4C;IAE5C;;;;OAIG;IACH,iCAA4B;IAE5B;;;;;;;;;;;OAWG;IACH,kBAFU,mBAAiB,IAAI,CAES;IA4BxC;;;;;;;OAOG;IACH,mBAFU,MAAM,CAEqB;IAErC;;;;;;;OAOG;IACH,kBAFU,MAAM,CAEoB;IAGxC;;;;;;;;;;;;;;OAcG;IACH,uCAPW,MAAM,GAGJ,OAAO,CA0KnB;IAkCD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gCAwCC;IAED;;;;;;;;;;;;;OAaG;IACH,4BAFW,MAAM,QAqChB;IAED;;;;;;;;OAQG;IACH,sBAJW,UAAU,UACV,MAAM,UACN,MAAM,QAchB;;CACJ;mBAjnBkB,uCAAuC"}
@@ -274,6 +274,10 @@ export class SimActionExecutor {
274
274
  /**
275
275
  * Execute an action: capture prior state of affected components, apply, log.
276
276
  *
277
+ * Not re-entrant: calling `execute` or {@link record} from inside `affected_components`,
278
+ * {@link authorize}, `apply`, `announce` or {@link on_component_written} is illegal (the
279
+ * executor is passed to actions for `slot_table` / `current_sender_id` reads only).
280
+ *
277
281
  * @param {SimAction} action
278
282
  * @param {number} [sender_id] peer that originated this action.
279
283
  * Defaults to {@link SENDER_LOCAL} for locally-originated actions.
@@ -1 +1 @@
1
- {"version":3,"file":"foliage_atlas_cutout.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/material/foliage_atlas_cutout.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;GAYG;AACH,mDARW,kBAAkB,WAClB,MAAM,WACN,UAAU,WACV,UAAU,gBACV,MAAM,SACN,MAAM,WACN,MAAM,QAiHhB;AAED;;;;;;;;GAQG;AACH,oDANW,kBAAkB,WAClB,MAAM,SACN,YAAY,SACZ,MAAM,WACN,MAAM,QAkBhB;AAED;;;;;;;;GAQG;AACH,8CAJW,OAAO,gCAAgC,EAAE,iBAAiB,QAC1D,kBAAkB,GAChB,kBAAkB,CAU9B;mCA7K4D,yBAAyB"}
1
+ {"version":3,"file":"foliage_atlas_cutout.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/material/foliage_atlas_cutout.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;GAYG;AACH,mDARW,kBAAkB,WAClB,MAAM,WACN,UAAU,WACV,UAAU,gBACV,MAAM,SACN,MAAM,WACN,MAAM,QAiHhB;AAED;;;;;;;;GAQG;AACH,oDANW,kBAAkB,WAClB,MAAM,SACN,YAAY,SACZ,MAAM,WACN,MAAM,QAkBhB;AAED;;;;;;;;GAQG;AACH,8CAJW,OAAO,gCAAgC,EAAE,iBAAiB,QAC1D,kBAAkB,GAChB,kBAAkB,CAqB9B;mCA3L4D,yBAAyB"}
@@ -1,11 +1,16 @@
1
+ import { HashMap } from "../../../core/collection/map/HashMap.js";
1
2
  import { convex_hull_fixed_count_2d_relaxation } from "../../../core/geom/2d/convex-hull/convex_hull_fixed_count_2d_relaxation.js";
2
3
  import { convex_hull_monotone_2d } from "../../../core/geom/2d/convex-hull/convex_hull_monotone_2d.js";
3
4
  import { polygon2_clip_axis_halfplane } from "../../../core/geom/2d/polygon/polygon2_clip_axis_halfplane.js";
4
5
  import { polygon2_is_counter_clockwise } from "../../../core/geom/2d/polygon/polygon2_is_counter_clockwise.js";
5
6
  import { clamp } from "../../../core/math/clamp.js";
7
+ import { TreeSpeciesConfig } from "../config/TreeSpeciesConfig.js";
6
8
  import { CUTOUT_HULL_VERTEX_COUNT, FoliageAtlasCutout } from "./FoliageAtlasCutout.js";
7
9
  import { foliage_tile_layout, foliage_tile_raster } from "./foliage_tile.js";
8
10
 
11
+ /** @type {HashMap<TreeSpeciesConfig, FoliageAtlasCutout>} */
12
+ const CUTOUT_CACHE = new HashMap();
13
+
9
14
  /**
10
15
  * Fits one tile's hull from the texel rows its silhouette covers. Each covered row contributes the outer corners of
11
16
  * its first and last covered texel, so the hull holds every texel with any coverage at all: no alpha threshold, and
@@ -169,11 +174,22 @@ export function foliage_atlas_cutout_fit_alpha(out, variant, alpha, width, heigh
169
174
  * @returns {FoliageAtlasCutout}
170
175
  */
171
176
  export function foliage_atlas_cutout(species, out = new FoliageAtlasCutout()) {
172
- const layout = foliage_tile_layout(species);
173
- out.resize(layout.variant_count);
174
- for (let v = 0; v < layout.variant_count; v++) {
175
- const raster = foliage_tile_raster(species, layout, v, true);
176
- foliage_atlas_cutout_fit_alpha(out, v, raster.alpha, layout.resolution);
177
+ const key = new TreeSpeciesConfig();
178
+ key.seed = 0;
179
+ key.foliage.copy(species.foliage);
180
+ key.foliage_material.copy(species.foliage_material);
181
+ let cached = CUTOUT_CACHE.get(key);
182
+ if (cached === undefined) {
183
+ const layout = foliage_tile_layout(key);
184
+ cached = new FoliageAtlasCutout().resize(layout.variant_count);
185
+ for (let v = 0; v < layout.variant_count; v++) {
186
+ const raster = foliage_tile_raster(key, layout, v, true);
187
+ foliage_atlas_cutout_fit_alpha(cached, v, raster.alpha, layout.resolution);
188
+ }
189
+ CUTOUT_CACHE.set(key, cached);
177
190
  }
191
+ out.resize(cached.variant_count);
192
+ out.hulls.set(cached.hulls);
193
+ out.coverage.set(cached.coverage);
178
194
  return out;
179
195
  }
@@ -81,6 +81,14 @@ export type CutShape = {
81
81
  * its tile's, at its LOD's texel
82
82
  */
83
83
  bytes: number;
84
+ /**
85
+ * its tile's width in texels
86
+ */
87
+ tw: number;
88
+ /**
89
+ * its tile's height in texels
90
+ */
91
+ th: number;
84
92
  };
85
93
  /**
86
94
  * One LOD's cluster cards, and the error it is drawn to.
@@ -1 +1 @@
1
- {"version":3,"file":"tree_cluster_representatives.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/mesh/tree_cluster_representatives.js"],"names":[],"mappings":"AA4CA;;;;;;;GAOG;AAEH;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,uDATW,OAAO,6BAA6B,EAAE,YAAY,eAClD,OAAO,kCAAkC,EAAE,oBAAoB,UAC/D,OAAO,8CAA8C,EAAE,QAAQ,QAC/D,cAAc,EAAE,cAChB,MAAM,iBACN,MAAM,UACN,MAAM,GACJ,0BAA0B,CActC;;;;;SAxFa,MAAM;;;;UACN,MAAM;;;;;UACN,MAAM;cAEN,MAAM;;;;cACN,MAAM;;;;iBACN,MAAM;;;;YACN,MAAM;YACN,MAAM;;;;WACN,MAAM;;;;;;cAmBN,OAAO,oBAAoB,EAAE,WAAW,EAAE;WAC1C,OAAO,yBAAyB,EAAE,eAAe,EAAE;;;;WACnD,MAAM;;;;;;;;;WAON,OAAO,yBAAyB,EAAE,eAAe,EAAE;;;;YACnD,YAAY;;;;aACZ,MAAM,EAAE,EAAE;;;;;;gBACV,MAAM;QAAC,GAAG,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAC,CAAC"}
1
+ {"version":3,"file":"tree_cluster_representatives.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/mesh/tree_cluster_representatives.js"],"names":[],"mappings":"AA6CA;;;;;;;GAOG;AAEH;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,uDATW,OAAO,6BAA6B,EAAE,YAAY,eAClD,OAAO,kCAAkC,EAAE,oBAAoB,UAC/D,OAAO,8CAA8C,EAAE,QAAQ,QAC/D,cAAc,EAAE,cAChB,MAAM,iBACN,MAAM,UACN,MAAM,GACJ,0BAA0B,CAoHtC;;;;;SAhMa,MAAM;;;;UACN,MAAM;;;;;UACN,MAAM;cAEN,MAAM;;;;cACN,MAAM;;;;iBACN,MAAM;;;;YACN,MAAM;YACN,MAAM;;;;WACN,MAAM;;;;QACN,MAAM;;;;QACN,MAAM;;;;;;cAmBN,OAAO,oBAAoB,EAAE,WAAW,EAAE;WAC1C,OAAO,yBAAyB,EAAE,eAAe,EAAE;;;;WACnD,MAAM;;;;;;;;;WAON,OAAO,yBAAyB,EAAE,eAAe,EAAE;;;;YACnD,YAAY;;;;aACZ,MAAM,EAAE,EAAE;;;;;;gBACV,MAAM;QAAC,GAAG,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAC,CAAC"}
@@ -1,7 +1,6 @@
1
1
  import { assert } from "../../../core/assert.js";
2
2
  import { tree_cluster_atlas_pack } from "../material/tree_cluster_atlas_pack.js";
3
3
  import { tree_cluster_press } from "../material/tree_cluster_press.js";
4
- import { tree_cluster_tiles } from "../material/tree_cluster_tiles.js";
5
4
  import { foliage_scale_spread } from "./foliage_scale_spread.js";
6
5
 
7
6
  /**
@@ -28,6 +27,8 @@ const SCRATCH_B = new Float32Array(3);
28
27
  * @property {number} hang_u where it hangs, on its plane along its tile's u, m from its origin
29
28
  * @property {number} hang_v
30
29
  * @property {number} bytes its tile's, at its LOD's texel
30
+ * @property {number} tw its tile's width in texels
31
+ * @property {number} th its tile's height in texels
31
32
  */
32
33
 
33
34
  /**
@@ -99,52 +100,78 @@ export function tree_cluster_representatives(skeleton, attachments, leaves, lods
99
100
  assert.greaterThan(fine_texel, 0, 'fine_texel');
100
101
  assert.greaterThan(legible_texel, 0, 'legible_texel');
101
102
 
102
- // every cut's leaves pressed onto it, whatever the texel
103
+ // every cut's leaves pressed onto it, whatever the texel, and its frame, unpadded extent, shown area and hang
103
104
  const pressed_lods = lods.map(lod => tree_cluster_press(leaves, attachments, lod.cards));
104
- // Ends: a cut's size is never under a texel, so once a texel is as large as every cut, one tile draws them all
105
- for (let texel = Math.min(fine_texel, legible_texel); ; texel = texel < legible_texel ? Math.min(2 * texel, legible_texel) : 2 * texel) {
106
- const representatives = choose(skeleton, attachments, leaves, lods, pressed_lods, texel, budget);
107
- if (representatives !== null) return representatives;
108
- }
109
- }
110
-
111
- /**
112
- * The representatives at LOD0's texel `leaf_texel` (`tree_cluster_representatives`), or `null` when the atlas cannot
113
- * hold tiles that draw every cut at a size the tree grows.
114
- *
115
- * @returns {TreeClusterRepresentatives|null}
116
- */
117
- function choose(skeleton, attachments, leaves, lods, pressed_lods, leaf_texel, budget) {
118
-
119
- // ---- every cut's shape and tile, at its LOD's texel
120
- const lod_texels = lods.map((lod, k) => k === 0 ? leaf_texel : Math.max(leaf_texel, lods[k - 1].error));
121
- /** @type {CutShape[]} */
122
- const shapes = [];
123
- const lod_first = [];
124
- const lod_tiles = [];
125
- for (let k = 0; k < lods.length; k++) {
126
- const { clusters, cards } = lods[k];
127
- lod_first.push(shapes.length);
105
+ const index = leaves.index.data;
106
+ const tris_per_leaf = index.length / 3 / attachments.count;
107
+ const nodes = [], edges = [];
108
+ const lod_geom = lods.map(({ clusters, cards }, k) => {
128
109
  const pressed = pressed_lods[k];
129
- const texel = lod_texels[k];
130
- const tiles = tree_cluster_tiles(skeleton, cards, pressed, cards.map(() => texel));
131
- lod_tiles.push(tiles);
132
110
  const P = pressed.positions;
133
- const nodes = [], edges = [];
134
- const index = leaves.index.data;
135
- const tris_per_leaf = index.length / 3 / attachments.count;
136
- for (let i = 0; i < cards.length; i++) {
111
+ const verts_per_leaf = pressed.verts_per_leaf;
112
+ const count = cards.length;
113
+ const frames = new Float64Array(count * 12);
114
+ const bounds = new Float64Array(count * 4);
115
+ const areas = new Float64Array(count);
116
+ const hang_u = new Float64Array(count);
117
+ const hang_v = new Float64Array(count);
118
+ for (let i = 0; i < count; i++) {
137
119
  const card = cards[i];
120
+ const ox = card.origin[0], oy = card.origin[1], oz = card.origin[2];
121
+ const nx = card.normal[0], ny = card.normal[1], nz = card.normal[2];
122
+ const e1x = card.axis[0], e1y = card.axis[1], e1z = card.axis[2];
123
+ const e2x = ny * e1z - nz * e1y, e2y = nz * e1x - nx * e1z, e2z = nx * e1y - ny * e1x;
138
124
  const f = i * 12;
139
- const w = tiles.extents[i * 4 + 2] - tiles.extents[i * 4] - 2 * texel;
140
- const h = tiles.extents[i * 4 + 3] - tiles.extents[i * 4 + 1] - 2 * texel;
141
- const span = Math.max(texel * texel, w * h);
125
+ frames[f] = ox;
126
+ frames[f + 1] = oy;
127
+ frames[f + 2] = oz;
128
+ frames[f + 3] = e1x;
129
+ frames[f + 4] = e1y;
130
+ frames[f + 5] = e1z;
131
+ frames[f + 6] = e2x;
132
+ frames[f + 7] = e2y;
133
+ frames[f + 8] = e2z;
134
+ frames[f + 9] = nx;
135
+ frames[f + 10] = ny;
136
+ frames[f + 11] = nz;
137
+
138
+ let min1 = Infinity, max1 = -Infinity, min2 = Infinity, max2 = -Infinity;
139
+ for (let v = pressed.first[i] * verts_per_leaf; v < pressed.first[i + 1] * verts_per_leaf; v++) {
140
+ const x = P[v * 3], y = P[v * 3 + 1], z = P[v * 3 + 2];
141
+ const a = (x - ox) * e1x + (y - oy) * e1y + (z - oz) * e1z;
142
+ const b = (x - ox) * e2x + (y - oy) * e2y + (z - oz) * e2z;
143
+ if (a < min1) min1 = a;
144
+ if (a > max1) max1 = a;
145
+ if (b < min2) min2 = b;
146
+ if (b > max2) max2 = b;
147
+ }
148
+ for (let s2 = 0; s2 < card.segments.length; s2 += 2) {
149
+ skeleton.collect_branch_chain(card.segments[s2], nodes, edges);
150
+ for (const v of [nodes[card.segments[s2 + 1]], nodes[card.segments[s2 + 1] + 1]]) {
151
+ skeleton.node_read_position(SCRATCH_A, 0, v);
152
+ const pad = skeleton.node_read_radius(v);
153
+ const a = (SCRATCH_A[0] - ox) * e1x + (SCRATCH_A[1] - oy) * e1y + (SCRATCH_A[2] - oz) * e1z;
154
+ const b = (SCRATCH_A[0] - ox) * e2x + (SCRATCH_A[1] - oy) * e2y + (SCRATCH_A[2] - oz) * e2z;
155
+ if (a - pad < min1) min1 = a - pad;
156
+ if (a + pad > max1) max1 = a + pad;
157
+ if (b - pad < min2) min2 = b - pad;
158
+ if (b + pad > max2) max2 = b + pad;
159
+ }
160
+ }
161
+ if (!(max1 >= min1)) {
162
+ min1 = max1 = min2 = max2 = 0;
163
+ }
164
+ bounds[i * 4] = min1;
165
+ bounds[i * 4 + 1] = min2;
166
+ bounds[i * 4 + 2] = max1;
167
+ bounds[i * 4 + 3] = max2;
168
+
142
169
  // pressed flat, a leaf's triangles show their whole area
143
170
  let area = 0;
144
171
  for (let j = 0; j < card.leaves.length; j++) {
145
172
  const c = card.leaves[j];
146
173
  // from the leaf's vertices to the card's pressed copy's
147
- const shift = (pressed.first[i] + j - c) * pressed.verts_per_leaf;
174
+ const shift = (pressed.first[i] + j - c) * verts_per_leaf;
148
175
  for (let t = c * tris_per_leaf; t < (c + 1) * tris_per_leaf; t++) {
149
176
  const i0 = (index[t * 3] + shift) * 3, i1 = (index[t * 3 + 1] + shift) * 3, i2 = (index[t * 3 + 2] + shift) * 3;
150
177
  const ax = P[i1] - P[i0], ay = P[i1 + 1] - P[i0 + 1], az = P[i1 + 2] - P[i0 + 2];
@@ -153,40 +180,82 @@ function choose(skeleton, attachments, leaves, lods, pressed_lods, leaf_texel, b
153
180
  }
154
181
  }
155
182
  // a twig shows its length on the plane by its diameter
156
- const n = card.normal;
157
183
  for (let s2 = 0; s2 < card.segments.length; s2 += 2) {
158
184
  skeleton.collect_branch_chain(card.segments[s2], nodes, edges);
159
185
  const va = nodes[card.segments[s2 + 1]], vb = nodes[card.segments[s2 + 1] + 1];
160
186
  skeleton.node_read_position(SCRATCH_A, 0, va);
161
187
  skeleton.node_read_position(SCRATCH_B, 0, vb);
162
188
  const ex = SCRATCH_B[0] - SCRATCH_A[0], ey = SCRATCH_B[1] - SCRATCH_A[1], ez = SCRATCH_B[2] - SCRATCH_A[2];
163
- const along = ex * n[0] + ey * n[1] + ez * n[2];
164
- const shown = Math.hypot(ex - along * n[0], ey - along * n[1], ez - along * n[2]);
189
+ const along = ex * nx + ey * ny + ez * nz;
190
+ const shown = Math.hypot(ex - along * nx, ey - along * ny, ez - along * nz);
165
191
  area += shown * (skeleton.node_read_radius(va) + skeleton.node_read_radius(vb));
166
192
  }
167
- const size = Math.sqrt(Math.max(texel * texel, area));
193
+ areas[i] = area;
194
+
168
195
  const H = clusters[card.cluster].position;
169
- const dx = H[0] - tiles.frames[f], dy = H[1] - tiles.frames[f + 1], dz = H[2] - tiles.frames[f + 2];
170
- const hang_u = dx * tiles.frames[f + 3] + dy * tiles.frames[f + 4] + dz * tiles.frames[f + 5];
171
- const hang_v = dx * tiles.frames[f + 6] + dy * tiles.frames[f + 7] + dz * tiles.frames[f + 8];
196
+ const dx = H[0] - ox, dy = H[1] - oy, dz = H[2] - oz;
197
+ hang_u[i] = dx * e1x + dy * e1y + dz * e1z;
198
+ hang_v[i] = dx * e2x + dy * e2y + dz * e2z;
199
+ }
200
+ return { frames, bounds, areas, hang_u, hang_v };
201
+ });
202
+
203
+ const spread = foliage_scale_spread(attachments.scales, attachments.scales.length);
204
+ const shrink = Math.log(spread.low);
205
+ const grow = Math.log(spread.high);
206
+
207
+ // Ends: a cut's size is never under a texel, so once a texel is as large as every cut, one tile draws them all
208
+ for (let texel = Math.min(fine_texel, legible_texel); ; texel = texel < legible_texel ? Math.min(2 * texel, legible_texel) : 2 * texel) {
209
+ const representatives = choose(lods, lod_geom, shrink, grow, texel, budget);
210
+ if (representatives !== null) return representatives;
211
+ }
212
+ }
213
+
214
+ /**
215
+ * The representatives at LOD0's texel `leaf_texel` (`tree_cluster_representatives`), or `null` when the atlas cannot
216
+ * hold tiles that draw every cut at a size the tree grows.
217
+ *
218
+ * @returns {TreeClusterRepresentatives|null}
219
+ */
220
+ function choose(lods, lod_geom, shrink, grow, leaf_texel, budget) {
221
+
222
+ // ---- every cut's shape and tile, at its LOD's texel
223
+ const lod_texels = lods.map((lod, k) => k === 0 ? leaf_texel : Math.max(leaf_texel, lods[k - 1].error));
224
+ /** @type {CutShape[]} */
225
+ const shapes = [];
226
+ const lod_first = [];
227
+ for (let k = 0; k < lods.length; k++) {
228
+ const { cards } = lods[k];
229
+ lod_first.push(shapes.length);
230
+ const texel = lod_texels[k];
231
+ const { bounds, areas, hang_u, hang_v } = lod_geom[k];
232
+ for (let i = 0; i < cards.length; i++) {
233
+ const min1 = bounds[i * 4], min2 = bounds[i * 4 + 1], max1 = bounds[i * 4 + 2], max2 = bounds[i * 4 + 3];
234
+ const tw = Math.ceil((max1 - min1) / texel) + 2;
235
+ const th = Math.ceil((max2 - min2) / texel) + 2;
236
+ const w = (min1 - texel + tw * texel) - (min1 - texel) - 2 * texel;
237
+ const h = (min2 - texel + th * texel) - (min2 - texel) - 2 * texel;
238
+ const span = Math.max(texel * texel, w * h);
239
+ const area = areas[i];
240
+ const size = Math.sqrt(Math.max(texel * texel, area));
241
+ const hu = hang_u[i], hv = hang_v[i];
172
242
  shapes.push({
173
243
  lod: k,
174
244
  card: i,
175
245
  size,
176
246
  log_size: Math.log(size),
177
247
  coverage: area / span,
178
- hang_offset: Math.hypot(hang_u, hang_v) / Math.sqrt(span),
179
- hang_u,
180
- hang_v,
181
- bytes: tiles.sizes[i * 2] * tiles.sizes[i * 2 + 1] * CLUSTER_TEXEL_BYTES
248
+ hang_offset: Math.hypot(hu, hv) / Math.sqrt(span),
249
+ hang_u: hu,
250
+ hang_v: hv,
251
+ bytes: tw * th * CLUSTER_TEXEL_BYTES,
252
+ tw,
253
+ th
182
254
  });
183
255
  }
184
256
  }
185
257
 
186
258
  // ---- the fewest representatives that draw every cut at a size the tree's own leaves grow to, while the atlas fits
187
- const spread = foliage_scale_spread(attachments.scales, attachments.scales.length);
188
- const shrink = Math.log(spread.low);
189
- const grow = Math.log(spread.high);
190
259
  // whether representative `r` draws cut `c` as the tree would grow it: no finer LOD's cut, its leaves magnified
191
260
  // within their own spread
192
261
  const draws = (c, r) => {
@@ -233,40 +302,60 @@ function choose(skeleton, attachments, leaves, lods, pressed_lods, leaf_texel, b
233
302
  }
234
303
  return lo;
235
304
  };
305
+ const from_ranks = new Int32Array(n);
306
+ const to_ranks = new Int32Array(n);
307
+ for (let r = 0; r < n; r++) {
308
+ from_ranks[r] = first_rank(shapes[r].log_size, shrink, false);
309
+ to_ranks[r] = first_rank(shapes[r].log_size, grow, true);
310
+ }
236
311
  const counts = new Int32Array(n);
237
312
  const window = new Int32Array(n);
313
+ const unlikes = new Float64Array(n).fill(NaN);
314
+ let counts_dirty = true;
238
315
  while (undrawn > 0) {
239
316
  // the one that draws the most cuts not yet drawn, the least unlike them where several do
240
317
  let pick_count = 0;
241
- for (let r = 0; r < n; r++) {
242
- counts[r] = 0;
243
- if (taken[r]) continue;
244
- if (chosen.length === 0 ? affordable && shapes[r].bytes > budget : spent + shapes[r].bytes > budget) continue;
245
- const s = shapes[r];
246
- const from = first_rank(s.log_size, shrink, false);
247
- const to = first_rank(s.log_size, grow, true);
248
- let count = 0;
249
- for (let k = s.lod; k < lods.length; k++) {
250
- count += fenwick_sum(undrawn_of_lod[k], to) - fenwick_sum(undrawn_of_lod[k], from);
318
+ if (counts_dirty) {
319
+ unlikes.fill(NaN);
320
+ for (let r = 0; r < n; r++) {
321
+ counts[r] = 0;
322
+ if (taken[r]) continue;
323
+ if (chosen.length === 0 ? affordable && shapes[r].bytes > budget : spent + shapes[r].bytes > budget) continue;
324
+ const s = shapes[r];
325
+ const from = from_ranks[r];
326
+ const to = to_ranks[r];
327
+ let count = 0;
328
+ for (let k = s.lod; k < lods.length; k++) {
329
+ count += fenwick_sum(undrawn_of_lod[k], to) - fenwick_sum(undrawn_of_lod[k], from);
330
+ }
331
+ counts[r] = count;
332
+ if (count > pick_count) pick_count = count;
333
+ }
334
+ counts_dirty = false;
335
+ } else {
336
+ for (let r = 0; r < n; r++) {
337
+ if (counts[r] > pick_count) pick_count = counts[r];
251
338
  }
252
- counts[r] = count;
253
- if (count > pick_count) pick_count = count;
254
339
  }
255
340
  let pick = -1, pick_unlike = Infinity;
256
341
  if (pick_count > 0) {
257
342
  for (let r = 0; r < n; r++) {
258
343
  if (counts[r] !== pick_count) continue;
259
- // the cuts it draws, from its window, summed in the order of the cuts
260
- const s = shapes[r];
261
- const to = first_rank(s.log_size, grow, true);
262
- let w = 0;
263
- for (let i = first_rank(s.log_size, shrink, false); i < to; i++) {
264
- const c = by_size[i];
265
- if (!drawn[c] && shapes[c].lod >= s.lod) window[w++] = c;
344
+ let unlike = unlikes[r];
345
+ if (Number.isNaN(unlike)) {
346
+ // the cuts it draws, from its window, summed in the order of the cuts
347
+ const s = shapes[r];
348
+ const to = to_ranks[r];
349
+ let w = 0;
350
+ for (let i = from_ranks[r]; i < to; i++) {
351
+ const c = by_size[i];
352
+ if (!drawn[c] && shapes[c].lod >= s.lod) window[w++] = c;
353
+ }
354
+ window.subarray(0, w).sort();
355
+ unlike = 0;
356
+ for (let i = 0; i < w; i++) unlike += cut_distance(shapes[window[i]], s);
357
+ unlikes[r] = unlike;
266
358
  }
267
- window.subarray(0, w).sort();
268
- let unlike = 0;
269
- for (let i = 0; i < w; i++) unlike += cut_distance(shapes[window[i]], s);
270
359
  if (unlike < pick_unlike) {
271
360
  pick = r;
272
361
  pick_unlike = unlike;
@@ -275,18 +364,29 @@ function choose(skeleton, attachments, leaves, lods, pressed_lods, leaf_texel, b
275
364
  }
276
365
  if (pick < 0) break;
277
366
  const s = shapes[pick];
278
- chosen_sizes.push(lod_tiles[s.lod].sizes[s.card * 2], lod_tiles[s.lod].sizes[s.card * 2 + 1]);
367
+ const tw = s.tw, th = s.th;
279
368
  taken[pick] = 1;
369
+ counts[pick] = 0;
280
370
  if (chosen.length > 0) {
371
+ chosen_sizes.push(tw, th);
281
372
  const packed = tree_cluster_atlas_pack(chosen_sizes, chosen.length + 1);
282
373
  if (packed.atlas_w * packed.atlas_h * CLUSTER_TEXEL_BYTES > budget) {
283
374
  // its tile fits the sum but not the packing
284
375
  chosen_sizes.length -= 2;
376
+ for (let r = 0; r < n; r++) {
377
+ if (shapes[r].tw === tw && shapes[r].th === th) {
378
+ taken[r] = 1;
379
+ counts[r] = 0;
380
+ }
381
+ }
285
382
  continue;
286
383
  }
384
+ } else {
385
+ chosen_sizes.push(tw, th);
287
386
  }
288
387
  chosen.push(pick);
289
388
  spent += s.bytes;
389
+ counts_dirty = true;
290
390
  for (let c = lod_first[s.lod]; c < n; c++) {
291
391
  if (!drawn[c] && draws(c, pick)) {
292
392
  drawn[c] = 1;
@@ -303,7 +403,7 @@ function choose(skeleton, attachments, leaves, lods, pressed_lods, leaf_texel, b
303
403
  const count = lods[k].cards.length;
304
404
  const rep = new Int32Array(count);
305
405
  const frames = new Float64Array(count * 12);
306
- const tiles = lod_tiles[k];
406
+ const tile_frames = lod_geom[k].frames;
307
407
  for (let i = 0; i < count; i++) {
308
408
  const own = lod_first[k] + i;
309
409
  const c = shapes[own];
@@ -331,11 +431,11 @@ function choose(skeleton, attachments, leaves, lods, pressed_lods, leaf_texel, b
331
431
  const tv = c.hang_v - (sin * s.hang_u + cos * s.hang_v);
332
432
  const f = i * 12;
333
433
  for (let d = 0; d < 3; d++) {
334
- const e1 = tiles.frames[f + 3 + d], e2 = tiles.frames[f + 6 + d];
335
- frames[f + d] = tiles.frames[f + d] + e1 * tu + e2 * tv;
434
+ const e1 = tile_frames[f + 3 + d], e2 = tile_frames[f + 6 + d];
435
+ frames[f + d] = tile_frames[f + d] + e1 * tu + e2 * tv;
336
436
  frames[f + 3 + d] = e1 * cos + e2 * sin;
337
437
  frames[f + 6 + d] = -e1 * sin + e2 * cos;
338
- frames[f + 9 + d] = tiles.frames[f + 9 + d];
438
+ frames[f + 9 + d] = tile_frames[f + 9 + d];
339
439
  }
340
440
  }
341
441
  placements.push({ rep, frames });
@@ -1 +1 @@
1
- {"version":3,"file":"tree_mesh_build_bark.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/mesh/tree_mesh_build_bark.js"],"names":[],"mappings":"AA+iBA;;;;;GAKG;AACH,2DAJW,QAAQ,SACR,MAAM,GACJ,WAAW,CAevB;AAED;;;;;;;;;;GAUG;AACH,+CANW,OAAO,6BAA6B,EAAE,YAAY,WAClD,iBAAiB,eACjB,aAAa,QACb,OAAO,8CAA8C,EAAE,QAAQ,yBAC7D,QAAQ,CAyxBpB;AAED;;;;;;;;;;;;;;GAcG;AACH,yDAVW,OAAO,6BAA6B,EAAE,YAAY,WAClD,iBAAiB,eACjB,aAAa,GACX,IAAI,MAAM,EAAE,MAAM;IAC9B,EAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvC,CAAK,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAC5D,EAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACnD,EAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAC/C,CAAC,CAAC,CAQL;yBAv3CwB,8CAA8C;kCAOrC,gCAAgC;8BADpC,4BAA4B"}
1
+ {"version":3,"file":"tree_mesh_build_bark.d.ts","sourceRoot":"","sources":["../../../../../src/generation/foliage/mesh/tree_mesh_build_bark.js"],"names":[],"mappings":"AAynBA;;;;;GAKG;AACH,2DAJW,QAAQ,SACR,MAAM,GACJ,WAAW,CAevB;AAED;;;;;;;;;;GAUG;AACH,+CANW,OAAO,6BAA6B,EAAE,YAAY,WAClD,iBAAiB,eACjB,aAAa,QACb,OAAO,8CAA8C,EAAE,QAAQ,yBAC7D,QAAQ,CAgyBpB;AAED;;;;;;;;;;;;;;GAcG;AACH,yDAVW,OAAO,6BAA6B,EAAE,YAAY,WAClD,iBAAiB,eACjB,aAAa,GACX,IAAI,MAAM,EAAE,MAAM;IAC9B,EAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACvC,CAAK,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAC5D,EAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IACnD,EAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAC/C,CAAC,CAAC,CAQL;yBAx8CwB,8CAA8C;kCAOrC,gCAAgC;8BADpC,4BAA4B"}