@navaramap/three 0.0.0

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/LICENSE +8 -0
  2. package/dist/assets/atmosphere/README.md +1 -0
  3. package/dist/assets/atmosphere/higher_order_scattering.bin +0 -0
  4. package/dist/assets/atmosphere/higher_order_scattering.exr +0 -0
  5. package/dist/assets/atmosphere/irradiance.bin +0 -0
  6. package/dist/assets/atmosphere/irradiance.exr +0 -0
  7. package/dist/assets/atmosphere/scattering.bin +0 -0
  8. package/dist/assets/atmosphere/scattering.exr +0 -0
  9. package/dist/assets/atmosphere/single_mie_scattering.bin +0 -0
  10. package/dist/assets/atmosphere/single_mie_scattering.exr +0 -0
  11. package/dist/assets/atmosphere/stars.bin +0 -0
  12. package/dist/assets/atmosphere/transmittance.bin +0 -0
  13. package/dist/assets/atmosphere/transmittance.exr +0 -0
  14. package/dist/assets/cloud/README.md +1 -0
  15. package/dist/assets/cloud/local_weather.png +0 -0
  16. package/dist/assets/cloud/shape.bin +1 -0
  17. package/dist/assets/cloud/shape_detail.bin +1 -0
  18. package/dist/assets/cloud/turbulence.png +0 -0
  19. package/dist/assets/fontWorker-CEJEfRpb.js +2 -0
  20. package/dist/assets/fontWorker-CEJEfRpb.js.map +1 -0
  21. package/dist/assets/index-BUB-ijMO.js +12 -0
  22. package/dist/assets/index-BUB-ijMO.js.map +1 -0
  23. package/dist/assets/navara_wasm_font_worker_bg-665OLxjy.wasm +0 -0
  24. package/dist/assets/navara_wasm_worker_bg-BXhKC5bE.wasm +0 -0
  25. package/dist/assets/noise/README.md +1 -0
  26. package/dist/assets/noise/stbn.bin +0 -0
  27. package/dist/assets/water/README.md +3 -0
  28. package/dist/assets/water/waternormals.jpg +0 -0
  29. package/dist/index.d.ts +10114 -0
  30. package/dist/index.js +34481 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/index.umd.cjs +6345 -0
  33. package/dist/index.umd.cjs.map +1 -0
  34. package/package.json +95 -0
  35. package/src/Color.ts +111 -0
  36. package/src/ShadowMapViewers.ts +49 -0
  37. package/src/atmosphere.test.ts +76 -0
  38. package/src/atmosphere.ts +364 -0
  39. package/src/bufferView.ts +90 -0
  40. package/src/camera.ts +182 -0
  41. package/src/concurrency.ts +15 -0
  42. package/src/constants/assets.ts +30 -0
  43. package/src/constants/decoder.ts +7 -0
  44. package/src/constants/index.ts +2 -0
  45. package/src/core/BaseDesc.ts +142 -0
  46. package/src/core/BaseHandle.ts +126 -0
  47. package/src/core/DescRegistry.ts +88 -0
  48. package/src/core/EffectDesc.ts +343 -0
  49. package/src/core/EffectDescRegistry.ts +31 -0
  50. package/src/core/InstancedMeshDesc.ts +413 -0
  51. package/src/core/LightDesc.ts +216 -0
  52. package/src/core/LightDescRegistry.ts +32 -0
  53. package/src/core/MeshDesc.ts +457 -0
  54. package/src/core/MeshDescRegistry.ts +32 -0
  55. package/src/core/MeshDescWithSelectiveEffect.ts +129 -0
  56. package/src/core/Registries.ts +59 -0
  57. package/src/core/SelectiveEffectRegistry.ts +90 -0
  58. package/src/core/ViewContext.ts +235 -0
  59. package/src/core/errors.ts +16 -0
  60. package/src/core/index.ts +50 -0
  61. package/src/device.ts +414 -0
  62. package/src/effects/CustomEffectPass.ts +28 -0
  63. package/src/effects/copy.ts +10 -0
  64. package/src/effects/effect.ts +87 -0
  65. package/src/effects/index.ts +4 -0
  66. package/src/effects/render.ts +10 -0
  67. package/src/evaluations/FeatureEvaluator.ts +529 -0
  68. package/src/evaluations/index.ts +1 -0
  69. package/src/event/HillshadeContext.test.ts +232 -0
  70. package/src/event/HillshadeContext.ts +299 -0
  71. package/src/event/context.ts +279 -0
  72. package/src/event/feature.ts +357 -0
  73. package/src/event/featureEvent.ts +81 -0
  74. package/src/event/features/billboard.ts +30 -0
  75. package/src/event/features/model.ts +192 -0
  76. package/src/event/features/modelGpuBytes.test.ts +69 -0
  77. package/src/event/features/modelGpuBytes.ts +87 -0
  78. package/src/event/features/point.ts +25 -0
  79. package/src/event/features/polygon.ts +23 -0
  80. package/src/event/features/polygonOutline.ts +19 -0
  81. package/src/event/features/polyline.ts +19 -0
  82. package/src/event/features/text.ts +71 -0
  83. package/src/event/hillshade.test.ts +842 -0
  84. package/src/event/hillshade.ts +588 -0
  85. package/src/event/index.ts +700 -0
  86. package/src/event/loaders.ts +53 -0
  87. package/src/event/tile.ts +19 -0
  88. package/src/event/worker.ts +999 -0
  89. package/src/event/workerTaskSettlement.test.ts +243 -0
  90. package/src/event/workerTaskSettlement.ts +128 -0
  91. package/src/inMemoryBufferStore.test.ts +60 -0
  92. package/src/inMemoryBufferStore.ts +67 -0
  93. package/src/index.iife.ts +11 -0
  94. package/src/index.ts +2556 -0
  95. package/src/input.ts +144 -0
  96. package/src/layer.ts +183 -0
  97. package/src/layers/effect/FinalCopyEffectDesc.ts +29 -0
  98. package/src/layers/effect/MRTPassEffectDesc.ts +105 -0
  99. package/src/layers/effect/README.md +9 -0
  100. package/src/layers/effect/SelectiveEffectDesc.ts +113 -0
  101. package/src/layers/effect/SkyEnvMapEffectDesc.ts +58 -0
  102. package/src/layers/effect/TransparentPassEffectDesc.ts +62 -0
  103. package/src/layers/effect/index.ts +5 -0
  104. package/src/layers/index.ts +1 -0
  105. package/src/layersManager.ts +63 -0
  106. package/src/light.ts +15 -0
  107. package/src/loaders/AbortableImageLoader.ts +203 -0
  108. package/src/loaders/AbortableTextureLoader.ts +74 -0
  109. package/src/loaders/index.ts +5 -0
  110. package/src/material/enhancer/DESIGN.md +300 -0
  111. package/src/material/enhancer/MaterialEnhancer.ts +112 -0
  112. package/src/material/enhancer/ShaderReplacer.test.ts +114 -0
  113. package/src/material/enhancer/ShaderReplacer.ts +97 -0
  114. package/src/material/enhancer/batchTexture.ts +8 -0
  115. package/src/material/enhancer/index.ts +46 -0
  116. package/src/material/enhancer/instancedSprite/index.ts +7 -0
  117. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/index.test.ts +214 -0
  118. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/index.ts +134 -0
  119. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/markers.ts +21 -0
  120. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/material.ts +32 -0
  121. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/mutates.test.ts +277 -0
  122. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/mutates.ts +151 -0
  123. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/shader.test.ts +114 -0
  124. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/shader.ts +49 -0
  125. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/state.test.ts +82 -0
  126. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/state.ts +80 -0
  127. package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/types.ts +146 -0
  128. package/src/material/enhancer/instancedSprite/instancedSpriteMaterialEnhancer.ts +105 -0
  129. package/src/material/enhancer/model/index.ts +25 -0
  130. package/src/material/enhancer/model/modelBaseEnhancer/index.test.ts +74 -0
  131. package/src/material/enhancer/model/modelBaseEnhancer/index.ts +110 -0
  132. package/src/material/enhancer/model/modelBaseEnhancer/markers.ts +27 -0
  133. package/src/material/enhancer/model/modelBaseEnhancer/material.test.ts +66 -0
  134. package/src/material/enhancer/model/modelBaseEnhancer/material.ts +44 -0
  135. package/src/material/enhancer/model/modelBaseEnhancer/mutates.test.ts +84 -0
  136. package/src/material/enhancer/model/modelBaseEnhancer/mutates.ts +47 -0
  137. package/src/material/enhancer/model/modelBaseEnhancer/shader.test.ts +24 -0
  138. package/src/material/enhancer/model/modelBaseEnhancer/shader.ts +162 -0
  139. package/src/material/enhancer/model/modelBaseEnhancer/state.test.ts +103 -0
  140. package/src/material/enhancer/model/modelBaseEnhancer/state.ts +52 -0
  141. package/src/material/enhancer/model/modelBaseEnhancer/types.ts +89 -0
  142. package/src/material/enhancer/model/modelMaterialEnhancer.ts +91 -0
  143. package/src/material/enhancer/model/modelWaterEnhancer/index.test.ts +71 -0
  144. package/src/material/enhancer/model/modelWaterEnhancer/index.ts +175 -0
  145. package/src/material/enhancer/model/modelWaterEnhancer/material.test.ts +48 -0
  146. package/src/material/enhancer/model/modelWaterEnhancer/material.ts +25 -0
  147. package/src/material/enhancer/model/modelWaterEnhancer/mutates.test.ts +89 -0
  148. package/src/material/enhancer/model/modelWaterEnhancer/mutates.ts +89 -0
  149. package/src/material/enhancer/model/modelWaterEnhancer/shader.test.ts +34 -0
  150. package/src/material/enhancer/model/modelWaterEnhancer/shader.ts +111 -0
  151. package/src/material/enhancer/model/modelWaterEnhancer/state.test.ts +105 -0
  152. package/src/material/enhancer/model/modelWaterEnhancer/state.ts +59 -0
  153. package/src/material/enhancer/model/modelWaterEnhancer/types.ts +141 -0
  154. package/src/material/enhancer/model/pntsEnhancer/index.test.ts +96 -0
  155. package/src/material/enhancer/model/pntsEnhancer/index.ts +82 -0
  156. package/src/material/enhancer/model/pntsEnhancer/markers.ts +6 -0
  157. package/src/material/enhancer/model/pntsEnhancer/material.test.ts +37 -0
  158. package/src/material/enhancer/model/pntsEnhancer/material.ts +21 -0
  159. package/src/material/enhancer/model/pntsEnhancer/mutates.test.ts +80 -0
  160. package/src/material/enhancer/model/pntsEnhancer/mutates.ts +29 -0
  161. package/src/material/enhancer/model/pntsEnhancer/shader.test.ts +32 -0
  162. package/src/material/enhancer/model/pntsEnhancer/shader.ts +56 -0
  163. package/src/material/enhancer/model/pntsEnhancer/state.test.ts +87 -0
  164. package/src/material/enhancer/model/pntsEnhancer/state.ts +29 -0
  165. package/src/material/enhancer/model/pntsEnhancer/types.ts +38 -0
  166. package/src/material/enhancer/polygon/index.ts +22 -0
  167. package/src/material/enhancer/polygon/polygonBaseEnhancer/index.test.ts +101 -0
  168. package/src/material/enhancer/polygon/polygonBaseEnhancer/index.ts +130 -0
  169. package/src/material/enhancer/polygon/polygonBaseEnhancer/markers.ts +23 -0
  170. package/src/material/enhancer/polygon/polygonBaseEnhancer/material.test.ts +19 -0
  171. package/src/material/enhancer/polygon/polygonBaseEnhancer/material.ts +38 -0
  172. package/src/material/enhancer/polygon/polygonBaseEnhancer/mutates.test.ts +75 -0
  173. package/src/material/enhancer/polygon/polygonBaseEnhancer/mutates.ts +122 -0
  174. package/src/material/enhancer/polygon/polygonBaseEnhancer/shader.test.ts +25 -0
  175. package/src/material/enhancer/polygon/polygonBaseEnhancer/shader.ts +249 -0
  176. package/src/material/enhancer/polygon/polygonBaseEnhancer/state.test.ts +102 -0
  177. package/src/material/enhancer/polygon/polygonBaseEnhancer/state.ts +92 -0
  178. package/src/material/enhancer/polygon/polygonBaseEnhancer/types.ts +150 -0
  179. package/src/material/enhancer/polygon/polygonMaterialEnhancer.ts +97 -0
  180. package/src/material/enhancer/polygon/polygonWaterEnhancer/index.test.ts +72 -0
  181. package/src/material/enhancer/polygon/polygonWaterEnhancer/index.ts +164 -0
  182. package/src/material/enhancer/polygon/polygonWaterEnhancer/material.test.ts +48 -0
  183. package/src/material/enhancer/polygon/polygonWaterEnhancer/material.ts +35 -0
  184. package/src/material/enhancer/polygon/polygonWaterEnhancer/mutates.ts +61 -0
  185. package/src/material/enhancer/polygon/polygonWaterEnhancer/shader.test.ts +34 -0
  186. package/src/material/enhancer/polygon/polygonWaterEnhancer/shader.ts +96 -0
  187. package/src/material/enhancer/polygon/polygonWaterEnhancer/state.test.ts +98 -0
  188. package/src/material/enhancer/polygon/polygonWaterEnhancer/state.ts +57 -0
  189. package/src/material/enhancer/polygon/polygonWaterEnhancer/types.ts +115 -0
  190. package/src/material/enhancer/polyline/index.ts +7 -0
  191. package/src/material/enhancer/polyline/polylineBaseEnhancer/index.test.ts +157 -0
  192. package/src/material/enhancer/polyline/polylineBaseEnhancer/index.ts +154 -0
  193. package/src/material/enhancer/polyline/polylineBaseEnhancer/markers.ts +19 -0
  194. package/src/material/enhancer/polyline/polylineBaseEnhancer/material.test.ts +42 -0
  195. package/src/material/enhancer/polyline/polylineBaseEnhancer/material.ts +38 -0
  196. package/src/material/enhancer/polyline/polylineBaseEnhancer/mutates.test.ts +120 -0
  197. package/src/material/enhancer/polyline/polylineBaseEnhancer/mutates.ts +169 -0
  198. package/src/material/enhancer/polyline/polylineBaseEnhancer/shader.test.ts +67 -0
  199. package/src/material/enhancer/polyline/polylineBaseEnhancer/shader.ts +75 -0
  200. package/src/material/enhancer/polyline/polylineBaseEnhancer/state.test.ts +55 -0
  201. package/src/material/enhancer/polyline/polylineBaseEnhancer/state.ts +91 -0
  202. package/src/material/enhancer/polyline/polylineBaseEnhancer/types.ts +170 -0
  203. package/src/material/enhancer/polyline/polylineMaterialEnhancer.ts +102 -0
  204. package/src/material/enhancer/sdfText/index.ts +7 -0
  205. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/index.ts +125 -0
  206. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/markers.ts +19 -0
  207. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/material.test.ts +35 -0
  208. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/material.ts +32 -0
  209. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.test.ts +381 -0
  210. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.ts +232 -0
  211. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/shader.ts +36 -0
  212. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/state.test.ts +118 -0
  213. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/state.ts +107 -0
  214. package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/types.ts +184 -0
  215. package/src/material/enhancer/sdfText/sdfTextMaterialEnhancer.ts +100 -0
  216. package/src/material/enhancer/shadowMap/index.ts +7 -0
  217. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/index.ts +97 -0
  218. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/markers.ts +10 -0
  219. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/material.ts +31 -0
  220. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/mutates.ts +8 -0
  221. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/shader.test.ts +17 -0
  222. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/shader.ts +53 -0
  223. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/state.ts +17 -0
  224. package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/types.ts +26 -0
  225. package/src/material/enhancer/test-utils/shaderCompatibility.ts +124 -0
  226. package/src/material/enhancer/tileComposite/compose.test.ts +95 -0
  227. package/src/material/enhancer/tileComposite/compose.ts +112 -0
  228. package/src/material/enhancer/tileComposite/index.ts +23 -0
  229. package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/index.ts +11 -0
  230. package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/mutates.ts +132 -0
  231. package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/shader.ts +245 -0
  232. package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/types.ts +43 -0
  233. package/src/material/enhancer/tileComposite/tileElevationHeatmapEnhancer/index.ts +29 -0
  234. package/src/material/enhancer/tileComposite/tileElevationHeatmapEnhancer/mutates.ts +68 -0
  235. package/src/material/enhancer/tileComposite/tileElevationHeatmapEnhancer/shader.ts +24 -0
  236. package/src/material/enhancer/tileComposite/tileHillshadeEnhancer/index.ts +29 -0
  237. package/src/material/enhancer/tileComposite/tileHillshadeEnhancer/mutates.ts +34 -0
  238. package/src/material/enhancer/tileComposite/tileHillshadeEnhancer/shader.ts +36 -0
  239. package/src/material/enhancer/tileComposite/tileWaterEnhancer/index.ts +23 -0
  240. package/src/material/enhancer/tileComposite/tileWaterEnhancer/mutates.ts +23 -0
  241. package/src/material/enhancer/tileComposite/tileWaterEnhancer/shader.ts +8 -0
  242. package/src/material/enhancer/tileComposite/tileWatermaskEnhancer/index.ts +23 -0
  243. package/src/material/enhancer/tileComposite/tileWatermaskEnhancer/mutates.ts +34 -0
  244. package/src/material/enhancer/tileComposite/tileWatermaskEnhancer/shader.ts +13 -0
  245. package/src/material/enhancer/tileComposite/types.ts +58 -0
  246. package/src/material/index.ts +3 -0
  247. package/src/material/macro/index.ts +1 -0
  248. package/src/material/macro/tileShader.test.ts +136 -0
  249. package/src/material/macro/tileShader.ts +287 -0
  250. package/src/material/overrideMaterialsForMRT.ts +439 -0
  251. package/src/material/selectiveEffectMaterialSetup.test.ts +52 -0
  252. package/src/material/selectiveEffectMaterialSetup.ts +53 -0
  253. package/src/material/types/index.ts +1 -0
  254. package/src/material/types/uniform.ts +1 -0
  255. package/src/mesh/DrapedMesh.ts +101 -0
  256. package/src/mesh/batchTexture.test.ts +646 -0
  257. package/src/mesh/batchTexture.ts +437 -0
  258. package/src/mesh/batchedFeature.ts +186 -0
  259. package/src/mesh/batchedSdfText.ts +484 -0
  260. package/src/mesh/featureMesh.ts +43 -0
  261. package/src/mesh/index.ts +16 -0
  262. package/src/mesh/instanced.ts +117 -0
  263. package/src/mesh/model.ts +483 -0
  264. package/src/mesh/pickableMesh.ts +55 -0
  265. package/src/mesh/pickableMeshWrapper.ts +529 -0
  266. package/src/mesh/polygon.ts +699 -0
  267. package/src/mesh/polygonOutline.ts +393 -0
  268. package/src/mesh/polyline.ts +523 -0
  269. package/src/mesh/releaseGeometryArrays.ts +57 -0
  270. package/src/mesh/rtcRteHelper.ts +211 -0
  271. package/src/mesh/sdfText.test.ts +200 -0
  272. package/src/mesh/sdfText.ts +1019 -0
  273. package/src/mesh/sprite/billboardAtlas.test.ts +177 -0
  274. package/src/mesh/sprite/billboardAtlas.ts +210 -0
  275. package/src/mesh/sprite/billboardAtlasImageLoader.ts +29 -0
  276. package/src/mesh/sprite/index.ts +1 -0
  277. package/src/mesh/sprite/instancedSprite.ts +694 -0
  278. package/src/mesh/tile.test.ts +393 -0
  279. package/src/mesh/tile.ts +1790 -0
  280. package/src/object3DEvent.ts +6 -0
  281. package/src/orchestrators/RenderPassOrchestrator.ts +147 -0
  282. package/src/orchestrators/index.ts +1 -0
  283. package/src/passes/AllDepthCopyPass.ts +165 -0
  284. package/src/passes/CustomRenderPass.ts +279 -0
  285. package/src/passes/NormalCopyPass.ts +125 -0
  286. package/src/passes/RenderTargetCopyPass.ts +91 -0
  287. package/src/passes/SkyEnvMapPass.ts +58 -0
  288. package/src/passes/index.ts +5 -0
  289. package/src/pick/pickHelper.ts +273 -0
  290. package/src/pick/pickTerrain.ts +254 -0
  291. package/src/plugins/AttributionPlugin/AttributionPlugin.test.ts +210 -0
  292. package/src/plugins/AttributionPlugin/attribution.test.ts +225 -0
  293. package/src/plugins/AttributionPlugin/attribution.ts +355 -0
  294. package/src/plugins/AttributionPlugin/attributionStyles.ts +163 -0
  295. package/src/plugins/AttributionPlugin/index.ts +702 -0
  296. package/src/plugins/index.ts +1 -0
  297. package/src/quality.ts +1 -0
  298. package/src/renderOrder.ts +3 -0
  299. package/src/scene.test.ts +164 -0
  300. package/src/scene.ts +127 -0
  301. package/src/shaders/index.ts +1 -0
  302. package/src/solar.test.ts +81 -0
  303. package/src/solar.ts +101 -0
  304. package/src/source.ts +80 -0
  305. package/src/stats.ts +102 -0
  306. package/src/tasks/computeVertexNormalsAsync.ts +15 -0
  307. package/src/tasks/constructPolygonBatchedFeature.ts +34 -0
  308. package/src/tasks/constructPolylineBatchedFeature.ts +27 -0
  309. package/src/tasks/constructQuantizedMeshTerrainMesh.ts +24 -0
  310. package/src/tasks/constructTerrainMesh.ts +25 -0
  311. package/src/tasks/getImageDataFromBlob.ts +13 -0
  312. package/src/tasks/getImageDataFromImageBitmap.ts +12 -0
  313. package/src/tasks/parseMvtTile.ts +22 -0
  314. package/src/tasks/queueTask.ts +19 -0
  315. package/src/tasks/toCreasedNormalsAsync.ts +18 -0
  316. package/src/tasks/upsampleQuantizedMeshTerrainMesh.ts +44 -0
  317. package/src/tasks/upsampleTerrainMesh.ts +39 -0
  318. package/src/texture.ts +19 -0
  319. package/src/textures.ts +13 -0
  320. package/src/tileTexture/CompositeShader.snapshot.test.ts +59 -0
  321. package/src/tileTexture/CompositeShader.test.ts +168 -0
  322. package/src/tileTexture/CompositeShader.ts +53 -0
  323. package/src/tileTexture/SlotPlanner.test.ts +105 -0
  324. package/src/tileTexture/SlotPlanner.ts +102 -0
  325. package/src/tileTexture/TileTextureCache.test.ts +227 -0
  326. package/src/tileTexture/TileTextureCache.ts +192 -0
  327. package/src/tileTexture/TileTextureCompositor.test.ts +260 -0
  328. package/src/tileTexture/TileTextureCompositor.ts +421 -0
  329. package/src/tileTexture/__snapshots__/CompositeShader.snapshot.test.ts.snap +2649 -0
  330. package/src/tileTexture/index.ts +8 -0
  331. package/src/tileTexture/types.ts +150 -0
  332. package/src/type/index.ts +261 -0
  333. package/src/uniforms.ts +20 -0
  334. package/src/utils/arraysEqual.ts +9 -0
  335. package/src/utils/blendModes.ts +80 -0
  336. package/src/utils/geometry.ts +53 -0
  337. package/src/utils/hillshadeNormalMapGenerator.ts +193 -0
  338. package/src/utils/index.ts +8 -0
  339. package/src/utils/object.test.ts +14 -0
  340. package/src/utils/object.ts +7 -0
  341. package/src/utils/replacer.test.ts +42 -0
  342. package/src/utils/replacer.ts +89 -0
  343. package/src/utils/screen.ts +29 -0
  344. package/src/utils/textureFragmentIndex.test.ts +224 -0
  345. package/src/utils/textureFragmentIndex.ts +97 -0
  346. package/src/utils/worker.ts +3 -0
  347. package/src/vite-env.d.ts +2 -0
  348. package/src/worker/index.ts +13 -0
  349. package/src/worker/tasks/computeVertexNormals.ts +15 -0
  350. package/src/worker/tasks/toCreasedNormals.ts +22 -0
@@ -0,0 +1,413 @@
1
+ import type { BaseEventMap, XYZ } from "@navaramap/core";
2
+ import {
3
+ BufferGeometry,
4
+ Color as ThreeColor,
5
+ Euler,
6
+ InstancedMesh,
7
+ Material,
8
+ Matrix4,
9
+ Quaternion,
10
+ Vector3,
11
+ } from "three";
12
+ import invariant from "tiny-invariant";
13
+
14
+ import {
15
+ MeshDescWithSelectiveEffect,
16
+ type MeshConfigWithSelectiveEffect,
17
+ type MeshUpdateWithSelectiveEffect,
18
+ } from "./MeshDescWithSelectiveEffect";
19
+
20
+ export type InstancedMeshConfig = MeshConfigWithSelectiveEffect;
21
+ export type InstancedMeshUpdate = MeshUpdateWithSelectiveEffect;
22
+
23
+ /**
24
+ * Common transform fields for individual instances within an instanced mesh descriptor.
25
+ * Mirrors the transform fields of `MeshConfig` at the parent level.
26
+ *
27
+ * When `matrix` is provided, it is used directly and `position`, `rotation`, `scale`
28
+ * are ignored.
29
+ */
30
+ export type InstancedChildConfig = {
31
+ /** Local position relative to the parent group. */
32
+ position?: XYZ;
33
+ /** Local rotation (Euler angles in radians). */
34
+ rotation?: XYZ;
35
+ /** Local scale. */
36
+ scale?: XYZ;
37
+ /** Pre-computed transform matrix. When set, position/rotation/scale are ignored. */
38
+ matrix?: Matrix4;
39
+ };
40
+
41
+ const DEFAULT_CAPACITY = 64;
42
+ const GROWTH_FACTOR = 2;
43
+
44
+ // Reusable temporaries to avoid per-call allocations
45
+ const _position = new Vector3();
46
+ const _quaternion = new Quaternion();
47
+ const _scale = new Vector3();
48
+ const _euler = new Euler();
49
+ const _matrix = new Matrix4();
50
+ const _defaultColor = new ThreeColor(0xffffff);
51
+ const _swapMatrix = new Matrix4();
52
+ const _swapColor = new ThreeColor();
53
+
54
+ /**
55
+ * Abstract base class for instanced mesh descriptors using GPU instancing via Three.js `InstancedMesh`.
56
+ *
57
+ * All instances share a single geometry and material, rendered in one draw call.
58
+ * Per-instance variation is achieved through `instanceMatrix` (position, rotation, scale)
59
+ * and `instanceColor` (per-instance color).
60
+ *
61
+ * The parent's transform fields (position, scale, rotation, matrix, matrixWorld)
62
+ * define the parent coordinate space. Each instance's transform is local to the parent.
63
+ *
64
+ * Subclasses that maintain external per-instance state (e.g. picking batchIds)
65
+ * can override the `onInstance*` lifecycle hooks to stay in sync with
66
+ * `add` / `removeAt` / `clear` / `replaceAll` / capacity grows.
67
+ *
68
+ * @typeParam Config - Descriptor configuration type
69
+ * @typeParam UpdateConfig - Updatable properties type
70
+ * @typeParam ChildConfig - Configuration type for individual instances
71
+ * @typeParam CustomEvent - Additional custom events
72
+ */
73
+ export abstract class InstancedMeshDesc<
74
+ TGeometry extends BufferGeometry = BufferGeometry,
75
+ TMaterial extends Material = Material,
76
+ Config extends InstancedMeshConfig = InstancedMeshConfig,
77
+ UpdateConfig extends InstancedMeshUpdate = InstancedMeshUpdate,
78
+ ChildConfig extends InstancedChildConfig = InstancedChildConfig,
79
+ CustomEvent extends BaseEventMap = BaseEventMap,
80
+ > extends MeshDescWithSelectiveEffect<
81
+ Config,
82
+ UpdateConfig,
83
+ InstancedMesh<TGeometry, TMaterial>,
84
+ CustomEvent
85
+ > {
86
+ protected configs: ChildConfig[] = [];
87
+ private capacity = 0;
88
+
89
+ /** Create the shared geometry for all instances. */
90
+ protected abstract createGeometry(): TGeometry;
91
+
92
+ /** Create the shared material for all instances. */
93
+ protected abstract createMaterial(): TMaterial;
94
+
95
+ /** Extract the initial array of instance configs from the descriptor config. */
96
+ protected abstract getChildConfigs(): ChildConfig[];
97
+
98
+ /** Extract the per-instance color, or undefined if no color. */
99
+ protected abstract getInstanceColor(
100
+ config: ChildConfig,
101
+ ): ThreeColor | undefined;
102
+
103
+ /**
104
+ * Compose a Matrix4 encoding position, rotation, and scale for one instance.
105
+ *
106
+ * When `config.matrix` is provided, it is returned directly.
107
+ * Otherwise the matrix is composed from `position`, `rotation`, and scale
108
+ * (computed by {@link getInstanceScale}).
109
+ *
110
+ * Override {@link getInstanceScale} to incorporate geometry-specific dimensions
111
+ * (e.g., width/height/depth for boxes) into the scale.
112
+ */
113
+ protected composeInstanceMatrix(config: ChildConfig): Matrix4 {
114
+ if (config.matrix) return config.matrix;
115
+
116
+ const pos = config.position;
117
+ _position.set(pos?.x ?? 0, pos?.y ?? 0, pos?.z ?? 0);
118
+
119
+ const rot = config.rotation;
120
+ if (rot) {
121
+ _euler.set(rot.x, rot.y, rot.z);
122
+ _quaternion.setFromEuler(_euler);
123
+ } else {
124
+ _quaternion.identity();
125
+ }
126
+
127
+ this.getInstanceScale(config, _scale);
128
+
129
+ _matrix.compose(_position, _quaternion, _scale);
130
+ return _matrix;
131
+ }
132
+
133
+ /**
134
+ * Compute per-instance scale. Override to incorporate geometry-specific
135
+ * dimensions (e.g., width/height/depth) into the scale.
136
+ *
137
+ * The default implementation uses `config.scale` directly.
138
+ */
139
+ protected getInstanceScale(config: ChildConfig, target: Vector3): void {
140
+ const s = config.scale;
141
+ target.set(s?.x ?? 1, s?.y ?? 1, s?.z ?? 1);
142
+ }
143
+
144
+ createMesh(): InstancedMesh<TGeometry, TMaterial> {
145
+ const configs = this.getChildConfigs();
146
+ this.capacity = Math.max(configs.length, DEFAULT_CAPACITY);
147
+
148
+ const mesh = new InstancedMesh(
149
+ this.createGeometry(),
150
+ this.createMaterial(),
151
+ this.capacity,
152
+ );
153
+ mesh.count = configs.length;
154
+
155
+ for (let i = 0; i < configs.length; i++) {
156
+ mesh.setMatrixAt(i, this.composeInstanceMatrix(configs[i]));
157
+ const color = this.getInstanceColor(configs[i]) ?? _defaultColor;
158
+ mesh.setColorAt(i, color);
159
+ }
160
+
161
+ mesh.instanceMatrix.needsUpdate = true;
162
+ if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
163
+ this.configs = [...configs];
164
+
165
+ return mesh;
166
+ }
167
+
168
+ /** Add a new instance. Returns the index of the added instance. */
169
+ add(config: ChildConfig): number {
170
+ const count = this.raw?.count ?? 0;
171
+ if (count >= this.capacity) {
172
+ this.grow();
173
+ }
174
+
175
+ const mesh = this.raw;
176
+ invariant(mesh, "Descriptor must be created before adding instances");
177
+
178
+ const index = mesh.count;
179
+ mesh.setMatrixAt(index, this.composeInstanceMatrix(config));
180
+ const color = this.getInstanceColor(config) ?? _defaultColor;
181
+ mesh.setColorAt(index, color);
182
+ mesh.count++;
183
+ mesh.instanceMatrix.needsUpdate = true;
184
+ if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
185
+ this.configs.push(config);
186
+
187
+ this.onInstanceAdded(index);
188
+
189
+ this.requestUpdate();
190
+ return index;
191
+ }
192
+
193
+ /**
194
+ * Remove an instance by index.
195
+ * Uses swap-with-last for O(1) removal. Order is not preserved.
196
+ */
197
+ removeAt(index: number): void {
198
+ const mesh = this.raw;
199
+ invariant(mesh, "Descriptor must be created before removing instances");
200
+
201
+ if (index < 0 || index >= mesh.count) {
202
+ throw new Error(`Index ${index} out of bounds [0, ${mesh.count})`);
203
+ }
204
+
205
+ const last = mesh.count - 1;
206
+ if (index !== last) {
207
+ // Swap with last instance
208
+ mesh.getMatrixAt(last, _swapMatrix);
209
+ mesh.setMatrixAt(index, _swapMatrix);
210
+
211
+ if (mesh.instanceColor) {
212
+ mesh.getColorAt(last, _swapColor);
213
+ mesh.setColorAt(index, _swapColor);
214
+ }
215
+
216
+ this.configs[index] = this.configs[last];
217
+ }
218
+
219
+ mesh.count--;
220
+ this.configs.pop();
221
+
222
+ this.onInstanceRemoved(index, index === last);
223
+
224
+ mesh.instanceMatrix.needsUpdate = true;
225
+ if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
226
+ this.requestUpdate();
227
+ }
228
+
229
+ /** Update an instance at the given index with partial config. */
230
+ updateAt(index: number, config: Partial<ChildConfig>): void {
231
+ const mesh = this.raw;
232
+ invariant(mesh, "Descriptor must be created before updating instances");
233
+
234
+ if (index < 0 || index >= mesh.count) {
235
+ throw new Error(`Index ${index} out of bounds [0, ${mesh.count})`);
236
+ }
237
+
238
+ const merged = { ...this.configs[index], ...config };
239
+ mesh.setMatrixAt(index, this.composeInstanceMatrix(merged));
240
+ const color = this.getInstanceColor(merged) ?? _defaultColor;
241
+ mesh.setColorAt(index, color);
242
+ mesh.instanceMatrix.needsUpdate = true;
243
+ if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
244
+ this.configs[index] = merged;
245
+ this.requestUpdate();
246
+ }
247
+
248
+ /** Remove all instances. */
249
+ clear(): void {
250
+ const mesh = this.raw;
251
+ if (mesh) {
252
+ mesh.count = 0;
253
+ mesh.instanceMatrix.needsUpdate = true;
254
+ if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true;
255
+ this.requestUpdate();
256
+ }
257
+ this.configs = [];
258
+ this.onInstancesCleared();
259
+ }
260
+
261
+ /**
262
+ * Replace all instances in a single batch. More efficient than `clear()` + `add()` loop
263
+ * because it suppresses per-instance update notifications and emits a single update at the end.
264
+ */
265
+ replaceAll(configs: ChildConfig[]): void {
266
+ const mesh = this.raw;
267
+ invariant(mesh, "Layer must be created before replacing instances");
268
+
269
+ // Grow capacity if needed
270
+ while (configs.length > this.capacity) {
271
+ this.grow();
272
+ }
273
+
274
+ // Re-read after potential grow() which replaces the mesh
275
+ const currentMesh = this.raw;
276
+ invariant(
277
+ currentMesh,
278
+ "Descriptor must be created before replacing instances",
279
+ );
280
+ currentMesh.count = configs.length;
281
+
282
+ for (let i = 0; i < configs.length; i++) {
283
+ currentMesh.setMatrixAt(i, this.composeInstanceMatrix(configs[i]));
284
+ const color = this.getInstanceColor(configs[i]) ?? _defaultColor;
285
+ currentMesh.setColorAt(i, color);
286
+ }
287
+
288
+ currentMesh.instanceMatrix.needsUpdate = true;
289
+ if (currentMesh.instanceColor) currentMesh.instanceColor.needsUpdate = true;
290
+ this.configs = [...configs];
291
+
292
+ this.onInstancesReplaced(configs.length);
293
+
294
+ this.requestUpdate();
295
+ }
296
+
297
+ /** Number of active instances. */
298
+ get count(): number {
299
+ return this.configs.length;
300
+ }
301
+
302
+ // ---------------------------------------------------------------------------
303
+ // Subclass lifecycle hooks — override these to sync external per-instance
304
+ // state (e.g. a PickableInstancedMeshWrapper). Base implementations are
305
+ // intentionally no-ops.
306
+ // ---------------------------------------------------------------------------
307
+
308
+ /** Called after a new instance has been appended at `index`. */
309
+ protected onInstanceAdded(_index: number): void {}
310
+
311
+ /**
312
+ * Called after an instance at `index` has been removed via swap-with-last.
313
+ * `wasLast` is true if the removed instance was already the last one
314
+ * (no swap happened).
315
+ */
316
+ protected onInstanceRemoved(_index: number, _wasLast: boolean): void {}
317
+
318
+ /** Called after all instances have been cleared. */
319
+ protected onInstancesCleared(): void {}
320
+
321
+ /** Called after all instances have been replaced; `count` is the new instance count. */
322
+ protected onInstancesReplaced(_count: number): void {}
323
+
324
+ /**
325
+ * Called after the underlying `InstancedMesh` has been replaced (capacity grow).
326
+ * `this.raw` already points at the new mesh when this fires.
327
+ */
328
+ protected onInstanceMeshReplaced(
329
+ _newMesh: InstancedMesh<TGeometry, TMaterial>,
330
+ ): void {}
331
+
332
+ /**
333
+ * Grow the internal buffers by replacing the InstancedMesh with a larger one.
334
+ * Copies existing instance data to the new mesh.
335
+ */
336
+ private grow(): void {
337
+ const oldMesh = this.raw;
338
+ invariant(oldMesh, "Descriptor must be created before growing");
339
+
340
+ const newCapacity = Math.max(
341
+ this.capacity * GROWTH_FACTOR,
342
+ DEFAULT_CAPACITY,
343
+ );
344
+ const oldCount = oldMesh.count;
345
+
346
+ const newMesh = new InstancedMesh(
347
+ oldMesh.geometry,
348
+ oldMesh.material,
349
+ newCapacity,
350
+ );
351
+ newMesh.count = oldCount;
352
+
353
+ // Copy instance matrices
354
+ const matrix = new Matrix4();
355
+ for (let i = 0; i < oldCount; i++) {
356
+ oldMesh.getMatrixAt(i, matrix);
357
+ newMesh.setMatrixAt(i, matrix);
358
+ }
359
+ newMesh.instanceMatrix.needsUpdate = true;
360
+
361
+ // Copy instance colors if they exist
362
+ if (oldMesh.instanceColor) {
363
+ const color = new ThreeColor();
364
+ for (let i = 0; i < oldCount; i++) {
365
+ oldMesh.getColorAt(i, color);
366
+ newMesh.setColorAt(i, color);
367
+ }
368
+ if (newMesh.instanceColor) newMesh.instanceColor.needsUpdate = true;
369
+ }
370
+
371
+ // Copy transform and visibility
372
+ newMesh.position.copy(oldMesh.position);
373
+ newMesh.rotation.copy(oldMesh.rotation);
374
+ newMesh.scale.copy(oldMesh.scale);
375
+ newMesh.matrix.copy(oldMesh.matrix);
376
+ newMesh.matrixWorld.copy(oldMesh.matrixWorld);
377
+ newMesh.matrixAutoUpdate = oldMesh.matrixAutoUpdate;
378
+ newMesh.matrixWorldAutoUpdate = oldMesh.matrixWorldAutoUpdate;
379
+ newMesh.visible = oldMesh.visible;
380
+ newMesh.castShadow = oldMesh.castShadow;
381
+ newMesh.receiveShadow = oldMesh.receiveShadow;
382
+
383
+ // Swap in scene
384
+ const parent = oldMesh.parent;
385
+ if (parent) {
386
+ parent.remove(oldMesh);
387
+ parent.add(newMesh);
388
+ }
389
+
390
+ // Dispose old instance buffers (not geometry/material — they're shared)
391
+ oldMesh.dispose();
392
+
393
+ this._instance = newMesh;
394
+ this.capacity = newCapacity;
395
+
396
+ this.onInstanceMeshReplaced(newMesh);
397
+ }
398
+
399
+ override onDestroy(): void {
400
+ const mesh = this.raw;
401
+ if (mesh) {
402
+ mesh.geometry.dispose();
403
+ if (Array.isArray(mesh.material)) {
404
+ for (const m of mesh.material) m.dispose();
405
+ } else {
406
+ mesh.material.dispose();
407
+ }
408
+ mesh.dispose();
409
+ }
410
+ this.configs = [];
411
+ super.onDestroy();
412
+ }
413
+ }
@@ -0,0 +1,216 @@
1
+ import type { XYZ } from "@navaramap/core";
2
+ import { Light } from "three";
3
+
4
+ import type ThreeView from "../index";
5
+
6
+ import {
7
+ BaseDesc,
8
+ type BaseInstance,
9
+ type BaseDescConfig,
10
+ type BaseDescConfigUpdate,
11
+ } from "./BaseDesc";
12
+ import type { ViewContext } from "./ViewContext";
13
+
14
+ export type LightConfig = {
15
+ type?: "light";
16
+ position?: XYZ;
17
+ } & BaseDescConfig;
18
+
19
+ export type LightUpdate = Pick<LightConfig, "position"> & BaseDescConfigUpdate;
20
+
21
+ export type LightBaseInstance<Instance extends object = object> =
22
+ Instance extends Light
23
+ ? Instance
24
+ : Instance extends {
25
+ raw: infer Raw extends Light;
26
+ }
27
+ ? Instance & { raw: Raw } & BaseInstance
28
+ : BaseInstance;
29
+
30
+ /**
31
+ * Abstract base class for creating custom light descriptors.
32
+ *
33
+ * Extend this class to add custom Three.js lights (directional, point, spot, ambient, etc.)
34
+ * to the Navara scene. The light is automatically added to `view.scenes.light` and
35
+ * position synchronization is handled by the base class.
36
+ *
37
+ * ## Implementing a Custom Light Descriptor
38
+ *
39
+ * ### 1. Define configuration types
40
+ *
41
+ * Create a description type for your light-specific options, then merge it with the
42
+ * base config and update types:
43
+ *
44
+ * ```typescript
45
+ * type MyLightDescription = {
46
+ * myLight?: {
47
+ * intensity?: number;
48
+ * color?: Color;
49
+ * };
50
+ * };
51
+ *
52
+ * type MyLightConfig = LightConfig & MyLightDescription;
53
+ * type MyLightUpdate = LightUpdate & MyLightDescription;
54
+ * ```
55
+ *
56
+ * ### 2. Extend `LightDesc`
57
+ *
58
+ * Implement the {@link createLight} factory method. Optionally override
59
+ * {@link onUpdateConfig} for dynamic property updates and {@link update} for
60
+ * per-frame animation.
61
+ *
62
+ * ```typescript
63
+ * class MyLightDesc extends LightDesc<
64
+ * MyLightConfig,
65
+ * MyLightUpdate,
66
+ * PointLight
67
+ * > {
68
+ * private config: MyLightConfig;
69
+ *
70
+ * constructor(view: ThreeView, ctx: ViewContext, config: MyLightConfig) {
71
+ * super(view, ctx, config);
72
+ * this.config = config;
73
+ * }
74
+ *
75
+ * createLight() {
76
+ * const cfg = this.config.myLight ?? {};
77
+ * return new PointLight(
78
+ * cfg.color?.raw ?? 0xffffff,
79
+ * cfg.intensity ?? 1,
80
+ * );
81
+ * }
82
+ *
83
+ * onUpdateConfig(updates: MyLightUpdate): void {
84
+ * super.onUpdateConfig(updates);
85
+ * if (updates.myLight && this._instance) {
86
+ * if (updates.myLight.intensity !== undefined) {
87
+ * this._instance.intensity = updates.myLight.intensity;
88
+ * }
89
+ * }
90
+ * }
91
+ * }
92
+ * ```
93
+ *
94
+ * ### 3. Register and use the descriptor
95
+ *
96
+ * ```typescript
97
+ * view.registerLight("myLight", MyLightDesc);
98
+ *
99
+ * const handle = view.addLight<MyLightDesc>({
100
+ * position: { x: 0, y: 100, z: 0 },
101
+ * myLight: { intensity: 2, color: new Color("#ff0000") },
102
+ * });
103
+ *
104
+ * // Update dynamically
105
+ * handle.update({ myLight: { intensity: 0.5 } });
106
+ *
107
+ * // Remove the descriptor
108
+ * handle.delete();
109
+ * ```
110
+ *
111
+ * ## Lifecycle
112
+ *
113
+ * 1. **Construction** - The descriptor is instantiated with the view context and config.
114
+ * 2. **{@link createLight}** - Called during {@link onCreate} to create the Three.js light.
115
+ * The base class adds it to `view.scenes.light` and applies the initial position.
116
+ * 3. **{@link onUpdateConfig}** - Called when `handle.update()` is invoked. The base class
117
+ * handles `visible` and `position`; override to handle your custom properties.
118
+ * 4. **{@link update}** - Optional per-frame callback for animation (e.g. moving lights).
119
+ * 5. **{@link onDestroy}** - Called on `handle.delete()`. The base class removes the light
120
+ * from its parent scene.
121
+ *
122
+ * @see {@link AmbientLightDesc} for a minimal built-in example.
123
+ * @see {@link SunLightDesc} for an advanced example with CSM shadows and atmosphere integration.
124
+ *
125
+ * @typeParam Config - Configuration type (extends {@link LightConfig})
126
+ * @typeParam UpdateConfig - Updatable properties (extends {@link LightUpdate})
127
+ * @typeParam InstanceObj - The Three.js Light type or a wrapper with a `raw` property
128
+ * @typeParam Instance - Resolved instance type (inferred automatically)
129
+ */
130
+ export abstract class LightDesc<
131
+ Config extends LightConfig = LightConfig,
132
+ UpdateConfig extends LightUpdate = LightUpdate,
133
+ InstanceObj extends Light | { raw: Light } = Light | { raw: Light },
134
+ Instance extends LightBaseInstance<InstanceObj> =
135
+ LightBaseInstance<InstanceObj>,
136
+ > extends BaseDesc<Config, UpdateConfig, Instance> {
137
+ public position?: XYZ;
138
+
139
+ constructor(
140
+ view: ThreeView,
141
+ ctx: ViewContext,
142
+ config: Config = {} as Config,
143
+ ) {
144
+ super(view, ctx, config);
145
+ this.position = config.position;
146
+ }
147
+
148
+ /**
149
+ * Factory method to create the Three.js light instance.
150
+ *
151
+ * Override this to return your custom light. The returned object can be either:
152
+ * - A Three.js `Light` directly (e.g. `PointLight`, `DirectionalLight`)
153
+ * - A wrapper object with a `raw` property containing the `Light`
154
+ *
155
+ * The base class calls this during {@link onCreate} and automatically adds the
156
+ * light to `view.scenes.light`.
157
+ */
158
+ abstract createLight(): Instance;
159
+
160
+ get raw() {
161
+ if (!this._instance) return;
162
+
163
+ if (this._instance instanceof Light) {
164
+ return this._instance as Instance extends Light ? Instance : never;
165
+ }
166
+ if ("raw" in this._instance) {
167
+ return this._instance.raw as Instance extends {
168
+ raw: infer Raw extends Light;
169
+ }
170
+ ? Raw
171
+ : never;
172
+ }
173
+ return;
174
+ }
175
+
176
+ onCreate() {
177
+ this._instance = this.createLight();
178
+
179
+ if (this._instance) {
180
+ this._instance.visible = this.visible;
181
+ }
182
+
183
+ if (this.position) {
184
+ this.raw?.position.copy(this.position);
185
+ }
186
+
187
+ // Add to scene
188
+ if (this.raw) {
189
+ this.ctx.scenes.light.add(this.raw);
190
+ }
191
+ }
192
+
193
+ onUpdateConfig(updates: UpdateConfig): void {
194
+ super.onUpdateConfig(updates);
195
+
196
+ if (updates.position) {
197
+ this.raw?.position.copy(updates.position);
198
+ }
199
+ }
200
+
201
+ onDestroy(): void {
202
+ if (this.raw && this.raw.parent) {
203
+ this.raw.parent.remove(this.raw);
204
+ }
205
+
206
+ this._instance = undefined;
207
+ }
208
+
209
+ /**
210
+ * Optional per-frame update callback.
211
+ * Override this to animate the light (e.g. orbiting, flickering, color shifts).
212
+ * @param time - High-resolution timestamp (in milliseconds) provided by the render loop,
213
+ * the same value passed to `requestAnimationFrame` callbacks.
214
+ */
215
+ update?(time: number): void;
216
+ }
@@ -0,0 +1,32 @@
1
+ import type ThreeView from "../index";
2
+
3
+ import { DescRegistry } from "./DescRegistry";
4
+ import type { LightConfig, LightDesc } from "./LightDesc";
5
+ import type { ViewContext } from "./ViewContext";
6
+
7
+ export type LightDescConstructor = new (
8
+ view: ThreeView,
9
+ ctx: ViewContext,
10
+ config: LightConfig,
11
+ ) => LightDesc;
12
+
13
+ export class LightDescRegistry extends DescRegistry<
14
+ LightDescConstructor,
15
+ LightDesc,
16
+ LightConfig
17
+ > {
18
+ create(name: string, config: LightConfig): LightDesc {
19
+ const LightClass = this.getConstructor(name);
20
+ if (!LightClass) {
21
+ throw new Error(`Unknown light type: ${name}`);
22
+ }
23
+ return new LightClass(this.view, this.ctx, config);
24
+ }
25
+
26
+ /**
27
+ * Find light type from config (alias for findTypeFromConfig for backward compatibility)
28
+ */
29
+ findLightType(config: Record<string, unknown>): string | null {
30
+ return this.findTypeFromConfig(config);
31
+ }
32
+ }