@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.
- package/LICENSE +8 -0
- package/dist/assets/atmosphere/README.md +1 -0
- package/dist/assets/atmosphere/higher_order_scattering.bin +0 -0
- package/dist/assets/atmosphere/higher_order_scattering.exr +0 -0
- package/dist/assets/atmosphere/irradiance.bin +0 -0
- package/dist/assets/atmosphere/irradiance.exr +0 -0
- package/dist/assets/atmosphere/scattering.bin +0 -0
- package/dist/assets/atmosphere/scattering.exr +0 -0
- package/dist/assets/atmosphere/single_mie_scattering.bin +0 -0
- package/dist/assets/atmosphere/single_mie_scattering.exr +0 -0
- package/dist/assets/atmosphere/stars.bin +0 -0
- package/dist/assets/atmosphere/transmittance.bin +0 -0
- package/dist/assets/atmosphere/transmittance.exr +0 -0
- package/dist/assets/cloud/README.md +1 -0
- package/dist/assets/cloud/local_weather.png +0 -0
- package/dist/assets/cloud/shape.bin +1 -0
- package/dist/assets/cloud/shape_detail.bin +1 -0
- package/dist/assets/cloud/turbulence.png +0 -0
- package/dist/assets/fontWorker-CEJEfRpb.js +2 -0
- package/dist/assets/fontWorker-CEJEfRpb.js.map +1 -0
- package/dist/assets/index-BUB-ijMO.js +12 -0
- package/dist/assets/index-BUB-ijMO.js.map +1 -0
- package/dist/assets/navara_wasm_font_worker_bg-665OLxjy.wasm +0 -0
- package/dist/assets/navara_wasm_worker_bg-BXhKC5bE.wasm +0 -0
- package/dist/assets/noise/README.md +1 -0
- package/dist/assets/noise/stbn.bin +0 -0
- package/dist/assets/water/README.md +3 -0
- package/dist/assets/water/waternormals.jpg +0 -0
- package/dist/index.d.ts +10114 -0
- package/dist/index.js +34481 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.cjs +6345 -0
- package/dist/index.umd.cjs.map +1 -0
- package/package.json +95 -0
- package/src/Color.ts +111 -0
- package/src/ShadowMapViewers.ts +49 -0
- package/src/atmosphere.test.ts +76 -0
- package/src/atmosphere.ts +364 -0
- package/src/bufferView.ts +90 -0
- package/src/camera.ts +182 -0
- package/src/concurrency.ts +15 -0
- package/src/constants/assets.ts +30 -0
- package/src/constants/decoder.ts +7 -0
- package/src/constants/index.ts +2 -0
- package/src/core/BaseDesc.ts +142 -0
- package/src/core/BaseHandle.ts +126 -0
- package/src/core/DescRegistry.ts +88 -0
- package/src/core/EffectDesc.ts +343 -0
- package/src/core/EffectDescRegistry.ts +31 -0
- package/src/core/InstancedMeshDesc.ts +413 -0
- package/src/core/LightDesc.ts +216 -0
- package/src/core/LightDescRegistry.ts +32 -0
- package/src/core/MeshDesc.ts +457 -0
- package/src/core/MeshDescRegistry.ts +32 -0
- package/src/core/MeshDescWithSelectiveEffect.ts +129 -0
- package/src/core/Registries.ts +59 -0
- package/src/core/SelectiveEffectRegistry.ts +90 -0
- package/src/core/ViewContext.ts +235 -0
- package/src/core/errors.ts +16 -0
- package/src/core/index.ts +50 -0
- package/src/device.ts +414 -0
- package/src/effects/CustomEffectPass.ts +28 -0
- package/src/effects/copy.ts +10 -0
- package/src/effects/effect.ts +87 -0
- package/src/effects/index.ts +4 -0
- package/src/effects/render.ts +10 -0
- package/src/evaluations/FeatureEvaluator.ts +529 -0
- package/src/evaluations/index.ts +1 -0
- package/src/event/HillshadeContext.test.ts +232 -0
- package/src/event/HillshadeContext.ts +299 -0
- package/src/event/context.ts +279 -0
- package/src/event/feature.ts +357 -0
- package/src/event/featureEvent.ts +81 -0
- package/src/event/features/billboard.ts +30 -0
- package/src/event/features/model.ts +192 -0
- package/src/event/features/modelGpuBytes.test.ts +69 -0
- package/src/event/features/modelGpuBytes.ts +87 -0
- package/src/event/features/point.ts +25 -0
- package/src/event/features/polygon.ts +23 -0
- package/src/event/features/polygonOutline.ts +19 -0
- package/src/event/features/polyline.ts +19 -0
- package/src/event/features/text.ts +71 -0
- package/src/event/hillshade.test.ts +842 -0
- package/src/event/hillshade.ts +588 -0
- package/src/event/index.ts +700 -0
- package/src/event/loaders.ts +53 -0
- package/src/event/tile.ts +19 -0
- package/src/event/worker.ts +999 -0
- package/src/event/workerTaskSettlement.test.ts +243 -0
- package/src/event/workerTaskSettlement.ts +128 -0
- package/src/inMemoryBufferStore.test.ts +60 -0
- package/src/inMemoryBufferStore.ts +67 -0
- package/src/index.iife.ts +11 -0
- package/src/index.ts +2556 -0
- package/src/input.ts +144 -0
- package/src/layer.ts +183 -0
- package/src/layers/effect/FinalCopyEffectDesc.ts +29 -0
- package/src/layers/effect/MRTPassEffectDesc.ts +105 -0
- package/src/layers/effect/README.md +9 -0
- package/src/layers/effect/SelectiveEffectDesc.ts +113 -0
- package/src/layers/effect/SkyEnvMapEffectDesc.ts +58 -0
- package/src/layers/effect/TransparentPassEffectDesc.ts +62 -0
- package/src/layers/effect/index.ts +5 -0
- package/src/layers/index.ts +1 -0
- package/src/layersManager.ts +63 -0
- package/src/light.ts +15 -0
- package/src/loaders/AbortableImageLoader.ts +203 -0
- package/src/loaders/AbortableTextureLoader.ts +74 -0
- package/src/loaders/index.ts +5 -0
- package/src/material/enhancer/DESIGN.md +300 -0
- package/src/material/enhancer/MaterialEnhancer.ts +112 -0
- package/src/material/enhancer/ShaderReplacer.test.ts +114 -0
- package/src/material/enhancer/ShaderReplacer.ts +97 -0
- package/src/material/enhancer/batchTexture.ts +8 -0
- package/src/material/enhancer/index.ts +46 -0
- package/src/material/enhancer/instancedSprite/index.ts +7 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/index.test.ts +214 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/index.ts +134 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/markers.ts +21 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/material.ts +32 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/mutates.test.ts +277 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/mutates.ts +151 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/shader.test.ts +114 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/shader.ts +49 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/state.test.ts +82 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/state.ts +80 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteBaseEnhancer/types.ts +146 -0
- package/src/material/enhancer/instancedSprite/instancedSpriteMaterialEnhancer.ts +105 -0
- package/src/material/enhancer/model/index.ts +25 -0
- package/src/material/enhancer/model/modelBaseEnhancer/index.test.ts +74 -0
- package/src/material/enhancer/model/modelBaseEnhancer/index.ts +110 -0
- package/src/material/enhancer/model/modelBaseEnhancer/markers.ts +27 -0
- package/src/material/enhancer/model/modelBaseEnhancer/material.test.ts +66 -0
- package/src/material/enhancer/model/modelBaseEnhancer/material.ts +44 -0
- package/src/material/enhancer/model/modelBaseEnhancer/mutates.test.ts +84 -0
- package/src/material/enhancer/model/modelBaseEnhancer/mutates.ts +47 -0
- package/src/material/enhancer/model/modelBaseEnhancer/shader.test.ts +24 -0
- package/src/material/enhancer/model/modelBaseEnhancer/shader.ts +162 -0
- package/src/material/enhancer/model/modelBaseEnhancer/state.test.ts +103 -0
- package/src/material/enhancer/model/modelBaseEnhancer/state.ts +52 -0
- package/src/material/enhancer/model/modelBaseEnhancer/types.ts +89 -0
- package/src/material/enhancer/model/modelMaterialEnhancer.ts +91 -0
- package/src/material/enhancer/model/modelWaterEnhancer/index.test.ts +71 -0
- package/src/material/enhancer/model/modelWaterEnhancer/index.ts +175 -0
- package/src/material/enhancer/model/modelWaterEnhancer/material.test.ts +48 -0
- package/src/material/enhancer/model/modelWaterEnhancer/material.ts +25 -0
- package/src/material/enhancer/model/modelWaterEnhancer/mutates.test.ts +89 -0
- package/src/material/enhancer/model/modelWaterEnhancer/mutates.ts +89 -0
- package/src/material/enhancer/model/modelWaterEnhancer/shader.test.ts +34 -0
- package/src/material/enhancer/model/modelWaterEnhancer/shader.ts +111 -0
- package/src/material/enhancer/model/modelWaterEnhancer/state.test.ts +105 -0
- package/src/material/enhancer/model/modelWaterEnhancer/state.ts +59 -0
- package/src/material/enhancer/model/modelWaterEnhancer/types.ts +141 -0
- package/src/material/enhancer/model/pntsEnhancer/index.test.ts +96 -0
- package/src/material/enhancer/model/pntsEnhancer/index.ts +82 -0
- package/src/material/enhancer/model/pntsEnhancer/markers.ts +6 -0
- package/src/material/enhancer/model/pntsEnhancer/material.test.ts +37 -0
- package/src/material/enhancer/model/pntsEnhancer/material.ts +21 -0
- package/src/material/enhancer/model/pntsEnhancer/mutates.test.ts +80 -0
- package/src/material/enhancer/model/pntsEnhancer/mutates.ts +29 -0
- package/src/material/enhancer/model/pntsEnhancer/shader.test.ts +32 -0
- package/src/material/enhancer/model/pntsEnhancer/shader.ts +56 -0
- package/src/material/enhancer/model/pntsEnhancer/state.test.ts +87 -0
- package/src/material/enhancer/model/pntsEnhancer/state.ts +29 -0
- package/src/material/enhancer/model/pntsEnhancer/types.ts +38 -0
- package/src/material/enhancer/polygon/index.ts +22 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/index.test.ts +101 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/index.ts +130 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/markers.ts +23 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/material.test.ts +19 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/material.ts +38 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/mutates.test.ts +75 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/mutates.ts +122 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/shader.test.ts +25 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/shader.ts +249 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/state.test.ts +102 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/state.ts +92 -0
- package/src/material/enhancer/polygon/polygonBaseEnhancer/types.ts +150 -0
- package/src/material/enhancer/polygon/polygonMaterialEnhancer.ts +97 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/index.test.ts +72 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/index.ts +164 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/material.test.ts +48 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/material.ts +35 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/mutates.ts +61 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/shader.test.ts +34 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/shader.ts +96 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/state.test.ts +98 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/state.ts +57 -0
- package/src/material/enhancer/polygon/polygonWaterEnhancer/types.ts +115 -0
- package/src/material/enhancer/polyline/index.ts +7 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/index.test.ts +157 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/index.ts +154 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/markers.ts +19 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/material.test.ts +42 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/material.ts +38 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/mutates.test.ts +120 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/mutates.ts +169 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/shader.test.ts +67 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/shader.ts +75 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/state.test.ts +55 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/state.ts +91 -0
- package/src/material/enhancer/polyline/polylineBaseEnhancer/types.ts +170 -0
- package/src/material/enhancer/polyline/polylineMaterialEnhancer.ts +102 -0
- package/src/material/enhancer/sdfText/index.ts +7 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/index.ts +125 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/markers.ts +19 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/material.test.ts +35 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/material.ts +32 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.test.ts +381 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.ts +232 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/shader.ts +36 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/state.test.ts +118 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/state.ts +107 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/types.ts +184 -0
- package/src/material/enhancer/sdfText/sdfTextMaterialEnhancer.ts +100 -0
- package/src/material/enhancer/shadowMap/index.ts +7 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/index.ts +97 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/markers.ts +10 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/material.ts +31 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/mutates.ts +8 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/shader.test.ts +17 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/shader.ts +53 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/state.ts +17 -0
- package/src/material/enhancer/shadowMap/shadowMapDepthEnhancer/types.ts +26 -0
- package/src/material/enhancer/test-utils/shaderCompatibility.ts +124 -0
- package/src/material/enhancer/tileComposite/compose.test.ts +95 -0
- package/src/material/enhancer/tileComposite/compose.ts +112 -0
- package/src/material/enhancer/tileComposite/index.ts +23 -0
- package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/index.ts +11 -0
- package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/mutates.ts +132 -0
- package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/shader.ts +245 -0
- package/src/material/enhancer/tileComposite/tileCompositeBaseEnhancer/types.ts +43 -0
- package/src/material/enhancer/tileComposite/tileElevationHeatmapEnhancer/index.ts +29 -0
- package/src/material/enhancer/tileComposite/tileElevationHeatmapEnhancer/mutates.ts +68 -0
- package/src/material/enhancer/tileComposite/tileElevationHeatmapEnhancer/shader.ts +24 -0
- package/src/material/enhancer/tileComposite/tileHillshadeEnhancer/index.ts +29 -0
- package/src/material/enhancer/tileComposite/tileHillshadeEnhancer/mutates.ts +34 -0
- package/src/material/enhancer/tileComposite/tileHillshadeEnhancer/shader.ts +36 -0
- package/src/material/enhancer/tileComposite/tileWaterEnhancer/index.ts +23 -0
- package/src/material/enhancer/tileComposite/tileWaterEnhancer/mutates.ts +23 -0
- package/src/material/enhancer/tileComposite/tileWaterEnhancer/shader.ts +8 -0
- package/src/material/enhancer/tileComposite/tileWatermaskEnhancer/index.ts +23 -0
- package/src/material/enhancer/tileComposite/tileWatermaskEnhancer/mutates.ts +34 -0
- package/src/material/enhancer/tileComposite/tileWatermaskEnhancer/shader.ts +13 -0
- package/src/material/enhancer/tileComposite/types.ts +58 -0
- package/src/material/index.ts +3 -0
- package/src/material/macro/index.ts +1 -0
- package/src/material/macro/tileShader.test.ts +136 -0
- package/src/material/macro/tileShader.ts +287 -0
- package/src/material/overrideMaterialsForMRT.ts +439 -0
- package/src/material/selectiveEffectMaterialSetup.test.ts +52 -0
- package/src/material/selectiveEffectMaterialSetup.ts +53 -0
- package/src/material/types/index.ts +1 -0
- package/src/material/types/uniform.ts +1 -0
- package/src/mesh/DrapedMesh.ts +101 -0
- package/src/mesh/batchTexture.test.ts +646 -0
- package/src/mesh/batchTexture.ts +437 -0
- package/src/mesh/batchedFeature.ts +186 -0
- package/src/mesh/batchedSdfText.ts +484 -0
- package/src/mesh/featureMesh.ts +43 -0
- package/src/mesh/index.ts +16 -0
- package/src/mesh/instanced.ts +117 -0
- package/src/mesh/model.ts +483 -0
- package/src/mesh/pickableMesh.ts +55 -0
- package/src/mesh/pickableMeshWrapper.ts +529 -0
- package/src/mesh/polygon.ts +699 -0
- package/src/mesh/polygonOutline.ts +393 -0
- package/src/mesh/polyline.ts +523 -0
- package/src/mesh/releaseGeometryArrays.ts +57 -0
- package/src/mesh/rtcRteHelper.ts +211 -0
- package/src/mesh/sdfText.test.ts +200 -0
- package/src/mesh/sdfText.ts +1019 -0
- package/src/mesh/sprite/billboardAtlas.test.ts +177 -0
- package/src/mesh/sprite/billboardAtlas.ts +210 -0
- package/src/mesh/sprite/billboardAtlasImageLoader.ts +29 -0
- package/src/mesh/sprite/index.ts +1 -0
- package/src/mesh/sprite/instancedSprite.ts +694 -0
- package/src/mesh/tile.test.ts +393 -0
- package/src/mesh/tile.ts +1790 -0
- package/src/object3DEvent.ts +6 -0
- package/src/orchestrators/RenderPassOrchestrator.ts +147 -0
- package/src/orchestrators/index.ts +1 -0
- package/src/passes/AllDepthCopyPass.ts +165 -0
- package/src/passes/CustomRenderPass.ts +279 -0
- package/src/passes/NormalCopyPass.ts +125 -0
- package/src/passes/RenderTargetCopyPass.ts +91 -0
- package/src/passes/SkyEnvMapPass.ts +58 -0
- package/src/passes/index.ts +5 -0
- package/src/pick/pickHelper.ts +273 -0
- package/src/pick/pickTerrain.ts +254 -0
- package/src/plugins/AttributionPlugin/AttributionPlugin.test.ts +210 -0
- package/src/plugins/AttributionPlugin/attribution.test.ts +225 -0
- package/src/plugins/AttributionPlugin/attribution.ts +355 -0
- package/src/plugins/AttributionPlugin/attributionStyles.ts +163 -0
- package/src/plugins/AttributionPlugin/index.ts +702 -0
- package/src/plugins/index.ts +1 -0
- package/src/quality.ts +1 -0
- package/src/renderOrder.ts +3 -0
- package/src/scene.test.ts +164 -0
- package/src/scene.ts +127 -0
- package/src/shaders/index.ts +1 -0
- package/src/solar.test.ts +81 -0
- package/src/solar.ts +101 -0
- package/src/source.ts +80 -0
- package/src/stats.ts +102 -0
- package/src/tasks/computeVertexNormalsAsync.ts +15 -0
- package/src/tasks/constructPolygonBatchedFeature.ts +34 -0
- package/src/tasks/constructPolylineBatchedFeature.ts +27 -0
- package/src/tasks/constructQuantizedMeshTerrainMesh.ts +24 -0
- package/src/tasks/constructTerrainMesh.ts +25 -0
- package/src/tasks/getImageDataFromBlob.ts +13 -0
- package/src/tasks/getImageDataFromImageBitmap.ts +12 -0
- package/src/tasks/parseMvtTile.ts +22 -0
- package/src/tasks/queueTask.ts +19 -0
- package/src/tasks/toCreasedNormalsAsync.ts +18 -0
- package/src/tasks/upsampleQuantizedMeshTerrainMesh.ts +44 -0
- package/src/tasks/upsampleTerrainMesh.ts +39 -0
- package/src/texture.ts +19 -0
- package/src/textures.ts +13 -0
- package/src/tileTexture/CompositeShader.snapshot.test.ts +59 -0
- package/src/tileTexture/CompositeShader.test.ts +168 -0
- package/src/tileTexture/CompositeShader.ts +53 -0
- package/src/tileTexture/SlotPlanner.test.ts +105 -0
- package/src/tileTexture/SlotPlanner.ts +102 -0
- package/src/tileTexture/TileTextureCache.test.ts +227 -0
- package/src/tileTexture/TileTextureCache.ts +192 -0
- package/src/tileTexture/TileTextureCompositor.test.ts +260 -0
- package/src/tileTexture/TileTextureCompositor.ts +421 -0
- package/src/tileTexture/__snapshots__/CompositeShader.snapshot.test.ts.snap +2649 -0
- package/src/tileTexture/index.ts +8 -0
- package/src/tileTexture/types.ts +150 -0
- package/src/type/index.ts +261 -0
- package/src/uniforms.ts +20 -0
- package/src/utils/arraysEqual.ts +9 -0
- package/src/utils/blendModes.ts +80 -0
- package/src/utils/geometry.ts +53 -0
- package/src/utils/hillshadeNormalMapGenerator.ts +193 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/object.test.ts +14 -0
- package/src/utils/object.ts +7 -0
- package/src/utils/replacer.test.ts +42 -0
- package/src/utils/replacer.ts +89 -0
- package/src/utils/screen.ts +29 -0
- package/src/utils/textureFragmentIndex.test.ts +224 -0
- package/src/utils/textureFragmentIndex.ts +97 -0
- package/src/utils/worker.ts +3 -0
- package/src/vite-env.d.ts +2 -0
- package/src/worker/index.ts +13 -0
- package/src/worker/tasks/computeVertexNormals.ts +15 -0
- 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
|
+
}
|