@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,646 @@
|
|
|
1
|
+
import { Color, MeshBasicMaterial } from "three";
|
|
2
|
+
import invariant from "tiny-invariant";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
type BatchTextureConfig,
|
|
7
|
+
MAX_BATCH_TEXTURE_WIDTH,
|
|
8
|
+
batchBaseIndex,
|
|
9
|
+
encodeFloatToRGBA,
|
|
10
|
+
getBatchDataTexture,
|
|
11
|
+
initBatchDataTexture,
|
|
12
|
+
initBatchedMaterial,
|
|
13
|
+
packShowOpacity,
|
|
14
|
+
unpackShowOpacity,
|
|
15
|
+
updateBatchAttribute,
|
|
16
|
+
} from "./batchTexture";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Tests for the encodeFloatToRGBA function
|
|
20
|
+
*
|
|
21
|
+
* This function encodes a floating-point number into an RGBA array (4 values between 0-1)
|
|
22
|
+
* by using the IEEE 754 binary representation of the float.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
test("encodeFloatToRGBA should encode 0 correctly", () => {
|
|
26
|
+
const result = encodeFloatToRGBA(0);
|
|
27
|
+
|
|
28
|
+
// Check result is an array of 4 numbers
|
|
29
|
+
expect(result.length, "result should have 4 components").toBe(4);
|
|
30
|
+
|
|
31
|
+
// Check all values are between 0 and 1
|
|
32
|
+
result.forEach((value, index) => {
|
|
33
|
+
expect(
|
|
34
|
+
value,
|
|
35
|
+
`component ${index} should be between 0 and 1`,
|
|
36
|
+
).toBeGreaterThanOrEqual(0);
|
|
37
|
+
expect(
|
|
38
|
+
value,
|
|
39
|
+
`component ${index} should be between 0 and 1`,
|
|
40
|
+
).toBeLessThanOrEqual(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// For 0, we expect a specific encoding
|
|
44
|
+
expect(result).toEqual([0, 0, 0, 0]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("encodeFloatToRGBA should encode positive numbers correctly", () => {
|
|
48
|
+
const testCases = [1, 10, 100, 1000, 100000, 1.5, 3.14159];
|
|
49
|
+
|
|
50
|
+
for (const value of testCases) {
|
|
51
|
+
const result = encodeFloatToRGBA(value);
|
|
52
|
+
|
|
53
|
+
// Check result is an array of 4 numbers
|
|
54
|
+
expect(result.length, `result for ${value} should have 4 components`).toBe(
|
|
55
|
+
4,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Check all values are between 0 and 1
|
|
59
|
+
result.forEach((component, index) => {
|
|
60
|
+
expect(
|
|
61
|
+
component,
|
|
62
|
+
`component ${index} for ${value} should be between 0 and 1`,
|
|
63
|
+
).toBeGreaterThanOrEqual(0);
|
|
64
|
+
expect(
|
|
65
|
+
component,
|
|
66
|
+
`component ${index} for ${value} should be between 0 and 1`,
|
|
67
|
+
).toBeLessThanOrEqual(1);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Decode the float back and verify it's close to the original
|
|
71
|
+
// This is a more comprehensive test that the encoding works correctly
|
|
72
|
+
const decoded = decodeRGBAToFloat(result);
|
|
73
|
+
expect(
|
|
74
|
+
decoded,
|
|
75
|
+
`decoded value should be close to original ${value}`,
|
|
76
|
+
).toBeCloseTo(value);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("encodeFloatToRGBA should encode negative numbers correctly", () => {
|
|
81
|
+
const testCases = [-1, -10, -100, -1000, -100000, -1.5, -3.14159];
|
|
82
|
+
|
|
83
|
+
for (const value of testCases) {
|
|
84
|
+
const result = encodeFloatToRGBA(value);
|
|
85
|
+
|
|
86
|
+
// Check result is an array of 4 numbers
|
|
87
|
+
expect(result.length, `result for ${value} should have 4 components`).toBe(
|
|
88
|
+
4,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// Check all values are between 0 and 1
|
|
92
|
+
result.forEach((component, index) => {
|
|
93
|
+
expect(
|
|
94
|
+
component,
|
|
95
|
+
`component ${index} for ${value} should be between 0 and 1`,
|
|
96
|
+
).toBeGreaterThanOrEqual(0);
|
|
97
|
+
expect(
|
|
98
|
+
component,
|
|
99
|
+
`component ${index} for ${value} should be between 0 and 1`,
|
|
100
|
+
).toBeLessThanOrEqual(1);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Decode the float back and verify it's close to the original
|
|
104
|
+
const decoded = decodeRGBAToFloat(result);
|
|
105
|
+
expect(
|
|
106
|
+
decoded,
|
|
107
|
+
`decoded value should be close to original ${value}`,
|
|
108
|
+
).toBeCloseTo(value);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("encodeFloatToRGBA should handle extreme values", () => {
|
|
113
|
+
const testCases = [
|
|
114
|
+
Number.MAX_VALUE,
|
|
115
|
+
Number.MIN_VALUE,
|
|
116
|
+
Number.EPSILON,
|
|
117
|
+
Number.MAX_SAFE_INTEGER,
|
|
118
|
+
Number.MIN_SAFE_INTEGER,
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
for (const value of testCases) {
|
|
122
|
+
const result = encodeFloatToRGBA(value);
|
|
123
|
+
|
|
124
|
+
// Check result is an array of 4 numbers
|
|
125
|
+
expect(result.length, `result for ${value} should have 4 components`).toBe(
|
|
126
|
+
4,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Check all values are between 0 and 1
|
|
130
|
+
result.forEach((component, index) => {
|
|
131
|
+
expect(
|
|
132
|
+
component,
|
|
133
|
+
`component ${index} for ${value} should be between 0 and 1`,
|
|
134
|
+
).toBeGreaterThanOrEqual(0);
|
|
135
|
+
expect(
|
|
136
|
+
component,
|
|
137
|
+
`component ${index} for ${value} should be between 0 and 1`,
|
|
138
|
+
).toBeLessThanOrEqual(1);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// For extreme values, we can't always expect exact decoding due to precision limitations,
|
|
142
|
+
// but we can check that the result is a valid encoding (4 numbers between 0-1)
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Helper function to decode RGBA values back to a float
|
|
148
|
+
* This is used to verify the encoding works correctly
|
|
149
|
+
*/
|
|
150
|
+
function decodeRGBAToFloat(rgba: [number, number, number, number]): number {
|
|
151
|
+
// Convert normalized 0-1 values back to 0-255 bytes
|
|
152
|
+
const bytes = new Uint8Array(4);
|
|
153
|
+
bytes[0] = Math.round(rgba[0] * 255);
|
|
154
|
+
bytes[1] = Math.round(rgba[1] * 255);
|
|
155
|
+
bytes[2] = Math.round(rgba[2] * 255);
|
|
156
|
+
bytes[3] = Math.round(rgba[3] * 255);
|
|
157
|
+
|
|
158
|
+
// Create a Float32Array view of the same buffer
|
|
159
|
+
const floatView = new Float32Array(bytes.buffer);
|
|
160
|
+
|
|
161
|
+
// Return the float value
|
|
162
|
+
return floatView[0];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Helper: create a Material and initialize it with batch texture for testing.
|
|
167
|
+
*/
|
|
168
|
+
function setupBatchMaterial(batchLength: number): {
|
|
169
|
+
material: MeshBasicMaterial;
|
|
170
|
+
config: BatchTextureConfig;
|
|
171
|
+
} {
|
|
172
|
+
const config: BatchTextureConfig = {
|
|
173
|
+
rows: ["COLOR_SHOW", "HEIGHT", "EXTRUDED_HEIGHT"],
|
|
174
|
+
batchLength,
|
|
175
|
+
};
|
|
176
|
+
const material = new MeshBasicMaterial();
|
|
177
|
+
initBatchedMaterial(material, config);
|
|
178
|
+
initBatchDataTexture(material, config);
|
|
179
|
+
return { material, config };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ── packShowOpacity / unpackShowOpacity ─────────────────────────────────
|
|
183
|
+
|
|
184
|
+
describe("packShowOpacity / unpackShowOpacity", () => {
|
|
185
|
+
test("round-trip preserves show and opacity (with 7-bit precision)", () => {
|
|
186
|
+
const testCases = [
|
|
187
|
+
{ show: 1, opacity: 0.0 },
|
|
188
|
+
{ show: 1, opacity: 0.25 },
|
|
189
|
+
{ show: 1, opacity: 0.5 },
|
|
190
|
+
{ show: 1, opacity: 0.75 },
|
|
191
|
+
{ show: 1, opacity: 1.0 },
|
|
192
|
+
{ show: 0, opacity: 0.0 },
|
|
193
|
+
{ show: 0, opacity: 0.5 },
|
|
194
|
+
{ show: 0, opacity: 1.0 },
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
for (const { show, opacity } of testCases) {
|
|
198
|
+
const packed = packShowOpacity(show, opacity);
|
|
199
|
+
const unpacked = unpackShowOpacity(packed);
|
|
200
|
+
expect(unpacked.show).toBe(show);
|
|
201
|
+
// 7-bit precision = 128 levels, quantization step ~1/127 ≈ 0.008
|
|
202
|
+
// Use tolerance of 1 decimal place (0.05) to account for quantization
|
|
203
|
+
expect(unpacked.opacity).toBeCloseTo(opacity, 1);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("clamps opacity to 0-1 range", () => {
|
|
208
|
+
const packed1 = packShowOpacity(1, -0.5);
|
|
209
|
+
const { opacity: opacity1 } = unpackShowOpacity(packed1);
|
|
210
|
+
expect(opacity1).toBeCloseTo(0.0, 2);
|
|
211
|
+
|
|
212
|
+
const packed2 = packShowOpacity(1, 1.5);
|
|
213
|
+
const { opacity: opacity2 } = unpackShowOpacity(packed2);
|
|
214
|
+
expect(opacity2).toBeCloseTo(1.0, 2);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// ── batchBaseIndex ──────────────────────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
describe("batchBaseIndex", () => {
|
|
221
|
+
test("maps batchId < texWidth to the first batch-row group", () => {
|
|
222
|
+
// texWidth=4096, rowCount=3, batchId=100, rowIndex=0
|
|
223
|
+
// col=100, batchRow=0, physicalRow=0*3+0=0 → index=(0*4096+100)*4=400
|
|
224
|
+
expect(batchBaseIndex(4096, 3, 100, 0)).toBe(400);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("maps different rowIndex within same batch-row group", () => {
|
|
228
|
+
// batchId=100, rowIndex=1 → physicalRow=0*3+1=1 → (1*4096+100)*4
|
|
229
|
+
expect(batchBaseIndex(4096, 3, 100, 1)).toBe((4096 + 100) * 4);
|
|
230
|
+
// batchId=100, rowIndex=2 → physicalRow=0*3+2=2 → (2*4096+100)*4
|
|
231
|
+
expect(batchBaseIndex(4096, 3, 100, 2)).toBe((2 * 4096 + 100) * 4);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("wraps batchId to second batch-row group when batchId >= texWidth", () => {
|
|
235
|
+
// batchId=4096, texWidth=4096 → col=0, batchRow=1
|
|
236
|
+
// rowIndex=0 → physicalRow=1*3+0=3 → (3*4096+0)*4
|
|
237
|
+
expect(batchBaseIndex(4096, 3, 4096, 0)).toBe(3 * 4096 * 4);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test("handles batchId in the middle of second batch-row group", () => {
|
|
241
|
+
// batchId=4200, texWidth=4096 → col=104, batchRow=1
|
|
242
|
+
// rowIndex=0 → physicalRow=3 → (3*4096+104)*4
|
|
243
|
+
expect(batchBaseIndex(4096, 3, 4200, 0)).toBe((3 * 4096 + 104) * 4);
|
|
244
|
+
// rowIndex=2 → physicalRow=5 → (5*4096+104)*4
|
|
245
|
+
expect(batchBaseIndex(4096, 3, 4200, 2)).toBe((5 * 4096 + 104) * 4);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test("handles large batchId in third+ batch-row group", () => {
|
|
249
|
+
// batchId=10000, texWidth=4096 → col=10000%4096=1808, batchRow=2
|
|
250
|
+
// rowIndex=0 → physicalRow=6 → (6*4096+1808)*4
|
|
251
|
+
expect(batchBaseIndex(4096, 3, 10000, 0)).toBe((6 * 4096 + 1808) * 4);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test("is equivalent to old 1D formula when batchId < texWidth", () => {
|
|
255
|
+
// Old formula: batchId * 4 + rowIndex * (texWidth * 4)
|
|
256
|
+
// New formula: (rowIndex * texWidth + batchId) * 4 (when batchRow=0)
|
|
257
|
+
// These are the same: batchId*4 + rowIndex*texWidth*4 = (rowIndex*texWidth + batchId)*4
|
|
258
|
+
const texWidth = 4096;
|
|
259
|
+
const rowCount = 3;
|
|
260
|
+
for (const batchId of [0, 1, 100, 2000, 4095]) {
|
|
261
|
+
for (const rowIndex of [0, 1, 2]) {
|
|
262
|
+
const oldIndex = batchId * 4 + rowIndex * texWidth * 4;
|
|
263
|
+
const newIndex = batchBaseIndex(texWidth, rowCount, batchId, rowIndex);
|
|
264
|
+
expect(newIndex).toBe(oldIndex);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// ── initBatchDataTexture ────────────────────────────────────────────────
|
|
271
|
+
|
|
272
|
+
describe("initBatchDataTexture", () => {
|
|
273
|
+
test("creates texture with batchLength as width when <= MAX_BATCH_TEXTURE_WIDTH", () => {
|
|
274
|
+
const { material } = setupBatchMaterial(100);
|
|
275
|
+
const texture = getBatchDataTexture(material);
|
|
276
|
+
invariant(texture);
|
|
277
|
+
expect(texture.image.width).toBe(100);
|
|
278
|
+
expect(texture.image.height).toBe(3); // 1 batch-row * 3 attribute rows
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("caps texture width at MAX_BATCH_TEXTURE_WIDTH for large batch counts", () => {
|
|
282
|
+
const batchLength = 20000;
|
|
283
|
+
const { material } = setupBatchMaterial(batchLength);
|
|
284
|
+
const texture = getBatchDataTexture(material);
|
|
285
|
+
invariant(texture);
|
|
286
|
+
expect(texture.image.width).toBe(MAX_BATCH_TEXTURE_WIDTH);
|
|
287
|
+
// ceil(20000/4096)=5 batch-row groups, each with 3 attribute rows → 15
|
|
288
|
+
const expectedHeight = Math.ceil(batchLength / MAX_BATCH_TEXTURE_WIDTH) * 3;
|
|
289
|
+
expect(texture.image.height).toBe(expectedHeight);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("allocates correct data size for large batch counts", () => {
|
|
293
|
+
const batchLength = 20000;
|
|
294
|
+
const { material } = setupBatchMaterial(batchLength);
|
|
295
|
+
const texture = getBatchDataTexture(material);
|
|
296
|
+
invariant(texture);
|
|
297
|
+
const data = texture.image.data as Float32Array;
|
|
298
|
+
expect(data.length).toBe(
|
|
299
|
+
MAX_BATCH_TEXTURE_WIDTH *
|
|
300
|
+
4 *
|
|
301
|
+
Math.ceil(batchLength / MAX_BATCH_TEXTURE_WIDTH) *
|
|
302
|
+
3,
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test("does not recreate texture on second call", () => {
|
|
307
|
+
const { material, config } = setupBatchMaterial(100);
|
|
308
|
+
const tex1 = getBatchDataTexture(material);
|
|
309
|
+
initBatchDataTexture(material, config);
|
|
310
|
+
const tex2 = getBatchDataTexture(material);
|
|
311
|
+
expect(tex1).toBe(tex2);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
test("initializes COLOR_SHOW alpha to packed(show=1, opacity=1) for all batchIds", () => {
|
|
315
|
+
const config: BatchTextureConfig = {
|
|
316
|
+
rows: ["COLOR_SHOW", "HEIGHT"],
|
|
317
|
+
batchLength: 100,
|
|
318
|
+
};
|
|
319
|
+
const material = new MeshBasicMaterial();
|
|
320
|
+
initBatchedMaterial(material, config);
|
|
321
|
+
initBatchDataTexture(material, config);
|
|
322
|
+
|
|
323
|
+
const texture = getBatchDataTexture(material);
|
|
324
|
+
invariant(texture);
|
|
325
|
+
const data = texture.image.data as Float32Array;
|
|
326
|
+
const texWidth = texture.image.width;
|
|
327
|
+
const rowCount = config.rows.length;
|
|
328
|
+
const colorShowRowIndex = config.rows.indexOf("COLOR_SHOW");
|
|
329
|
+
|
|
330
|
+
const expectedPacked = packShowOpacity(1, 1);
|
|
331
|
+
|
|
332
|
+
// Check all 100 batch IDs have alpha = packed(show=1, opacity=1)
|
|
333
|
+
for (let batchId = 0; batchId < 100; batchId++) {
|
|
334
|
+
const baseIndex = batchBaseIndex(
|
|
335
|
+
texWidth,
|
|
336
|
+
rowCount,
|
|
337
|
+
batchId,
|
|
338
|
+
colorShowRowIndex,
|
|
339
|
+
);
|
|
340
|
+
// Alpha channel contains packed show and opacity
|
|
341
|
+
expect(
|
|
342
|
+
data[baseIndex + 3],
|
|
343
|
+
`batchId ${batchId} should have packed(1, 1)`,
|
|
344
|
+
).toBeCloseTo(expectedPacked, 5);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
test("opacity bundled with show: updating opacity updates COLOR_SHOW alpha with bit packing", () => {
|
|
349
|
+
const config: BatchTextureConfig = {
|
|
350
|
+
rows: ["COLOR_SHOW", "HEIGHT"],
|
|
351
|
+
batchLength: 10,
|
|
352
|
+
};
|
|
353
|
+
const material = new MeshBasicMaterial();
|
|
354
|
+
initBatchedMaterial(material, config);
|
|
355
|
+
initBatchDataTexture(material, config);
|
|
356
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
357
|
+
|
|
358
|
+
const texture = getBatchDataTexture(material);
|
|
359
|
+
invariant(texture);
|
|
360
|
+
const data = texture.image.data as Float32Array;
|
|
361
|
+
const texWidth = texture.image.width;
|
|
362
|
+
const rowCount = config.rows.length;
|
|
363
|
+
const colorShowRowIndex = config.rows.indexOf("COLOR_SHOW");
|
|
364
|
+
|
|
365
|
+
// Update opacity for batchId 5 to 0.5
|
|
366
|
+
updateBatchAttribute(material, 5, "opacity", 0.5, defaultValues);
|
|
367
|
+
|
|
368
|
+
// Verify batchId 5 has packed(show=1, opacity=0.5)
|
|
369
|
+
let baseIndex = batchBaseIndex(texWidth, rowCount, 5, colorShowRowIndex);
|
|
370
|
+
const expectedPacked1 = packShowOpacity(1, 0.5);
|
|
371
|
+
expect(data[baseIndex + 3]).toBeCloseTo(expectedPacked1, 2);
|
|
372
|
+
|
|
373
|
+
// Verify other batchIds still have default packed(show=1, opacity=1)
|
|
374
|
+
const defaultPacked = packShowOpacity(1, 1);
|
|
375
|
+
for (const batchId of [0, 1, 9]) {
|
|
376
|
+
baseIndex = batchBaseIndex(
|
|
377
|
+
texWidth,
|
|
378
|
+
rowCount,
|
|
379
|
+
batchId,
|
|
380
|
+
colorShowRowIndex,
|
|
381
|
+
);
|
|
382
|
+
expect(
|
|
383
|
+
data[baseIndex + 3],
|
|
384
|
+
`batchId ${batchId} should still have packed(1, 1)`,
|
|
385
|
+
).toBeCloseTo(defaultPacked, 5);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Update show to false for batchId 5
|
|
389
|
+
updateBatchAttribute(material, 5, "show", false, defaultValues);
|
|
390
|
+
// Now alpha should be packed(show=0, opacity=0.5)
|
|
391
|
+
baseIndex = batchBaseIndex(texWidth, rowCount, 5, colorShowRowIndex);
|
|
392
|
+
const expectedPacked2 = packShowOpacity(0, 0.5);
|
|
393
|
+
expect(data[baseIndex + 3]).toBeCloseTo(expectedPacked2, 2);
|
|
394
|
+
|
|
395
|
+
// Update show back to true for batchId 5
|
|
396
|
+
updateBatchAttribute(material, 5, "show", true, defaultValues);
|
|
397
|
+
// Opacity should be preserved: packed(show=1, opacity=0.5)
|
|
398
|
+
baseIndex = batchBaseIndex(texWidth, rowCount, 5, colorShowRowIndex);
|
|
399
|
+
expect(data[baseIndex + 3]).toBeCloseTo(expectedPacked1, 2);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test("initializes LINE_WIDTH row to -1.0 for all batchIds when LINE_WIDTH is in config", () => {
|
|
403
|
+
const config: BatchTextureConfig = {
|
|
404
|
+
rows: ["COLOR_SHOW", "LINE_WIDTH"],
|
|
405
|
+
batchLength: 100,
|
|
406
|
+
};
|
|
407
|
+
const material = new MeshBasicMaterial();
|
|
408
|
+
initBatchedMaterial(material, config);
|
|
409
|
+
initBatchDataTexture(material, config);
|
|
410
|
+
|
|
411
|
+
const texture = getBatchDataTexture(material);
|
|
412
|
+
invariant(texture);
|
|
413
|
+
const data = texture.image.data as Float32Array;
|
|
414
|
+
const texWidth = texture.image.width;
|
|
415
|
+
const rowCount = config.rows.length;
|
|
416
|
+
const lineWidthRowIndex = config.rows.indexOf("LINE_WIDTH");
|
|
417
|
+
|
|
418
|
+
// Check all 100 batch IDs have lineWidth -1.0 (sentinel for "use default")
|
|
419
|
+
for (let batchId = 0; batchId < 100; batchId++) {
|
|
420
|
+
const baseIndex = batchBaseIndex(
|
|
421
|
+
texWidth,
|
|
422
|
+
rowCount,
|
|
423
|
+
batchId,
|
|
424
|
+
lineWidthRowIndex,
|
|
425
|
+
);
|
|
426
|
+
const encoded: [number, number, number, number] = [
|
|
427
|
+
data[baseIndex],
|
|
428
|
+
data[baseIndex + 1],
|
|
429
|
+
data[baseIndex + 2],
|
|
430
|
+
data[baseIndex + 3],
|
|
431
|
+
];
|
|
432
|
+
const lineWidth = decodeRGBAToFloat(encoded);
|
|
433
|
+
expect(
|
|
434
|
+
lineWidth,
|
|
435
|
+
`batchId ${batchId} should have lineWidth -1.0`,
|
|
436
|
+
).toBeCloseTo(-1.0);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// ── initBatchedMaterial ─────────────────────────────────────────────────
|
|
442
|
+
|
|
443
|
+
describe("initBatchedMaterial", () => {
|
|
444
|
+
test("sets BATCHED_TEXTURE_ROW_COUNT define", () => {
|
|
445
|
+
const config: BatchTextureConfig = {
|
|
446
|
+
rows: ["COLOR_SHOW", "HEIGHT", "EXTRUDED_HEIGHT"],
|
|
447
|
+
batchLength: 100,
|
|
448
|
+
};
|
|
449
|
+
const material = new MeshBasicMaterial();
|
|
450
|
+
initBatchedMaterial(material, config);
|
|
451
|
+
|
|
452
|
+
expect(material.userData.defines.BATCHED_TEXTURE_ROW_COUNT).toBe("3.0");
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
test("sets individual row defines", () => {
|
|
456
|
+
const config: BatchTextureConfig = {
|
|
457
|
+
rows: ["COLOR_SHOW", "HEIGHT"],
|
|
458
|
+
batchLength: 10,
|
|
459
|
+
};
|
|
460
|
+
const material = new MeshBasicMaterial();
|
|
461
|
+
initBatchedMaterial(material, config);
|
|
462
|
+
|
|
463
|
+
expect(material.userData.defines.BATCHED_TEXTURE_ROW_COLOR_SHOW).toBe(
|
|
464
|
+
"0.0",
|
|
465
|
+
);
|
|
466
|
+
expect(material.userData.defines.BATCHED_TEXTURE_ROW_HEIGHT).toBe("1.0");
|
|
467
|
+
expect(material.userData.defines.BATCHED_TEXTURE_ROW_COUNT).toBe("2.0");
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// ── updateBatchAttribute with 2D layout ─────────────────────────────────
|
|
472
|
+
|
|
473
|
+
describe("updateBatchAttribute with 2D layout", () => {
|
|
474
|
+
test("writes color to correct position for batchId < texWidth", () => {
|
|
475
|
+
const { material } = setupBatchMaterial(100);
|
|
476
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
477
|
+
|
|
478
|
+
updateBatchAttribute(material, 5, "color", [0.5, 0.6, 0.7], defaultValues);
|
|
479
|
+
|
|
480
|
+
const texture = getBatchDataTexture(material);
|
|
481
|
+
invariant(texture);
|
|
482
|
+
const data = texture.image.data as Float32Array;
|
|
483
|
+
// batchId=5, rowIndex=0 (COLOR_SHOW), texWidth=100
|
|
484
|
+
// physicalRow=0, col=5 → baseIndex=(0*100+5)*4=20
|
|
485
|
+
expect(data[20]).toBeCloseTo(0.5);
|
|
486
|
+
expect(data[21]).toBeCloseTo(0.6);
|
|
487
|
+
expect(data[22]).toBeCloseTo(0.7);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test("writes color to correct position when batchId exceeds texWidth", () => {
|
|
491
|
+
const batchLength = 10000;
|
|
492
|
+
const { material } = setupBatchMaterial(batchLength);
|
|
493
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
494
|
+
|
|
495
|
+
// batchId = 5000 → col=5000%4096=904, batchRow=1
|
|
496
|
+
// rowIndex=0 (COLOR_SHOW), rowCount=3 → physicalRow=1*3+0=3
|
|
497
|
+
// baseIndex = (3*4096+904)*4
|
|
498
|
+
const expectedIndex = (3 * MAX_BATCH_TEXTURE_WIDTH + 904) * 4;
|
|
499
|
+
|
|
500
|
+
updateBatchAttribute(
|
|
501
|
+
material,
|
|
502
|
+
5000,
|
|
503
|
+
"color",
|
|
504
|
+
[0.1, 0.2, 0.3],
|
|
505
|
+
defaultValues,
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
const texture2 = getBatchDataTexture(material);
|
|
509
|
+
invariant(texture2);
|
|
510
|
+
const data = texture2.image.data as Float32Array;
|
|
511
|
+
expect(data[expectedIndex]).toBeCloseTo(0.1);
|
|
512
|
+
expect(data[expectedIndex + 1]).toBeCloseTo(0.2);
|
|
513
|
+
expect(data[expectedIndex + 2]).toBeCloseTo(0.3);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test("writes height to correct 2D position for large batchId", () => {
|
|
517
|
+
const batchLength = 10000;
|
|
518
|
+
const { material } = setupBatchMaterial(batchLength);
|
|
519
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
520
|
+
|
|
521
|
+
// batchId=5000 → col=904, batchRow=1
|
|
522
|
+
// rowIndex=1 (HEIGHT), rowCount=3 → physicalRow=1*3+1=4
|
|
523
|
+
// baseIndex = (4*4096+904)*4
|
|
524
|
+
const expectedIndex = (4 * MAX_BATCH_TEXTURE_WIDTH + 904) * 4;
|
|
525
|
+
|
|
526
|
+
updateBatchAttribute(material, 5000, "height", 42.5, defaultValues);
|
|
527
|
+
|
|
528
|
+
const texture = getBatchDataTexture(material);
|
|
529
|
+
invariant(texture);
|
|
530
|
+
const data = texture.image.data as Float32Array;
|
|
531
|
+
// Height is RGBA-encoded, so the 4 floats at expectedIndex should decode to 42.5
|
|
532
|
+
const encoded: [number, number, number, number] = [
|
|
533
|
+
data[expectedIndex],
|
|
534
|
+
data[expectedIndex + 1],
|
|
535
|
+
data[expectedIndex + 2],
|
|
536
|
+
data[expectedIndex + 3],
|
|
537
|
+
];
|
|
538
|
+
expect(decodeRGBAToFloat(encoded)).toBeCloseTo(42.5);
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
test("writes show attribute for batchId in second batch-row group", () => {
|
|
542
|
+
const batchLength = 10000;
|
|
543
|
+
const { material } = setupBatchMaterial(batchLength);
|
|
544
|
+
const defaultValues = { color: new Color(0.8, 0.9, 1.0) };
|
|
545
|
+
|
|
546
|
+
// batchId=4096 → col=0, batchRow=1
|
|
547
|
+
// rowIndex=0 (COLOR_SHOW), rowCount=3 → physicalRow=3
|
|
548
|
+
// baseIndex = (3*4096+0)*4
|
|
549
|
+
const expectedIndex = 3 * MAX_BATCH_TEXTURE_WIDTH * 4;
|
|
550
|
+
|
|
551
|
+
updateBatchAttribute(material, 4096, "show", false, defaultValues);
|
|
552
|
+
|
|
553
|
+
const texture = getBatchDataTexture(material);
|
|
554
|
+
invariant(texture);
|
|
555
|
+
const data = texture.image.data as Float32Array;
|
|
556
|
+
// Alpha channel should be packed(show=0, opacity=1)
|
|
557
|
+
const expectedPacked = packShowOpacity(0, 1);
|
|
558
|
+
expect(data[expectedIndex + 3]).toBeCloseTo(expectedPacked, 2);
|
|
559
|
+
// RGB should have default color since _batchColorTouched is false
|
|
560
|
+
expect(data[expectedIndex]).toBeCloseTo(0.8);
|
|
561
|
+
expect(data[expectedIndex + 1]).toBeCloseTo(0.9);
|
|
562
|
+
expect(data[expectedIndex + 2]).toBeCloseTo(1.0);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
test("ignores extrudedHeight and leaves define unset when EXTRUDED_HEIGHT row is absent (polyline rows)", () => {
|
|
566
|
+
// Polyline-style rows: no EXTRUDED_HEIGHT. Setting the attribute must be a
|
|
567
|
+
// no-op — enabling USE_BATCH_EXTRUDED_HEIGHT would reference the
|
|
568
|
+
// undeclared `addExtrudedHeight` in the polyline shaders and fail to compile.
|
|
569
|
+
const config: BatchTextureConfig = {
|
|
570
|
+
rows: ["COLOR_SHOW", "HEIGHT", "LINE_WIDTH"],
|
|
571
|
+
batchLength: 10,
|
|
572
|
+
};
|
|
573
|
+
const material = new MeshBasicMaterial();
|
|
574
|
+
initBatchedMaterial(material, config);
|
|
575
|
+
initBatchDataTexture(material, config);
|
|
576
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
577
|
+
|
|
578
|
+
const texture = getBatchDataTexture(material);
|
|
579
|
+
invariant(texture);
|
|
580
|
+
const before = Float32Array.from(texture.image.data as Float32Array);
|
|
581
|
+
|
|
582
|
+
updateBatchAttribute(material, 5, "extrudedHeight", 120, defaultValues);
|
|
583
|
+
|
|
584
|
+
expect(material.userData.defines.USE_BATCH_EXTRUDED_HEIGHT).toBeUndefined();
|
|
585
|
+
expect(texture.image.data as Float32Array).toEqual(before);
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
test("ignores lineWidth and leaves define unset when LINE_WIDTH row is absent (polygon rows)", () => {
|
|
589
|
+
// Polygon-style rows: no LINE_WIDTH. Same reasoning as above with the
|
|
590
|
+
// undeclared `batchLineWidth` in the polygon shaders.
|
|
591
|
+
const config: BatchTextureConfig = {
|
|
592
|
+
rows: ["COLOR_SHOW", "HEIGHT", "EXTRUDED_HEIGHT"],
|
|
593
|
+
batchLength: 10,
|
|
594
|
+
};
|
|
595
|
+
const material = new MeshBasicMaterial();
|
|
596
|
+
initBatchedMaterial(material, config);
|
|
597
|
+
initBatchDataTexture(material, config);
|
|
598
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
599
|
+
|
|
600
|
+
const texture = getBatchDataTexture(material);
|
|
601
|
+
invariant(texture);
|
|
602
|
+
const before = Float32Array.from(texture.image.data as Float32Array);
|
|
603
|
+
|
|
604
|
+
updateBatchAttribute(material, 5, "lineWidth", 10, defaultValues);
|
|
605
|
+
|
|
606
|
+
expect(material.userData.defines.USE_BATCH_LINE_WIDTH).toBeUndefined();
|
|
607
|
+
expect(texture.image.data as Float32Array).toEqual(before);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
test("multiple batchIds across different batch-row groups do not collide", () => {
|
|
611
|
+
const batchLength = 10000;
|
|
612
|
+
const { material } = setupBatchMaterial(batchLength);
|
|
613
|
+
const defaultValues = { color: new Color(1, 1, 1) };
|
|
614
|
+
|
|
615
|
+
// Write distinct colors to batchId 100 (group 0) and 4196 (group 1, col=100)
|
|
616
|
+
updateBatchAttribute(
|
|
617
|
+
material,
|
|
618
|
+
100,
|
|
619
|
+
"color",
|
|
620
|
+
[1.0, 0.0, 0.0],
|
|
621
|
+
defaultValues,
|
|
622
|
+
);
|
|
623
|
+
updateBatchAttribute(
|
|
624
|
+
material,
|
|
625
|
+
4196,
|
|
626
|
+
"color",
|
|
627
|
+
[0.0, 1.0, 0.0],
|
|
628
|
+
defaultValues,
|
|
629
|
+
);
|
|
630
|
+
|
|
631
|
+
const texture = getBatchDataTexture(material);
|
|
632
|
+
invariant(texture);
|
|
633
|
+
const data = texture.image.data as Float32Array;
|
|
634
|
+
|
|
635
|
+
// batchId=100: col=100, batchRow=0, physicalRow=0 → (0*4096+100)*4=400
|
|
636
|
+
expect(data[400]).toBeCloseTo(1.0);
|
|
637
|
+
expect(data[401]).toBeCloseTo(0.0);
|
|
638
|
+
expect(data[402]).toBeCloseTo(0.0);
|
|
639
|
+
|
|
640
|
+
// batchId=4196: col=100, batchRow=1, physicalRow=3 → (3*4096+100)*4
|
|
641
|
+
const idx4196 = (3 * MAX_BATCH_TEXTURE_WIDTH + 100) * 4;
|
|
642
|
+
expect(data[idx4196]).toBeCloseTo(0.0);
|
|
643
|
+
expect(data[idx4196 + 1]).toBeCloseTo(1.0);
|
|
644
|
+
expect(data[idx4196 + 2]).toBeCloseTo(0.0);
|
|
645
|
+
});
|
|
646
|
+
});
|