@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,694 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PointMesh as NavaraPointMesh,
|
|
3
|
+
BillboardMesh as NavaraBillboardMesh,
|
|
4
|
+
} from "@navaramap/engine";
|
|
5
|
+
import { degreeToRadian } from "@navaramap/three_api";
|
|
6
|
+
import {
|
|
7
|
+
InstancedBufferAttribute,
|
|
8
|
+
InstancedBufferGeometry,
|
|
9
|
+
Mesh,
|
|
10
|
+
Object3D,
|
|
11
|
+
ShaderMaterial,
|
|
12
|
+
BufferAttribute,
|
|
13
|
+
Color,
|
|
14
|
+
PerspectiveCamera,
|
|
15
|
+
Vector2,
|
|
16
|
+
} from "three";
|
|
17
|
+
import invariant from "tiny-invariant";
|
|
18
|
+
|
|
19
|
+
import type { EventContext } from "../../event/context";
|
|
20
|
+
import { createInstancedSpriteMaterialEnhancer } from "../../material/enhancer";
|
|
21
|
+
import { PickableMesh } from "../pickableMesh";
|
|
22
|
+
|
|
23
|
+
import { BillboardAtlas, type AtlasRect } from "./billboardAtlas";
|
|
24
|
+
import { loadAtlasImageFromUrl } from "./billboardAtlasImageLoader";
|
|
25
|
+
|
|
26
|
+
export type InstancedSpriteOptions = {
|
|
27
|
+
renderOrder?: number;
|
|
28
|
+
ctx: EventContext;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type PositionsInfo = {
|
|
32
|
+
position:
|
|
33
|
+
| Float32Array<ArrayBufferLike>
|
|
34
|
+
| {
|
|
35
|
+
high: Float32Array<ArrayBufferLike>;
|
|
36
|
+
low: Float32Array<ArrayBufferLike>;
|
|
37
|
+
};
|
|
38
|
+
batchIDs: Float32Array<ArrayBufferLike> | null;
|
|
39
|
+
positionSize: number;
|
|
40
|
+
batchIDSize: number;
|
|
41
|
+
nPositions: number;
|
|
42
|
+
RTE: boolean;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Reusable Vector2 to avoid per-frame allocations in onBeforeRender. */
|
|
46
|
+
const _tmpSize = new Vector2();
|
|
47
|
+
|
|
48
|
+
// Coupled with crates/navara_feature/src/geometry/point.rs::pixel_to_world
|
|
49
|
+
export class InstancedSpriteMesh extends Mesh implements PickableMesh {
|
|
50
|
+
private _batchIdToInstance = new Map<number, number>();
|
|
51
|
+
private _initialColor: Color = new Color(0xffffff);
|
|
52
|
+
private _initialHeight = 0.0;
|
|
53
|
+
private _initialSize = -1.0; // Negative value indicates "use uScale" in shader
|
|
54
|
+
private _atlas?: BillboardAtlas;
|
|
55
|
+
private _defaultUrl?: string;
|
|
56
|
+
/** Atlas rect of the current default image; re-applied to an instance when
|
|
57
|
+
* its per-feature override is cleared. */
|
|
58
|
+
private _defaultRect?: AtlasRect;
|
|
59
|
+
/** Instance ids whose image was overridden per-feature; the default image
|
|
60
|
+
* from the material no longer applies to them. */
|
|
61
|
+
private _imageOverrides = new Set<number>();
|
|
62
|
+
/** Latest override URL requested per instance. An async pack only applies
|
|
63
|
+
* if it still matches, so a newer override or a clear wins over slow loads. */
|
|
64
|
+
private _requestedImageUrls = new Map<number, string>();
|
|
65
|
+
/** Forwards the atlas byte footprint to the engine's memory ledger; wired
|
|
66
|
+
* by the feature-added handler once the owning entity bits are known. */
|
|
67
|
+
private _atlasBytesReporter?: (bytes: number) => void;
|
|
68
|
+
private _reportedAtlasBytes = 0;
|
|
69
|
+
private _active = true;
|
|
70
|
+
readonly ctx: EventContext;
|
|
71
|
+
/** Material enhancer for encapsulated state management */
|
|
72
|
+
private _enhancedMaterial?: ReturnType<
|
|
73
|
+
typeof createInstancedSpriteMaterialEnhancer
|
|
74
|
+
>;
|
|
75
|
+
constructor(options: InstancedSpriteOptions) {
|
|
76
|
+
super();
|
|
77
|
+
this.renderOrder = options.renderOrder ?? this.renderOrder;
|
|
78
|
+
this.ctx = options.ctx;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
setActive(active: boolean) {
|
|
82
|
+
this._active = active;
|
|
83
|
+
this.updateVisibility();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async _init(m: NavaraPointMesh | NavaraBillboardMesh) {
|
|
87
|
+
const positionsInfo = this.extractPositions(m);
|
|
88
|
+
if (positionsInfo === null) {
|
|
89
|
+
console.warn("No position data found for InstancedSpriteMesh");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Create Geometry
|
|
94
|
+
this.geometry = this._initGeometry(positionsInfo, m);
|
|
95
|
+
|
|
96
|
+
// Create Material
|
|
97
|
+
this.material = await this._initMaterial(positionsInfo, m);
|
|
98
|
+
|
|
99
|
+
this.frustumCulled = false; // Disable since bounding box doesn't account for instance positions
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async _update(m: NavaraPointMesh | NavaraBillboardMesh) {
|
|
103
|
+
const enhancer = this.getEnhancer();
|
|
104
|
+
const material = this.material as ShaderMaterial;
|
|
105
|
+
|
|
106
|
+
if (material.visible !== m.material.show) {
|
|
107
|
+
material.visible = m.material.show ?? true;
|
|
108
|
+
this.updateVisibility();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Update enhancer state for uniform-backed properties
|
|
112
|
+
enhancer.update({
|
|
113
|
+
base: {
|
|
114
|
+
scale: m.material.size ?? 100.0,
|
|
115
|
+
center: [m.material.center?.x ?? 0.0, m.material.center?.y ?? 0.0],
|
|
116
|
+
sizeInMeters: m.material.sizeInMeters ?? true,
|
|
117
|
+
offsetDepth: m.material.offsetDepth ?? true,
|
|
118
|
+
transparent: m.material.transparent ?? true,
|
|
119
|
+
depthTest: m.material.depthTest ?? true,
|
|
120
|
+
effectIdsMask:
|
|
121
|
+
this.ctx.viewContext.selectiveEffectRegistry?.computeMask(
|
|
122
|
+
m.material.effectIds ?? [],
|
|
123
|
+
) ?? 0,
|
|
124
|
+
emissiveColor: m.material.emissiveColor ?? 0,
|
|
125
|
+
emissiveIntensity: m.material.emissiveIntensity ?? 0,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Color (per-instance attribute)
|
|
130
|
+
if (this._initialColor.getHex() !== (m.material.color ?? 0xffffff)) {
|
|
131
|
+
this._initialColor.setHex(m.material.color ?? 0xffffff);
|
|
132
|
+
const colorAttr = this.geometry.getAttribute(
|
|
133
|
+
"instanceColor",
|
|
134
|
+
) as InstancedBufferAttribute;
|
|
135
|
+
const instanceCount = colorAttr.count;
|
|
136
|
+
for (let i = 0; i < instanceCount; i++) {
|
|
137
|
+
colorAttr.setXYZ(
|
|
138
|
+
i,
|
|
139
|
+
this._initialColor.r,
|
|
140
|
+
this._initialColor.g,
|
|
141
|
+
this._initialColor.b,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
colorAttr.needsUpdate = true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Height (per-instance attribute - X component of instanceParams vec4)
|
|
148
|
+
if (this._initialHeight !== (m.material.height ?? 0.0)) {
|
|
149
|
+
this._initialHeight = m.material.height ?? 0.0;
|
|
150
|
+
const paramsAttr = this.geometry.getAttribute(
|
|
151
|
+
"instanceParams",
|
|
152
|
+
) as InstancedBufferAttribute;
|
|
153
|
+
const instanceCount = paramsAttr.count;
|
|
154
|
+
for (let i = 0; i < instanceCount; i++) {
|
|
155
|
+
paramsAttr.setX(i, m.material.height ?? 0.0);
|
|
156
|
+
}
|
|
157
|
+
paramsAttr.needsUpdate = true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Position updates (per-instance attributes)
|
|
161
|
+
{
|
|
162
|
+
const positionsInfo = this.extractPositions(m);
|
|
163
|
+
|
|
164
|
+
if (positionsInfo) {
|
|
165
|
+
if (positionsInfo.RTE) {
|
|
166
|
+
const pos = positionsInfo.position as {
|
|
167
|
+
high: Float32Array<ArrayBufferLike>;
|
|
168
|
+
low: Float32Array<ArrayBufferLike>;
|
|
169
|
+
};
|
|
170
|
+
const pLow = this.geometry.getAttribute(
|
|
171
|
+
"instancePositionLOW",
|
|
172
|
+
) as InstancedBufferAttribute;
|
|
173
|
+
const pHigh = this.geometry.getAttribute(
|
|
174
|
+
"instancePositionHIGH",
|
|
175
|
+
) as InstancedBufferAttribute;
|
|
176
|
+
pLow.copyArray(pos.low);
|
|
177
|
+
pHigh.copyArray(pos.high);
|
|
178
|
+
pLow.needsUpdate = true;
|
|
179
|
+
pHigh.needsUpdate = true;
|
|
180
|
+
} else {
|
|
181
|
+
const pos = positionsInfo.position as Float32Array<ArrayBufferLike>;
|
|
182
|
+
const p = this.geometry.getAttribute(
|
|
183
|
+
"instancePosition",
|
|
184
|
+
) as InstancedBufferAttribute;
|
|
185
|
+
p.copyArray(pos);
|
|
186
|
+
p.needsUpdate = true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Billboard-specific updates
|
|
192
|
+
if (m instanceof NavaraBillboardMesh) {
|
|
193
|
+
enhancer.update({
|
|
194
|
+
base: { alphaTest: m.material.alphaTest ?? 0.0 },
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (m.material.url) {
|
|
198
|
+
await this._setDefaultImage(m.material.url);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private _initGeometry(
|
|
204
|
+
positionsInfo: PositionsInfo,
|
|
205
|
+
m: NavaraPointMesh | NavaraBillboardMesh,
|
|
206
|
+
) {
|
|
207
|
+
invariant(positionsInfo.batchIDs, "Batch IDs not found!");
|
|
208
|
+
|
|
209
|
+
// prettier-ignore
|
|
210
|
+
const vertices = new Float32Array([
|
|
211
|
+
-0.5, -0.5, 0.0, // v0
|
|
212
|
+
0.5, -0.5, 0.0, // v1
|
|
213
|
+
0.5, 0.5, 0.0, // v2
|
|
214
|
+
-0.5, -0.5, 0.0, // v3
|
|
215
|
+
0.5, 0.5, 0.0, // v4
|
|
216
|
+
-0.5, 0.5, 0.0, // v5
|
|
217
|
+
]);
|
|
218
|
+
|
|
219
|
+
// prettier-ignore
|
|
220
|
+
const uvs = new Float32Array([
|
|
221
|
+
0.0, 0.0, // v0
|
|
222
|
+
1.0, 0.0, // v1
|
|
223
|
+
1.0, 1.0, // v2
|
|
224
|
+
0.0, 0.0, // v3
|
|
225
|
+
1.0, 1.0, // v4
|
|
226
|
+
0.0, 1.0, // v5
|
|
227
|
+
]);
|
|
228
|
+
|
|
229
|
+
const instanceCount = positionsInfo.nPositions;
|
|
230
|
+
|
|
231
|
+
// Create the Instanced Mesh
|
|
232
|
+
// We use InstancedBufferGeometry to inject our custom attributes
|
|
233
|
+
const instancedGeometry = new InstancedBufferGeometry();
|
|
234
|
+
instancedGeometry.setAttribute(
|
|
235
|
+
"position",
|
|
236
|
+
new BufferAttribute(vertices, 3),
|
|
237
|
+
);
|
|
238
|
+
instancedGeometry.setAttribute("uv", new BufferAttribute(uvs, 2));
|
|
239
|
+
instancedGeometry.instanceCount = instanceCount;
|
|
240
|
+
|
|
241
|
+
// Add Custom Attributes
|
|
242
|
+
// instanceParams: vec4(height, size, show, opacity)
|
|
243
|
+
const paramsBuffer = new Float32Array(instanceCount * 4);
|
|
244
|
+
const colorBuffer = new Float32Array(instanceCount * 3);
|
|
245
|
+
|
|
246
|
+
this._initialColor = new Color().setHex(m.material.color ?? 0xffffff);
|
|
247
|
+
// instanceSize defaults to a negative value to indicate "use uScale" in the shader.
|
|
248
|
+
this._initialSize = -1.0;
|
|
249
|
+
const initialShow =
|
|
250
|
+
m.material.show !== undefined ? (m.material.show ? 1.0 : 0.0) : 1.0;
|
|
251
|
+
const initialOpacityRaw = m.material.opacity ?? 1.0;
|
|
252
|
+
const initialOpacity = Number.isFinite(initialOpacityRaw)
|
|
253
|
+
? Math.max(0.0, Math.min(1.0, initialOpacityRaw))
|
|
254
|
+
: 1.0;
|
|
255
|
+
|
|
256
|
+
for (let i = 0; i < instanceCount; i++) {
|
|
257
|
+
paramsBuffer[i * 4 + 0] = m.material.height ?? 0.0; // height
|
|
258
|
+
paramsBuffer[i * 4 + 1] = this._initialSize; // size
|
|
259
|
+
paramsBuffer[i * 4 + 2] = initialShow; // show
|
|
260
|
+
paramsBuffer[i * 4 + 3] = initialOpacity; // opacity
|
|
261
|
+
|
|
262
|
+
colorBuffer[i * 3 + 0] = this._initialColor.r;
|
|
263
|
+
colorBuffer[i * 3 + 1] = this._initialColor.g;
|
|
264
|
+
colorBuffer[i * 3 + 2] = this._initialColor.b;
|
|
265
|
+
|
|
266
|
+
// Map batch ID to instance id
|
|
267
|
+
// assuming batch IDs are 32bit floats
|
|
268
|
+
const batchId = positionsInfo.batchIDs[i];
|
|
269
|
+
this._batchIdToInstance.set(batchId, i);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (m instanceof NavaraBillboardMesh) {
|
|
273
|
+
// instanceUvRect: vec4(x, y, w, h) — this instance's atlas sub-rect in
|
|
274
|
+
// pixels. Zeroed until an image is packed; a zero-height rect samples a
|
|
275
|
+
// transparent texel, so instances stay invisible rather than garbled.
|
|
276
|
+
instancedGeometry.setAttribute(
|
|
277
|
+
"instanceUvRect",
|
|
278
|
+
new InstancedBufferAttribute(new Float32Array(instanceCount * 4), 4),
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (positionsInfo.RTE) {
|
|
283
|
+
const pos = positionsInfo.position as {
|
|
284
|
+
high: Float32Array<ArrayBufferLike>;
|
|
285
|
+
low: Float32Array<ArrayBufferLike>;
|
|
286
|
+
};
|
|
287
|
+
instancedGeometry.setAttribute(
|
|
288
|
+
"instancePositionLOW",
|
|
289
|
+
new InstancedBufferAttribute(pos.low, positionsInfo.positionSize),
|
|
290
|
+
);
|
|
291
|
+
instancedGeometry.setAttribute(
|
|
292
|
+
"instancePositionHIGH",
|
|
293
|
+
new InstancedBufferAttribute(pos.high, positionsInfo.positionSize),
|
|
294
|
+
);
|
|
295
|
+
} else {
|
|
296
|
+
const pos = positionsInfo.position as Float32Array<ArrayBufferLike>;
|
|
297
|
+
instancedGeometry.setAttribute(
|
|
298
|
+
"instancePosition",
|
|
299
|
+
new InstancedBufferAttribute(pos, positionsInfo.positionSize),
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
instancedGeometry.setAttribute(
|
|
303
|
+
"instanceParams",
|
|
304
|
+
new InstancedBufferAttribute(paramsBuffer, 4),
|
|
305
|
+
);
|
|
306
|
+
instancedGeometry.setAttribute(
|
|
307
|
+
"instanceColor",
|
|
308
|
+
new InstancedBufferAttribute(colorBuffer, 3),
|
|
309
|
+
);
|
|
310
|
+
instancedGeometry.setAttribute(
|
|
311
|
+
"instanceBatchID",
|
|
312
|
+
new InstancedBufferAttribute(
|
|
313
|
+
positionsInfo.batchIDs,
|
|
314
|
+
positionsInfo.batchIDSize,
|
|
315
|
+
),
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
return instancedGeometry;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private async _initMaterial(
|
|
322
|
+
positionsInfo: PositionsInfo,
|
|
323
|
+
m: NavaraPointMesh | NavaraBillboardMesh,
|
|
324
|
+
) {
|
|
325
|
+
const isBillboard = m instanceof NavaraBillboardMesh;
|
|
326
|
+
const material = new ShaderMaterial();
|
|
327
|
+
|
|
328
|
+
// Create enhancer
|
|
329
|
+
const enhancer = createInstancedSpriteMaterialEnhancer(material);
|
|
330
|
+
this._enhancedMaterial = enhancer;
|
|
331
|
+
|
|
332
|
+
// Mount with initial props
|
|
333
|
+
enhancer.mount({
|
|
334
|
+
base: {
|
|
335
|
+
useRTE: positionsInfo.RTE,
|
|
336
|
+
billboard: isBillboard,
|
|
337
|
+
scale: m.material.size ?? 100.0,
|
|
338
|
+
center: [m.material.center?.x ?? 0.0, m.material.center?.y ?? 0.0],
|
|
339
|
+
sizeInMeters: m.material.sizeInMeters ?? true,
|
|
340
|
+
offsetDepth: m.material.offsetDepth ?? true,
|
|
341
|
+
alphaTest: isBillboard ? (m.material.alphaTest ?? 0.0) : 0.0,
|
|
342
|
+
pickable: false,
|
|
343
|
+
transparent: m.material.transparent ?? true,
|
|
344
|
+
depthTest: m.material.depthTest ?? true,
|
|
345
|
+
rtcCenter: [m.transform.tx, m.transform.ty, m.transform.tz],
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// Initialize uniforms early so they're available before onBeforeCompile
|
|
350
|
+
const mutates = enhancer.mutates();
|
|
351
|
+
mutates.updateUniforms(material.uniforms, enhancer.states());
|
|
352
|
+
|
|
353
|
+
// Set up onBeforeRender for per-frame updates (farPlane + RTE eye position)
|
|
354
|
+
material.onBeforeRender = (
|
|
355
|
+
_renderer,
|
|
356
|
+
_scene,
|
|
357
|
+
camera,
|
|
358
|
+
_geometry,
|
|
359
|
+
_mat,
|
|
360
|
+
_group,
|
|
361
|
+
) => {
|
|
362
|
+
const pCam = camera as PerspectiveCamera;
|
|
363
|
+
mutates.updateFarPlane(pCam.far);
|
|
364
|
+
mutates.updateFovRad(degreeToRadian(pCam.fov));
|
|
365
|
+
mutates.updateScreenHeightPx(
|
|
366
|
+
_renderer.getDrawingBufferSize(_tmpSize).y / _renderer.getPixelRatio(),
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
if (positionsInfo.RTE) {
|
|
370
|
+
mutates.updateRteUniforms(
|
|
371
|
+
camera.position.x,
|
|
372
|
+
camera.position.y,
|
|
373
|
+
camera.position.z,
|
|
374
|
+
enhancer.states(),
|
|
375
|
+
);
|
|
376
|
+
} else {
|
|
377
|
+
mutates.updateRtcUniforms(camera.matrixWorldInverse, enhancer.states());
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
// Set custom program cache key and onBeforeCompile
|
|
382
|
+
material.customProgramCacheKey = enhancer.programCacheKey;
|
|
383
|
+
material.onBeforeCompile = enhancer.transformShader;
|
|
384
|
+
|
|
385
|
+
// Handle billboard texture
|
|
386
|
+
if (isBillboard && m.material.url) {
|
|
387
|
+
await this._setDefaultImage(m.material.url);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
material.visible = m.material.show ?? true;
|
|
391
|
+
this.updateVisibility();
|
|
392
|
+
return material;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
private updateVisibility() {
|
|
396
|
+
const material = this.material;
|
|
397
|
+
const materialVisible =
|
|
398
|
+
material instanceof ShaderMaterial ? material.visible : true;
|
|
399
|
+
this.visible = this._active && materialVisible;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
private extractPositions(
|
|
403
|
+
m: NavaraPointMesh | NavaraBillboardMesh,
|
|
404
|
+
): PositionsInfo | null {
|
|
405
|
+
const { buf } = this.ctx;
|
|
406
|
+
const g = m.geometry;
|
|
407
|
+
|
|
408
|
+
const batchIdsData = g.batch_ids;
|
|
409
|
+
const batchIDs = buf.removeF32(batchIdsData.data);
|
|
410
|
+
const batchIDSize = batchIdsData.size;
|
|
411
|
+
|
|
412
|
+
const positionData = g.position;
|
|
413
|
+
const position = positionData
|
|
414
|
+
? buf.removeF32(positionData.data)
|
|
415
|
+
: undefined;
|
|
416
|
+
|
|
417
|
+
if (position && positionData) {
|
|
418
|
+
const positionSize = positionData.size;
|
|
419
|
+
const nPositions = position.length / positionSize;
|
|
420
|
+
|
|
421
|
+
return {
|
|
422
|
+
position,
|
|
423
|
+
batchIDs,
|
|
424
|
+
batchIDSize,
|
|
425
|
+
positionSize,
|
|
426
|
+
nPositions,
|
|
427
|
+
RTE: false,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const positionHighData = g.position_3d_high;
|
|
432
|
+
const positionLowData = g.position_3d_low;
|
|
433
|
+
const positionHigh = positionHighData
|
|
434
|
+
? buf.removeF32(positionHighData.data)
|
|
435
|
+
: undefined;
|
|
436
|
+
const positionLow = positionLowData
|
|
437
|
+
? buf.removeF32(positionLowData.data)
|
|
438
|
+
: undefined;
|
|
439
|
+
|
|
440
|
+
if (positionHigh && positionLow && positionHighData && positionLowData) {
|
|
441
|
+
const positionLowSize = positionLowData.size;
|
|
442
|
+
const positionHighSize = positionHighData.size;
|
|
443
|
+
invariant(
|
|
444
|
+
positionLowSize === positionHighSize,
|
|
445
|
+
"Position high and low size mismatch",
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
const nPositions = positionHigh.length / positionHighSize;
|
|
449
|
+
|
|
450
|
+
return {
|
|
451
|
+
position: { high: positionHigh, low: positionLow },
|
|
452
|
+
batchIDs,
|
|
453
|
+
batchIDSize,
|
|
454
|
+
positionSize: positionHighSize,
|
|
455
|
+
nPositions,
|
|
456
|
+
RTE: true,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private _ensureAtlas(): BillboardAtlas {
|
|
464
|
+
this._atlas ??= new BillboardAtlas({ loadImage: loadAtlasImageFromUrl });
|
|
465
|
+
return this._atlas;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Wire the callback that reports this mesh's atlas footprint to the
|
|
470
|
+
* engine's memory ledger, and immediately report the current footprint —
|
|
471
|
+
* the default image may have been packed during `_init`, before the
|
|
472
|
+
* feature-added handler could wire the reporter.
|
|
473
|
+
*/
|
|
474
|
+
setAtlasBytesReporter(reporter: (bytes: number) => void): void {
|
|
475
|
+
this._atlasBytesReporter = reporter;
|
|
476
|
+
this._reportAtlasBytes();
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/** Report the atlas footprint if it changed since the last report. Must run
|
|
480
|
+
* after every `pack()` — the atlas may have grown even when the pack failed
|
|
481
|
+
* (growth up to `maxSize` happens before "no space" is decided). */
|
|
482
|
+
private _reportAtlasBytes(): void {
|
|
483
|
+
if (!this._atlasBytesReporter) return;
|
|
484
|
+
const bytes = this._atlas?.byteLength ?? 0;
|
|
485
|
+
if (bytes === this._reportedAtlasBytes) return;
|
|
486
|
+
this._reportedAtlasBytes = bytes;
|
|
487
|
+
this._atlasBytesReporter(bytes);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Push the atlas texture and size to the material. The texture object is
|
|
492
|
+
* replaced whenever the atlas grows, so this must run after every pack().
|
|
493
|
+
*/
|
|
494
|
+
private _syncAtlasUniforms(): void {
|
|
495
|
+
const atlas = this._atlas;
|
|
496
|
+
if (!atlas) return;
|
|
497
|
+
this.getEnhancer().update({
|
|
498
|
+
base: {
|
|
499
|
+
texture: { value: atlas.texture },
|
|
500
|
+
atlasSize: [atlas.size, atlas.size],
|
|
501
|
+
},
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Load the material-level image and apply its rect to every instance that
|
|
507
|
+
* hasn't been overridden per-feature via setFeatureImageByBatchId.
|
|
508
|
+
*/
|
|
509
|
+
private async _setDefaultImage(url: string): Promise<void> {
|
|
510
|
+
if (this._defaultUrl === url) return;
|
|
511
|
+
this._defaultUrl = url;
|
|
512
|
+
|
|
513
|
+
const rect = await this._ensureAtlas().pack(url);
|
|
514
|
+
this._reportAtlasBytes();
|
|
515
|
+
if (!rect) return;
|
|
516
|
+
// A newer default image won the race while this one was loading.
|
|
517
|
+
if (this._defaultUrl !== url) return;
|
|
518
|
+
|
|
519
|
+
this._defaultRect = rect;
|
|
520
|
+
this._syncAtlasUniforms();
|
|
521
|
+
const rectAttr = this.geometry.getAttribute(
|
|
522
|
+
"instanceUvRect",
|
|
523
|
+
) as InstancedBufferAttribute;
|
|
524
|
+
for (let i = 0; i < rectAttr.count; i++) {
|
|
525
|
+
if (this._imageOverrides.has(i)) continue;
|
|
526
|
+
rectAttr.setXYZW(i, rect.x, rect.y, rect.w, rect.h);
|
|
527
|
+
}
|
|
528
|
+
rectAttr.needsUpdate = true;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
onBeforePicking(): void {
|
|
532
|
+
this.getEnhancer().update({ base: { pickable: true } });
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
onAfterPicking(): void {
|
|
536
|
+
this.getEnhancer().update({ base: { pickable: false } });
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
getRenderable(): Object3D {
|
|
540
|
+
return this;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Get the enhancer, throwing if not initialized.
|
|
545
|
+
*/
|
|
546
|
+
private getEnhancer(): NonNullable<typeof this._enhancedMaterial> {
|
|
547
|
+
if (!this._enhancedMaterial) {
|
|
548
|
+
throw new Error(
|
|
549
|
+
"InstancedSpriteMesh material enhancer is not initialized. This usually indicates a failure during construction or geometry/material setup.",
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
return this._enhancedMaterial;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
setFeatureColorByBatchId(batchId: number, color: Color) {
|
|
556
|
+
const instanceId = this._batchIdToInstance.get(batchId);
|
|
557
|
+
if (instanceId === undefined) return;
|
|
558
|
+
|
|
559
|
+
const colorAttr = this.geometry.getAttribute(
|
|
560
|
+
"instanceColor",
|
|
561
|
+
) as InstancedBufferAttribute;
|
|
562
|
+
colorAttr.setXYZ(instanceId, color.r, color.g, color.b);
|
|
563
|
+
colorAttr.needsUpdate = true;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
setFeatureShowByBatchId(batchId: number, rawVisible: boolean) {
|
|
567
|
+
const instanceId = this._batchIdToInstance.get(batchId);
|
|
568
|
+
if (instanceId === undefined) return;
|
|
569
|
+
|
|
570
|
+
const paramsAttr = this.geometry.getAttribute(
|
|
571
|
+
"instanceParams",
|
|
572
|
+
) as InstancedBufferAttribute;
|
|
573
|
+
paramsAttr.setZ(instanceId, rawVisible ? 1.0 : 0.0);
|
|
574
|
+
paramsAttr.needsUpdate = true;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
setFeatureOpacityByBatchId(batchId: number, opacity: number) {
|
|
578
|
+
const instanceId = this._batchIdToInstance.get(batchId);
|
|
579
|
+
if (instanceId === undefined) return;
|
|
580
|
+
|
|
581
|
+
const paramsAttr = this.geometry.getAttribute(
|
|
582
|
+
"instanceParams",
|
|
583
|
+
) as InstancedBufferAttribute;
|
|
584
|
+
const clampedOpacity = Number.isFinite(opacity)
|
|
585
|
+
? Math.max(0.0, Math.min(1.0, opacity))
|
|
586
|
+
: 1.0;
|
|
587
|
+
paramsAttr.setW(instanceId, clampedOpacity);
|
|
588
|
+
paramsAttr.needsUpdate = true;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
setFeatureHeightByBatchId(batchId: number, height: number) {
|
|
592
|
+
const instanceId = this._batchIdToInstance.get(batchId);
|
|
593
|
+
if (instanceId === undefined) return;
|
|
594
|
+
|
|
595
|
+
const paramsAttr = this.geometry.getAttribute(
|
|
596
|
+
"instanceParams",
|
|
597
|
+
) as InstancedBufferAttribute;
|
|
598
|
+
|
|
599
|
+
const sanitizedHeight = Number.isFinite(height) ? height : 0.0;
|
|
600
|
+
paramsAttr.setX(instanceId, sanitizedHeight);
|
|
601
|
+
paramsAttr.needsUpdate = true;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
setFeatureSizeByBatchId(batchId: number, size: number) {
|
|
605
|
+
const instanceId = this._batchIdToInstance.get(batchId);
|
|
606
|
+
if (instanceId === undefined) return;
|
|
607
|
+
|
|
608
|
+
const paramsAttr = this.geometry.getAttribute(
|
|
609
|
+
"instanceParams",
|
|
610
|
+
) as InstancedBufferAttribute;
|
|
611
|
+
|
|
612
|
+
const sanitizedSize = Number.isFinite(size)
|
|
613
|
+
? size < 0.0
|
|
614
|
+
? -1.0
|
|
615
|
+
: size
|
|
616
|
+
: -1.0;
|
|
617
|
+
paramsAttr.setY(instanceId, sanitizedSize);
|
|
618
|
+
paramsAttr.needsUpdate = true;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Give one feature its own image, packed into this mesh's texture atlas.
|
|
623
|
+
* Loads are deduplicated by URL, so styling many features with few distinct
|
|
624
|
+
* images fetches each image once. On load failure the feature keeps its
|
|
625
|
+
* current (default) image. Passing a nullish `url` clears the override and
|
|
626
|
+
* reverts the feature to the material's default image. No-op for
|
|
627
|
+
* non-billboard (point) meshes.
|
|
628
|
+
*/
|
|
629
|
+
async setFeatureImageByBatchId(
|
|
630
|
+
batchId: number,
|
|
631
|
+
url: string | null | undefined,
|
|
632
|
+
): Promise<void> {
|
|
633
|
+
const instanceId = this._batchIdToInstance.get(batchId);
|
|
634
|
+
if (instanceId === undefined) return;
|
|
635
|
+
|
|
636
|
+
const rectAttr = this.geometry.getAttribute("instanceUvRect") as
|
|
637
|
+
| InstancedBufferAttribute
|
|
638
|
+
| undefined;
|
|
639
|
+
if (!rectAttr) return;
|
|
640
|
+
|
|
641
|
+
if (url == null) {
|
|
642
|
+
this._requestedImageUrls.delete(instanceId);
|
|
643
|
+
if (!this._imageOverrides.delete(instanceId)) return;
|
|
644
|
+
// Zero rect (invisible) until the default image finishes loading, same
|
|
645
|
+
// as instances that never had an override.
|
|
646
|
+
const rect = this._defaultRect;
|
|
647
|
+
rectAttr.setXYZW(
|
|
648
|
+
instanceId,
|
|
649
|
+
rect?.x ?? 0,
|
|
650
|
+
rect?.y ?? 0,
|
|
651
|
+
rect?.w ?? 0,
|
|
652
|
+
rect?.h ?? 0,
|
|
653
|
+
);
|
|
654
|
+
rectAttr.needsUpdate = true;
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
this._requestedImageUrls.set(instanceId, url);
|
|
659
|
+
const rect = await this._ensureAtlas().pack(url);
|
|
660
|
+
this._reportAtlasBytes();
|
|
661
|
+
if (!rect) return;
|
|
662
|
+
// A newer override or a clear superseded this load while it was in flight.
|
|
663
|
+
if (this._requestedImageUrls.get(instanceId) !== url) return;
|
|
664
|
+
|
|
665
|
+
this._imageOverrides.add(instanceId);
|
|
666
|
+
this._syncAtlasUniforms();
|
|
667
|
+
rectAttr.setXYZW(instanceId, rect.x, rect.y, rect.w, rect.h);
|
|
668
|
+
rectAttr.needsUpdate = true;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
dispose(): void {
|
|
672
|
+
this.geometry?.dispose();
|
|
673
|
+
|
|
674
|
+
// The material's uTexture points at the atlas texture; the atlas owns it.
|
|
675
|
+
this._atlas?.dispose();
|
|
676
|
+
this._atlas = undefined;
|
|
677
|
+
|
|
678
|
+
// Clear this mesh's atlas term from the memory ledger. When disposal was
|
|
679
|
+
// caused by the owning tile's eviction the entity is already gone and the
|
|
680
|
+
// report is a no-op; when only this feature was removed the tile survives
|
|
681
|
+
// and the term must not linger.
|
|
682
|
+
if (this._reportedAtlasBytes !== 0) {
|
|
683
|
+
this._reportedAtlasBytes = 0;
|
|
684
|
+
this._atlasBytesReporter?.(0);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
(this.material as ShaderMaterial).dispose();
|
|
688
|
+
|
|
689
|
+
// Clear internal collections to release references
|
|
690
|
+
this._batchIdToInstance.clear();
|
|
691
|
+
this._imageOverrides.clear();
|
|
692
|
+
this._requestedImageUrls.clear();
|
|
693
|
+
}
|
|
694
|
+
}
|