@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.
- package/assets/city-materials/v1/library.json +117 -0
- package/assets/city-materials/v1/tex/asphalt_col.ktx2 +0 -0
- package/assets/city-materials/v1/tex/asphalt_decals.ktx2 +0 -0
- package/assets/city-materials/v1/tex/asphalt_macro.ktx2 +0 -0
- package/assets/city-materials/v1/tex/asphalt_nrm.ktx2 +0 -0
- package/assets/city-materials/v1/tex/curb_col.ktx2 +0 -0
- package/assets/city-materials/v1/tex/interiors.ktx2 +0 -0
- package/assets/city-materials/v1/tex/markings.ktx2 +0 -0
- package/assets/city-materials/v1/tex/noise.ktx2 +0 -0
- package/assets/city-materials/v1/tex/sidewalk_col.ktx2 +0 -0
- package/assets/city-materials/v1/tex/sidewalk_nrm.ktx2 +0 -0
- package/assets/city-materials/v1/tex/walls_col.ktx2 +0 -0
- package/assets/city-materials/v1/tex/walls_hao.ktx2 +0 -0
- package/assets/city-materials/v1/tex/walls_nrm.ktx2 +0 -0
- package/assets/city-trees/v1/catalog.json +185 -0
- package/assets/city-trees/v1/models/376342e60bc932242ffab9f03fc01abf0b4e294aeeaae5848c4a42055bd213e5.glb +0 -0
- package/assets/city-trees/v1/models/3d2b8c6447c4266e2f97ce952ea166c58baf97f3df8fb8177eeecea9cc121c17.glb +0 -0
- package/assets/city-trees/v1/models/43e62e0515b1c4c41147a2203cdd75bf2416c95ab97c871412e09f12fa1d205e.glb +0 -0
- package/assets/city-trees/v1/models/9ef4bd999d2186fba7ccf684bd7105285d5bdc9f46ad5f0c70aee7fb467ab55c.glb +0 -0
- package/assets/city-trees/v1/models/b41e176d5f3befbb235cc1e1949144523439a661a683eaab3972a6507bf1a93e.glb +0 -0
- package/assets/city-trees/v1/models/f4352bf90f5d789aea7d39dbe76d62fab339d756a6bc7fad82007180ee8ce29a.glb +0 -0
- package/assets/city-trees/v1/textures/01d3c8fd30762202b6b9c6a1d2c8682a3e0e3b11f8ed04c8b387ac22b4fdd296.ktx2 +0 -0
- package/assets/city-trees/v1/textures/06bb700e7a88f845e995b3f6d2c3c27e7aee7cf1389f28c6bae3975969835ab1.ktx2 +0 -0
- package/assets/city-trees/v1/textures/06f6bbd2615b4f70752e8d8e97b2b84b3d79b379c818dfd6716683f720b6ec2d.ktx2 +0 -0
- package/assets/city-trees/v1/textures/1fc45e3b5c15854045237d3f8c48d5155738c1edc5ac9b78cf4d37f849ed9e99.ktx2 +0 -0
- package/assets/city-trees/v1/textures/351e981819402b378bfe074e40d2a204027bc753eb32ce13d401e29e72b2a1cf.ktx2 +0 -0
- package/assets/city-trees/v1/textures/361aab85b489e6ca1bce49361f3d6a62f15dc4765a450530eb218a8924909206.ktx2 +0 -0
- package/assets/city-trees/v1/textures/3a2e24762c29b0eacdf6c3021888adc07536670ba5ab10bddd44d06f024ef8be.ktx2 +0 -0
- package/assets/city-trees/v1/textures/7f967df64359672e773594ea8463250d175b8d9352477d8e14889f95c06fa9e1.ktx2 +0 -0
- package/assets/city-trees/v1/textures/99df4fd05a5f0d464b3424fc314fce0477c950ffe605327b6e9f530537b53575.ktx2 +0 -0
- package/assets/city-trees/v1/textures/a6af40f688e82bbcb628b10006768af02fdb0565a4753fd28bc2efbc2e80f8ff.ktx2 +0 -0
- package/assets/city-trees/v1/textures/bdc5c8fe3fc7ca6fbe862905177255b143ff798c7107f4b5b1d5b05cfc20ac68.ktx2 +0 -0
- package/assets/city-trees/v1/textures/ce51daa31bae9f404e1cf04ef7716e2834bf5f4c16e4db7a295c9b086b861306.ktx2 +0 -0
- package/assets/city-trees/v1/textures/d817f748f8018c85c127f72a274fbe394b8026c424ea0c07bfb19b5377ba36d1.ktx2 +0 -0
- package/assets/city-trees/v1/textures/faab5c3fe6e127743697c347cf476ecadfdeee029beee2d0d96b76e902dd2f0a.ktx2 +0 -0
- package/dist/city/assemble/compose.d.ts +42 -0
- package/dist/city/assemble/compose.js +200 -0
- package/dist/city/assemble/compose.js.map +1 -0
- package/dist/city/assemble/create.d.ts +46 -0
- package/dist/city/assemble/create.js +159 -0
- package/dist/city/assemble/create.js.map +1 -0
- package/dist/city/assemble/glbParts.d.ts +41 -0
- package/dist/city/assemble/glbParts.js +99 -0
- package/dist/city/assemble/glbParts.js.map +1 -0
- package/dist/city/assemble/materials.d.ts +26 -0
- package/dist/city/assemble/materials.js +55 -0
- package/dist/city/assemble/materials.js.map +1 -0
- package/dist/city/assemble/plan.d.ts +43 -0
- package/dist/city/assemble/plan.js +51 -0
- package/dist/city/assemble/plan.js.map +1 -0
- package/dist/city/assemble/spawn.d.ts +11 -0
- package/dist/city/assemble/spawn.js +36 -0
- package/dist/city/assemble/spawn.js.map +1 -0
- package/dist/city/assemble/splat.d.ts +19 -0
- package/dist/city/assemble/splat.js +137 -0
- package/dist/city/assemble/splat.js.map +1 -0
- package/dist/city/assemble/terrain.d.ts +35 -0
- package/dist/city/assemble/terrain.js +121 -0
- package/dist/city/assemble/terrain.js.map +1 -0
- package/dist/city/props/index.d.ts +41 -0
- package/dist/city/props/index.js +109 -0
- package/dist/city/props/index.js.map +1 -0
- package/dist/city/roads/build.d.ts +77 -0
- package/dist/city/roads/build.js +270 -0
- package/dist/city/roads/build.js.map +1 -0
- package/dist/city/roads/command.d.ts +2 -0
- package/dist/city/roads/command.js +63 -0
- package/dist/city/roads/command.js.map +1 -0
- package/dist/city/roads/constants.d.ts +108 -0
- package/dist/city/roads/constants.js +96 -0
- package/dist/city/roads/constants.js.map +1 -0
- package/dist/city/roads/elevation.d.ts +26 -0
- package/dist/city/roads/elevation.js +315 -0
- package/dist/city/roads/elevation.js.map +1 -0
- package/dist/city/roads/fixtures-interchange.d.ts +4 -0
- package/dist/city/roads/fixtures-interchange.js +95 -0
- package/dist/city/roads/fixtures-interchange.js.map +1 -0
- package/dist/city/roads/fixtures.d.ts +24 -0
- package/dist/city/roads/fixtures.js +223 -0
- package/dist/city/roads/fixtures.js.map +1 -0
- package/dist/city/roads/geom.d.ts +57 -0
- package/dist/city/roads/geom.js +241 -0
- package/dist/city/roads/geom.js.map +1 -0
- package/dist/city/roads/glb.d.ts +23 -0
- package/dist/city/roads/glb.js +245 -0
- package/dist/city/roads/glb.js.map +1 -0
- package/dist/city/roads/index.d.ts +5 -0
- package/dist/city/roads/index.js +33 -0
- package/dist/city/roads/index.js.map +1 -0
- package/dist/city/roads/junctions.d.ts +68 -0
- package/dist/city/roads/junctions.js +325 -0
- package/dist/city/roads/junctions.js.map +1 -0
- package/dist/city/roads/markings.d.ts +11 -0
- package/dist/city/roads/markings.js +154 -0
- package/dist/city/roads/markings.js.map +1 -0
- package/dist/city/roads/medians.d.ts +2 -0
- package/dist/city/roads/medians.js +95 -0
- package/dist/city/roads/medians.js.map +1 -0
- package/dist/city/roads/mesh.d.ts +41 -0
- package/dist/city/roads/mesh.js +226 -0
- package/dist/city/roads/mesh.js.map +1 -0
- package/dist/city/roads/network.d.ts +85 -0
- package/dist/city/roads/network.js +213 -0
- package/dist/city/roads/network.js.map +1 -0
- package/dist/city/roads/ribbons.d.ts +29 -0
- package/dist/city/roads/ribbons.js +222 -0
- package/dist/city/roads/ribbons.js.map +1 -0
- package/dist/city/roads/roundabouts.d.ts +16 -0
- package/dist/city/roads/roundabouts.js +168 -0
- package/dist/city/roads/roundabouts.js.map +1 -0
- package/dist/city/roads/testing.d.ts +37 -0
- package/dist/city/roads/testing.js +106 -0
- package/dist/city/roads/testing.js.map +1 -0
- package/dist/city/terrain/conform.d.ts +73 -0
- package/dist/city/terrain/conform.js +382 -0
- package/dist/city/terrain/conform.js.map +1 -0
- package/dist/city/terrain/ground.d.ts +33 -0
- package/dist/city/terrain/ground.js +344 -0
- package/dist/city/terrain/ground.js.map +1 -0
- package/dist/city/terrain/index.d.ts +2 -0
- package/dist/city/terrain/index.js +17 -0
- package/dist/city/terrain/index.js.map +1 -0
- package/dist/city/vegetation/index.d.ts +44 -0
- package/dist/city/vegetation/index.js +205 -0
- package/dist/city/vegetation/index.js.map +1 -0
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/sceneCreate/commands.d.ts +4 -0
- package/dist/sceneCreate/commands.js +118 -0
- package/dist/sceneCreate/commands.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/city-roads.md +120 -0
- package/docs/scene-create.md +61 -0
- package/package.json +5 -3
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_stock_events.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/fmod_studio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/fsb5.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_ac.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_beamng.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_fixtures.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_beamng_engine.cpython-312.pyc +0 -0
- 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
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|