From 39c7ae22ede51f4b755dc658e2e27b24b26b807e Mon Sep 17 00:00:00 2001 From: OpenAI Codex Date: Mon, 31 Aug 2026 12:17:06 +0800 Subject: [PATCH] feat: establish formal raster particle source chain --- CMakeLists.txt | 10 ++ ...040_Android离线Fixture正式粒子最小闭环_v1.md | 39 ++++ ...线Fixture到正式粒子渲染最小闭环验证报告_v1.md | 25 ++- .../raster_particle_layer_factory.hpp | 15 ++ .../shaders/gl/particle_gpu_validation.hpp | 7 +- .../style/layers/raster_particle_layer.hpp | 28 +++ .../style/sources/raster_array_source.hpp | 43 +++++ include/mbgl/style/types.hpp | 3 +- particle-fixtures/nodata/field.f32 | Bin 0 -> 2048 bytes particle-fixtures/nodata/metadata.json | 15 ++ .../src/cpp/style/layers/layer_manager.cpp | 2 + .../particle-fixtures/nodata/field.f32 | Bin 0 -> 2048 bytes .../particle-fixtures/nodata/metadata.json | 15 ++ .../particle-fixtures/uniform-east/field.f32 | Bin 0 -> 2048 bytes .../uniform-east/metadata.json | 15 ++ .../particle-fixtures/uniform-north/field.f32 | Bin 0 -> 2048 bytes .../uniform-north/metadata.json | 15 ++ .../particle-fixtures/vortex/field.f32 | Bin 0 -> 2048 bytes .../particle-fixtures/vortex/metadata.json | 15 ++ .../ParticleCoreLayerValidationActivity.kt | 31 +++- .../src/mbgl/layermanager/layer_manager.cpp | 2 + shaders/particle_gpu_validation.fragment.glsl | 7 +- .../particle_validation_layer_factory.cpp | 3 +- .../raster_particle_layer_factory.cpp | 25 +++ .../offline_fixture_particle_adapter.cpp | 37 +++- .../offline_fixture_particle_adapter.hpp | 9 + .../render_particle_validation_layer.cpp | 167 +++++++++++------- .../render_particle_validation_layer.hpp | 35 +--- .../layers/render_raster_particle_layer.hpp | 38 ++++ src/mbgl/renderer/render_source.cpp | 4 + .../sources/render_raster_array_source.hpp | 40 +++++ src/mbgl/style/conversion/source.cpp | 23 +++ .../particle_render_layer_properties.hpp | 20 +++ .../style/layers/raster_particle_layer.cpp | 99 +++++++++++ .../layers/raster_particle_layer_impl.hpp | 20 +++ .../style/sources/raster_array_source.cpp | 80 +++++++++ .../sources/raster_array_source_impl.hpp | 31 ++++ src/mbgl/style/types.cpp | 3 +- tools/generate_particle_fixture_f32.py | 12 +- 粒子开发记录.md | 8 + 40 files changed, 811 insertions(+), 130 deletions(-) create mode 100644 docs/50_Step记录/STEP-040_Android离线Fixture正式粒子最小闭环_v1.md create mode 100644 include/mbgl/layermanager/raster_particle_layer_factory.hpp create mode 100644 include/mbgl/style/layers/raster_particle_layer.hpp create mode 100644 include/mbgl/style/sources/raster_array_source.hpp create mode 100644 particle-fixtures/nodata/field.f32 create mode 100644 particle-fixtures/nodata/metadata.json create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/field.f32 create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/metadata.json create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/uniform-east/field.f32 create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/uniform-east/metadata.json create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/uniform-north/field.f32 create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/uniform-north/metadata.json create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/vortex/field.f32 create mode 100644 platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/vortex/metadata.json create mode 100644 src/mbgl/layermanager/raster_particle_layer_factory.cpp create mode 100644 src/mbgl/renderer/layers/render_raster_particle_layer.hpp create mode 100644 src/mbgl/renderer/sources/render_raster_array_source.hpp create mode 100644 src/mbgl/style/layers/particle_render_layer_properties.hpp create mode 100644 src/mbgl/style/layers/raster_particle_layer.cpp create mode 100644 src/mbgl/style/layers/raster_particle_layer_impl.hpp create mode 100644 src/mbgl/style/sources/raster_array_source.cpp create mode 100644 src/mbgl/style/sources/raster_array_source_impl.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a53ed1df7..e7a72cb6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,6 +249,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_buffer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/background_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/particle_validation_layer_factory.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/raster_particle_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/circle_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/custom_layer_factory.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/layermanager/fill_extrusion_layer_factory.hpp @@ -361,6 +362,8 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/style/layer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/background_layer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/particle_validation_layer.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/raster_particle_layer.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/raster_array_source.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/circle_layer.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_layer_host.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_layer_init_parameters.hpp @@ -506,6 +509,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_vector.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/background_layer_factory.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/particle_validation_layer_factory.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/raster_particle_layer_factory.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/circle_layer_factory.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/layermanager/fill_layer_factory.cpp @@ -585,6 +589,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_background_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_particle_validation_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_particle_validation_layer.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_raster_particle_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_circle_layer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -756,6 +761,9 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/background_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/particle_validation_layer.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/particle_validation_layer_impl.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/particle_render_layer_properties.hpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/raster_particle_layer.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/raster_particle_layer_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/background_layer_impl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/background_layer_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/background_layer_properties.cpp @@ -833,6 +841,8 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_dem_source.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/tile_source.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_source.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_array_source.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/raster_array_source_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/tile_source_impl.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/tile_source_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/style/sources/vector_source.cpp diff --git a/docs/50_Step记录/STEP-040_Android离线Fixture正式粒子最小闭环_v1.md b/docs/50_Step记录/STEP-040_Android离线Fixture正式粒子最小闭环_v1.md new file mode 100644 index 000000000..101cd06cd --- /dev/null +++ b/docs/50_Step记录/STEP-040_Android离线Fixture正式粒子最小闭环_v1.md @@ -0,0 +1,39 @@ +# STEP-040 Android 离线 Fixture 正式粒子最小闭环 v1 + +## 状态 + +进行中。40-01 Stage A 的代码和 Linux 静态验证完成;最终 Android 状态固定为 `WAITING_MANUAL_VALIDATION`,尚未进入手工 APK 验收。 + +## 目标与基线 + +- 目标:建立 `RasterArraySource -> RenderRasterArraySource -> RasterParticleLayer -> RenderRasterParticleLayer` 的第一条正式离线粒子闭环,并修复 STATIC recreation 的零步 bootstrap。 +- 基线:`343cecc778c3ffaa00adf94f82d7ad5f494a3877`,分支 `particle/main`。 +- 前置:30-01、30-02、30-03 均为 PASS;EGL context recreation 的独立实机证据仍是已接受风险。 + +## 必做项 + +- [x] `RasterArraySource` 以 FileSource byte boundary 读取 fixture metadata 与 field,生成 immutable `ParticleFieldSnapshot`。 +- [x] `RenderRasterArraySource`、`RasterParticleLayer`(`Source::Required`)和 `RenderRasterParticleLayer` 进入 Style/RenderTree 链。 +- [x] 正式 RenderLayer 复用既有 GPU field、State A/B、Trail A/B、mask、camera/world-wrap/antimeridian 与 resource lifecycle;没有第二套 simulation。 +- [x] Android Test App 从 APK `asset://integration/particle-fixtures/...` 提供正式 source 输入;Linux smoke helper 仍可读取仓库 fixture。 +- [x] NoData cell 作为 GPU field texture alpha=0 上传;shader 遇到 invalid sample 确定性回到 seed position,不把 NoData 当速度。 +- [x] STATIC recreation 仍走 zero-step State/Trail/bootstrap composite,commit 不增加 `simulationFrame`。 +- [ ] Android OpenGL APK 手工编译与 T1-T12:仅 GPT 复审远端代码通过后由用户执行。 + +## 允许修改 + +隔离 particle field/source/layer/render source/render layer、最小 LayerManager/Style Source/shader 注册、Android Test App fixture assets 与本 Step 文档。 + +## 禁止修改 + +不得运行 Gradle、安装 APK、ADB/T1-T12;不得新增 Overlay、Android UI/Core 耦合、在线数据、第二套 GPU simulation,或声称 Android/Vulkan/iOS PASS。 + +## 构建与检查 + +- Linux OpenGL 受影响 Core 精确对象编译:PASS。 +- `clang-format --dry-run --Werror`、`git diff --check`、fixture generator:待本轮最终收尾复跑。 +- adapter smoke:`uniform-east`、`uniform-north`、`vortex` 均 valid;`nodata` valid 且有 1 个 invalid cell。 + +## 当前结果、阻塞与下一步 + +正式 Source/Layer/RenderLayer 已不依赖 source-less `particle-validation` Layer;历史 validation Layer 只保留为既有验证工具。唯一阻塞是按用户指令等待 GPT 复审新远端 commit;复审通过后才允许用户开始 Android OpenGL APK 手工验收。 diff --git a/docs/60_测试/40_01_Android离线Fixture到正式粒子渲染最小闭环验证报告_v1.md b/docs/60_测试/40_01_Android离线Fixture到正式粒子渲染最小闭环验证报告_v1.md index bc6a2628e..dcdc05df1 100644 --- a/docs/60_测试/40_01_Android离线Fixture到正式粒子渲染最小闭环验证报告_v1.md +++ b/docs/60_测试/40_01_Android离线Fixture到正式粒子渲染最小闭环验证报告_v1.md @@ -9,23 +9,21 @@ - 分支:`particle/main` - 开始 HEAD:`1ec44701146925dec9a87618e3f90bee9a12073f` - 平台范围:Android OpenGL;未修改 iOS、Vulkan、NavSea 或在线数据链。 -- Test App 继续使用既有 `Particle Core Layer Validation` 入口;Core adapter 不依赖 Kotlin/Android UI。 +- Test App 继续使用既有 `Particle Core Layer Validation` 入口,但其 Style 现在创建正式 `raster-array` source 和 `raster-particle` layer;Core adapter 不依赖 Kotlin/Android UI 或 Android asset API。 ## 已实现的 Stage A 链路 ```text -particle-fixtures/{uniform-east,uniform-north,vortex} - -> OfflineFixtureParticleAdapter - -> ParticleFieldSnapshot - -> GPU field texture - -> State A/B field sampling - -> Trail A/B consuming State A/B - -> canonical world composite / shared coastal mask +APK asset://integration/particle-fixtures/{uniform-east,uniform-north}/ + -> RasterArraySource -> RenderRasterArraySource + -> ParticleFieldSnapshot -> GPU field texture + -> RasterParticleLayer (Source::Required) -> RenderRasterParticleLayer + -> State A/B field sampling -> Trail A/B -> canonical world composite / shared coastal mask ``` -- fixture contract 使用 `metadata.json + field.f32`,校验 schema、id、WIND/GLOBAL、EPSG:4326、bounds、grid registration/order、interleaved UV、little-endian float32、NoData 声明、长度和 SHA-256。 +- fixture contract 使用 `metadata.json + field.f32`,校验 schema、id、WIND/GLOBAL、EPSG:4326、bounds、grid registration/order、interleaved UV、little-endian float32、NoData 声明、长度和 SHA-256。Android asset 由 Test App 打包,Core 只接收 FileSource 返回的 metadata/field bytes;Linux helper 才读取仓库 `particle-fixtures/`。 - `uniform-east`、`uniform-north` 和 `vortex` 均为确定性 16x16 fixture;不会在每帧解析或上传。切换 fixture 时递增 `fieldGeneration/gpuFieldGeneration`,清空旧 trail;Camera 操作不触发 field upload。 -- shader 的 State pass 实际采样 GPU field texture,Trail pass 从 State write texture 读取粒子位置,未使用 Kotlin/CPU 每帧粒子循环。 +- shader 的 State pass 实际采样 GPU field texture,Trail pass 从 State write texture 读取粒子位置,未使用 Kotlin/CPU 每帧粒子循环。field texture alpha 表示 cell validity;NoData cell 上传为 alpha=0,State pass 在该 sample 上确定性 respawn 到 seed position,绝不将 `-9999` clamp 成速度。 - STATIC 不再因资源缺失提前返回。新的 context/resource generation 会建立 field、mask、trail 和 state;STATIC 首帧走零步 bootstrap,提交 state/trail slot 但不增加 `simulationFrame`,之后保持 frozen composite。 - Activity Bundle 保存/恢复 active、enabled、mask mode 与 fixture mode;GPU runtime state 不写入 Bundle。 @@ -33,11 +31,12 @@ particle-fixtures/{uniform-east,uniform-north,vortex} | 检查 | 结果 | |---|---| -| `ninja -C build-linux-opengl` 受影响 Core 对象 | PASS:`offline_fixture_particle_adapter.cpp`、`render_particle_validation_layer.cpp`、`shader_info.cpp`、`particle_validation_layer.cpp` | +| `ninja -C build-linux-opengl` 受影响 Core 对象 | PASS:正式 `raster_array_source.cpp`、`raster_particle_layer.cpp`、`raster_particle_layer_factory.cpp`、`render_source.cpp`、`RenderRasterParticleLayer` 实现、adapter 与 source conversion | | `clang-format --dry-run --Werror` | PASS | | `git diff --check` | PASS | | `python3 tools/generate_particle_fixture_f32.py` 后 metadata JSON 与 SHA-256 | PASS | -| adapter smoke test | PASS:`uniform-east`、`uniform-north`、`vortex` 分别加载为 16x16 | +| adapter smoke test | PASS:`uniform-east`、`uniform-north`、`vortex` 分别加载为 16x16;`nodata` 为合法 16x16 field 且恰有 1 个 invalid cell | +| APK asset parity | PASS:四份 Android asset 的 metadata 与 field bytes 均与仓库 fixture 完全相同 | 首次整库构建尝试被 sandbox 默认 ccache 目录只读中断;以 `CCACHE_DIR=/tmp/maplibre-particle-ccache` 重新执行上述受影响对象检查后通过。这不是代码编译失败。 @@ -57,7 +56,7 @@ cd platform/android - T1-T12 Android 设备验收、截图和 OpenGL shader 实机链接尚未执行。 - 独立 EGL context-loss 设备证据沿用 30-02 的 Accepted Risk;本实现已按 resource generation 重建 CPU field 的 GPU texture。 - iOS、Metal、Android Vulkan、真实数据、生产 coastline/mask、最终粒子数和性能指标均不在本 Stage A 范围。 -- fixture 含 NoData cell 的实机路径尚未有单独 fixture;adapter 已校验 NoData contract,当前三份 deterministic field 均无 NoData cell。 +- Android T1-T12 和实机 OpenGL shader 链接尚未执行;NoData 已有 deterministic fixture/static smoke 覆盖,但没有实机视觉证据。 ## 下一步 diff --git a/include/mbgl/layermanager/raster_particle_layer_factory.hpp b/include/mbgl/layermanager/raster_particle_layer_factory.hpp new file mode 100644 index 000000000..917cd3b0b --- /dev/null +++ b/include/mbgl/layermanager/raster_particle_layer_factory.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace mbgl { + +class RasterParticleLayerFactory final : public LayerFactory { +public: + const style::LayerTypeInfo* getTypeInfo() const noexcept override; + std::unique_ptr createLayer(const std::string&, + const style::conversion::Convertible&) noexcept override; + std::unique_ptr createRenderLayer(Immutable) noexcept override; +}; + +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/particle_gpu_validation.hpp b/include/mbgl/shaders/gl/particle_gpu_validation.hpp index 41d458794..2585f2462 100644 --- a/include/mbgl/shaders/gl/particle_gpu_validation.hpp +++ b/include/mbgl/shaders/gl/particle_gpu_validation.hpp @@ -56,7 +56,12 @@ void main() { // texture encodes canonical U-east/V-north at that geographic sample. vec2 position = previous.rg; if (previous.a < 0.5) position = v_uv; - vec2 velocity = texture(u_field_texture, position).rg * 2.0 - 1.0; + vec4 field = texture(u_field_texture, position); + vec2 velocity = field.rg * 2.0 - 1.0; + if (field.a < 0.5) { + position = v_uv; + velocity = vec2(0.0); + } position = fract(position + velocity * u_pass.y * 0.004); if (any(isnan(velocity))) position = v_uv; fragColor = vec4(position, fract(previous.b + 0.03125 * u_pass.y), 1.0); diff --git a/include/mbgl/style/layers/raster_particle_layer.hpp b/include/mbgl/style/layers/raster_particle_layer.hpp new file mode 100644 index 000000000..55f0c5748 --- /dev/null +++ b/include/mbgl/style/layers/raster_particle_layer.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace mbgl::style { + +class RasterParticleLayer final : public Layer { +public: + RasterParticleLayer(const std::string& layerID, const std::string& sourceID); + ~RasterParticleLayer() override; + bool isActive() const; + void setActive(bool); + uint8_t getMaskMode() const; + void setMaskMode(uint8_t); + class Impl; + const Impl& impl() const; + Mutable mutableImpl() const; + +private: + explicit RasterParticleLayer(Immutable); + std::optional setPropertyInternal(const std::string&, const conversion::Convertible&) override; + StyleProperty getProperty(const std::string&) const override; + Value serialize() const override; + std::unique_ptr cloneRef(const std::string&) const override; + Mutable mutableBaseImpl() const override; +}; + +} // namespace mbgl::style diff --git a/include/mbgl/style/sources/raster_array_source.hpp b/include/mbgl/style/sources/raster_array_source.hpp new file mode 100644 index 000000000..3a755aa41 --- /dev/null +++ b/include/mbgl/style/sources/raster_array_source.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include + +namespace mbgl { +class AsyncRequest; + +namespace style { + +class RasterArraySource final : public Source { +public: + RasterArraySource(std::string id, std::string fixtureID, std::string metadataURL, std::string fieldURL); + ~RasterArraySource() override; + + class Impl; + const Impl& impl() const; + void loadDescription(FileSource&) override; + bool supportsLayerType(const LayerTypeInfo*) const override; + mapbox::base::WeakPtr makeWeakPtr() override { return weakFactory.makeWeakPtr(); } + +protected: + Mutable createMutable() const noexcept override; + +private: + void tryLoad(); + + std::unique_ptr metadataRequest; + std::unique_ptr fieldRequest; + std::optional metadata; + std::optional> fieldBytes; + uint64_t generation = 0; + mapbox::base::WeakPtrFactory weakFactory{this}; +}; + +template <> +inline bool Source::is() const { + return getType() == SourceType::RasterArray; +} + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index 3955514e9..2c78b425d 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -15,7 +15,8 @@ enum class SourceType : uint8_t { Video, Annotations, Image, - CustomVector + CustomVector, + RasterArray }; enum class VisibilityType : bool { diff --git a/particle-fixtures/nodata/field.f32 b/particle-fixtures/nodata/field.f32 new file mode 100644 index 0000000000000000000000000000000000000000..97db3aac3383e27acf9e9f51a8ad641f05693be3 GIT binary patch literal 2048 wcmZQzXs~AhgHd`k96%ueO$RnI#~45u#vi3e^T}vAfyf`D`C&9a41@dt05)5|egFUf literal 0 HcmV?d00001 diff --git a/particle-fixtures/nodata/metadata.json b/particle-fixtures/nodata/metadata.json new file mode 100644 index 000000000..2cd9e60e8 --- /dev/null +++ b/particle-fixtures/nodata/metadata.json @@ -0,0 +1,15 @@ +{ + "schema": "maplibre-particle-fixture/v1", + "fixtureId": "nodata", + "fieldType": "WIND", + "displayDomain": "GLOBAL", + "dataVersion": 1, + "timeIndex": 0, + "timestamp": null, + "bounds": {"west": -180.0, "south": -85.0, "east": 180.0, "north": 85.0}, + "crs": "EPSG:4326", + "grid": {"width": 16, "height": 16, "registration": "node", "origin": "north-west", "rowOrder": "north-to-south", "columnOrder": "west-to-east"}, + "vector": {"uPositive": "east", "vPositive": "north", "unit": "m/s", "layout": "interleaved-uv", "encoding": "float32-le", "noData": -9999.0, "file": "field.f32"}, + "mask": {"mode": "none"}, + "integrity": {"fieldByteLength": 2048, "fieldSha256": "5756a6ac403a435ff001ff7261160de718c4a2964434ba7b9be2bfe74f071ff0"} +} diff --git a/platform/android/MapLibreAndroid/src/cpp/style/layers/layer_manager.cpp b/platform/android/MapLibreAndroid/src/cpp/style/layers/layer_manager.cpp index adb974efd..1d57dd157 100644 --- a/platform/android/MapLibreAndroid/src/cpp/style/layers/layer_manager.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/style/layers/layer_manager.cpp @@ -20,6 +20,7 @@ #include "fill_extrusion_layer.hpp" #include "location_indicator_layer.hpp" #include +#include namespace mbgl { @@ -28,6 +29,7 @@ namespace android { LayerManagerAndroid::LayerManagerAndroid() { // VALIDATION ONLY: JSON style access; intentionally no Android product API/JNI peer. addLayerTypeCoreOnly(std::make_unique()); + addLayerTypeCoreOnly(std::make_unique()); #if defined(MBGL_LAYER_FILL_DISABLE_RUNTIME) addLayerTypeCoreOnly(std::make_unique()); #elif !defined(MBGL_LAYER_FILL_DISABLE_ALL) diff --git a/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/field.f32 b/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/field.f32 new file mode 100644 index 0000000000000000000000000000000000000000..97db3aac3383e27acf9e9f51a8ad641f05693be3 GIT binary patch literal 2048 wcmZQzXs~AhgHd`k96%ueO$RnI#~45u#vi3e^T}vAfyf`D`C&9a41@dt05)5|egFUf literal 0 HcmV?d00001 diff --git a/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/metadata.json b/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/metadata.json new file mode 100644 index 000000000..2cd9e60e8 --- /dev/null +++ b/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/nodata/metadata.json @@ -0,0 +1,15 @@ +{ + "schema": "maplibre-particle-fixture/v1", + "fixtureId": "nodata", + "fieldType": "WIND", + "displayDomain": "GLOBAL", + "dataVersion": 1, + "timeIndex": 0, + "timestamp": null, + "bounds": {"west": -180.0, "south": -85.0, "east": 180.0, "north": 85.0}, + "crs": "EPSG:4326", + "grid": {"width": 16, "height": 16, "registration": "node", "origin": "north-west", "rowOrder": "north-to-south", "columnOrder": "west-to-east"}, + "vector": {"uPositive": "east", "vPositive": "north", "unit": "m/s", "layout": "interleaved-uv", "encoding": "float32-le", "noData": -9999.0, "file": "field.f32"}, + "mask": {"mode": "none"}, + "integrity": {"fieldByteLength": 2048, "fieldSha256": "5756a6ac403a435ff001ff7261160de718c4a2964434ba7b9be2bfe74f071ff0"} +} diff --git a/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/uniform-east/field.f32 b/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/uniform-east/field.f32 new file mode 100644 index 0000000000000000000000000000000000000000..54c3635ddc47f0e87c84337d6f4d018fc611b0bc GIT binary patch literal 2048 kcmZQzXs~AhgHd`k96%v3nhr+O!Du=d%?G39z(^ho_szv{dG{;mD**Yf?{_v%x(eB1Z;dQ`hP-%EXWed<%6`qZcXnEve3<5l(Dw+#2{ zY|ie^yU(h=clD`Hed<$xOn>(2QJ?zUGW^WZ^Vw(mTh2$-ch{#r^{G$&G5y)6M}6w^ zGkecRJ^PNnclGE0T=m`csZV|CkLk}oJ6_e<=u@Bi)W3Ky_1*WX@2*dM>QjGAfA-n& zGf&U@cKXz({+stw-(8>j)Tci6sXwMad(SdgeX72_KJ}?Te>?Y5-(8>j)Tci6sXsc~ z=bOChQ}yljsn6;Et)JhwrXQytryr*uryr*ur_Zl-o__ArkJFFSkJFFSkNUoK-b;OV zed_bc@T$&ce*gShcl~*<>bvVxpZe6lcrW$c^{LM%!_T~X*0r=x>q|h--wrQ#dpQjGAfA;B7pMHMoQ=j_OKbYZX_MW$@@0mXJsXwMa`}C+!ed<%6 j`qV$!nO)9%?_1UPjz0CNKc+wX^r%mL>QkTkJb(TJa3;*q literal 0 HcmV?d00001 diff --git a/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/vortex/metadata.json b/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/vortex/metadata.json new file mode 100644 index 000000000..da7b3b670 --- /dev/null +++ b/platform/android/MapLibreAndroidTestApp/src/main/assets/integration/particle-fixtures/vortex/metadata.json @@ -0,0 +1,15 @@ +{ + "schema": "maplibre-particle-fixture/v1", + "fixtureId": "vortex", + "fieldType": "WIND", + "displayDomain": "GLOBAL", + "dataVersion": 1, + "timeIndex": 0, + "timestamp": null, + "bounds": {"west": -180.0, "south": -85.0, "east": 180.0, "north": 85.0}, + "crs": "EPSG:4326", + "grid": {"width": 16, "height": 16, "registration": "node", "origin": "north-west", "rowOrder": "north-to-south", "columnOrder": "west-to-east"}, + "vector": {"uPositive": "east", "vPositive": "north", "unit": "m/s", "layout": "interleaved-uv", "encoding": "float32-le", "noData": -9999.0, "file": "field.f32"}, + "mask": {"mode": "none"}, + "integrity": {"fieldByteLength": 2048, "fieldSha256": "aa7fd26d5e4605dc363636b99e17c6bb495d51350a5a2cd8abe5bf0ada741c5a"} +} diff --git a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt index dfe640220..30060d97e 100644 --- a/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt +++ b/platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt @@ -13,7 +13,7 @@ import org.maplibre.android.maps.Style import org.maplibre.android.style.layers.PaintPropertyValue import org.maplibre.android.testapp.R -/** VALIDATION ONLY: Android OpenGL host for the 30-01/30-02 Core RenderLayer experiments. */ +/** Android OpenGL host for the formal raster-array to raster-particle fixture path. */ class ParticleCoreLayerValidationActivity : AppCompatActivity() { private lateinit var mapView: MapView private lateinit var maplibreMap: MapLibreMap @@ -72,10 +72,12 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() { if (this::maplibreMap.isInitialized) setValidationProperties(active = active, maskMode = MASK_OCEAN_B) } findViewById