@holoscript/core 7.0.0 → 8.0.1

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 (350) hide show
  1. package/README.md +4 -4
  2. package/bin/holoscript.cjs +3 -0
  3. package/dist/GLTFPipeline-N6B6PJ6G.cjs +38 -0
  4. package/dist/GLTFPipeline-P3WMNYCN.js +17 -0
  5. package/dist/HoloScriptPlusParser-7FBIFUFC.js +693 -0
  6. package/dist/HoloScriptPlusParser-A2W7OCN2.cjs +698 -0
  7. package/dist/HoloScriptPlusParser-F2Z56FJR.js +10 -0
  8. package/dist/HoloScriptPlusParser-WKHRIH6T.cjs +27 -0
  9. package/dist/HoloScriptRuntime-CBYJX3LZ.js +10 -0
  10. package/dist/HoloScriptRuntime-VJ374RER.cjs +19 -0
  11. package/dist/USDZExporter-3FWJ25JI.cjs +1037 -0
  12. package/dist/USDZExporter-D2HQLQYK.js +1035 -0
  13. package/dist/agents/index.cjs +19 -0
  14. package/dist/agents/index.d.ts +100 -0
  15. package/dist/agents/index.js +17 -0
  16. package/dist/chunk-2BSMSUCE.js +1941 -0
  17. package/dist/chunk-2IWC4FP7.cjs +1189 -0
  18. package/dist/chunk-2M2DPHKB.js +762 -0
  19. package/dist/chunk-2X7NGX3M.js +2426 -0
  20. package/dist/chunk-2YSNA2F2.cjs +1274 -0
  21. package/dist/chunk-3FOKASKO.cjs +348 -0
  22. package/dist/chunk-3WZEJHUQ.cjs +116 -0
  23. package/dist/chunk-4C57PR42.js +468 -0
  24. package/dist/chunk-4GU5GCIY.js +1384 -0
  25. package/dist/chunk-4N4SXXWF.js +769 -0
  26. package/dist/chunk-4PDEPEQW.cjs +41 -0
  27. package/dist/chunk-4R6SBXDB.js +45 -0
  28. package/dist/chunk-4SDKXQ4C.js +811 -0
  29. package/dist/chunk-4V2E7U7Q.cjs +2015 -0
  30. package/dist/chunk-5FSKKMR7.cjs +2092 -0
  31. package/dist/chunk-5GLCTO44.js +161 -0
  32. package/dist/chunk-5H2G27PK.cjs +627 -0
  33. package/dist/chunk-5JEU52DW.js +382 -0
  34. package/dist/chunk-5NWINHR5.cjs +689 -0
  35. package/dist/chunk-5S7RKFGR.cjs +446 -0
  36. package/dist/chunk-5WUNN6ZN.cjs +428 -0
  37. package/dist/chunk-6CTRH7HT.cjs +1985 -0
  38. package/dist/chunk-6EX3I5P4.cjs +130 -0
  39. package/dist/chunk-6Q7RC2MK.cjs +1418 -0
  40. package/dist/chunk-7H33U5SM.cjs +413 -0
  41. package/dist/chunk-7M3PNU2M.cjs +672 -0
  42. package/dist/chunk-7T25IEZ2.js +449 -0
  43. package/dist/chunk-7V4JI5TB.cjs +6947 -0
  44. package/dist/chunk-A6KINLZJ.js +236 -0
  45. package/dist/chunk-ADADVMXY.js +404 -0
  46. package/dist/chunk-AIA52I7T.cjs +543 -0
  47. package/dist/chunk-ALC6K7GL.cjs +4402 -0
  48. package/dist/chunk-ANXZFVY2.js +113 -0
  49. package/dist/chunk-AOVGZ25K.cjs +56583 -0
  50. package/dist/chunk-AVJHHUC5.cjs +718 -0
  51. package/dist/chunk-BGY3SDG3.js +4396 -0
  52. package/dist/chunk-BOVPWH4H.js +3857 -0
  53. package/dist/chunk-BRQJKJGT.cjs +20 -0
  54. package/dist/chunk-C37BHB7N.cjs +636 -0
  55. package/dist/chunk-CBJY23VL.js +126 -0
  56. package/dist/chunk-CCATWPXM.js +778 -0
  57. package/dist/chunk-CIWWXYHZ.cjs +50 -0
  58. package/dist/chunk-CMT5NMMS.js +669 -0
  59. package/dist/chunk-CR4FMIWL.cjs +1049 -0
  60. package/dist/chunk-CR7XRXRN.cjs +639 -0
  61. package/dist/chunk-CSD27UNQ.js +2176 -0
  62. package/dist/chunk-D3STJ56J.js +714 -0
  63. package/dist/chunk-DAJXW4KX.js +725 -0
  64. package/dist/chunk-DHO2YRIM.js +756 -0
  65. package/dist/chunk-DTGBOSEM.cjs +319 -0
  66. package/dist/chunk-E6XXE66V.js +2252 -0
  67. package/dist/chunk-E7JP3BS3.cjs +61 -0
  68. package/dist/chunk-EKBKLK7P.js +1169 -0
  69. package/dist/chunk-EKYL4PE3.cjs +404 -0
  70. package/dist/chunk-EXKSFGSX.cjs +274 -0
  71. package/dist/chunk-EXUP2BUM.cjs +1173 -0
  72. package/dist/chunk-FDSGHPAK.js +130 -0
  73. package/dist/chunk-FEWUHQNM.cjs +144 -0
  74. package/dist/chunk-FFAOS5HQ.js +70 -0
  75. package/dist/chunk-FGGJQRLZ.js +270 -0
  76. package/dist/chunk-FHP6LXJS.js +415 -0
  77. package/dist/chunk-FJPADH77.cjs +666 -0
  78. package/dist/chunk-FL33V6U7.js +421 -0
  79. package/dist/chunk-FYSPZT4V.cjs +169 -0
  80. package/dist/chunk-GIOYPNTH.js +5575 -0
  81. package/dist/chunk-GJNCFRJU.cjs +125 -0
  82. package/dist/chunk-GMP623FG.cjs +1508 -0
  83. package/dist/chunk-GQHQOPXZ.cjs +5580 -0
  84. package/dist/chunk-GTU2Z2WW.cjs +262 -0
  85. package/dist/chunk-GYZE55MO.js +2007 -0
  86. package/dist/chunk-GZG4KA4E.js +529 -0
  87. package/dist/chunk-H652NHX5.js +600 -0
  88. package/dist/chunk-HCCQLAA4.cjs +74 -0
  89. package/dist/chunk-HKEXJUWS.cjs +4007 -0
  90. package/dist/chunk-HNDK4IQU.cjs +5737 -0
  91. package/dist/chunk-HR2OSYVQ.js +56165 -0
  92. package/dist/chunk-HYNTS5CP.js +422 -0
  93. package/dist/chunk-I6XZ5DZF.cjs +488 -0
  94. package/dist/chunk-ILRBGFVD.cjs +72 -0
  95. package/dist/chunk-IUDGEUDO.cjs +1409 -0
  96. package/dist/chunk-IUTY5WQ2.cjs +424 -0
  97. package/dist/chunk-IVY74O6C.js +247 -0
  98. package/dist/chunk-IWC5DM2M.cjs +611 -0
  99. package/dist/chunk-J32ZJZJH.js +554 -0
  100. package/dist/chunk-J52VSAQ7.js +6884 -0
  101. package/dist/chunk-J6M4FPK5.js +421 -0
  102. package/dist/chunk-J7XZV333.js +844 -0
  103. package/dist/chunk-JBNDTXXV.cjs +2433 -0
  104. package/dist/chunk-JC5YBPSF.cjs +984 -0
  105. package/dist/chunk-JD7CIZ33.js +1949 -0
  106. package/dist/chunk-JIBL5LRK.js +4287 -0
  107. package/dist/chunk-JIYN45TV.cjs +2525 -0
  108. package/dist/chunk-K574J76X.cjs +457 -0
  109. package/dist/chunk-KHDZJE5D.cjs +2196 -0
  110. package/dist/chunk-KKFZ3B6J.cjs +557 -0
  111. package/dist/chunk-KKP7JKN4.cjs +6002 -0
  112. package/dist/chunk-KPJL34Y7.cjs +186 -0
  113. package/dist/chunk-KQCN6AKJ.cjs +3042 -0
  114. package/dist/chunk-L5LKKENW.cjs +424 -0
  115. package/dist/chunk-LHAXPADA.js +882 -0
  116. package/dist/chunk-LM2VU56C.cjs +37 -0
  117. package/dist/chunk-M56JSP4A.js +400 -0
  118. package/dist/chunk-MBOOR7X4.js +18 -0
  119. package/dist/chunk-MQWAT42R.cjs +4310 -0
  120. package/dist/chunk-MXFUTKCO.js +56 -0
  121. package/dist/chunk-MYY4PMWX.cjs +264 -0
  122. package/dist/chunk-N75IH2HY.js +258 -0
  123. package/dist/chunk-NCWCUZNS.cjs +72 -0
  124. package/dist/chunk-NG77ATEW.cjs +778 -0
  125. package/dist/chunk-NW5G5FBQ.js +215 -0
  126. package/dist/chunk-OBIYPYYS.cjs +1993 -0
  127. package/dist/chunk-OH2FAIVU.js +608 -0
  128. package/dist/chunk-OIQYIIO3.cjs +473 -0
  129. package/dist/chunk-OL46QLBJ.js +61 -0
  130. package/dist/chunk-OMXII44L.js +5386 -0
  131. package/dist/chunk-OSYNRVOV.cjs +243 -0
  132. package/dist/chunk-PGANYCAG.cjs +220 -0
  133. package/dist/chunk-PHENW4MQ.js +65 -0
  134. package/dist/chunk-PY37LNDP.js +686 -0
  135. package/dist/chunk-Q56TT7IL.js +483 -0
  136. package/dist/chunk-QD32ADK6.js +1046 -0
  137. package/dist/chunk-QPOQ7VPI.js +1491 -0
  138. package/dist/chunk-QPSKHBJP.js +5963 -0
  139. package/dist/chunk-QXH7QDSZ.js +1989 -0
  140. package/dist/chunk-R24NNAEG.js +1399 -0
  141. package/dist/chunk-R75BSDH7.cjs +50 -0
  142. package/dist/chunk-RARB3MBR.js +207 -0
  143. package/dist/chunk-ROHLEP2W.cjs +847 -0
  144. package/dist/chunk-S3MDHNKB.cjs +490 -0
  145. package/dist/chunk-S6YWHCKV.cjs +410 -0
  146. package/dist/chunk-SIEXCILW.js +229 -0
  147. package/dist/chunk-SLU6UPJI.cjs +410 -0
  148. package/dist/chunk-SMIWS6DE.cjs +212 -0
  149. package/dist/chunk-T5J7ZKP3.cjs +4885 -0
  150. package/dist/chunk-TDCNJHWO.js +341 -0
  151. package/dist/chunk-TG7O4WBC.js +406 -0
  152. package/dist/chunk-THCK6ECW.js +2085 -0
  153. package/dist/chunk-TJHVSBP2.js +439 -0
  154. package/dist/chunk-TVHSPJ4N.cjs +606 -0
  155. package/dist/chunk-TWUXUCEW.cjs +781 -0
  156. package/dist/chunk-U44IKGG7.cjs +5390 -0
  157. package/dist/chunk-UFZZ7TSN.cjs +886 -0
  158. package/dist/chunk-UJXISJBN.js +487 -0
  159. package/dist/chunk-UOIGFQXC.cjs +9750 -0
  160. package/dist/chunk-URG2SJLK.js +2521 -0
  161. package/dist/chunk-UWJHCOH2.js +623 -0
  162. package/dist/chunk-V6MKC2FZ.js +979 -0
  163. package/dist/chunk-VJ3L7CHT.cjs +169 -0
  164. package/dist/chunk-VMLKSV26.js +1216 -0
  165. package/dist/chunk-VVKVQZI6.js +55 -0
  166. package/dist/chunk-W6RW64BB.cjs +1219 -0
  167. package/dist/chunk-WKX5AMOY.js +309 -0
  168. package/dist/chunk-WNNE3PO3.js +34 -0
  169. package/dist/chunk-WRKUDAZJ.js +3038 -0
  170. package/dist/chunk-WRLUBRKS.cjs +1943 -0
  171. package/dist/chunk-WRNEH5MO.js +3169 -0
  172. package/dist/chunk-WRWEX5ZF.js +658 -0
  173. package/dist/chunk-X3GJPRVK.cjs +3246 -0
  174. package/dist/chunk-X3UVCWNL.cjs +2257 -0
  175. package/dist/chunk-XB274MW5.cjs +814 -0
  176. package/dist/chunk-XHIV6326.cjs +793 -0
  177. package/dist/chunk-XIVIE43A.cjs +729 -0
  178. package/dist/chunk-XJAN7CZG.cjs +432 -0
  179. package/dist/chunk-XKTPFXGA.js +164 -0
  180. package/dist/chunk-XL6INWKT.js +121 -0
  181. package/dist/chunk-XSFNHP2E.js +632 -0
  182. package/dist/chunk-XT6JY5W5.js +9684 -0
  183. package/dist/chunk-XUILI4KB.cjs +430 -0
  184. package/dist/chunk-YF2I3MV3.js +46 -0
  185. package/dist/chunk-YIMN575O.js +4847 -0
  186. package/dist/chunk-YIVFJNYV.js +176 -0
  187. package/dist/chunk-YKGPCZEE.cjs +237 -0
  188. package/dist/chunk-YN2YWTXW.js +5731 -0
  189. package/dist/chunk-YN6V7R3L.cjs +327 -0
  190. package/dist/chunk-YQELFNJV.js +39 -0
  191. package/dist/chunk-YVD3CSO3.js +1183 -0
  192. package/dist/chunk-YVOAF4ML.js +623 -0
  193. package/dist/chunk-YWOBW2PV.cjs +759 -0
  194. package/dist/chunk-YYXH45E2.js +426 -0
  195. package/dist/chunk-ZDSYWBIE.cjs +69 -0
  196. package/dist/chunk-ZU7NIRT6.js +325 -0
  197. package/dist/chunk-ZZ7RO2UQ.js +1243 -0
  198. package/dist/cli/holoscript-runner.cjs +2255 -0
  199. package/dist/cli/holoscript-runner.js +2230 -0
  200. package/dist/codebase/index.cjs +336 -0
  201. package/dist/codebase/index.js +331 -0
  202. package/dist/compiler/agent-inference.cjs +31 -0
  203. package/dist/compiler/agent-inference.js +8 -0
  204. package/dist/compiler/android-xr.cjs +24 -0
  205. package/dist/compiler/android-xr.js +14 -0
  206. package/dist/compiler/android.cjs +24 -0
  207. package/dist/compiler/android.js +14 -0
  208. package/dist/compiler/ar.cjs +23 -0
  209. package/dist/compiler/ar.js +11 -0
  210. package/dist/compiler/babylon.cjs +21 -0
  211. package/dist/compiler/babylon.js +15 -0
  212. package/dist/compiler/business-quest.cjs +43 -0
  213. package/dist/compiler/business-quest.js +4 -0
  214. package/dist/compiler/coco.cjs +27 -0
  215. package/dist/compiler/coco.js +4 -0
  216. package/dist/compiler/context.cjs +25 -0
  217. package/dist/compiler/context.d.ts +28 -0
  218. package/dist/compiler/context.js +8 -0
  219. package/dist/compiler/domain-block-utils.cjs +609 -0
  220. package/dist/compiler/domain-block-utils.js +11 -0
  221. package/dist/compiler/dtdl.cjs +27 -0
  222. package/dist/compiler/dtdl.js +11 -0
  223. package/dist/compiler/gltf-pipeline.cjs +39 -0
  224. package/dist/compiler/gltf-pipeline.js +4 -0
  225. package/dist/compiler/godot.cjs +18 -0
  226. package/dist/compiler/godot.js +12 -0
  227. package/dist/compiler/incremental.cjs +34 -0
  228. package/dist/compiler/incremental.js +9 -0
  229. package/dist/compiler/index.cjs +5408 -0
  230. package/dist/compiler/index.d.ts +334 -21
  231. package/dist/compiler/index.js +5069 -0
  232. package/dist/compiler/ios.cjs +23 -0
  233. package/dist/compiler/ios.js +13 -0
  234. package/dist/compiler/llm-provider-capabilities.cjs +25 -0
  235. package/dist/compiler/llm-provider-capabilities.d.ts +43 -0
  236. package/dist/compiler/llm-provider-capabilities.js +8 -0
  237. package/dist/compiler/multi-layer.cjs +24 -0
  238. package/dist/compiler/multi-layer.js +15 -0
  239. package/dist/compiler/nodetoy.cjs +23 -0
  240. package/dist/compiler/nodetoy.d.ts +69 -0
  241. package/dist/compiler/nodetoy.js +4 -0
  242. package/dist/compiler/openxr.cjs +19 -0
  243. package/dist/compiler/openxr.js +13 -0
  244. package/dist/compiler/playcanvas.cjs +19 -0
  245. package/dist/compiler/playcanvas.js +13 -0
  246. package/dist/compiler/r3f.cjs +39 -0
  247. package/dist/compiler/r3f.d.ts +22 -0
  248. package/dist/compiler/r3f.js +17 -0
  249. package/dist/compiler/remotion.cjs +23 -0
  250. package/dist/compiler/remotion.js +4 -0
  251. package/dist/compiler/reproducibility.cjs +39 -0
  252. package/dist/compiler/reproducibility.js +4 -0
  253. package/dist/compiler/sdf.cjs +24 -0
  254. package/dist/compiler/sdf.js +12 -0
  255. package/dist/compiler/semantic-scene.cjs +31 -0
  256. package/dist/compiler/semantic-scene.js +4 -0
  257. package/dist/compiler/state.cjs +21 -0
  258. package/dist/compiler/state.js +11 -0
  259. package/dist/compiler/trait-composition.cjs +30 -0
  260. package/dist/compiler/trait-composition.js +9 -0
  261. package/dist/compiler/unity.cjs +19 -0
  262. package/dist/compiler/unity.js +13 -0
  263. package/dist/compiler/unreal.cjs +23 -0
  264. package/dist/compiler/unreal.js +13 -0
  265. package/dist/compiler/urdf.cjs +52 -0
  266. package/dist/compiler/urdf.js +12 -0
  267. package/dist/compiler/usd-physics.cjs +26 -0
  268. package/dist/compiler/usd-physics.js +9 -0
  269. package/dist/compiler/visionos.cjs +19 -0
  270. package/dist/compiler/visionos.js +13 -0
  271. package/dist/compiler/vrchat.cjs +22 -0
  272. package/dist/compiler/vrchat.js +12 -0
  273. package/dist/compiler/vrr.cjs +24 -0
  274. package/dist/compiler/vrr.js +12 -0
  275. package/dist/compiler/wasm.cjs +36 -0
  276. package/dist/compiler/wasm.js +12 -0
  277. package/dist/compiler/webgpu.cjs +18 -0
  278. package/dist/compiler/webgpu.js +12 -0
  279. package/dist/coordinators/index.cjs +1266 -0
  280. package/dist/coordinators/index.d.ts +72 -1
  281. package/dist/coordinators/index.js +1259 -0
  282. package/dist/debugger.cjs +24 -0
  283. package/dist/debugger.js +11 -0
  284. package/dist/dist-ACXG6IH5.cjs +3113 -0
  285. package/dist/dist-VD4L6V7Q.js +3076 -0
  286. package/dist/entries/interop.cjs +64 -0
  287. package/dist/entries/interop.js +7 -0
  288. package/dist/entries/scripting.cjs +55 -0
  289. package/dist/entries/scripting.js +10 -0
  290. package/dist/hololand/index.cjs +146 -0
  291. package/dist/hololand/index.d.ts +70 -0
  292. package/dist/hololand/index.js +5 -0
  293. package/dist/index.cjs +44660 -0
  294. package/dist/index.d.ts +978 -21
  295. package/dist/index.js +41422 -0
  296. package/dist/math/tropical-spmv.cjs +45 -0
  297. package/dist/math/tropical-spmv.js +4 -0
  298. package/dist/math/vec3.cjs +57 -0
  299. package/dist/math/vec3.js +4 -0
  300. package/dist/ml-dsa-FSKBTE3W.cjs +1265 -0
  301. package/dist/ml-dsa-Z7JDKW4L.js +1265 -0
  302. package/dist/paper-0c-spike/index.cjs +150 -0
  303. package/dist/paper-0c-spike/index.js +141 -0
  304. package/dist/parser.cjs +61 -0
  305. package/dist/parser.d.ts +11 -0
  306. package/dist/parser.js +12 -0
  307. package/dist/playwright-3AT3AKTV.cjs +98673 -0
  308. package/dist/playwright-VZPDVUEQ.js +98660 -0
  309. package/dist/reconstruction/index.cjs +153 -0
  310. package/dist/reconstruction/index.d.ts +29 -2
  311. package/dist/reconstruction/index.js +8 -0
  312. package/dist/runtime.cjs +316 -0
  313. package/dist/runtime.d.ts +61 -0
  314. package/dist/runtime.js +31 -0
  315. package/dist/self-improvement/index.cjs +563 -0
  316. package/dist/self-improvement/index.js +545 -0
  317. package/dist/src-4ROC227P.cjs +2094 -0
  318. package/dist/src-HCCCSYP7.js +2073 -0
  319. package/dist/storage/index.cjs +38 -0
  320. package/dist/storage/index.js +5 -0
  321. package/dist/testing.cjs +25 -0
  322. package/dist/testing.d.ts +70 -0
  323. package/dist/testing.js +4 -0
  324. package/dist/traitDocs/traitDocs.cjs +33 -0
  325. package/dist/traitDocs/traitDocs.js +7 -0
  326. package/dist/traits/botanical-lotus.cjs +177 -0
  327. package/dist/traits/botanical-lotus.d.ts +502 -0
  328. package/dist/traits/botanical-lotus.js +7 -0
  329. package/dist/traits/engines/index.cjs +520 -0
  330. package/dist/traits/engines/index.js +380 -0
  331. package/dist/traits/index.cjs +24548 -0
  332. package/dist/traits/index.d.ts +171 -35
  333. package/dist/traits/index.js +21638 -0
  334. package/dist/traits/simulation-solver-factory.cjs +13 -0
  335. package/dist/traits/simulation-solver-factory.d.ts +23 -0
  336. package/dist/traits/simulation-solver-factory.js +4 -0
  337. package/dist/traits/webcam-gaze.cjs +35 -0
  338. package/dist/traits/webcam-gaze.d.ts +17 -0
  339. package/dist/traits/webcam-gaze.js +4 -0
  340. package/dist/type-checker.cjs +19 -0
  341. package/dist/type-checker.js +6 -0
  342. package/dist/world/index.cjs +947 -0
  343. package/dist/world/index.d.ts +147 -0
  344. package/dist/world/index.js +939 -0
  345. package/dist/world-model/index.cjs +1446 -0
  346. package/dist/world-model/index.d.ts +119 -0
  347. package/dist/world-model/index.js +1414 -0
  348. package/dist/wot/index.cjs +29 -0
  349. package/dist/wot/index.js +4 -0
  350. package/package.json +93 -49
@@ -0,0 +1,2257 @@
1
+ 'use strict';
2
+
3
+ var chunkEXUP2BUM_cjs = require('./chunk-EXUP2BUM.cjs');
4
+ var chunkALC6K7GL_cjs = require('./chunk-ALC6K7GL.cjs');
5
+ var chunkOIQYIIO3_cjs = require('./chunk-OIQYIIO3.cjs');
6
+ var chunkHKEXJUWS_cjs = require('./chunk-HKEXJUWS.cjs');
7
+ var chunkKKP7JKN4_cjs = require('./chunk-KKP7JKN4.cjs');
8
+ var ans = require('@holoscript/core-types/ans');
9
+
10
+ // src/compiler/GLTFPipeline.ts
11
+ chunkOIQYIIO3_cjs.init_TraitCompositor();
12
+ chunkALC6K7GL_cjs.init_R3FCompiler();
13
+ chunkKKP7JKN4_cjs.init_CompilerBase();
14
+ chunkHKEXJUWS_cjs.init_DomainBlockCompilerMixin();
15
+
16
+ // src/compiler/gltf/extensions.ts
17
+ function createEmissiveStrengthExtension(strength) {
18
+ return {
19
+ KHR_materials_emissive_strength: {
20
+ emissiveStrength: Math.max(0, strength)
21
+ }
22
+ };
23
+ }
24
+ function createClearcoatExtension(options) {
25
+ return {
26
+ KHR_materials_clearcoat: {
27
+ clearcoatFactor: options.factor ?? 1,
28
+ clearcoatRoughnessFactor: options.roughness ?? 0
29
+ }
30
+ };
31
+ }
32
+ function createTransmissionExtension(factor) {
33
+ return {
34
+ KHR_materials_transmission: {
35
+ transmissionFactor: Math.max(0, Math.min(1, factor))
36
+ }
37
+ };
38
+ }
39
+ function createIORExtension(ior) {
40
+ return {
41
+ KHR_materials_ior: {
42
+ ior: Math.max(1, ior)
43
+ }
44
+ };
45
+ }
46
+ function createSheenExtension(options) {
47
+ return {
48
+ KHR_materials_sheen: {
49
+ sheenColorFactor: options.color ?? [1, 1, 1],
50
+ sheenRoughnessFactor: options.roughness ?? 0.5
51
+ }
52
+ };
53
+ }
54
+ function createAnisotropyExtension(options) {
55
+ return {
56
+ KHR_materials_anisotropy: {
57
+ anisotropyStrength: Math.max(0, Math.min(1, options.strength ?? 0.5)),
58
+ anisotropyRotation: options.rotation ?? 0
59
+ }
60
+ };
61
+ }
62
+ function createVolumeExtension(options) {
63
+ return {
64
+ KHR_materials_volume: {
65
+ thicknessFactor: options.thickness ?? 1,
66
+ attenuationDistance: options.attenuationDistance ?? 1,
67
+ attenuationColor: options.attenuationColor ?? [1, 1, 1]
68
+ }
69
+ };
70
+ }
71
+ function createIridescenceExtension(options) {
72
+ return {
73
+ KHR_materials_iridescence: {
74
+ iridescenceFactor: options.factor ?? 1,
75
+ iridescenceIor: options.ior ?? 1.3,
76
+ iridescenceThicknessMinimum: options.thicknessRange?.[0] ?? 100,
77
+ iridescenceThicknessMaximum: options.thicknessRange?.[1] ?? 400
78
+ }
79
+ };
80
+ }
81
+ function collectUsedExtensions(gltf) {
82
+ const extensions = /* @__PURE__ */ new Set();
83
+ const materials = gltf.materials;
84
+ if (materials) {
85
+ for (const material of materials) {
86
+ if (material.extensions) {
87
+ Object.keys(material.extensions).forEach((ext) => extensions.add(ext));
88
+ }
89
+ }
90
+ }
91
+ const nodes = gltf.nodes;
92
+ if (nodes) {
93
+ for (const node of nodes) {
94
+ if (node.extensions) {
95
+ Object.keys(node.extensions).forEach((ext) => extensions.add(ext));
96
+ }
97
+ }
98
+ }
99
+ if (gltf.extensions) {
100
+ Object.keys(gltf.extensions).forEach((ext) => extensions.add(ext));
101
+ }
102
+ return Array.from(extensions);
103
+ }
104
+ function isExtensionRequired(extension) {
105
+ const requiredExtensions = [
106
+ "KHR_draco_mesh_compression",
107
+ "KHR_mesh_quantization",
108
+ "KHR_texture_basisu"
109
+ ];
110
+ return requiredExtensions.includes(extension);
111
+ }
112
+ function declareExtensions(gltf) {
113
+ const usedExtensions = collectUsedExtensions(gltf);
114
+ if (usedExtensions.length === 0) return;
115
+ gltf.extensionsUsed = usedExtensions;
116
+ const required = usedExtensions.filter(isExtensionRequired);
117
+ if (required.length > 0) {
118
+ gltf.extensionsRequired = required;
119
+ }
120
+ }
121
+
122
+ // src/compiler/GLTFPipeline.ts
123
+ chunkALC6K7GL_cjs.init_ObjectPool();
124
+ var gltfNodePool = new chunkALC6K7GL_cjs.ASTNodePool(
125
+ () => ({ name: "" }),
126
+ (node) => {
127
+ node.name = "";
128
+ node.translation = void 0;
129
+ node.rotation = void 0;
130
+ node.scale = void 0;
131
+ node.mesh = void 0;
132
+ node.skin = void 0;
133
+ node.children = void 0;
134
+ node.camera = void 0;
135
+ node.extras = void 0;
136
+ },
137
+ 0
138
+ // Was 10000 — demand-allocate instead of pre-allocating
139
+ );
140
+ var PRIMITIVE_GENERATORS = {
141
+ cube: generateCubeGeometry,
142
+ box: generateCubeGeometry,
143
+ sphere: generateSphereGeometry,
144
+ orb: generateSphereGeometry,
145
+ cylinder: generateCylinderGeometry,
146
+ cone: generateConeGeometry,
147
+ pyramid: generateConeGeometry,
148
+ plane: generatePlaneGeometry,
149
+ ground: generatePlaneGeometry
150
+ };
151
+ function generateScaleTexture(size = 512, baseColor = [30, 15, 61], borderColor = [20, 12, 40], highlightColor = [70, 50, 120]) {
152
+ const data = new Uint8Array(size * size * 4);
153
+ const scaleSize = size / 16;
154
+ const hexH = scaleSize;
155
+ const hexW = scaleSize * Math.sqrt(3);
156
+ function scaleHash(row, col) {
157
+ let h = row * 73856093 ^ col * 19349663;
158
+ h = (h >> 16 ^ h) * 73244475;
159
+ h = (h >> 16 ^ h) * 73244475;
160
+ return (h >> 16 ^ h) & 255;
161
+ }
162
+ for (let y = 0; y < size; y++) {
163
+ for (let x = 0; x < size; x++) {
164
+ const row = Math.floor(y / (hexH * 0.75));
165
+ const isOddRow = row % 2 === 1;
166
+ const xOff = isOddRow ? hexW * 0.5 : 0;
167
+ const col = Math.floor((x + xOff) / hexW);
168
+ const cx = col * hexW - xOff + hexW * 0.5;
169
+ const cy = row * hexH * 0.75 + hexH * 0.5;
170
+ const dx = (x - cx) / (hexW * 0.5);
171
+ const dy = (y - cy) / (hexH * 0.5);
172
+ const q = Math.abs(dx);
173
+ const r = Math.abs(dy);
174
+ const hexDist = Math.max(q, (q + r * Math.sqrt(3)) / 2);
175
+ const jitter = (scaleHash(row, col) / 255 - 0.5) * 40;
176
+ const jR = Math.round(jitter * 0.4);
177
+ const jG = Math.round(jitter * 0.3);
178
+ const jB = Math.round(jitter * 0.6);
179
+ const idx = (y * size + x) * 4;
180
+ if (hexDist > 0.94) {
181
+ data[idx] = Math.max(0, borderColor[0] + jR);
182
+ data[idx + 1] = Math.max(0, borderColor[1] + jG);
183
+ data[idx + 2] = Math.max(0, borderColor[2] + jB);
184
+ data[idx + 3] = 255;
185
+ } else if (hexDist < 0.12) {
186
+ const t = hexDist / 0.12;
187
+ const specR = 100, specG = 80, specB = 160;
188
+ data[idx] = Math.min(255, Math.round(specR * (1 - t) + highlightColor[0] * t) + jR);
189
+ data[idx + 1] = Math.min(255, Math.round(specG * (1 - t) + highlightColor[1] * t) + jG);
190
+ data[idx + 2] = Math.min(255, Math.round(specB * (1 - t) + highlightColor[2] * t) + jB);
191
+ data[idx + 3] = 255;
192
+ } else if (hexDist < 0.35) {
193
+ const t = (hexDist - 0.12) / 0.23;
194
+ data[idx] = Math.min(255, Math.round(highlightColor[0] * (1 - t) + baseColor[0] * t) + jR);
195
+ data[idx + 1] = Math.min(
196
+ 255,
197
+ Math.round(highlightColor[1] * (1 - t) + baseColor[1] * t) + jG
198
+ );
199
+ data[idx + 2] = Math.min(
200
+ 255,
201
+ Math.round(highlightColor[2] * (1 - t) + baseColor[2] * t) + jB
202
+ );
203
+ data[idx + 3] = 255;
204
+ } else {
205
+ const t = (hexDist - 0.35) / 0.59;
206
+ data[idx] = Math.max(
207
+ 0,
208
+ Math.min(255, Math.round(baseColor[0] * (1 - t * 0.3) + borderColor[0] * (t * 0.3)) + jR)
209
+ );
210
+ data[idx + 1] = Math.max(
211
+ 0,
212
+ Math.min(255, Math.round(baseColor[1] * (1 - t * 0.3) + borderColor[1] * (t * 0.3)) + jG)
213
+ );
214
+ data[idx + 2] = Math.max(
215
+ 0,
216
+ Math.min(255, Math.round(baseColor[2] * (1 - t * 0.3) + borderColor[2] * (t * 0.3)) + jB)
217
+ );
218
+ data[idx + 3] = 255;
219
+ }
220
+ }
221
+ }
222
+ return data;
223
+ }
224
+ function generateScaleNormalMap(size = 512) {
225
+ const data = new Uint8Array(size * size * 4);
226
+ const scaleSize = size / 16;
227
+ const hexH = scaleSize;
228
+ const hexW = scaleSize * Math.sqrt(3);
229
+ for (let y = 0; y < size; y++) {
230
+ for (let x = 0; x < size; x++) {
231
+ const row = Math.floor(y / (hexH * 0.75));
232
+ const isOddRow = row % 2 === 1;
233
+ const xOff = isOddRow ? hexW * 0.5 : 0;
234
+ const col = Math.floor((x + xOff) / hexW);
235
+ const cx = col * hexW - xOff + hexW * 0.5;
236
+ const cy = row * hexH * 0.75 + hexH * 0.5;
237
+ const dx = (x - cx) / (hexW * 0.5);
238
+ const dy = (y - cy) / (hexH * 0.5);
239
+ const q = Math.abs(dx);
240
+ const r = Math.abs(dy);
241
+ const hexDist = Math.max(q, (q + r * Math.sqrt(3)) / 2);
242
+ const idx = (y * size + x) * 4;
243
+ let nx = 0, ny = 0, nz = 1;
244
+ if (hexDist > 0.92 && hexDist < 1) {
245
+ const len = Math.sqrt(dx * dx + dy * dy) || 1;
246
+ const strength = 0.55;
247
+ nx = dx / len * strength;
248
+ ny = dy / len * strength;
249
+ nz = Math.sqrt(Math.max(0, 1 - nx * nx - ny * ny));
250
+ } else if (hexDist < 0.5) {
251
+ const strength = 0.25;
252
+ nx = -dx * strength;
253
+ ny = -dy * strength;
254
+ nz = Math.sqrt(Math.max(0, 1 - nx * nx - ny * ny));
255
+ }
256
+ data[idx] = Math.round((nx * 0.5 + 0.5) * 255);
257
+ data[idx + 1] = Math.round((ny * 0.5 + 0.5) * 255);
258
+ data[idx + 2] = Math.round((nz * 0.5 + 0.5) * 255);
259
+ data[idx + 3] = 255;
260
+ }
261
+ }
262
+ return data;
263
+ }
264
+ function encodePNG(pixels, width, height) {
265
+ const rowSize = width * 4 + 1;
266
+ const rawData = new Uint8Array(rowSize * height);
267
+ for (let y = 0; y < height; y++) {
268
+ rawData[y * rowSize] = 0;
269
+ rawData.set(pixels.slice(y * width * 4, (y + 1) * width * 4), y * rowSize + 1);
270
+ }
271
+ const deflated = deflateStored(rawData);
272
+ const crcTable = [];
273
+ for (let n = 0; n < 256; n++) {
274
+ let c = n;
275
+ for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
276
+ crcTable[n] = c;
277
+ }
278
+ function crc32(buf) {
279
+ let crc = 4294967295;
280
+ for (let i = 0; i < buf.length; i++) crc = crcTable[(crc ^ buf[i]) & 255] ^ crc >>> 8;
281
+ return (crc ^ 4294967295) >>> 0;
282
+ }
283
+ function writeChunk(type, data) {
284
+ const chunk = new Uint8Array(4 + 4 + data.length + 4);
285
+ const dv = new DataView(chunk.buffer);
286
+ dv.setUint32(0, data.length);
287
+ for (let i = 0; i < 4; i++) chunk[4 + i] = type.charCodeAt(i);
288
+ chunk.set(data, 8);
289
+ const crcInput = new Uint8Array(4 + data.length);
290
+ crcInput.set(chunk.slice(4, 8));
291
+ crcInput.set(data, 4);
292
+ dv.setUint32(8 + data.length, crc32(crcInput));
293
+ return chunk;
294
+ }
295
+ const signature = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
296
+ const ihdr = new Uint8Array(13);
297
+ const ihdrDV = new DataView(ihdr.buffer);
298
+ ihdrDV.setUint32(0, width);
299
+ ihdrDV.setUint32(4, height);
300
+ ihdr[8] = 8;
301
+ ihdr[9] = 6;
302
+ ihdr[10] = 0;
303
+ ihdr[11] = 0;
304
+ ihdr[12] = 0;
305
+ const ihdrChunk = writeChunk("IHDR", ihdr);
306
+ const idatChunk = writeChunk("IDAT", deflated);
307
+ const iendChunk = writeChunk("IEND", new Uint8Array(0));
308
+ const png = new Uint8Array(
309
+ signature.length + ihdrChunk.length + idatChunk.length + iendChunk.length
310
+ );
311
+ let offset = 0;
312
+ png.set(signature, offset);
313
+ offset += signature.length;
314
+ png.set(ihdrChunk, offset);
315
+ offset += ihdrChunk.length;
316
+ png.set(idatChunk, offset);
317
+ offset += idatChunk.length;
318
+ png.set(iendChunk, offset);
319
+ return png;
320
+ }
321
+ function decimateGeometry(geometry, ratio) {
322
+ const cellSize = Math.max(0.01, (1 - ratio) * 0.3);
323
+ const positions = geometry.positions;
324
+ const normals = geometry.normals;
325
+ const uvs = geometry.uvs;
326
+ const indices = geometry.indices;
327
+ const vertCount = positions.length / 3;
328
+ const cellMap = /* @__PURE__ */ new Map();
329
+ const remap = new Int32Array(vertCount);
330
+ const newPositions = [];
331
+ const newNormals = [];
332
+ const newUVs = [];
333
+ let newIdx = 0;
334
+ for (let i = 0; i < vertCount; i++) {
335
+ const px = positions[i * 3], py = positions[i * 3 + 1], pz = positions[i * 3 + 2];
336
+ const cx = Math.round(px / cellSize), cy = Math.round(py / cellSize), cz = Math.round(pz / cellSize);
337
+ const key = `${cx},${cy},${cz}`;
338
+ if (cellMap.has(key)) {
339
+ remap[i] = cellMap.get(key);
340
+ } else {
341
+ cellMap.set(key, newIdx);
342
+ remap[i] = newIdx;
343
+ newPositions.push(px, py, pz);
344
+ newNormals.push(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);
345
+ newUVs.push(uvs[i * 2], uvs[i * 2 + 1]);
346
+ newIdx++;
347
+ }
348
+ }
349
+ const newIndices = [];
350
+ for (let i = 0; i < indices.length; i += 3) {
351
+ const a = remap[indices[i]], b = remap[indices[i + 1]], c = remap[indices[i + 2]];
352
+ if (a !== b && b !== c && a !== c) {
353
+ newIndices.push(a, b, c);
354
+ }
355
+ }
356
+ const newVertexCount = newPositions.length / 3;
357
+ const IndexArrayType = newVertexCount > 65535 ? Uint32Array : Uint16Array;
358
+ return {
359
+ positions: new Float32Array(newPositions),
360
+ normals: new Float32Array(newNormals),
361
+ uvs: new Float32Array(newUVs),
362
+ indices: new IndexArrayType(newIndices)
363
+ };
364
+ }
365
+ var DRAGON_SKELETON = [
366
+ { name: "Root", position: [0, 2.5, 0] },
367
+ { name: "Spine", position: [0, 2.5, 0], parent: "Root" },
368
+ { name: "Neck", position: [0, 3.5, 2], parent: "Spine" },
369
+ { name: "Head", position: [0, 4.5, 4.2], parent: "Neck" },
370
+ { name: "Jaw", position: [0, 4.2, 4.6], parent: "Head" },
371
+ { name: "Tail1", position: [0, 2.2, -2], parent: "Spine" },
372
+ { name: "Tail2", position: [0, 1, -3.5], parent: "Tail1" },
373
+ { name: "TailTip", position: [0, -0.05, -4.6], parent: "Tail2" },
374
+ { name: "LeftWing", position: [-1.2, 3, 0.2], parent: "Spine" },
375
+ { name: "LeftWingTip", position: [-2.6, 3.8, 0.2], parent: "LeftWing" },
376
+ { name: "RightWing", position: [1.2, 3, 0.2], parent: "Spine" },
377
+ { name: "RightWingTip", position: [2.6, 3.8, 0.2], parent: "RightWing" },
378
+ { name: "LeftFrontLeg", position: [-0.9, 1.6, 1.2], parent: "Spine" },
379
+ { name: "LeftFrontFoot", position: [-0.95, 0.15, 1.4], parent: "LeftFrontLeg" },
380
+ { name: "RightFrontLeg", position: [0.9, 1.6, 1.2], parent: "Spine" },
381
+ { name: "RightFrontFoot", position: [0.95, 0.15, 1.4], parent: "RightFrontLeg" },
382
+ { name: "LeftBackLeg", position: [-0.9, 1.5, -1], parent: "Spine" },
383
+ { name: "LeftBackFoot", position: [-0.95, 0.1, -1.15], parent: "LeftBackLeg" },
384
+ { name: "RightBackLeg", position: [0.9, 1.5, -1], parent: "Spine" },
385
+ { name: "RightBackFoot", position: [0.95, 0.1, -1.15], parent: "RightBackLeg" }
386
+ ];
387
+ function deflateStored(data) {
388
+ const BLOCK_MAX = 65535;
389
+ const numBlocks = Math.ceil(data.length / BLOCK_MAX) || 1;
390
+ let size = 2 + 4;
391
+ for (let i = 0; i < numBlocks; i++) {
392
+ size += 5;
393
+ const blockLen = Math.min(BLOCK_MAX, data.length - i * BLOCK_MAX);
394
+ size += blockLen;
395
+ }
396
+ const out = new Uint8Array(size);
397
+ let pos = 0;
398
+ out[pos++] = 120;
399
+ out[pos++] = 1;
400
+ for (let i = 0; i < numBlocks; i++) {
401
+ const blockStart = i * BLOCK_MAX;
402
+ const blockLen = Math.min(BLOCK_MAX, data.length - blockStart);
403
+ const isLast = i === numBlocks - 1;
404
+ out[pos++] = isLast ? 1 : 0;
405
+ out[pos++] = blockLen & 255;
406
+ out[pos++] = blockLen >> 8 & 255;
407
+ out[pos++] = ~blockLen & 255;
408
+ out[pos++] = ~blockLen >> 8 & 255;
409
+ out.set(data.slice(blockStart, blockStart + blockLen), pos);
410
+ pos += blockLen;
411
+ }
412
+ let a = 1, b = 0;
413
+ for (let i = 0; i < data.length; i++) {
414
+ a = (a + data[i]) % 65521;
415
+ b = (b + a) % 65521;
416
+ }
417
+ const adler = (b << 16 | a) >>> 0;
418
+ out[pos++] = adler >> 24 & 255;
419
+ out[pos++] = adler >> 16 & 255;
420
+ out[pos++] = adler >> 8 & 255;
421
+ out[pos++] = adler & 255;
422
+ return out;
423
+ }
424
+ var ADVANCED_GEOMETRY_TYPES = /* @__PURE__ */ new Set(["spline", "membrane", "hull", "blob", "metaball"]);
425
+ function generateCubeGeometry(scale) {
426
+ const [sx, sy, sz] = scale.map((s) => s * 0.5);
427
+ const positions = new Float32Array([
428
+ // Front face
429
+ -sx,
430
+ -sy,
431
+ sz,
432
+ sx,
433
+ -sy,
434
+ sz,
435
+ sx,
436
+ sy,
437
+ sz,
438
+ -sx,
439
+ sy,
440
+ sz,
441
+ // Back face
442
+ -sx,
443
+ -sy,
444
+ -sz,
445
+ -sx,
446
+ sy,
447
+ -sz,
448
+ sx,
449
+ sy,
450
+ -sz,
451
+ sx,
452
+ -sy,
453
+ -sz,
454
+ // Top face
455
+ -sx,
456
+ sy,
457
+ -sz,
458
+ -sx,
459
+ sy,
460
+ sz,
461
+ sx,
462
+ sy,
463
+ sz,
464
+ sx,
465
+ sy,
466
+ -sz,
467
+ // Bottom face
468
+ -sx,
469
+ -sy,
470
+ -sz,
471
+ sx,
472
+ -sy,
473
+ -sz,
474
+ sx,
475
+ -sy,
476
+ sz,
477
+ -sx,
478
+ -sy,
479
+ sz,
480
+ // Right face
481
+ sx,
482
+ -sy,
483
+ -sz,
484
+ sx,
485
+ sy,
486
+ -sz,
487
+ sx,
488
+ sy,
489
+ sz,
490
+ sx,
491
+ -sy,
492
+ sz,
493
+ // Left face
494
+ -sx,
495
+ -sy,
496
+ -sz,
497
+ -sx,
498
+ -sy,
499
+ sz,
500
+ -sx,
501
+ sy,
502
+ sz,
503
+ -sx,
504
+ sy,
505
+ -sz
506
+ ]);
507
+ const normals = new Float32Array([
508
+ // Front
509
+ 0,
510
+ 0,
511
+ 1,
512
+ 0,
513
+ 0,
514
+ 1,
515
+ 0,
516
+ 0,
517
+ 1,
518
+ 0,
519
+ 0,
520
+ 1,
521
+ // Back
522
+ 0,
523
+ 0,
524
+ -1,
525
+ 0,
526
+ 0,
527
+ -1,
528
+ 0,
529
+ 0,
530
+ -1,
531
+ 0,
532
+ 0,
533
+ -1,
534
+ // Top
535
+ 0,
536
+ 1,
537
+ 0,
538
+ 0,
539
+ 1,
540
+ 0,
541
+ 0,
542
+ 1,
543
+ 0,
544
+ 0,
545
+ 1,
546
+ 0,
547
+ // Bottom
548
+ 0,
549
+ -1,
550
+ 0,
551
+ 0,
552
+ -1,
553
+ 0,
554
+ 0,
555
+ -1,
556
+ 0,
557
+ 0,
558
+ -1,
559
+ 0,
560
+ // Right
561
+ 1,
562
+ 0,
563
+ 0,
564
+ 1,
565
+ 0,
566
+ 0,
567
+ 1,
568
+ 0,
569
+ 0,
570
+ 1,
571
+ 0,
572
+ 0,
573
+ // Left
574
+ -1,
575
+ 0,
576
+ 0,
577
+ -1,
578
+ 0,
579
+ 0,
580
+ -1,
581
+ 0,
582
+ 0,
583
+ -1,
584
+ 0,
585
+ 0
586
+ ]);
587
+ const uvs = new Float32Array([
588
+ // Front
589
+ 0,
590
+ 0,
591
+ 1,
592
+ 0,
593
+ 1,
594
+ 1,
595
+ 0,
596
+ 1,
597
+ // Back
598
+ 1,
599
+ 0,
600
+ 1,
601
+ 1,
602
+ 0,
603
+ 1,
604
+ 0,
605
+ 0,
606
+ // Top
607
+ 0,
608
+ 1,
609
+ 0,
610
+ 0,
611
+ 1,
612
+ 0,
613
+ 1,
614
+ 1,
615
+ // Bottom
616
+ 1,
617
+ 1,
618
+ 0,
619
+ 1,
620
+ 0,
621
+ 0,
622
+ 1,
623
+ 0,
624
+ // Right
625
+ 1,
626
+ 0,
627
+ 1,
628
+ 1,
629
+ 0,
630
+ 1,
631
+ 0,
632
+ 0,
633
+ // Left
634
+ 0,
635
+ 0,
636
+ 1,
637
+ 0,
638
+ 1,
639
+ 1,
640
+ 0,
641
+ 1
642
+ ]);
643
+ const indices = new Uint16Array([
644
+ 0,
645
+ 1,
646
+ 2,
647
+ 0,
648
+ 2,
649
+ 3,
650
+ // Front
651
+ 4,
652
+ 5,
653
+ 6,
654
+ 4,
655
+ 6,
656
+ 7,
657
+ // Back
658
+ 8,
659
+ 9,
660
+ 10,
661
+ 8,
662
+ 10,
663
+ 11,
664
+ // Top
665
+ 12,
666
+ 13,
667
+ 14,
668
+ 12,
669
+ 14,
670
+ 15,
671
+ // Bottom
672
+ 16,
673
+ 17,
674
+ 18,
675
+ 16,
676
+ 18,
677
+ 19,
678
+ // Right
679
+ 20,
680
+ 21,
681
+ 22,
682
+ 20,
683
+ 22,
684
+ 23
685
+ // Left
686
+ ]);
687
+ return { positions, normals, uvs, indices };
688
+ }
689
+ function generateSphereGeometry(scale) {
690
+ const sx = scale[0] * 0.5;
691
+ const sy = scale[1] * 0.5;
692
+ const sz = scale[2] * 0.5;
693
+ const segments = 32;
694
+ const rings = 24;
695
+ const positions = [];
696
+ const normals = [];
697
+ const uvs = [];
698
+ const indices = [];
699
+ for (let y = 0; y <= rings; y++) {
700
+ const v = y / rings;
701
+ const theta = v * Math.PI;
702
+ for (let x = 0; x <= segments; x++) {
703
+ const u = x / segments;
704
+ const phi = u * Math.PI * 2;
705
+ const nx = Math.sin(theta) * Math.cos(phi);
706
+ const ny = Math.cos(theta);
707
+ const nz = Math.sin(theta) * Math.sin(phi);
708
+ positions.push(nx * sx);
709
+ positions.push(ny * sy);
710
+ positions.push(nz * sz);
711
+ normals.push(nx, ny, nz);
712
+ uvs.push(u, 1 - v);
713
+ }
714
+ }
715
+ for (let y = 0; y < rings; y++) {
716
+ for (let x = 0; x < segments; x++) {
717
+ const a = y * (segments + 1) + x;
718
+ const b = a + segments + 1;
719
+ indices.push(a, b, a + 1);
720
+ indices.push(b, b + 1, a + 1);
721
+ }
722
+ }
723
+ return {
724
+ positions: new Float32Array(positions),
725
+ normals: new Float32Array(normals),
726
+ uvs: new Float32Array(uvs),
727
+ indices: new Uint16Array(indices)
728
+ };
729
+ }
730
+ function generateCylinderGeometry(scale) {
731
+ const radiusTop = scale[0] * 0.5;
732
+ const radiusBottom = scale[2] * 0.5;
733
+ const height = scale[1];
734
+ const segments = 32;
735
+ const positions = [];
736
+ const normals = [];
737
+ const uvs = [];
738
+ const indices = [];
739
+ const halfHeight = height / 2;
740
+ for (let y = 0; y <= 1; y++) {
741
+ const radius = y === 0 ? radiusBottom : radiusTop;
742
+ const posY = y === 0 ? -halfHeight : halfHeight;
743
+ for (let x = 0; x <= segments; x++) {
744
+ const u = x / segments;
745
+ const theta = u * Math.PI * 2;
746
+ const cosTheta = Math.cos(theta);
747
+ const sinTheta = Math.sin(theta);
748
+ positions.push(radius * cosTheta, posY, radius * sinTheta);
749
+ normals.push(cosTheta, 0, sinTheta);
750
+ uvs.push(u, y);
751
+ }
752
+ }
753
+ for (let x = 0; x < segments; x++) {
754
+ const a = x;
755
+ const b = x + segments + 1;
756
+ indices.push(a, b, a + 1);
757
+ indices.push(b, b + 1, a + 1);
758
+ }
759
+ const topCenterIndex = positions.length / 3;
760
+ positions.push(0, halfHeight, 0);
761
+ normals.push(0, 1, 0);
762
+ uvs.push(0.5, 0.5);
763
+ for (let x = 0; x <= segments; x++) {
764
+ const u = x / segments;
765
+ const theta = u * Math.PI * 2;
766
+ positions.push(radiusTop * Math.cos(theta), halfHeight, radiusTop * Math.sin(theta));
767
+ normals.push(0, 1, 0);
768
+ uvs.push(Math.cos(theta) * 0.5 + 0.5, Math.sin(theta) * 0.5 + 0.5);
769
+ }
770
+ for (let x = 0; x < segments; x++) {
771
+ indices.push(topCenterIndex, topCenterIndex + x + 1, topCenterIndex + x + 2);
772
+ }
773
+ const bottomCenterIndex = positions.length / 3;
774
+ positions.push(0, -halfHeight, 0);
775
+ normals.push(0, -1, 0);
776
+ uvs.push(0.5, 0.5);
777
+ for (let x = 0; x <= segments; x++) {
778
+ const u = x / segments;
779
+ const theta = u * Math.PI * 2;
780
+ positions.push(radiusBottom * Math.cos(theta), -halfHeight, radiusBottom * Math.sin(theta));
781
+ normals.push(0, -1, 0);
782
+ uvs.push(Math.cos(theta) * 0.5 + 0.5, Math.sin(theta) * 0.5 + 0.5);
783
+ }
784
+ for (let x = 0; x < segments; x++) {
785
+ indices.push(bottomCenterIndex, bottomCenterIndex + x + 2, bottomCenterIndex + x + 1);
786
+ }
787
+ return {
788
+ positions: new Float32Array(positions),
789
+ normals: new Float32Array(normals),
790
+ uvs: new Float32Array(uvs),
791
+ indices: new Uint16Array(indices)
792
+ };
793
+ }
794
+ function generateConeGeometry(scale) {
795
+ return generateCylinderGeometry([1e-3, scale[1], scale[2]]);
796
+ }
797
+ function generatePlaneGeometry(scale) {
798
+ const [sx, _, sz] = scale.map((s) => s * 0.5);
799
+ const positions = new Float32Array([
800
+ -sx,
801
+ 0,
802
+ -sz,
803
+ sx,
804
+ 0,
805
+ -sz,
806
+ sx,
807
+ 0,
808
+ sz,
809
+ -sx,
810
+ 0,
811
+ sz
812
+ ]);
813
+ const normals = new Float32Array([
814
+ 0,
815
+ 1,
816
+ 0,
817
+ 0,
818
+ 1,
819
+ 0,
820
+ 0,
821
+ 1,
822
+ 0,
823
+ 0,
824
+ 1,
825
+ 0
826
+ ]);
827
+ const uvs = new Float32Array([
828
+ 0,
829
+ 0,
830
+ 1,
831
+ 0,
832
+ 1,
833
+ 1,
834
+ 0,
835
+ 1
836
+ ]);
837
+ const indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
838
+ return { positions, normals, uvs, indices };
839
+ }
840
+ var INITIAL_COMPILE_BUFFER_SIZE = 1024 * 1024;
841
+ var MAX_RETAINED_BUFFER_SIZE = 1024 * 1024 * 20;
842
+ var SHARED_COMPILE_BUFFER = new Uint8Array(INITIAL_COMPILE_BUFFER_SIZE);
843
+ var GLTFPipeline = class extends chunkKKP7JKN4_cjs.CompilerBase {
844
+ constructor(options = {}) {
845
+ super();
846
+ this.compilerName = "GLTFPipeline";
847
+ this.bufferByteLength = 0;
848
+ this.accessors = [];
849
+ this.bufferViews = [];
850
+ this.meshes = [];
851
+ this.materials = [];
852
+ this.nodes = [];
853
+ this.scenes = [];
854
+ this.animations = [];
855
+ this.materialMap = /* @__PURE__ */ new Map();
856
+ this.images = [];
857
+ this.textures = [];
858
+ this.samplers = [];
859
+ this.scaleTextureIndex = -1;
860
+ this.scaleNormalTextureIndex = -1;
861
+ this.textureIndexMap = /* @__PURE__ */ new Map();
862
+ this.stats = {
863
+ nodeCount: 0,
864
+ meshCount: 0,
865
+ materialCount: 0,
866
+ textureCount: 0,
867
+ animationCount: 0,
868
+ totalVertices: 0,
869
+ totalTriangles: 0,
870
+ fileSizeBytes: 0
871
+ };
872
+ this._lodCoverages = null;
873
+ this._skins = null;
874
+ this._jointStartIndex = 0;
875
+ this.options = {
876
+ provenanceHash: options.provenanceHash ?? "",
877
+ format: options.format ?? "glb",
878
+ dracoCompression: options.dracoCompression ?? false,
879
+ quantize: options.quantize ?? true,
880
+ prune: options.prune ?? true,
881
+ dedupe: options.dedupe ?? true,
882
+ embedTextures: options.embedTextures ?? true,
883
+ textureData: options.textureData ?? {},
884
+ generator: options.generator ?? "HoloScript GLTFPipeline v1.0.0",
885
+ copyright: options.copyright ?? ""
886
+ };
887
+ this.compositor = new chunkOIQYIIO3_cjs.TraitCompositor();
888
+ }
889
+ getRequiredCapability() {
890
+ return ans.ANSCapabilityPath.GLTF;
891
+ }
892
+ get bufferData() {
893
+ return SHARED_COMPILE_BUFFER;
894
+ }
895
+ set bufferData(v) {
896
+ SHARED_COMPILE_BUFFER = v;
897
+ }
898
+ ensureBufferCapacity(needed) {
899
+ if (this.bufferByteLength + needed > this.bufferData.length) {
900
+ const newLen = Math.max(this.bufferData.length * 2, this.bufferByteLength + needed);
901
+ const newArr = new Uint8Array(newLen);
902
+ newArr.set(this.bufferData.subarray(0, this.bufferByteLength));
903
+ this.bufferData = newArr;
904
+ }
905
+ }
906
+ appendToBuffer(data) {
907
+ this.ensureBufferCapacity(data.length);
908
+ this.bufferData.set(data, this.bufferByteLength);
909
+ this.bufferByteLength += data.length;
910
+ }
911
+ padBuffer(alignment) {
912
+ const remainder = this.bufferByteLength % alignment;
913
+ if (remainder !== 0) {
914
+ const padding = alignment - remainder;
915
+ this.ensureBufferCapacity(padding);
916
+ this.bufferByteLength += padding;
917
+ }
918
+ }
919
+ /**
920
+ * Global smooth normals pass.
921
+ * Finds vertices at the same 3D position across all meshes and averages
922
+ * their normals. This eliminates hard seams where separate meshes meet
923
+ * (e.g., neck spline meets the head sphere).
924
+ */
925
+ smoothNormalsGlobal() {
926
+ const QUANT = 100;
927
+ const posMap = /* @__PURE__ */ new Map();
928
+ for (const mesh of this.meshes) {
929
+ for (const prim of mesh.primitives) {
930
+ const posIdx = prim.attributes.POSITION;
931
+ const nrmIdx = prim.attributes.NORMAL;
932
+ if (posIdx === void 0 || nrmIdx === void 0) continue;
933
+ const posAcc = this.accessors[posIdx];
934
+ const nrmAcc = this.accessors[nrmIdx];
935
+ if (!posAcc || !nrmAcc) continue;
936
+ const posBV = this.bufferViews[posAcc.bufferView];
937
+ const nrmBV = this.bufferViews[nrmAcc.bufferView];
938
+ if (!posBV || !nrmBV) continue;
939
+ const count = posAcc.count;
940
+ for (let i = 0; i < count; i++) {
941
+ const pOff = posBV.byteOffset + i * 12;
942
+ const px = this.readFloat32(pOff);
943
+ const py = this.readFloat32(pOff + 4);
944
+ const pz = this.readFloat32(pOff + 8);
945
+ const nOff = nrmBV.byteOffset + i * 12;
946
+ const nx = this.readFloat32(nOff);
947
+ const ny = this.readFloat32(nOff + 4);
948
+ const nz = this.readFloat32(nOff + 8);
949
+ const key = `${Math.round(px * QUANT)},${Math.round(py * QUANT)},${Math.round(pz * QUANT)}`;
950
+ let entries = posMap.get(key);
951
+ if (!entries) {
952
+ entries = [];
953
+ posMap.set(key, entries);
954
+ }
955
+ entries.push({ nx, ny, nz, byteOffset: nOff });
956
+ }
957
+ }
958
+ }
959
+ for (const entries of posMap.values()) {
960
+ if (entries.length < 2) continue;
961
+ let ax = 0, ay = 0, az = 0;
962
+ for (const e of entries) {
963
+ ax += e.nx;
964
+ ay += e.ny;
965
+ az += e.nz;
966
+ }
967
+ const len = Math.sqrt(ax * ax + ay * ay + az * az);
968
+ if (len < 1e-8) continue;
969
+ ax /= len;
970
+ ay /= len;
971
+ az /= len;
972
+ for (const e of entries) {
973
+ this.writeFloat32(e.byteOffset, ax);
974
+ this.writeFloat32(e.byteOffset + 4, ay);
975
+ this.writeFloat32(e.byteOffset + 8, az);
976
+ }
977
+ }
978
+ }
979
+ /** Read a Float32 from the buffer at byteOffset */
980
+ readFloat32(byteOffset) {
981
+ const bytes = new Uint8Array(4);
982
+ bytes.set(this.bufferData.subarray(byteOffset, byteOffset + 4));
983
+ return new Float32Array(bytes.buffer)[0];
984
+ }
985
+ /** Write a Float32 to the buffer at byteOffset */
986
+ writeFloat32(byteOffset, value) {
987
+ const f32 = new Float32Array([value]);
988
+ const view = new Uint8Array(f32.buffer);
989
+ this.bufferData.set(view, byteOffset);
990
+ }
991
+ /**
992
+ * Generate LOD meshes for the MSFT_lod extension.
993
+ * Creates 2 lower detail levels (50% and 25%) per mesh.
994
+ */
995
+ generateLODs() {
996
+ const ratios = [0.5, 0.25];
997
+ const originalCount = this.meshes.length;
998
+ const coverages = [];
999
+ for (let mi = 0; mi < originalCount; mi++) {
1000
+ const mesh = this.meshes[mi];
1001
+ const lodIds = [];
1002
+ for (const ratio of ratios) {
1003
+ for (const prim of mesh.primitives) {
1004
+ const posIdx = prim.attributes.POSITION;
1005
+ const nrmIdx = prim.attributes.NORMAL;
1006
+ const uvIdx = prim.attributes.TEXCOORD_0;
1007
+ const idxIdx = prim.indices;
1008
+ if (posIdx === void 0 || nrmIdx === void 0 || idxIdx === void 0) continue;
1009
+ const posAcc = this.accessors[posIdx];
1010
+ const nrmAcc = this.accessors[nrmIdx];
1011
+ const idxAcc = this.accessors[idxIdx];
1012
+ if (!posAcc || !nrmAcc || !idxAcc) continue;
1013
+ const posBV = this.bufferViews[posAcc.bufferView];
1014
+ const nrmBV = this.bufferViews[nrmAcc.bufferView];
1015
+ const idxBV = this.bufferViews[idxAcc.bufferView];
1016
+ if (!posBV || !nrmBV || !idxBV) continue;
1017
+ const vCount = posAcc.count;
1018
+ const iCount = idxAcc.count;
1019
+ const positions = new Float32Array(vCount * 3);
1020
+ const normals = new Float32Array(vCount * 3);
1021
+ const uvs = new Float32Array(vCount * 2);
1022
+ const indices = new Uint16Array(iCount);
1023
+ for (let i = 0; i < vCount * 3; i++) {
1024
+ positions[i] = this.readFloat32(posBV.byteOffset + i * 4);
1025
+ normals[i] = this.readFloat32(nrmBV.byteOffset + i * 4);
1026
+ }
1027
+ if (uvIdx !== void 0) {
1028
+ const uvAcc = this.accessors[uvIdx];
1029
+ const uvBV = uvAcc ? this.bufferViews[uvAcc.bufferView] : null;
1030
+ if (uvBV) {
1031
+ for (let i = 0; i < vCount * 2; i++) {
1032
+ uvs[i] = this.readFloat32(uvBV.byteOffset + i * 4);
1033
+ }
1034
+ }
1035
+ }
1036
+ const compSize = idxAcc.componentType === 5123 ? 2 : 4;
1037
+ for (let i = 0; i < iCount; i++) {
1038
+ const off = idxBV.byteOffset + i * compSize;
1039
+ if (compSize === 2) {
1040
+ indices[i] = this.bufferData[off] | this.bufferData[off + 1] << 8;
1041
+ } else {
1042
+ indices[i] = this.readFloat32(off);
1043
+ }
1044
+ }
1045
+ const geom = { positions, normals, uvs, indices };
1046
+ const decimated = decimateGeometry(geom, ratio);
1047
+ const lodMeshIndex = this.meshes.length;
1048
+ const lodPrim = { attributes: {}, material: prim.material };
1049
+ lodPrim.attributes.POSITION = this.createAccessor(decimated.positions, "VEC3", true);
1050
+ lodPrim.attributes.NORMAL = this.createAccessor(decimated.normals, "VEC3");
1051
+ lodPrim.attributes.TEXCOORD_0 = this.createAccessor(decimated.uvs, "VEC2");
1052
+ lodPrim.indices = this.createAccessor(decimated.indices, "SCALAR");
1053
+ this.meshes.push({ name: `LOD${ratio}_mesh${mi}`, primitives: [lodPrim] });
1054
+ lodIds.push(lodMeshIndex);
1055
+ }
1056
+ }
1057
+ if (lodIds.length > 0) {
1058
+ mesh["extensions"] = {
1059
+ MSFT_lod: { ids: lodIds }
1060
+ };
1061
+ coverages.push(0.5, 0.2);
1062
+ }
1063
+ }
1064
+ if (coverages.length > 0) {
1065
+ this._lodCoverages = coverages;
1066
+ }
1067
+ }
1068
+ /**
1069
+ * Build skeleton hierarchy and embed as glTF skin.
1070
+ * Creates 20 joint nodes with inverse bind matrices.
1071
+ */
1072
+ buildSkeleton() {
1073
+ const bones = DRAGON_SKELETON;
1074
+ const boneNameToIdx = /* @__PURE__ */ new Map();
1075
+ const jointStartIndex = this.nodes.length;
1076
+ for (let i = 0; i < bones.length; i++) {
1077
+ const bone = bones[i];
1078
+ const nodeIdx = this.nodes.length;
1079
+ boneNameToIdx.set(bone.name, nodeIdx);
1080
+ const node = {
1081
+ name: `Joint_${bone.name}`,
1082
+ translation: bone.position
1083
+ };
1084
+ this.nodes.push(node);
1085
+ }
1086
+ for (const bone of bones) {
1087
+ if (bone.parent) {
1088
+ const parentIdx = boneNameToIdx.get(bone.parent);
1089
+ const childIdx = boneNameToIdx.get(bone.name);
1090
+ if (parentIdx !== void 0 && childIdx !== void 0) {
1091
+ const parentNode = this.nodes[parentIdx];
1092
+ if (!parentNode.children) parentNode.children = [];
1093
+ parentNode.children.push(childIdx);
1094
+ }
1095
+ }
1096
+ }
1097
+ const ibmData = new Float32Array(bones.length * 16);
1098
+ for (let i = 0; i < bones.length; i++) {
1099
+ const p = bones[i].position;
1100
+ const off = i * 16;
1101
+ ibmData[off + 0] = 1;
1102
+ ibmData[off + 5] = 1;
1103
+ ibmData[off + 10] = 1;
1104
+ ibmData[off + 15] = 1;
1105
+ ibmData[off + 12] = -p[0];
1106
+ ibmData[off + 13] = -p[1];
1107
+ ibmData[off + 14] = -p[2];
1108
+ }
1109
+ const ibmAccessor = this.createAccessorRaw(ibmData, "MAT4", 5126);
1110
+ const joints = [];
1111
+ for (let i = 0; i < bones.length; i++) {
1112
+ joints.push(jointStartIndex + i);
1113
+ }
1114
+ this._skins = [
1115
+ {
1116
+ skeleton: jointStartIndex,
1117
+ joints,
1118
+ inverseBindMatrices: ibmAccessor
1119
+ }
1120
+ ];
1121
+ this._jointStartIndex = jointStartIndex;
1122
+ }
1123
+ /**
1124
+ * Skin all mesh nodes to the skeleton.
1125
+ * For each vertex, finds the 4 nearest bones by distance and assigns
1126
+ * normalized inverse-distance weights. Writes JOINTS_0 (Uint8) and
1127
+ * WEIGHTS_0 (Float32) attributes into each mesh primitive.
1128
+ */
1129
+ skinMeshes() {
1130
+ if (!this._skins || this._skins.length === 0) return;
1131
+ const bones = DRAGON_SKELETON;
1132
+ const bonePositions = bones.map((b) => b.position);
1133
+ const originalNodeCount = this._jointStartIndex;
1134
+ for (let ni = 0; ni < originalNodeCount; ni++) {
1135
+ const node = this.nodes[ni];
1136
+ if (node.mesh === void 0) continue;
1137
+ const mesh = this.meshes[node.mesh];
1138
+ if (!mesh) continue;
1139
+ for (const prim of mesh.primitives) {
1140
+ const posIdx = prim.attributes.POSITION;
1141
+ if (posIdx === void 0) continue;
1142
+ const posAcc = this.accessors[posIdx];
1143
+ if (!posAcc) continue;
1144
+ const posBV = this.bufferViews[posAcc.bufferView];
1145
+ if (!posBV) continue;
1146
+ const vCount = posAcc.count;
1147
+ if (vCount === 0) continue;
1148
+ const tx = node.translation ? node.translation[0] : 0;
1149
+ const ty = node.translation ? node.translation[1] : 0;
1150
+ const tz = node.translation ? node.translation[2] : 0;
1151
+ const jointsData = new Uint8Array(vCount * 4);
1152
+ const weightsData = new Float32Array(vCount * 4);
1153
+ for (let vi = 0; vi < vCount; vi++) {
1154
+ const pOff = posBV.byteOffset + vi * 12;
1155
+ const vx = this.readFloat32(pOff) + tx;
1156
+ const vy = this.readFloat32(pOff + 4) + ty;
1157
+ const vz = this.readFloat32(pOff + 8) + tz;
1158
+ const distances = [];
1159
+ for (let bi = 0; bi < bonePositions.length; bi++) {
1160
+ const bp = bonePositions[bi];
1161
+ const dx = vx - bp[0], dy = vy - bp[1], dz = vz - bp[2];
1162
+ distances.push({ boneIdx: bi, distSq: dx * dx + dy * dy + dz * dz });
1163
+ }
1164
+ distances.sort((a, b) => a.distSq - b.distSq);
1165
+ const top4 = distances.slice(0, 4);
1166
+ let totalWeight = 0;
1167
+ const rawWeights = [];
1168
+ for (const d of top4) {
1169
+ const w = 1 / (d.distSq + 1e-4);
1170
+ rawWeights.push(w);
1171
+ totalWeight += w;
1172
+ }
1173
+ const off = vi * 4;
1174
+ for (let j = 0; j < 4; j++) {
1175
+ if (j < top4.length) {
1176
+ jointsData[off + j] = top4[j].boneIdx;
1177
+ weightsData[off + j] = rawWeights[j] / totalWeight;
1178
+ } else {
1179
+ jointsData[off + j] = 0;
1180
+ weightsData[off + j] = 0;
1181
+ }
1182
+ }
1183
+ }
1184
+ prim.attributes.JOINTS_0 = this.createAccessorRaw(jointsData, "VEC4", 5121);
1185
+ prim.attributes.WEIGHTS_0 = this.createAccessor(weightsData, "VEC4");
1186
+ }
1187
+ }
1188
+ }
1189
+ /**
1190
+ * Compile a HoloScript composition to glTF format
1191
+ */
1192
+ compile(composition, agentToken, outputPath) {
1193
+ this.validateCompilerAccess(agentToken, outputPath);
1194
+ this.reset();
1195
+ this.processComposition(composition);
1196
+ this.smoothNormalsGlobal();
1197
+ this.generateLODs();
1198
+ this.buildSkeleton();
1199
+ this.skinMeshes();
1200
+ const buffer = this.bufferData.slice(0, this.bufferByteLength);
1201
+ if (SHARED_COMPILE_BUFFER.length > MAX_RETAINED_BUFFER_SIZE) {
1202
+ SHARED_COMPILE_BUFFER = new Uint8Array(INITIAL_COMPILE_BUFFER_SIZE);
1203
+ }
1204
+ const gltf = this.buildDocument(composition, buffer.byteLength);
1205
+ if (this.options.format === "glb") {
1206
+ const binary = this.createGLB(gltf, buffer);
1207
+ this.stats.fileSizeBytes = binary.byteLength;
1208
+ return {
1209
+ binary,
1210
+ stats: { ...this.stats }
1211
+ };
1212
+ } else {
1213
+ this.stats.fileSizeBytes = JSON.stringify(gltf).length + buffer.byteLength;
1214
+ return {
1215
+ json: gltf,
1216
+ buffer,
1217
+ stats: { ...this.stats }
1218
+ };
1219
+ }
1220
+ }
1221
+ /**
1222
+ * Reset pipeline state for new compilation
1223
+ */
1224
+ reset() {
1225
+ this.bufferByteLength = 0;
1226
+ this.accessors = [];
1227
+ this.bufferViews = [];
1228
+ this.meshes = [];
1229
+ this.materials = [];
1230
+ this.nodes = [];
1231
+ this.scenes = [];
1232
+ this.animations = [];
1233
+ this.materialMap.clear();
1234
+ this.images = [];
1235
+ this.textures = [];
1236
+ this.samplers = [];
1237
+ this.scaleTextureIndex = -1;
1238
+ this.scaleNormalTextureIndex = -1;
1239
+ this.textureIndexMap.clear();
1240
+ this.stats = {
1241
+ nodeCount: 0,
1242
+ meshCount: 0,
1243
+ materialCount: 0,
1244
+ textureCount: 0,
1245
+ animationCount: 0,
1246
+ totalVertices: 0,
1247
+ totalTriangles: 0,
1248
+ fileSizeBytes: 0
1249
+ };
1250
+ }
1251
+ /**
1252
+ * Process the entire composition
1253
+ */
1254
+ processComposition(composition) {
1255
+ const rootNodes = [];
1256
+ for (const object of composition.objects || []) {
1257
+ const nodeIndex = this.processObject(object);
1258
+ if (nodeIndex !== -1) {
1259
+ rootNodes.push(nodeIndex);
1260
+ }
1261
+ }
1262
+ for (const group of composition.spatialGroups || []) {
1263
+ const nodeIndex = this.processSpatialGroup(group);
1264
+ if (nodeIndex !== -1) {
1265
+ rootNodes.push(nodeIndex);
1266
+ }
1267
+ }
1268
+ for (const light of composition.lights || []) {
1269
+ const nodeIndex = this.processLight(light);
1270
+ if (nodeIndex !== -1) {
1271
+ rootNodes.push(nodeIndex);
1272
+ }
1273
+ }
1274
+ if (composition.camera) {
1275
+ const nodeIndex = this.processCamera(composition.camera);
1276
+ if (nodeIndex !== -1) {
1277
+ rootNodes.push(nodeIndex);
1278
+ }
1279
+ }
1280
+ for (const timeline of composition.timelines || []) {
1281
+ this.processTimeline(timeline);
1282
+ }
1283
+ const domainBlocks = composition.domainBlocks ?? [];
1284
+ if (domainBlocks.length > 0) {
1285
+ chunkHKEXJUWS_cjs.compileDomainBlocks(
1286
+ domainBlocks,
1287
+ {
1288
+ material: (block) => {
1289
+ const mat = chunkHKEXJUWS_cjs.compileMaterialBlock(block);
1290
+ const gltfMat = chunkHKEXJUWS_cjs.materialToGLTF(mat);
1291
+ this.materials.push(gltfMat);
1292
+ this.stats.materialCount++;
1293
+ return "";
1294
+ }
1295
+ },
1296
+ () => ""
1297
+ );
1298
+ }
1299
+ this.scenes.push({
1300
+ name: composition.name,
1301
+ nodes: rootNodes
1302
+ });
1303
+ }
1304
+ /**
1305
+ * Process a single object
1306
+ */
1307
+ processObject(object) {
1308
+ const position = this.extractVec3Prop(object, "position", [0, 0, 0]);
1309
+ const rotation = this.extractVec3Prop(object, "rotation", [0, 0, 0]);
1310
+ const scale = this.extractVec3Prop(object, "scale", [1, 1, 1]);
1311
+ const geometryProp = this.findProp(object, "geometry") || this.findProp(object, "mesh") || this.findProp(object, "type");
1312
+ const shapeType = (typeof geometryProp === "string" ? geometryProp : "box").toLowerCase();
1313
+ let meshIndex;
1314
+ if (PRIMITIVE_GENERATORS[shapeType]) {
1315
+ meshIndex = this.createPrimitiveMesh(object.name, shapeType, scale, object);
1316
+ } else if (ADVANCED_GEOMETRY_TYPES.has(shapeType)) {
1317
+ meshIndex = this.createAdvancedMesh(object.name, shapeType, scale, object);
1318
+ }
1319
+ const node = gltfNodePool.acquire();
1320
+ node.name = object.name || `node_${this.nodes.length}`;
1321
+ node.translation = position;
1322
+ node.rotation = this.eulerToQuaternion(rotation);
1323
+ node.scale = [1, 1, 1];
1324
+ if (meshIndex !== void 0) {
1325
+ node.mesh = meshIndex;
1326
+ }
1327
+ if (object.children && object.children.length > 0) {
1328
+ const childIndices = [];
1329
+ for (const child of object.children) {
1330
+ const childIdx = this.processObject(child);
1331
+ if (childIdx !== -1) childIndices.push(childIdx);
1332
+ }
1333
+ if (childIndices.length > 0) node.children = childIndices;
1334
+ }
1335
+ const nodeIndex = this.nodes.length;
1336
+ this.nodes.push(node);
1337
+ this.stats.nodeCount++;
1338
+ return nodeIndex;
1339
+ }
1340
+ /**
1341
+ * Process a spatial group
1342
+ */
1343
+ processSpatialGroup(group) {
1344
+ const childIndices = [];
1345
+ for (const child of group.objects || []) {
1346
+ const childIndex = this.processObject(child);
1347
+ if (childIndex !== -1) {
1348
+ childIndices.push(childIndex);
1349
+ }
1350
+ }
1351
+ if (group.groups) {
1352
+ for (const sub of group.groups) {
1353
+ const subIdx = this.processSpatialGroup(sub);
1354
+ if (subIdx !== -1) childIndices.push(subIdx);
1355
+ }
1356
+ }
1357
+ const posProp = (group.properties || []).find((p) => p.key === "position");
1358
+ const position = posProp && Array.isArray(posProp.value) ? [
1359
+ Number(posProp.value[0]) || 0,
1360
+ Number(posProp.value[1]) || 0,
1361
+ Number(posProp.value[2]) || 0
1362
+ ] : [0, 0, 0];
1363
+ const node = gltfNodePool.acquire();
1364
+ node.name = group.name || `group_${this.nodes.length}`;
1365
+ node.translation = position;
1366
+ if (childIndices.length > 0) {
1367
+ node.children = childIndices;
1368
+ }
1369
+ const nodeIndex = this.nodes.length;
1370
+ this.nodes.push(node);
1371
+ this.stats.nodeCount++;
1372
+ return nodeIndex;
1373
+ }
1374
+ /**
1375
+ * Process a timeline as animation.
1376
+ *
1377
+ * HoloTimeline has entries: HoloTimelineEntry[] where each entry has
1378
+ * { time: number, action: HoloTimelineAction }.
1379
+ * We extract 'animate' actions and group them by target + property.
1380
+ */
1381
+ processTimeline(timeline) {
1382
+ if (!timeline.entries || timeline.entries.length === 0) return;
1383
+ const animateEntries = timeline.entries.filter((e) => e.action.kind === "animate").map((e) => ({
1384
+ time: e.time,
1385
+ target: e.action.target,
1386
+ properties: e.action.properties
1387
+ }));
1388
+ if (animateEntries.length === 0) return;
1389
+ const channels = [];
1390
+ const samplers = [];
1391
+ const grouped = /* @__PURE__ */ new Map();
1392
+ for (const entry of animateEntries) {
1393
+ const targetNodeIndex = this.nodes.findIndex((n) => n.name === entry.target);
1394
+ if (targetNodeIndex === -1) continue;
1395
+ for (const [prop, value] of Object.entries(entry.properties)) {
1396
+ const gltfPath = this.mapPropertyToGLTFPath(prop);
1397
+ if (!gltfPath) continue;
1398
+ const key = `${targetNodeIndex}:${gltfPath}`;
1399
+ if (!grouped.has(key)) grouped.set(key, []);
1400
+ grouped.get(key).push({ time: entry.time, value });
1401
+ }
1402
+ }
1403
+ for (const [key, keyframes] of grouped) {
1404
+ const [nodeIdxStr, gltfPath] = key.split(":");
1405
+ const nodeIdx = parseInt(nodeIdxStr, 10);
1406
+ const times = keyframes.map((kf) => kf.time / 1e3);
1407
+ const inputAccessor = this.createAccessor(new Float32Array(times), "SCALAR");
1408
+ const values = [];
1409
+ for (const kf of keyframes) {
1410
+ if (Array.isArray(kf.value)) {
1411
+ if (gltfPath === "rotation") {
1412
+ const quat = this.eulerToQuaternion(kf.value);
1413
+ values.push(...quat);
1414
+ } else {
1415
+ values.push(...kf.value);
1416
+ }
1417
+ }
1418
+ }
1419
+ const outputType = gltfPath === "rotation" ? "VEC4" : "VEC3";
1420
+ const outputAccessor = this.createAccessor(new Float32Array(values), outputType);
1421
+ const samplerIndex = samplers.length;
1422
+ samplers.push({ input: inputAccessor, interpolation: "LINEAR", output: outputAccessor });
1423
+ channels.push({ sampler: samplerIndex, target: { node: nodeIdx, path: gltfPath } });
1424
+ }
1425
+ if (channels.length > 0) {
1426
+ this.animations.push({
1427
+ name: timeline.name || `animation_${this.animations.length}`,
1428
+ channels,
1429
+ samplers
1430
+ });
1431
+ this.stats.animationCount++;
1432
+ }
1433
+ }
1434
+ /**
1435
+ * Create a primitive mesh
1436
+ */
1437
+ createPrimitiveMesh(name, shapeType, scale, object) {
1438
+ const generator = PRIMITIVE_GENERATORS[shapeType];
1439
+ if (!generator) return -1;
1440
+ const geometry = generator(scale);
1441
+ const positionAccessor = this.createAccessor(geometry.positions, "VEC3", true);
1442
+ const normalAccessor = this.createAccessor(geometry.normals, "VEC3");
1443
+ const uvAccessor = this.createAccessor(geometry.uvs, "VEC2");
1444
+ const indexAccessor = this.createAccessor(geometry.indices, "SCALAR");
1445
+ const materialIndex = this.getOrCreateMaterial(object, shapeType);
1446
+ const mesh = {
1447
+ name: name || `mesh_${this.meshes.length}`,
1448
+ primitives: [
1449
+ {
1450
+ attributes: {
1451
+ POSITION: positionAccessor,
1452
+ NORMAL: normalAccessor,
1453
+ TEXCOORD_0: uvAccessor
1454
+ },
1455
+ indices: indexAccessor,
1456
+ material: materialIndex,
1457
+ mode: 4
1458
+ // TRIANGLES
1459
+ }
1460
+ ]
1461
+ };
1462
+ const meshIndex = this.meshes.length;
1463
+ this.meshes.push(mesh);
1464
+ this.stats.meshCount++;
1465
+ this.stats.totalVertices += geometry.positions.length / 3;
1466
+ this.stats.totalTriangles += geometry.indices.length / 3;
1467
+ return meshIndex;
1468
+ }
1469
+ /**
1470
+ * Create an advanced mesh (spline, membrane, hull/metaball).
1471
+ * These geometry types need additional properties beyond scale.
1472
+ */
1473
+ createAdvancedMesh(name, shapeType, scale, object) {
1474
+ let geometry;
1475
+ switch (shapeType) {
1476
+ case "spline": {
1477
+ const pointsProp = this.findProp(object, "points");
1478
+ const radiiProp = this.findProp(object, "radii");
1479
+ const segmentsProp = this.findProp(object, "segments");
1480
+ const stepsProp = this.findProp(object, "steps");
1481
+ const points = this.extractNestedArray(pointsProp, 3);
1482
+ const radii = Array.isArray(radiiProp) ? radiiProp.map(Number) : [0.1];
1483
+ while (radii.length < points.length) {
1484
+ radii.push(radii[radii.length - 1] ?? 0.1);
1485
+ }
1486
+ const radialSegments = typeof segmentsProp === "number" ? segmentsProp : 24;
1487
+ const lengthSteps = typeof stepsProp === "number" ? stepsProp : 8;
1488
+ geometry = chunkEXUP2BUM_cjs.generateSplineGeometry(points, radii, radialSegments, lengthSteps);
1489
+ break;
1490
+ }
1491
+ case "membrane": {
1492
+ const anchorsProp = this.findProp(object, "anchors");
1493
+ const subdivisionsProp = this.findProp(object, "subdivisions");
1494
+ const bulgeProp = this.findProp(object, "bulge");
1495
+ const anchors = this.extractNestedArray(anchorsProp, 3);
1496
+ const subdivisions = typeof subdivisionsProp === "number" ? subdivisionsProp : 8;
1497
+ const bulge = typeof bulgeProp === "number" ? bulgeProp : 0.15;
1498
+ geometry = chunkEXUP2BUM_cjs.generateMembraneGeometry(anchors, subdivisions, bulge);
1499
+ break;
1500
+ }
1501
+ case "hull":
1502
+ case "blob":
1503
+ case "metaball": {
1504
+ const blobsProp = this.findProp(object, "blobs");
1505
+ const resolutionProp = this.findProp(object, "resolution");
1506
+ const thresholdProp = this.findProp(object, "threshold");
1507
+ const blobs = [];
1508
+ if (Array.isArray(blobsProp)) {
1509
+ for (const blobItem of blobsProp) {
1510
+ if (blobItem && typeof blobItem === "object") {
1511
+ const b = blobItem;
1512
+ const center = Array.isArray(b.center) ? b.center.map(Number) : [0, 0, 0];
1513
+ const radius = Array.isArray(b.radius) ? b.radius.map(Number) : [0.5, 0.5, 0.5];
1514
+ blobs.push({ center, radius });
1515
+ }
1516
+ }
1517
+ }
1518
+ if (blobs.length === 0) {
1519
+ blobs.push({
1520
+ center: [0, 0, 0],
1521
+ radius: [scale[0] * 0.5, scale[1] * 0.5, scale[2] * 0.5]
1522
+ });
1523
+ }
1524
+ const resolution = typeof resolutionProp === "number" ? resolutionProp : 24;
1525
+ const threshold = typeof thresholdProp === "number" ? thresholdProp : 1;
1526
+ geometry = chunkEXUP2BUM_cjs.generateHullGeometry(blobs, resolution, threshold);
1527
+ break;
1528
+ }
1529
+ default:
1530
+ return -1;
1531
+ }
1532
+ const positionAccessor = this.createAccessor(geometry.positions, "VEC3", true);
1533
+ const normalAccessor = this.createAccessor(geometry.normals, "VEC3");
1534
+ const uvAccessor = this.createAccessor(geometry.uvs, "VEC2");
1535
+ const indexAccessor = this.createAccessor(geometry.indices, "SCALAR");
1536
+ const materialIndex = this.getOrCreateMaterial(object, shapeType);
1537
+ const mesh = {
1538
+ name: name || `mesh_${this.meshes.length}`,
1539
+ primitives: [
1540
+ {
1541
+ attributes: {
1542
+ POSITION: positionAccessor,
1543
+ NORMAL: normalAccessor,
1544
+ TEXCOORD_0: uvAccessor
1545
+ },
1546
+ indices: indexAccessor,
1547
+ material: materialIndex,
1548
+ mode: 4
1549
+ // TRIANGLES
1550
+ }
1551
+ ]
1552
+ };
1553
+ const meshIndex = this.meshes.length;
1554
+ this.meshes.push(mesh);
1555
+ this.stats.meshCount++;
1556
+ this.stats.totalVertices += geometry.positions.length / 3;
1557
+ this.stats.totalTriangles += geometry.indices.length / 3;
1558
+ return meshIndex;
1559
+ }
1560
+ /**
1561
+ * Extract a nested array of vec3s from a HoloValue.
1562
+ * e.g. [[0, 1, 2], [3, 4, 5]] => [[0,1,2], [3,4,5]]
1563
+ */
1564
+ extractNestedArray(val, expectedLength) {
1565
+ const result = [];
1566
+ if (!Array.isArray(val)) return result;
1567
+ for (const item of val) {
1568
+ if (Array.isArray(item) && item.length >= expectedLength) {
1569
+ result.push(item.slice(0, expectedLength).map(Number));
1570
+ }
1571
+ }
1572
+ return result;
1573
+ }
1574
+ /**
1575
+ * Get or create a material from object properties + traits.
1576
+ *
1577
+ * Material composition order (later overrides earlier):
1578
+ * 1. Defaults (white, metallic 0, roughness 0.5)
1579
+ * 2. Named material preset (e.g., material: "glass")
1580
+ * 3. TraitCompositor output (PBR from visual presets)
1581
+ * 4. Direct property overrides (color, opacity)
1582
+ */
1583
+ getOrCreateMaterial(object, shapeType) {
1584
+ let color = [1, 1, 1];
1585
+ let metallic = 0;
1586
+ let roughness = 0.5;
1587
+ let opacity = 1;
1588
+ let emissive = [0, 0, 0];
1589
+ let transmission = 0;
1590
+ let ior = 1.5;
1591
+ let thickness = 0;
1592
+ let clearcoat = 0;
1593
+ let clearcoatRoughness = 0;
1594
+ let sheen = 0;
1595
+ let sheenRoughness = 0.5;
1596
+ let sheenColor = [1, 1, 1];
1597
+ let iridescence = 0;
1598
+ let iridescenceIOR = 1.3;
1599
+ let anisotropy = 0;
1600
+ let anisotropyRotation = 0;
1601
+ let attenuationColor;
1602
+ let attenuationDistance;
1603
+ const namedMat = this.findProp(object, "material");
1604
+ if (typeof namedMat === "string" && chunkALC6K7GL_cjs.MATERIAL_PRESETS[namedMat]) {
1605
+ const preset = chunkALC6K7GL_cjs.MATERIAL_PRESETS[namedMat];
1606
+ if (preset.color) color = this.parseColorString(preset.color);
1607
+ if (preset.metalness !== void 0) metallic = preset.metalness;
1608
+ if (preset.roughness !== void 0) roughness = preset.roughness;
1609
+ if (preset.opacity !== void 0) opacity = preset.opacity;
1610
+ if (preset.transparent && opacity >= 1) opacity = 0.99;
1611
+ if (preset.emissive) emissive = this.parseColorString(preset.emissive);
1612
+ if (preset.transmission !== void 0) transmission = preset.transmission;
1613
+ if (preset.ior !== void 0) ior = preset.ior;
1614
+ if (preset.thickness !== void 0) thickness = preset.thickness;
1615
+ if (preset.clearcoat !== void 0) clearcoat = preset.clearcoat;
1616
+ if (preset.clearcoatRoughness !== void 0) clearcoatRoughness = preset.clearcoatRoughness;
1617
+ if (preset.sheen !== void 0) sheen = preset.sheen;
1618
+ if (preset.sheenRoughness !== void 0) sheenRoughness = preset.sheenRoughness;
1619
+ if (preset.sheenColor) sheenColor = this.parseColorString(preset.sheenColor);
1620
+ if (preset.iridescence !== void 0) iridescence = preset.iridescence;
1621
+ if (preset.iridescenceIOR !== void 0) iridescenceIOR = preset.iridescenceIOR;
1622
+ if (preset.anisotropy !== void 0) anisotropy = preset.anisotropy;
1623
+ if (preset.anisotropyRotation !== void 0) anisotropyRotation = preset.anisotropyRotation;
1624
+ if (preset.attenuationColor)
1625
+ attenuationColor = this.parseColorString(preset.attenuationColor);
1626
+ if (preset.attenuationDistance !== void 0)
1627
+ attenuationDistance = preset.attenuationDistance;
1628
+ }
1629
+ const traitNames = (object.traits || []).map((t) => t.name);
1630
+ if (traitNames.length > 0) {
1631
+ const composed = this.compositor.compose(traitNames);
1632
+ if (composed.color) color = this.parseColorString(composed.color);
1633
+ if (composed.metalness !== void 0) metallic = composed.metalness;
1634
+ if (composed.roughness !== void 0) roughness = composed.roughness;
1635
+ if (composed.opacity !== void 0) opacity = composed.opacity;
1636
+ if (composed.emissive) emissive = this.parseColorString(composed.emissive);
1637
+ if (composed.transparent) opacity = Math.min(opacity, 0.9);
1638
+ if (composed.transmission !== void 0) transmission = composed.transmission;
1639
+ if (composed.ior !== void 0) ior = composed.ior;
1640
+ if (composed.thickness !== void 0) thickness = composed.thickness;
1641
+ if (composed.clearcoat !== void 0) clearcoat = composed.clearcoat;
1642
+ if (composed.clearcoatRoughness !== void 0)
1643
+ clearcoatRoughness = composed.clearcoatRoughness;
1644
+ if (composed.sheen !== void 0) sheen = composed.sheen;
1645
+ if (composed.sheenRoughness !== void 0) sheenRoughness = composed.sheenRoughness;
1646
+ if (composed.sheenColor) sheenColor = this.parseColorString(composed.sheenColor);
1647
+ if (composed.iridescence !== void 0) iridescence = composed.iridescence;
1648
+ if (composed.iridescenceIOR !== void 0) iridescenceIOR = composed.iridescenceIOR;
1649
+ if (composed.anisotropy !== void 0) anisotropy = composed.anisotropy;
1650
+ if (composed.anisotropyRotation !== void 0)
1651
+ anisotropyRotation = composed.anisotropyRotation;
1652
+ if (composed.attenuationColor)
1653
+ attenuationColor = this.parseColorString(composed.attenuationColor);
1654
+ if (composed.attenuationDistance !== void 0)
1655
+ attenuationDistance = composed.attenuationDistance;
1656
+ }
1657
+ const colorProp = this.findProp(object, "color");
1658
+ if (typeof colorProp === "string") {
1659
+ color = this.parseColorString(colorProp);
1660
+ } else if (Array.isArray(colorProp) && colorProp.length >= 3) {
1661
+ color = [Number(colorProp[0]), Number(colorProp[1]), Number(colorProp[2])];
1662
+ }
1663
+ const opacityProp = this.findProp(object, "opacity");
1664
+ if (typeof opacityProp === "number") opacity = opacityProp;
1665
+ const metallicProp = this.findProp(object, "metallic") ?? this.findProp(object, "metalness");
1666
+ if (typeof metallicProp === "number") metallic = metallicProp;
1667
+ const roughnessProp = this.findProp(object, "roughness");
1668
+ if (typeof roughnessProp === "number") roughness = roughnessProp;
1669
+ const emissiveIntensityProp = this.findProp(object, "emissiveIntensity");
1670
+ const emissiveIntensity = typeof emissiveIntensityProp === "number" ? emissiveIntensityProp : 1;
1671
+ const emissiveProp = this.findProp(object, "emissive");
1672
+ if (typeof emissiveProp === "string") emissive = this.parseColorString(emissiveProp);
1673
+ const transmissionProp = this.findProp(object, "transmission");
1674
+ if (typeof transmissionProp === "number") transmission = transmissionProp;
1675
+ const iorProp = this.findProp(object, "ior");
1676
+ if (typeof iorProp === "number") ior = iorProp;
1677
+ const clearcoatProp = this.findProp(object, "clearcoat");
1678
+ if (typeof clearcoatProp === "number") clearcoat = clearcoatProp;
1679
+ const texturePaths = {};
1680
+ const TEX_PROP_MAP = {
1681
+ // HoloScript property name → glTF slot key
1682
+ baseColorMap: "baseColor",
1683
+ albedo_map: "baseColor",
1684
+ colorMap: "baseColor",
1685
+ normalMap: "normal",
1686
+ normal_map: "normal",
1687
+ roughnessMap: "metallicRoughness",
1688
+ roughness_map: "metallicRoughness",
1689
+ metallicMap: "metallicRoughness",
1690
+ metallic_map: "metallicRoughness",
1691
+ metalnessMap: "metallicRoughness",
1692
+ occlusionMap: "occlusion",
1693
+ ao_map: "occlusion",
1694
+ ambientOcclusionMap: "occlusion",
1695
+ emissiveMap: "emissive",
1696
+ emissive_map: "emissive",
1697
+ emissionMap: "emissive"
1698
+ };
1699
+ for (const [propName, slotKey] of Object.entries(TEX_PROP_MAP)) {
1700
+ const val = this.findProp(object, propName);
1701
+ if (typeof val === "string" && val.length > 0 && !texturePaths[slotKey]) {
1702
+ texturePaths[slotKey] = val;
1703
+ }
1704
+ }
1705
+ const key = JSON.stringify({
1706
+ color,
1707
+ metallic,
1708
+ roughness,
1709
+ opacity,
1710
+ emissive,
1711
+ transmission,
1712
+ ior,
1713
+ thickness,
1714
+ clearcoat,
1715
+ clearcoatRoughness,
1716
+ sheen,
1717
+ sheenRoughness,
1718
+ sheenColor,
1719
+ iridescence,
1720
+ iridescenceIOR,
1721
+ anisotropy,
1722
+ anisotropyRotation,
1723
+ attenuationColor,
1724
+ attenuationDistance,
1725
+ texturePaths
1726
+ });
1727
+ if (this.materialMap.has(key)) {
1728
+ return this.materialMap.get(key);
1729
+ }
1730
+ const material = {
1731
+ name: `material_${this.materials.length}`,
1732
+ pbrMetallicRoughness: {
1733
+ baseColorFactor: [...color, opacity],
1734
+ metallicFactor: metallic,
1735
+ roughnessFactor: roughness
1736
+ },
1737
+ doubleSided: opacity < 1 || transmission > 0
1738
+ };
1739
+ if (opacity < 1 || transmission > 0) {
1740
+ material.alphaMode = "BLEND";
1741
+ }
1742
+ const emissiveSum = emissive[0] + emissive[1] + emissive[2];
1743
+ if (emissiveSum > 0) {
1744
+ material.emissiveFactor = emissive.map((c) => c * emissiveIntensity);
1745
+ }
1746
+ const extensions = {};
1747
+ if (transmission > 0) {
1748
+ Object.assign(extensions, createTransmissionExtension(transmission));
1749
+ }
1750
+ if (ior !== 1.5) {
1751
+ Object.assign(extensions, createIORExtension(ior));
1752
+ }
1753
+ if (clearcoat > 0) {
1754
+ Object.assign(
1755
+ extensions,
1756
+ createClearcoatExtension({ factor: clearcoat, roughness: clearcoatRoughness })
1757
+ );
1758
+ }
1759
+ if (sheen > 0) {
1760
+ Object.assign(
1761
+ extensions,
1762
+ createSheenExtension({ color: sheenColor, roughness: sheenRoughness })
1763
+ );
1764
+ }
1765
+ if (iridescence > 0) {
1766
+ Object.assign(
1767
+ extensions,
1768
+ createIridescenceExtension({ factor: iridescence, ior: iridescenceIOR })
1769
+ );
1770
+ }
1771
+ if (anisotropy > 0) {
1772
+ Object.assign(
1773
+ extensions,
1774
+ createAnisotropyExtension({ strength: anisotropy, rotation: anisotropyRotation })
1775
+ );
1776
+ }
1777
+ if (thickness > 0 || attenuationDistance !== void 0) {
1778
+ Object.assign(
1779
+ extensions,
1780
+ createVolumeExtension({
1781
+ thickness: thickness || 1,
1782
+ attenuationDistance,
1783
+ attenuationColor
1784
+ })
1785
+ );
1786
+ }
1787
+ if (emissiveIntensity > 1) {
1788
+ Object.assign(extensions, createEmissiveStrengthExtension(emissiveIntensity));
1789
+ }
1790
+ if (Object.keys(extensions).length > 0) {
1791
+ material.extensions = extensions;
1792
+ }
1793
+ const isScaledGeometry = shapeType === "hull" || shapeType === "metaball";
1794
+ const isScaledMaterial = typeof namedMat === "string" && (namedMat === "skin_dark" || namedMat === "leather");
1795
+ if (isScaledGeometry || isScaledMaterial) {
1796
+ const texIdx = this.ensureScaleTexture();
1797
+ if (texIdx >= 0) {
1798
+ material.pbrMetallicRoughness.baseColorTexture = {
1799
+ index: texIdx,
1800
+ texCoord: 0
1801
+ };
1802
+ if (this.scaleNormalTextureIndex >= 0) {
1803
+ material.normalTexture = {
1804
+ index: this.scaleNormalTextureIndex,
1805
+ texCoord: 0,
1806
+ scale: 1
1807
+ };
1808
+ }
1809
+ this.stats.textureCount = 2;
1810
+ }
1811
+ }
1812
+ if (Object.keys(texturePaths).length > 0) {
1813
+ const pbr = material.pbrMetallicRoughness;
1814
+ if (texturePaths.baseColor && !pbr.baseColorTexture) {
1815
+ const idx = this.getOrCreateExternalTexture(texturePaths.baseColor);
1816
+ if (idx >= 0) pbr.baseColorTexture = { index: idx, texCoord: 0 };
1817
+ }
1818
+ if (texturePaths.metallicRoughness && !pbr.metallicRoughnessTexture) {
1819
+ const idx = this.getOrCreateExternalTexture(texturePaths.metallicRoughness);
1820
+ if (idx >= 0) pbr.metallicRoughnessTexture = { index: idx, texCoord: 0 };
1821
+ }
1822
+ const matRecord = material;
1823
+ if (texturePaths.normal && !matRecord.normalTexture) {
1824
+ const idx = this.getOrCreateExternalTexture(texturePaths.normal);
1825
+ if (idx >= 0) matRecord.normalTexture = { index: idx, texCoord: 0, scale: 1 };
1826
+ }
1827
+ if (texturePaths.occlusion && !matRecord.occlusionTexture) {
1828
+ const idx = this.getOrCreateExternalTexture(texturePaths.occlusion);
1829
+ if (idx >= 0) matRecord.occlusionTexture = { index: idx, texCoord: 0, strength: 1 };
1830
+ }
1831
+ if (texturePaths.emissive && !matRecord.emissiveTexture) {
1832
+ const idx = this.getOrCreateExternalTexture(texturePaths.emissive);
1833
+ if (idx >= 0) matRecord.emissiveTexture = { index: idx, texCoord: 0 };
1834
+ }
1835
+ }
1836
+ const materialIndex = this.materials.length;
1837
+ this.materials.push(material);
1838
+ this.materialMap.set(key, materialIndex);
1839
+ this.stats.materialCount++;
1840
+ return materialIndex;
1841
+ }
1842
+ /**
1843
+ * Embed an external texture image in the glTF buffer. Returns the texture
1844
+ * index, or -1 if the image data is not available in options.textureData.
1845
+ * Caches by path so the same image is only embedded once.
1846
+ */
1847
+ getOrCreateExternalTexture(path) {
1848
+ if (this.textureIndexMap.has(path)) {
1849
+ return this.textureIndexMap.get(path);
1850
+ }
1851
+ const imageData = this.options.textureData[path];
1852
+ if (!imageData || imageData.length === 0) {
1853
+ return -1;
1854
+ }
1855
+ const isPNG = imageData[0] === 137 && imageData[1] === 80;
1856
+ const isJPEG = imageData[0] === 255 && imageData[1] === 216;
1857
+ const mimeType = isPNG ? "image/png" : isJPEG ? "image/jpeg" : "image/png";
1858
+ const byteOffset = this.bufferByteLength;
1859
+ this.appendToBuffer(imageData);
1860
+ this.padBuffer(4);
1861
+ const bufferViewIndex = this.bufferViews.length;
1862
+ this.bufferViews.push({
1863
+ buffer: 0,
1864
+ byteOffset,
1865
+ byteLength: imageData.length
1866
+ });
1867
+ const imageIndex = this.images.length;
1868
+ this.images.push({
1869
+ bufferView: bufferViewIndex,
1870
+ mimeType
1871
+ });
1872
+ let samplerIndex;
1873
+ if (this.samplers.length > 0) {
1874
+ samplerIndex = 0;
1875
+ } else {
1876
+ samplerIndex = this.samplers.length;
1877
+ this.samplers.push({
1878
+ magFilter: 9729,
1879
+ // LINEAR
1880
+ minFilter: 9987,
1881
+ // LINEAR_MIPMAP_LINEAR
1882
+ wrapS: 10497,
1883
+ // REPEAT
1884
+ wrapT: 10497
1885
+ // REPEAT
1886
+ });
1887
+ }
1888
+ const textureIndex = this.textures.length;
1889
+ this.textures.push({
1890
+ source: imageIndex,
1891
+ sampler: samplerIndex
1892
+ });
1893
+ this.textureIndexMap.set(path, textureIndex);
1894
+ this.stats.textureCount++;
1895
+ return textureIndex;
1896
+ }
1897
+ /**
1898
+ * Ensure the procedural scale texture is generated and embedded in the glTF.
1899
+ * Returns the texture index, or -1 if generation failed.
1900
+ */
1901
+ ensureScaleTexture() {
1902
+ if (this.scaleTextureIndex >= 0) return this.scaleTextureIndex;
1903
+ const TEX_SIZE = 256;
1904
+ const pixels = generateScaleTexture(TEX_SIZE);
1905
+ const pngData = encodePNG(pixels, TEX_SIZE, TEX_SIZE);
1906
+ const byteOffset = this.bufferByteLength;
1907
+ this.appendToBuffer(pngData);
1908
+ this.padBuffer(4);
1909
+ const bufferViewIndex = this.bufferViews.length;
1910
+ this.bufferViews.push({
1911
+ buffer: 0,
1912
+ byteOffset,
1913
+ byteLength: pngData.length
1914
+ });
1915
+ const imageIndex = this.images.length;
1916
+ this.images.push({
1917
+ bufferView: bufferViewIndex,
1918
+ mimeType: "image/png"
1919
+ });
1920
+ const samplerIndex = this.samplers.length;
1921
+ this.samplers.push({
1922
+ magFilter: 9729,
1923
+ // LINEAR
1924
+ minFilter: 9987,
1925
+ // LINEAR_MIPMAP_LINEAR
1926
+ wrapS: 10497,
1927
+ // REPEAT
1928
+ wrapT: 10497
1929
+ // REPEAT
1930
+ });
1931
+ this.scaleTextureIndex = this.textures.length;
1932
+ this.textures.push({
1933
+ source: imageIndex,
1934
+ sampler: samplerIndex
1935
+ });
1936
+ const normalPixels = generateScaleNormalMap(TEX_SIZE);
1937
+ const normalPng = encodePNG(normalPixels, TEX_SIZE, TEX_SIZE);
1938
+ const normalByteOffset = this.bufferByteLength;
1939
+ this.appendToBuffer(normalPng);
1940
+ this.padBuffer(4);
1941
+ const normalBVIndex = this.bufferViews.length;
1942
+ this.bufferViews.push({
1943
+ buffer: 0,
1944
+ byteOffset: normalByteOffset,
1945
+ byteLength: normalPng.length
1946
+ });
1947
+ const normalImageIndex = this.images.length;
1948
+ this.images.push({
1949
+ bufferView: normalBVIndex,
1950
+ mimeType: "image/png"
1951
+ });
1952
+ this.scaleNormalTextureIndex = this.textures.length;
1953
+ this.textures.push({
1954
+ source: normalImageIndex,
1955
+ sampler: samplerIndex
1956
+ // reuse same sampler
1957
+ });
1958
+ return this.scaleTextureIndex;
1959
+ }
1960
+ /**
1961
+ * Create an accessor with arbitrary type string (e.g., MAT4 for skeleton data, VEC4 for skinning).
1962
+ * Supports Uint8Array for UNSIGNED_BYTE (5121), Uint16Array for UNSIGNED_SHORT (5123),
1963
+ * Uint32Array for UNSIGNED_INT (5125), and Float32Array for FLOAT (5126).
1964
+ */
1965
+ createAccessorRaw(data, type, componentType) {
1966
+ const byteOffset = this.bufferByteLength;
1967
+ const view = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
1968
+ this.appendToBuffer(view);
1969
+ this.padBuffer(4);
1970
+ const bufferViewIndex = this.bufferViews.length;
1971
+ this.bufferViews.push({
1972
+ buffer: 0,
1973
+ byteOffset,
1974
+ byteLength: data.byteLength
1975
+ });
1976
+ const comps = type === "MAT4" ? 16 : type === "VEC4" ? 4 : type === "VEC3" ? 3 : type === "VEC2" ? 2 : 1;
1977
+ const count = data.length / comps;
1978
+ const accessorIndex = this.accessors.length;
1979
+ this.accessors.push({
1980
+ bufferView: bufferViewIndex,
1981
+ componentType,
1982
+ count,
1983
+ type
1984
+ });
1985
+ return accessorIndex;
1986
+ }
1987
+ /**
1988
+ * Create an accessor and buffer view for data
1989
+ */
1990
+ createAccessor(data, type, computeBounds = false) {
1991
+ const byteOffset = this.bufferByteLength;
1992
+ const componentType = data instanceof Uint32Array ? 5125 : data instanceof Uint16Array ? 5123 : 5126;
1993
+ const view = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
1994
+ this.appendToBuffer(view);
1995
+ this.padBuffer(4);
1996
+ const bufferViewIndex = this.bufferViews.length;
1997
+ const bufferView = {
1998
+ buffer: 0,
1999
+ byteOffset,
2000
+ byteLength: data.byteLength
2001
+ };
2002
+ if (componentType === 5126) {
2003
+ bufferView.target = 34962;
2004
+ } else {
2005
+ bufferView.target = 34963;
2006
+ }
2007
+ this.bufferViews.push(bufferView);
2008
+ const componentsPerElement = type === "SCALAR" ? 1 : type === "VEC2" ? 2 : type === "VEC3" ? 3 : 4;
2009
+ const count = data.length / componentsPerElement;
2010
+ const accessor = {
2011
+ bufferView: bufferViewIndex,
2012
+ componentType,
2013
+ count,
2014
+ type
2015
+ };
2016
+ if (computeBounds && type === "VEC3" && data instanceof Float32Array) {
2017
+ const min = [Infinity, Infinity, Infinity];
2018
+ const max = [-Infinity, -Infinity, -Infinity];
2019
+ for (let i = 0; i < data.length; i += 3) {
2020
+ min[0] = Math.min(min[0], data[i]);
2021
+ min[1] = Math.min(min[1], data[i + 1]);
2022
+ min[2] = Math.min(min[2], data[i + 2]);
2023
+ max[0] = Math.max(max[0], data[i]);
2024
+ max[1] = Math.max(max[1], data[i + 1]);
2025
+ max[2] = Math.max(max[2], data[i + 2]);
2026
+ }
2027
+ accessor.min = min;
2028
+ accessor.max = max;
2029
+ }
2030
+ const accessorIndex = this.accessors.length;
2031
+ this.accessors.push(accessor);
2032
+ return accessorIndex;
2033
+ }
2034
+ /**
2035
+ * Build the glTF JSON document
2036
+ */
2037
+ buildDocument(composition, bufferLength) {
2038
+ const name = composition.name;
2039
+ const gltf = {
2040
+ asset: {
2041
+ version: "2.0",
2042
+ generator: this.options.generator
2043
+ },
2044
+ scene: 0,
2045
+ scenes: this.scenes,
2046
+ nodes: this.nodes,
2047
+ meshes: this.meshes,
2048
+ materials: this.materials,
2049
+ accessors: this.accessors,
2050
+ bufferViews: this.bufferViews,
2051
+ buffers: [
2052
+ {
2053
+ byteLength: bufferLength
2054
+ }
2055
+ ]
2056
+ };
2057
+ if (this.options.copyright) {
2058
+ gltf.asset.copyright = this.options.copyright;
2059
+ }
2060
+ if (this.animations.length > 0) {
2061
+ gltf.animations = this.animations;
2062
+ }
2063
+ if (this.images.length > 0) {
2064
+ gltf.images = this.images;
2065
+ gltf.textures = this.textures;
2066
+ gltf.samplers = this.samplers;
2067
+ }
2068
+ if (this._skins && this._skins.length > 0) {
2069
+ gltf.skins = this._skins;
2070
+ }
2071
+ const objectNames = (composition.objects || []).map((o) => o.name);
2072
+ const allTraits = /* @__PURE__ */ new Set();
2073
+ for (const obj of composition.objects || []) {
2074
+ for (const trait of obj.traits || []) {
2075
+ allTraits.add(typeof trait === "string" ? trait : trait.name);
2076
+ }
2077
+ }
2078
+ const groupNames = (composition.spatialGroups || []).map((g) => g.name);
2079
+ gltf.asset.extras = {
2080
+ holoscript: {
2081
+ version: "6.0",
2082
+ compositionName: name,
2083
+ objects: objectNames,
2084
+ traits: [...allTraits],
2085
+ spatialGroups: groupNames,
2086
+ ...this.options.provenanceHash ? { provenanceHash: this.options.provenanceHash } : {}
2087
+ }
2088
+ };
2089
+ declareExtensions(gltf);
2090
+ if (this.options.format === "gltf") {
2091
+ gltf.buffers[0].uri = `${name}.bin`;
2092
+ }
2093
+ return gltf;
2094
+ }
2095
+ /**
2096
+ * Create a GLB binary file
2097
+ */
2098
+ createGLB(gltf, buffer) {
2099
+ const jsonString = JSON.stringify(gltf);
2100
+ const jsonBuffer = new TextEncoder().encode(jsonString);
2101
+ const jsonPadding = (4 - jsonBuffer.byteLength % 4) % 4;
2102
+ const paddedJsonLength = jsonBuffer.byteLength + jsonPadding;
2103
+ const binPadding = (4 - buffer.byteLength % 4) % 4;
2104
+ const paddedBinLength = buffer.byteLength + binPadding;
2105
+ const totalSize = 12 + 8 + paddedJsonLength + 8 + paddedBinLength;
2106
+ const output = new ArrayBuffer(totalSize);
2107
+ const view = new DataView(output);
2108
+ const bytes = new Uint8Array(output);
2109
+ let offset = 0;
2110
+ view.setUint32(offset, 1179937895, true);
2111
+ offset += 4;
2112
+ view.setUint32(offset, 2, true);
2113
+ offset += 4;
2114
+ view.setUint32(offset, totalSize, true);
2115
+ offset += 4;
2116
+ view.setUint32(offset, paddedJsonLength, true);
2117
+ offset += 4;
2118
+ view.setUint32(offset, 1313821514, true);
2119
+ offset += 4;
2120
+ bytes.set(jsonBuffer, offset);
2121
+ offset += jsonBuffer.byteLength;
2122
+ for (let i = 0; i < jsonPadding; i++) {
2123
+ bytes[offset++] = 32;
2124
+ }
2125
+ view.setUint32(offset, paddedBinLength, true);
2126
+ offset += 4;
2127
+ view.setUint32(offset, 5130562, true);
2128
+ offset += 4;
2129
+ bytes.set(buffer, offset);
2130
+ offset += buffer.byteLength;
2131
+ for (let i = 0; i < binPadding; i++) {
2132
+ bytes[offset++] = 0;
2133
+ }
2134
+ return new Uint8Array(output);
2135
+ }
2136
+ /**
2137
+ * Process a light node (stored as extras for universal glTF compatibility)
2138
+ */
2139
+ processLight(light) {
2140
+ const props = light.properties || [];
2141
+ const findLightProp = (key) => props.find((p) => p.key === key)?.value;
2142
+ const position = findLightProp("position");
2143
+ const node = {
2144
+ name: light.name || `light_${this.nodes.length}`,
2145
+ translation: position ? [position[0], position[1], position[2]] : [0, 0, 0],
2146
+ extras: {
2147
+ type: "light",
2148
+ lightType: light.lightType,
2149
+ color: findLightProp("color") || "#ffffff",
2150
+ intensity: findLightProp("intensity") ?? 1
2151
+ }
2152
+ };
2153
+ const nodeIndex = this.nodes.length;
2154
+ this.nodes.push(node);
2155
+ this.stats.nodeCount++;
2156
+ return nodeIndex;
2157
+ }
2158
+ /**
2159
+ * Process a camera node
2160
+ */
2161
+ processCamera(camera) {
2162
+ const props = camera.properties || [];
2163
+ const findCamProp = (key) => props.find((p) => p.key === key)?.value;
2164
+ const position = findCamProp("position");
2165
+ const node = {
2166
+ name: "Camera",
2167
+ translation: position ? [position[0], position[1], position[2]] : [0, 0, 0],
2168
+ extras: {
2169
+ type: "camera",
2170
+ cameraType: camera.cameraType,
2171
+ fov: findCamProp("fov") ?? 75,
2172
+ near: findCamProp("near") ?? 0.1,
2173
+ far: findCamProp("far") ?? 1e3
2174
+ }
2175
+ };
2176
+ const nodeIndex = this.nodes.length;
2177
+ this.nodes.push(node);
2178
+ this.stats.nodeCount++;
2179
+ return nodeIndex;
2180
+ }
2181
+ // =============================================================================
2182
+ // UTILITY METHODS
2183
+ // =============================================================================
2184
+ /** Find a property by key in a HoloObjectDecl's property array. */
2185
+ findProp(object, key) {
2186
+ return object.properties?.find((p) => p.key === key)?.value;
2187
+ }
2188
+ /** Extract a vec3 from an object's properties array. */
2189
+ extractVec3Prop(object, key, defaultValue) {
2190
+ const val = this.findProp(object, key);
2191
+ if (Array.isArray(val) && val.length >= 3) {
2192
+ return [Number(val[0]) || 0, Number(val[1]) || 0, Number(val[2]) || 0];
2193
+ }
2194
+ return defaultValue;
2195
+ }
2196
+ parseColorString(color) {
2197
+ if (color.startsWith("#")) {
2198
+ const hex = color.slice(1);
2199
+ if (hex.length >= 6) {
2200
+ const r = parseInt(hex.slice(0, 2), 16) / 255;
2201
+ const g = parseInt(hex.slice(2, 4), 16) / 255;
2202
+ const b = parseInt(hex.slice(4, 6), 16) / 255;
2203
+ return [r, g, b];
2204
+ }
2205
+ }
2206
+ const colors = {
2207
+ red: [1, 0, 0],
2208
+ green: [0, 1, 0],
2209
+ blue: [0, 0, 1],
2210
+ white: [1, 1, 1],
2211
+ black: [0, 0, 0],
2212
+ yellow: [1, 1, 0],
2213
+ cyan: [0, 1, 1],
2214
+ magenta: [1, 0, 1],
2215
+ orange: [1, 0.5, 0],
2216
+ purple: [0.5, 0, 0.5]
2217
+ };
2218
+ return colors[color.toLowerCase()] || [1, 1, 1];
2219
+ }
2220
+ eulerToQuaternion(euler) {
2221
+ const toRad = Math.PI / 180;
2222
+ const x = euler[0] * toRad / 2;
2223
+ const y = euler[1] * toRad / 2;
2224
+ const z = euler[2] * toRad / 2;
2225
+ const cx = Math.cos(x);
2226
+ const sx = Math.sin(x);
2227
+ const cy = Math.cos(y);
2228
+ const sy = Math.sin(y);
2229
+ const cz = Math.cos(z);
2230
+ const sz = Math.sin(z);
2231
+ return [
2232
+ sx * cy * cz - cx * sy * sz,
2233
+ cx * sy * cz + sx * cy * sz,
2234
+ cx * cy * sz - sx * sy * cz,
2235
+ cx * cy * cz + sx * sy * sz
2236
+ ];
2237
+ }
2238
+ mapPropertyToGLTFPath(property) {
2239
+ const mapping = {
2240
+ position: "translation",
2241
+ translation: "translation",
2242
+ rotation: "rotation",
2243
+ scale: "scale"
2244
+ };
2245
+ return mapping[property.toLowerCase()] || null;
2246
+ }
2247
+ };
2248
+ function createGLTFPipeline(options) {
2249
+ return new GLTFPipeline(options);
2250
+ }
2251
+
2252
+ exports.GLTFPipeline = GLTFPipeline;
2253
+ exports.createGLTFPipeline = createGLTFPipeline;
2254
+ exports.generateScaleNormalMap = generateScaleNormalMap;
2255
+ exports.generateScaleTexture = generateScaleTexture;
2256
+ //# sourceMappingURL=chunk-X3UVCWNL.cjs.map
2257
+ //# sourceMappingURL=chunk-X3UVCWNL.cjs.map