@hypersoniclabs/helix-cli 0.1.25-helix3.484 → 0.1.25-helix3.486

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 (149) hide show
  1. package/assets/city-materials/v1/library.json +117 -0
  2. package/assets/city-materials/v1/tex/asphalt_col.ktx2 +0 -0
  3. package/assets/city-materials/v1/tex/asphalt_decals.ktx2 +0 -0
  4. package/assets/city-materials/v1/tex/asphalt_macro.ktx2 +0 -0
  5. package/assets/city-materials/v1/tex/asphalt_nrm.ktx2 +0 -0
  6. package/assets/city-materials/v1/tex/curb_col.ktx2 +0 -0
  7. package/assets/city-materials/v1/tex/interiors.ktx2 +0 -0
  8. package/assets/city-materials/v1/tex/markings.ktx2 +0 -0
  9. package/assets/city-materials/v1/tex/noise.ktx2 +0 -0
  10. package/assets/city-materials/v1/tex/sidewalk_col.ktx2 +0 -0
  11. package/assets/city-materials/v1/tex/sidewalk_nrm.ktx2 +0 -0
  12. package/assets/city-materials/v1/tex/walls_col.ktx2 +0 -0
  13. package/assets/city-materials/v1/tex/walls_hao.ktx2 +0 -0
  14. package/assets/city-materials/v1/tex/walls_nrm.ktx2 +0 -0
  15. package/assets/city-trees/v1/catalog.json +185 -0
  16. package/assets/city-trees/v1/models/376342e60bc932242ffab9f03fc01abf0b4e294aeeaae5848c4a42055bd213e5.glb +0 -0
  17. package/assets/city-trees/v1/models/3d2b8c6447c4266e2f97ce952ea166c58baf97f3df8fb8177eeecea9cc121c17.glb +0 -0
  18. package/assets/city-trees/v1/models/43e62e0515b1c4c41147a2203cdd75bf2416c95ab97c871412e09f12fa1d205e.glb +0 -0
  19. package/assets/city-trees/v1/models/9ef4bd999d2186fba7ccf684bd7105285d5bdc9f46ad5f0c70aee7fb467ab55c.glb +0 -0
  20. package/assets/city-trees/v1/models/b41e176d5f3befbb235cc1e1949144523439a661a683eaab3972a6507bf1a93e.glb +0 -0
  21. package/assets/city-trees/v1/models/f4352bf90f5d789aea7d39dbe76d62fab339d756a6bc7fad82007180ee8ce29a.glb +0 -0
  22. package/assets/city-trees/v1/textures/01d3c8fd30762202b6b9c6a1d2c8682a3e0e3b11f8ed04c8b387ac22b4fdd296.ktx2 +0 -0
  23. package/assets/city-trees/v1/textures/06bb700e7a88f845e995b3f6d2c3c27e7aee7cf1389f28c6bae3975969835ab1.ktx2 +0 -0
  24. package/assets/city-trees/v1/textures/06f6bbd2615b4f70752e8d8e97b2b84b3d79b379c818dfd6716683f720b6ec2d.ktx2 +0 -0
  25. package/assets/city-trees/v1/textures/1fc45e3b5c15854045237d3f8c48d5155738c1edc5ac9b78cf4d37f849ed9e99.ktx2 +0 -0
  26. package/assets/city-trees/v1/textures/351e981819402b378bfe074e40d2a204027bc753eb32ce13d401e29e72b2a1cf.ktx2 +0 -0
  27. package/assets/city-trees/v1/textures/361aab85b489e6ca1bce49361f3d6a62f15dc4765a450530eb218a8924909206.ktx2 +0 -0
  28. package/assets/city-trees/v1/textures/3a2e24762c29b0eacdf6c3021888adc07536670ba5ab10bddd44d06f024ef8be.ktx2 +0 -0
  29. package/assets/city-trees/v1/textures/7f967df64359672e773594ea8463250d175b8d9352477d8e14889f95c06fa9e1.ktx2 +0 -0
  30. package/assets/city-trees/v1/textures/99df4fd05a5f0d464b3424fc314fce0477c950ffe605327b6e9f530537b53575.ktx2 +0 -0
  31. package/assets/city-trees/v1/textures/a6af40f688e82bbcb628b10006768af02fdb0565a4753fd28bc2efbc2e80f8ff.ktx2 +0 -0
  32. package/assets/city-trees/v1/textures/bdc5c8fe3fc7ca6fbe862905177255b143ff798c7107f4b5b1d5b05cfc20ac68.ktx2 +0 -0
  33. package/assets/city-trees/v1/textures/ce51daa31bae9f404e1cf04ef7716e2834bf5f4c16e4db7a295c9b086b861306.ktx2 +0 -0
  34. package/assets/city-trees/v1/textures/d817f748f8018c85c127f72a274fbe394b8026c424ea0c07bfb19b5377ba36d1.ktx2 +0 -0
  35. package/assets/city-trees/v1/textures/faab5c3fe6e127743697c347cf476ecadfdeee029beee2d0d96b76e902dd2f0a.ktx2 +0 -0
  36. package/dist/city/assemble/compose.d.ts +42 -0
  37. package/dist/city/assemble/compose.js +200 -0
  38. package/dist/city/assemble/compose.js.map +1 -0
  39. package/dist/city/assemble/create.d.ts +46 -0
  40. package/dist/city/assemble/create.js +159 -0
  41. package/dist/city/assemble/create.js.map +1 -0
  42. package/dist/city/assemble/glbParts.d.ts +41 -0
  43. package/dist/city/assemble/glbParts.js +99 -0
  44. package/dist/city/assemble/glbParts.js.map +1 -0
  45. package/dist/city/assemble/materials.d.ts +26 -0
  46. package/dist/city/assemble/materials.js +55 -0
  47. package/dist/city/assemble/materials.js.map +1 -0
  48. package/dist/city/assemble/plan.d.ts +43 -0
  49. package/dist/city/assemble/plan.js +51 -0
  50. package/dist/city/assemble/plan.js.map +1 -0
  51. package/dist/city/assemble/spawn.d.ts +11 -0
  52. package/dist/city/assemble/spawn.js +36 -0
  53. package/dist/city/assemble/spawn.js.map +1 -0
  54. package/dist/city/assemble/splat.d.ts +19 -0
  55. package/dist/city/assemble/splat.js +137 -0
  56. package/dist/city/assemble/splat.js.map +1 -0
  57. package/dist/city/assemble/terrain.d.ts +35 -0
  58. package/dist/city/assemble/terrain.js +121 -0
  59. package/dist/city/assemble/terrain.js.map +1 -0
  60. package/dist/city/props/index.d.ts +41 -0
  61. package/dist/city/props/index.js +109 -0
  62. package/dist/city/props/index.js.map +1 -0
  63. package/dist/city/roads/build.d.ts +77 -0
  64. package/dist/city/roads/build.js +270 -0
  65. package/dist/city/roads/build.js.map +1 -0
  66. package/dist/city/roads/command.d.ts +2 -0
  67. package/dist/city/roads/command.js +63 -0
  68. package/dist/city/roads/command.js.map +1 -0
  69. package/dist/city/roads/constants.d.ts +108 -0
  70. package/dist/city/roads/constants.js +96 -0
  71. package/dist/city/roads/constants.js.map +1 -0
  72. package/dist/city/roads/elevation.d.ts +26 -0
  73. package/dist/city/roads/elevation.js +315 -0
  74. package/dist/city/roads/elevation.js.map +1 -0
  75. package/dist/city/roads/fixtures-interchange.d.ts +4 -0
  76. package/dist/city/roads/fixtures-interchange.js +95 -0
  77. package/dist/city/roads/fixtures-interchange.js.map +1 -0
  78. package/dist/city/roads/fixtures.d.ts +24 -0
  79. package/dist/city/roads/fixtures.js +223 -0
  80. package/dist/city/roads/fixtures.js.map +1 -0
  81. package/dist/city/roads/geom.d.ts +57 -0
  82. package/dist/city/roads/geom.js +241 -0
  83. package/dist/city/roads/geom.js.map +1 -0
  84. package/dist/city/roads/glb.d.ts +23 -0
  85. package/dist/city/roads/glb.js +245 -0
  86. package/dist/city/roads/glb.js.map +1 -0
  87. package/dist/city/roads/index.d.ts +5 -0
  88. package/dist/city/roads/index.js +33 -0
  89. package/dist/city/roads/index.js.map +1 -0
  90. package/dist/city/roads/junctions.d.ts +68 -0
  91. package/dist/city/roads/junctions.js +325 -0
  92. package/dist/city/roads/junctions.js.map +1 -0
  93. package/dist/city/roads/markings.d.ts +11 -0
  94. package/dist/city/roads/markings.js +154 -0
  95. package/dist/city/roads/markings.js.map +1 -0
  96. package/dist/city/roads/medians.d.ts +2 -0
  97. package/dist/city/roads/medians.js +95 -0
  98. package/dist/city/roads/medians.js.map +1 -0
  99. package/dist/city/roads/mesh.d.ts +41 -0
  100. package/dist/city/roads/mesh.js +226 -0
  101. package/dist/city/roads/mesh.js.map +1 -0
  102. package/dist/city/roads/network.d.ts +85 -0
  103. package/dist/city/roads/network.js +213 -0
  104. package/dist/city/roads/network.js.map +1 -0
  105. package/dist/city/roads/ribbons.d.ts +29 -0
  106. package/dist/city/roads/ribbons.js +222 -0
  107. package/dist/city/roads/ribbons.js.map +1 -0
  108. package/dist/city/roads/roundabouts.d.ts +16 -0
  109. package/dist/city/roads/roundabouts.js +168 -0
  110. package/dist/city/roads/roundabouts.js.map +1 -0
  111. package/dist/city/roads/testing.d.ts +37 -0
  112. package/dist/city/roads/testing.js +106 -0
  113. package/dist/city/roads/testing.js.map +1 -0
  114. package/dist/city/terrain/conform.d.ts +73 -0
  115. package/dist/city/terrain/conform.js +382 -0
  116. package/dist/city/terrain/conform.js.map +1 -0
  117. package/dist/city/terrain/ground.d.ts +33 -0
  118. package/dist/city/terrain/ground.js +344 -0
  119. package/dist/city/terrain/ground.js.map +1 -0
  120. package/dist/city/terrain/index.d.ts +2 -0
  121. package/dist/city/terrain/index.js +17 -0
  122. package/dist/city/terrain/index.js.map +1 -0
  123. package/dist/city/vegetation/index.d.ts +44 -0
  124. package/dist/city/vegetation/index.js +205 -0
  125. package/dist/city/vegetation/index.js.map +1 -0
  126. package/dist/index.js +8 -4
  127. package/dist/index.js.map +1 -1
  128. package/dist/sceneCreate/commands.d.ts +4 -0
  129. package/dist/sceneCreate/commands.js +118 -0
  130. package/dist/sceneCreate/commands.js.map +1 -0
  131. package/dist/tsconfig.build.tsbuildinfo +1 -1
  132. package/docs/city-roads.md +120 -0
  133. package/docs/scene-create.md +61 -0
  134. package/package.json +5 -3
  135. package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
  136. package/plugins/beamng-vehicle/bin/__pycache__/beamng_audio.cpython-312.pyc +0 -0
  137. package/plugins/beamng-vehicle/bin/__pycache__/beamng_engine.cpython-312.pyc +0 -0
  138. package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
  139. package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
  140. package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
  141. package/plugins/beamng-vehicle/bin/__pycache__/beamng_stock_events.cpython-312.pyc +0 -0
  142. package/plugins/beamng-vehicle/bin/__pycache__/fmod_studio.cpython-312.pyc +0 -0
  143. package/plugins/beamng-vehicle/bin/__pycache__/fsb5.cpython-312.pyc +0 -0
  144. package/plugins/beamng-vehicle/bin/__pycache__/sim_audio.cpython-312.pyc +0 -0
  145. package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_ac.cpython-312.pyc +0 -0
  146. package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_beamng.cpython-312.pyc +0 -0
  147. package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_fixtures.cpython-312.pyc +0 -0
  148. package/plugins/beamng-vehicle/bin/__pycache__/test_beamng_engine.cpython-312.pyc +0 -0
  149. package/plugins/beamng-vehicle/bin/__pycache__/test_sim_audio.cpython-312.pyc +0 -0
@@ -0,0 +1,117 @@
1
+ {
2
+ "schema": "helix.city-materials-library/1",
3
+ "version": 1,
4
+ "gpuBytes": {
5
+ "high": 41267408,
6
+ "low": 12933504
7
+ },
8
+ "textures": {
9
+ "wallsCol": {
10
+ "path": "tex/walls_col.ktx2",
11
+ "bytes": 3386447,
12
+ "sha256": "0f8826c47f877b71a57259778b12913cbbb0f95c79999d5424ae4a97689e2c05",
13
+ "width": 1024,
14
+ "height": 1024,
15
+ "layers": 16,
16
+ "srgb": true
17
+ },
18
+ "wallsNrm": {
19
+ "path": "tex/walls_nrm.ktx2",
20
+ "bytes": 1202459,
21
+ "sha256": "98ecb7b0317af6f99eeb45262e2423ae4c36c8c8e4b738392b542b85e07657af",
22
+ "width": 256,
23
+ "height": 256,
24
+ "layers": 16,
25
+ "srgb": false
26
+ },
27
+ "wallsHao": {
28
+ "path": "tex/walls_hao.ktx2",
29
+ "bytes": 333343,
30
+ "sha256": "616ae9abea262e95359a5ddbc74f08fd981e48c46fe404f0623422b090abd2f4",
31
+ "width": 128,
32
+ "height": 128,
33
+ "layers": 17,
34
+ "srgb": false
35
+ },
36
+ "interiors": {
37
+ "path": "tex/interiors.ktx2",
38
+ "bytes": 773983,
39
+ "sha256": "bbbeceb4ce8b31e78bffbc0f9d66611d7bfdf1b4579b1785d58d828c0705aa0a",
40
+ "width": 2048,
41
+ "height": 2048,
42
+ "srgb": true
43
+ },
44
+ "noise": {
45
+ "path": "tex/noise.ktx2",
46
+ "bytes": 341741,
47
+ "sha256": "7db4002bb73fe2ce7d2c377285d524d2666df72362c748a5a2268fe60bf27d55",
48
+ "width": 512,
49
+ "height": 512,
50
+ "srgb": false
51
+ },
52
+ "asphaltCol": {
53
+ "path": "tex/asphalt_col.ktx2",
54
+ "bytes": 947301,
55
+ "sha256": "215dd62acd3e2b5fbd2b1cfdedb45fe1c6f41a16bbdac1196f0646a8c62db1e8",
56
+ "width": 2048,
57
+ "height": 2048,
58
+ "srgb": true
59
+ },
60
+ "asphaltNrm": {
61
+ "path": "tex/asphalt_nrm.ktx2",
62
+ "bytes": 335490,
63
+ "sha256": "cd154fff171328aa50319f930f387f27f1b44727743ab3e4c309ed7855d60d3b",
64
+ "width": 512,
65
+ "height": 512,
66
+ "srgb": false
67
+ },
68
+ "asphaltMacro": {
69
+ "path": "tex/asphalt_macro.ktx2",
70
+ "bytes": 322070,
71
+ "sha256": "4aa520e170fe23cf640db8b55bc7307d885b4fa75dba794f6ddc42a822525f3e",
72
+ "width": 512,
73
+ "height": 512,
74
+ "srgb": false
75
+ },
76
+ "asphaltDecals": {
77
+ "path": "tex/asphalt_decals.ktx2",
78
+ "bytes": 489146,
79
+ "sha256": "5fa1b27e5ac9854e5920360f13e00860043db5a6c352ab0e14dde2d2137a5b21",
80
+ "width": 1024,
81
+ "height": 1024,
82
+ "srgb": false
83
+ },
84
+ "sidewalkCol": {
85
+ "path": "tex/sidewalk_col.ktx2",
86
+ "bytes": 258668,
87
+ "sha256": "7f2db748d6097ec4005952057cf2696078035aeb9d75a13c1b6e32d8fab859bf",
88
+ "width": 1024,
89
+ "height": 1024,
90
+ "srgb": true
91
+ },
92
+ "sidewalkNrm": {
93
+ "path": "tex/sidewalk_nrm.ktx2",
94
+ "bytes": 327989,
95
+ "sha256": "4f04480df9e5f23006d97373979ba69ba24e8c542ae4268e16db38ca27c4d284",
96
+ "width": 512,
97
+ "height": 512,
98
+ "srgb": false
99
+ },
100
+ "curbCol": {
101
+ "path": "tex/curb_col.ktx2",
102
+ "bytes": 101354,
103
+ "sha256": "42014eb1e8a6e4a71e0dd21aa011b6ad5b619c518370981decba4cdb4b24a450",
104
+ "width": 512,
105
+ "height": 512,
106
+ "srgb": true
107
+ },
108
+ "markings": {
109
+ "path": "tex/markings.ktx2",
110
+ "bytes": 551422,
111
+ "sha256": "72ade7d2544f2c122abfb6126a2abe577590a6d8f6a74de53fea31ceb7e53d4d",
112
+ "width": 1024,
113
+ "height": 1024,
114
+ "srgb": true
115
+ }
116
+ }
117
+ }
@@ -0,0 +1,185 @@
1
+ {
2
+ "schema": "helix.placements-assets/1",
3
+ "textures": {
4
+ "textures/351e981819402b378bfe074e40d2a204027bc753eb32ce13d401e29e72b2a1cf.ktx2": {
5
+ "sha256": "351e981819402b378bfe074e40d2a204027bc753eb32ce13d401e29e72b2a1cf"
6
+ },
7
+ "textures/01d3c8fd30762202b6b9c6a1d2c8682a3e0e3b11f8ed04c8b387ac22b4fdd296.ktx2": {
8
+ "sha256": "01d3c8fd30762202b6b9c6a1d2c8682a3e0e3b11f8ed04c8b387ac22b4fdd296"
9
+ },
10
+ "textures/06f6bbd2615b4f70752e8d8e97b2b84b3d79b379c818dfd6716683f720b6ec2d.ktx2": {
11
+ "sha256": "06f6bbd2615b4f70752e8d8e97b2b84b3d79b379c818dfd6716683f720b6ec2d"
12
+ },
13
+ "textures/1fc45e3b5c15854045237d3f8c48d5155738c1edc5ac9b78cf4d37f849ed9e99.ktx2": {
14
+ "sha256": "1fc45e3b5c15854045237d3f8c48d5155738c1edc5ac9b78cf4d37f849ed9e99"
15
+ },
16
+ "textures/bdc5c8fe3fc7ca6fbe862905177255b143ff798c7107f4b5b1d5b05cfc20ac68.ktx2": {
17
+ "sha256": "bdc5c8fe3fc7ca6fbe862905177255b143ff798c7107f4b5b1d5b05cfc20ac68"
18
+ },
19
+ "textures/d817f748f8018c85c127f72a274fbe394b8026c424ea0c07bfb19b5377ba36d1.ktx2": {
20
+ "sha256": "d817f748f8018c85c127f72a274fbe394b8026c424ea0c07bfb19b5377ba36d1"
21
+ },
22
+ "textures/3a2e24762c29b0eacdf6c3021888adc07536670ba5ab10bddd44d06f024ef8be.ktx2": {
23
+ "sha256": "3a2e24762c29b0eacdf6c3021888adc07536670ba5ab10bddd44d06f024ef8be"
24
+ },
25
+ "textures/361aab85b489e6ca1bce49361f3d6a62f15dc4765a450530eb218a8924909206.ktx2": {
26
+ "sha256": "361aab85b489e6ca1bce49361f3d6a62f15dc4765a450530eb218a8924909206"
27
+ },
28
+ "textures/99df4fd05a5f0d464b3424fc314fce0477c950ffe605327b6e9f530537b53575.ktx2": {
29
+ "sha256": "99df4fd05a5f0d464b3424fc314fce0477c950ffe605327b6e9f530537b53575"
30
+ },
31
+ "textures/faab5c3fe6e127743697c347cf476ecadfdeee029beee2d0d96b76e902dd2f0a.ktx2": {
32
+ "sha256": "faab5c3fe6e127743697c347cf476ecadfdeee029beee2d0d96b76e902dd2f0a"
33
+ },
34
+ "textures/7f967df64359672e773594ea8463250d175b8d9352477d8e14889f95c06fa9e1.ktx2": {
35
+ "sha256": "7f967df64359672e773594ea8463250d175b8d9352477d8e14889f95c06fa9e1"
36
+ },
37
+ "textures/06bb700e7a88f845e995b3f6d2c3c27e7aee7cf1389f28c6bae3975969835ab1.ktx2": {
38
+ "sha256": "06bb700e7a88f845e995b3f6d2c3c27e7aee7cf1389f28c6bae3975969835ab1"
39
+ },
40
+ "textures/a6af40f688e82bbcb628b10006768af02fdb0565a4753fd28bc2efbc2e80f8ff.ktx2": {
41
+ "sha256": "a6af40f688e82bbcb628b10006768af02fdb0565a4753fd28bc2efbc2e80f8ff"
42
+ },
43
+ "textures/ce51daa31bae9f404e1cf04ef7716e2834bf5f4c16e4db7a295c9b086b861306.ktx2": {
44
+ "sha256": "ce51daa31bae9f404e1cf04ef7716e2834bf5f4c16e4db7a295c9b086b861306"
45
+ }
46
+ },
47
+ "prototypes": [
48
+ {
49
+ "id": "douglas-fir",
50
+ "category": "tree",
51
+ "structural": true,
52
+ "bounds": {
53
+ "min": [
54
+ -2.4772729873657227,
55
+ 0,
56
+ -2.491356372833252
57
+ ],
58
+ "max": [
59
+ 2.4772729873657227,
60
+ 9.229426383972168,
61
+ 2.491356372833252
62
+ ]
63
+ },
64
+ "families": {
65
+ "small": {
66
+ "textures": [
67
+ "textures/351e981819402b378bfe074e40d2a204027bc753eb32ce13d401e29e72b2a1cf.ktx2",
68
+ "textures/01d3c8fd30762202b6b9c6a1d2c8682a3e0e3b11f8ed04c8b387ac22b4fdd296.ktx2",
69
+ "textures/06f6bbd2615b4f70752e8d8e97b2b84b3d79b379c818dfd6716683f720b6ec2d.ktx2",
70
+ "textures/1fc45e3b5c15854045237d3f8c48d5155738c1edc5ac9b78cf4d37f849ed9e99.ktx2",
71
+ "textures/bdc5c8fe3fc7ca6fbe862905177255b143ff798c7107f4b5b1d5b05cfc20ac68.ktx2",
72
+ "textures/d817f748f8018c85c127f72a274fbe394b8026c424ea0c07bfb19b5377ba36d1.ktx2",
73
+ "textures/3a2e24762c29b0eacdf6c3021888adc07536670ba5ab10bddd44d06f024ef8be.ktx2"
74
+ ],
75
+ "lods": [
76
+ {
77
+ "file": "models/b41e176d5f3befbb235cc1e1949144523439a661a683eaab3972a6507bf1a93e.glb",
78
+ "sha256": "b41e176d5f3befbb235cc1e1949144523439a661a683eaab3972a6507bf1a93e",
79
+ "triangles": 8210,
80
+ "materialCount": 2,
81
+ "minPixels": 120
82
+ },
83
+ {
84
+ "file": "models/3d2b8c6447c4266e2f97ce952ea166c58baf97f3df8fb8177eeecea9cc121c17.glb",
85
+ "sha256": "3d2b8c6447c4266e2f97ce952ea166c58baf97f3df8fb8177eeecea9cc121c17",
86
+ "triangles": 458,
87
+ "materialCount": 2,
88
+ "minPixels": 96
89
+ },
90
+ {
91
+ "file": "models/376342e60bc932242ffab9f03fc01abf0b4e294aeeaae5848c4a42055bd213e5.glb",
92
+ "sha256": "376342e60bc932242ffab9f03fc01abf0b4e294aeeaae5848c4a42055bd213e5",
93
+ "triangles": 288,
94
+ "materialCount": 2,
95
+ "minPixels": 0
96
+ }
97
+ ]
98
+ }
99
+ },
100
+ "wind": {
101
+ "model": "broad",
102
+ "maxDisplacementM": 2.7688279151916504
103
+ },
104
+ "collider": {
105
+ "shape": "cylinder",
106
+ "center": [
107
+ 0,
108
+ 4,
109
+ 0
110
+ ],
111
+ "radius": 0.28,
112
+ "height": 8
113
+ },
114
+ "giProxy": null
115
+ },
116
+ {
117
+ "id": "ponderosa-pine",
118
+ "category": "tree",
119
+ "structural": true,
120
+ "bounds": {
121
+ "min": [
122
+ -5.092374324798584,
123
+ 0,
124
+ -5.157204627990723
125
+ ],
126
+ "max": [
127
+ 5.092374324798584,
128
+ 23.090269088745117,
129
+ 5.157204627990723
130
+ ]
131
+ },
132
+ "families": {
133
+ "small": {
134
+ "textures": [
135
+ "textures/361aab85b489e6ca1bce49361f3d6a62f15dc4765a450530eb218a8924909206.ktx2",
136
+ "textures/99df4fd05a5f0d464b3424fc314fce0477c950ffe605327b6e9f530537b53575.ktx2",
137
+ "textures/faab5c3fe6e127743697c347cf476ecadfdeee029beee2d0d96b76e902dd2f0a.ktx2",
138
+ "textures/7f967df64359672e773594ea8463250d175b8d9352477d8e14889f95c06fa9e1.ktx2",
139
+ "textures/06bb700e7a88f845e995b3f6d2c3c27e7aee7cf1389f28c6bae3975969835ab1.ktx2",
140
+ "textures/a6af40f688e82bbcb628b10006768af02fdb0565a4753fd28bc2efbc2e80f8ff.ktx2",
141
+ "textures/ce51daa31bae9f404e1cf04ef7716e2834bf5f4c16e4db7a295c9b086b861306.ktx2"
142
+ ],
143
+ "lods": [
144
+ {
145
+ "file": "models/f4352bf90f5d789aea7d39dbe76d62fab339d756a6bc7fad82007180ee8ce29a.glb",
146
+ "sha256": "f4352bf90f5d789aea7d39dbe76d62fab339d756a6bc7fad82007180ee8ce29a",
147
+ "triangles": 10140,
148
+ "materialCount": 2,
149
+ "minPixels": 120
150
+ },
151
+ {
152
+ "file": "models/9ef4bd999d2186fba7ccf684bd7105285d5bdc9f46ad5f0c70aee7fb467ab55c.glb",
153
+ "sha256": "9ef4bd999d2186fba7ccf684bd7105285d5bdc9f46ad5f0c70aee7fb467ab55c",
154
+ "triangles": 695,
155
+ "materialCount": 2,
156
+ "minPixels": 96
157
+ },
158
+ {
159
+ "file": "models/43e62e0515b1c4c41147a2203cdd75bf2416c95ab97c871412e09f12fa1d205e.glb",
160
+ "sha256": "43e62e0515b1c4c41147a2203cdd75bf2416c95ab97c871412e09f12fa1d205e",
161
+ "triangles": 300,
162
+ "materialCount": 2,
163
+ "minPixels": 0
164
+ }
165
+ ]
166
+ }
167
+ },
168
+ "wind": {
169
+ "model": "broad",
170
+ "maxDisplacementM": 6
171
+ },
172
+ "collider": {
173
+ "shape": "cylinder",
174
+ "center": [
175
+ 0,
176
+ 4,
177
+ 0
178
+ ],
179
+ "radius": 0.28,
180
+ "height": 8
181
+ },
182
+ "giProxy": null
183
+ }
184
+ ]
185
+ }
@@ -0,0 +1,42 @@
1
+ import { type HelixSceneV2 } from '@hypersoniclabs/helix-manifest';
2
+ import type { BuildingsManifest, CellEntry, FarEntry } from '../buildings';
3
+ import type { BundleFile, PackagedCityLibrary } from './materials';
4
+ export declare const CITY_HLOD_LAYER = "buildings";
5
+ export interface ComposeInput {
6
+ sceneId: string;
7
+ title: string;
8
+ /** Folder holding `terrain.json` (a terrain source folder). */
9
+ terrainDir: string;
10
+ /** Folder holding `placements.json` (`helix placements bake`), when the city has vegetation or props. */
11
+ placementsDir?: string;
12
+ /** The `helix city buildings build` output folder and its manifest. */
13
+ buildingsDir: string;
14
+ buildings: BuildingsManifest;
15
+ library: PackagedCityLibrary;
16
+ memoryBudgetMiB: number;
17
+ streamRadiusM: number;
18
+ spawn: {
19
+ position: [number, number, number];
20
+ rotationYDeg?: number;
21
+ };
22
+ }
23
+ export interface ComposeStats {
24
+ buildingCells: number;
25
+ colliderTriangles: number;
26
+ hlodClusters: number;
27
+ hlodTriangles: number;
28
+ hlodBytes: number;
29
+ nearBytes: number;
30
+ colliderBytes: number;
31
+ nodes: number;
32
+ streamGroups: number;
33
+ resources: number;
34
+ documentBytes: number;
35
+ }
36
+ export interface ComposeResult {
37
+ scene: HelixSceneV2;
38
+ files: BundleFile[];
39
+ stats: ComposeStats;
40
+ }
41
+ export declare function composeCityScene(input: ComposeInput): Promise<ComposeResult>;
42
+ export type { CellEntry, FarEntry };
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ // Scene v2 composition for a generated city (design `SCENE-PIPELINE-DESIGN` section 3.2-3.3): the compiled terrain (and
3
+ // placements) from `compileSceneElementsBundle`, plus one streamed node per building cell with its box-level collider, the
4
+ // generator-written far layer sealed as a complete HLOD v2 layer, the city material library and the optional
5
+ // `web.city-materials/1` extension. Everything is content-addressed and the document is sealed and validated here.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.CITY_HLOD_LAYER = void 0;
8
+ exports.composeCityScene = composeCityScene;
9
+ const node_fs_1 = require("node:fs");
10
+ const node_path_1 = require("node:path");
11
+ const helix_manifest_1 = require("@hypersoniclabs/helix-manifest");
12
+ const compiler_1 = require("../../sceneElements/compiler");
13
+ const glbParts_1 = require("./glbParts");
14
+ const MIB = 1024 * 1024;
15
+ exports.CITY_HLOD_LAYER = 'buildings';
16
+ const cellId = (cx, cz) => `${cx}.${cz}`;
17
+ function pad(bounds, y) {
18
+ const min = [bounds.min[0], bounds.min[1] - y, bounds.min[2]];
19
+ const max = [bounds.max[0], Math.max(bounds.max[1] + y, min[1] + 0.5), bounds.max[2]];
20
+ for (let axis = 0; axis < 3; axis += 1)
21
+ if (max[axis] <= min[axis])
22
+ max[axis] = min[axis] + 0.01;
23
+ return { min, max };
24
+ }
25
+ function read(dir, ref) {
26
+ const data = (0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, ref.file));
27
+ if (data.length !== ref.bytes || (0, glbParts_1.sha256Hex)(data) !== ref.sha256)
28
+ throw new Error(`scene create city: ${ref.file} does not match buildings.json (length or sha256); rebuild the buildings`);
29
+ return data;
30
+ }
31
+ /** Registers a resource once per (kind, digest) and returns its id; one digest is one bundle path. */
32
+ class ResourceTable {
33
+ resources = [];
34
+ files = new Map();
35
+ byDigest = new Map();
36
+ add(id, kind, mimeType, uri, data) {
37
+ const sha256 = (0, glbParts_1.sha256Hex)(data);
38
+ const key = `${kind}\0${sha256}`;
39
+ const existing = this.byDigest.get(key);
40
+ if (existing)
41
+ return existing;
42
+ this.byDigest.set(key, id);
43
+ this.resources.push({ id, kind, source: { kind: 'bundle', assetId: `city:${kind}:${sha256}`, uri }, integrity: { sha256 }, bytes: data.length, mimeType, required: true });
44
+ this.files.set(uri, { uri, data, bytes: data.length, sha256 });
45
+ return id;
46
+ }
47
+ }
48
+ async function composeCityScene(input) {
49
+ const { buildings, buildingsDir } = input;
50
+ if (!buildings.cells.length)
51
+ throw new Error('scene create city: the source has no buildings; a city scene needs at least one building cell');
52
+ // 1. Terrain (and placements) through the same compiler every scene uses.
53
+ const baseDir = (0, node_path_1.dirname)((0, node_path_1.resolve)(input.terrainDir));
54
+ const doc = {
55
+ format: 'helix.scene-elements', version: 2, id: input.sceneId, title: input.title,
56
+ spawn: { position: input.spawn.position, ...(input.spawn.rotationYDeg === undefined ? {} : { rotationYDeg: input.spawn.rotationYDeg }) },
57
+ terrain: { type: 'terrain', id: 'terrain', source: (0, node_path_1.basename)((0, node_path_1.resolve)(input.terrainDir)) },
58
+ ...(input.placementsDir ? { placements: { source: relativeFrom(baseDir, input.placementsDir) } } : {}),
59
+ buildings: [],
60
+ runtimePolicy: { memoryBudgetMiB: input.memoryBudgetMiB, streamRadiusM: input.streamRadiusM },
61
+ };
62
+ const base = (0, compiler_1.compileSceneElementsBundle)(doc, { baseDir });
63
+ const scene = structuredClone(base.scene);
64
+ const table = new ResourceTable();
65
+ const files = new Map();
66
+ for (const file of base.bundleFiles)
67
+ files.set(file.uri, { uri: file.uri, path: file.path, bytes: file.bytes, sha256: file.sha256 });
68
+ // 2. One node per building cell, with its box-level collider, in its own distance group.
69
+ const minIx = Math.min(...buildings.cells.map((c) => c.ix)), minIz = Math.min(...buildings.cells.map((c) => c.iz));
70
+ const farMinX = Math.min(...buildings.far.map((c) => c.ix)), farMinZ = Math.min(...buildings.far.map((c) => c.iz));
71
+ const index = (cell) => cellId(cell.ix - minIx, cell.iz - minIz);
72
+ const identity = { position: [0, 0, 0], rotation: [0, 0, 0, 1], scale: [1, 1, 1] };
73
+ const nodes = [];
74
+ const groups = [];
75
+ const collisionSets = [];
76
+ const nodeByCell = new Map();
77
+ let nearBytes = 0, colliderBytes = 0, colliderTriangles = 0;
78
+ const sortedCells = [...buildings.cells].sort((a, b) => a.iz - b.iz || a.ix - b.ix);
79
+ for (const cell of sortedCells) {
80
+ const id = index(cell);
81
+ if (!cell.near)
82
+ continue; // an all-mesh-building cell draws no procedural near level
83
+ const nearData = read(buildingsDir, cell.near);
84
+ const boxData = read(buildingsDir, cell.box);
85
+ const collider = await (0, glbParts_1.colliderFromBoxLevel)(boxData);
86
+ const nearInfo = (0, glbParts_1.inspectGlb)(nearData);
87
+ const render = table.add(`res.near.${id}`, 'model', 'model/gltf-binary', `buildings/near/${cell.near.sha256}.glb`, nearData);
88
+ const collide = table.add(`res.collider.${id}`, 'collider', 'model/gltf-binary', `buildings/collider/${(0, glbParts_1.sha256Hex)(collider.bytes)}.glb`, collider.bytes);
89
+ nearBytes += nearData.length;
90
+ colliderBytes += collider.bytes.length;
91
+ colliderTriangles += collider.triangles;
92
+ const nodeId = `building.cell.${id}`, carrier = `building.collider.${id}`, groupId = `stream.building.${id}`, setId = `collision.building.${id}`;
93
+ nodes.push({
94
+ id: nodeId, resource: render, transform: { ...identity, position: [cell.origin[0], cell.origin[1], cell.origin[2]] }, streamGroup: groupId,
95
+ hlod: { mode: 'include', layer: exports.CITY_HLOD_LAYER },
96
+ components: [{ type: 'render.mesh', castShadow: true, receiveShadow: true }],
97
+ });
98
+ nodes.push({ id: carrier, transform: identity, streamGroup: groupId, components: [{ type: 'collision.proxy-set', set: setId }] });
99
+ collisionSets.push({
100
+ id: setId, node: carrier,
101
+ static: [{ id: `collider.building.${id}`, shape: 'triangle-mesh', resource: collide, transform: { ...identity, position: [cell.origin[0], cell.origin[1], cell.origin[2]] } }],
102
+ });
103
+ // Decoded cost: the encoded bytes, plus CPU and GPU copies of every accessor (padded), plus the collider's.
104
+ const decoded = nearData.length + 2 * nearInfo.accessorBytes + collider.bytes.length * 6;
105
+ groups.push({
106
+ id: groupId, mode: 'distance', priority: 60,
107
+ cells: [{ id: `cell.building.${id}`, bounds: pad(cell.bounds, 0.5), nodes: [nodeId, carrier] }],
108
+ dependencies: ['stream.root'], estimatedMemoryMiB: Math.max(1, Math.ceil(decoded / MIB)),
109
+ });
110
+ nodeByCell.set(cell.key, { node: nodeId, cell: `cell.building.${id}` });
111
+ }
112
+ // 3. The generator's far layer is the complete HLOD v2 layer: one cluster per far entry, sources in `cells` order.
113
+ const carrier = await (0, glbParts_1.facadeMaterialCarrierGlb)([0.62, 0.58, 0.52]);
114
+ const materialId = table.add('res.hlod.material', 'model', 'model/gltf-binary', `hlod-complete/${(0, glbParts_1.sha256Hex)(carrier.bytes)}.glb`, carrier.bytes);
115
+ const clusters = [];
116
+ let hlodTriangles = 0, hlodBytes = 0;
117
+ for (const far of [...buildings.far].sort((a, b) => a.iz - b.iz || a.ix - b.ix)) {
118
+ const members = far.cells.map((key) => nodeByCell.get(key));
119
+ if (members.some((m) => !m))
120
+ throw new Error(`scene create city: far cluster ${far.key} names a building cell with no near level`);
121
+ const data = read(buildingsDir, far);
122
+ const info = (0, glbParts_1.inspectGlb)(data);
123
+ const id = `${far.ix - farMinX}.${far.iz - farMinZ}`;
124
+ const resource = table.add(`res.hlod.${id}`, 'model', 'model/gltf-binary', `hlod-complete/${far.sha256}.glb`, data);
125
+ clusters.push({
126
+ id: `hlod.${id}`, layer: exports.CITY_HLOD_LAYER, cell: members[0].cell, cells: members.map((m) => m.cell), nodes: members.map((m) => m.node),
127
+ resource, material: materialId, coverage: 'source', origin: far.origin, bounds: { min: [...far.bounds.min], max: [...far.bounds.max] },
128
+ sourceHash: '', triangles: far.triangles, estimatedBytes: data.length + 2 * info.accessorBytes + far.cells.length * 8 + 4096,
129
+ });
130
+ hlodTriangles += far.triangles;
131
+ hlodBytes += data.length;
132
+ }
133
+ if (clusters.length > 2048)
134
+ throw new Error('scene create city: more than 2,048 far clusters; use a larger --far-cell');
135
+ // 4. Fold everything into the document.
136
+ let placementBounds = scene.placement.bounds;
137
+ for (const cell of buildings.cells) {
138
+ placementBounds = {
139
+ min: placementBounds.min.map((v, a) => Math.min(v, cell.bounds.min[a])),
140
+ max: placementBounds.max.map((v, a) => Math.max(v, cell.bounds.max[a])),
141
+ };
142
+ }
143
+ scene.placement = { ...scene.placement, bounds: placementBounds };
144
+ scene.resources = [...scene.resources, ...table.resources, ...input.library.resources];
145
+ scene.nodes = [...scene.nodes, ...nodes];
146
+ scene.streamGroups = [...scene.streamGroups, ...groups];
147
+ scene.scenes = scene.scenes.map((root) => ({ ...root, nodes: [...root.nodes, ...nodes.map((n) => n.id)], streamGroups: [...root.streamGroups, ...groups.map((g) => g.id)] }));
148
+ scene.collision = { sets: [...scene.collision.sets, ...collisionSets] };
149
+ scene.hlod = {
150
+ version: 2, defaultLayer: exports.CITY_HLOD_LAYER,
151
+ layers: [{ id: exports.CITY_HLOD_LAYER, distanceM: 128, maxDistanceM: 8192, fadeMs: 350, triangleRatio: 1, maxErrorM: 0.02, atlasSize: 512, residency: 'complete' }],
152
+ clusters,
153
+ sharedMaterials: [{ resource: materialId, estimatedBytes: carrier.estimatedBytes, extension: 'HELIX_materials_city' }],
154
+ bake: { cellSizeM: buildings.options.farCellM, voxelSizeM: 2, texelsPerM: 1, minTileSize: 64, maxTileSize: 256 },
155
+ };
156
+ scene.runtimeExtensions = [
157
+ ...scene.runtimeExtensions,
158
+ { id: 'ext.city-materials', extension: 'web.city-materials/1', runtime: 'web', targetNodes: [], required: false, fallback: 'portable', parameters: { version: 1, library: input.library.manifestResourceId } },
159
+ ];
160
+ const required = new Set(scene.capabilities.required);
161
+ required.add('render.mesh/1');
162
+ required.add(helix_manifest_1.SCENE_HLOD_COMPLETE_CAPABILITY);
163
+ scene.capabilities = { ...scene.capabilities, required: [...required].sort() };
164
+ // The shared hasher reads nodes, cells, resources and extensions, so it runs once everything above is in place.
165
+ const hasher = (0, helix_manifest_1.createSceneHlodSourceHasher)(scene);
166
+ for (const cluster of scene.hlod.clusters)
167
+ cluster.sourceHash = hasher(cluster);
168
+ // Dedupe: a resource id appears once.
169
+ const seen = new Set();
170
+ scene.resources = scene.resources.filter((r) => (seen.has(r.id) ? false : (seen.add(r.id), true)));
171
+ scene.resources.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
172
+ scene.revision = (0, helix_manifest_1.computeSceneDocumentIntegrity)({ ...scene, integrity: { sha256: '0'.repeat(64) } }).slice(0, 16);
173
+ scene.integrity = { sha256: (0, helix_manifest_1.computeSceneDocumentIntegrity)(scene) };
174
+ const verdict = (0, helix_manifest_1.validateSceneDocument)(scene);
175
+ if (!verdict.valid)
176
+ throw new Error(`scene create city: the composed Scene v2 is invalid:\n ${verdict.errors.slice(0, 20).join('\n ')}`);
177
+ // The validator returns the normalised document; the seal is over exactly the bytes that ship.
178
+ const sealed = verdict.scene;
179
+ sealed.integrity = { sha256: (0, helix_manifest_1.computeSceneDocumentIntegrity)(sealed) };
180
+ for (const file of table.files.values())
181
+ files.set(file.uri, file);
182
+ for (const file of input.library.files)
183
+ files.set(file.uri, file);
184
+ const documentBytes = Buffer.byteLength(JSON.stringify(scene));
185
+ return {
186
+ scene: sealed,
187
+ files: [...files.values()].sort((a, b) => (a.uri < b.uri ? -1 : 1)),
188
+ stats: {
189
+ buildingCells: groups.length, colliderTriangles, hlodClusters: clusters.length, hlodTriangles, hlodBytes, nearBytes, colliderBytes,
190
+ nodes: scene.nodes.length, streamGroups: scene.streamGroups.length, resources: scene.resources.length, documentBytes,
191
+ },
192
+ };
193
+ }
194
+ function relativeFrom(base, dir) {
195
+ const abs = (0, node_path_1.resolve)(dir), root = (0, node_path_1.resolve)(base);
196
+ if (!abs.startsWith(`${root}/`))
197
+ throw new Error(`scene create city: ${dir} must sit inside ${base}`);
198
+ return abs.slice(root.length + 1);
199
+ }
200
+ //# sourceMappingURL=compose.js.map