Files
MapLibreParticleLab/docs/20_调查/STEP-065_MapLibreParticleLab_V3通用ScalarVectorField现状调查_v1.md
OpenAI Codex 44999edb25
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: freeze V3 scalar vector field contract
2026-09-10 21:53:56 +08:00

5.2 KiB
Raw Blame History

STEP-065 MapLibreParticleLab V3 通用 Scalar / Vector Field 现状调查

状态:完成(只读调查) 基线:particle/main / 2e3ab26275a8d1873d764cf6927783a7b0406836,origin/particle/main 同一提交。

调查范围与方法

已完整阅读项目基线、协作/构建/Step/架构/官方基线规范、STEP-064 任务与冻结记录/报告;只读核对 Particle Core、两 renderer、GLSL、RasterArray Timeline、Android Host/JNI、RN package、两个 RN Test Host,以及 /root/sourceserver/weatherV2 指定六文件。未修改 WeatherV2/NavSea/生产代码,未执行 Gradle、APK、ADB 或 Jest。

A. 当前 Field Contract 与 Wind-only 点

include/mbgl/particle/field/field_data_adapter.hpp 的 ParticleFieldDescriptor 只有一个 layout/encoding/byteLength/stride,ParticleFieldSnapshot 只有 velocity: vector<float> 与 valid: vector<uint8_t>。field_data_adapter.cpp 只接受 interleaved-uv + float32-le、每 cell 两 float;isValid() 与 decode 末尾硬性要求 fieldType == "WIND"、displayDomain == "GLOBAL"。local_particle_field_feed.cpp 的 maplibre-particle-field/v1 parser 也强制 vector 与一个 payload。

fieldType / displayDomain 还参与 timeline-compatible 比较;当前 fixture、Consumer metadata 皆为 WIND/GLOBAL。这不是 provider-neutral 的能力表达,且不能承载 scalar-only 或 Wave 的 direction vector。

B. GPU、validity、shader 的真实结构

render_weather_color_layer.cpp 每快照把 U/V 按快照最大绝对值编码进 RG、validity 编入 A;T0/T1 各一张 Texture2D。render_particle_validation_layer.cpp(正式 RasterParticleLayer 也经此 renderer)同样把 U/V+validity 压入 RGBA,维护 fieldTexture/nextFieldTexture、各自 scale 和 image。二者独立拥有资源,不共享 GPU texture;均以 sameFieldGpuContent() 比较并可把 OLD_T1 移至 NEW_T0,仅上传新内容。

shaders/particle_gpu_validation.fragment.glsl 的 Field pass 从 RG 恢复 U/V,A 同时是 shared validity;weatherRampColor(length(velocity)) 是图场唯一值来源。无独立 scalar texture、mask texture 或 channel-level validity;粒子另有验证用 coast mask,但不属于 field validity。

C. Particle 数值与单位假设

GLSL fieldVelocityAt() 混合 T0/T1 的 U/V,要求两时刻 A 有效且 length > 1e-5。状态 pass 用 dx=u*simulationSeconds/EarthCircumference、dy=-v*simulationSeconds/(EarthCircumference*cos(latitude)),明确 U east、V north、物理 m/s。C++ 的 VisualSimulationSecondsPerRealSecond=1200 只是展示时钟;不会改变 canonical U/V 单位。故现状不适合直接把 Wave unit direction 当 velocity。

D. RN 到 Core binary ingress 与 ownership

公共 FieldRuntime.submitField(metadataJson, payloadFileUri) 在 RN 薄映射内部 submitWindField。Kotlin bridge 只接受 file:// 或绝对本地路径,metadata 上限 1 MiB、payload 1..64 MiB,读为 ByteArray;无 number[]/JSON array/Base64。WeatherRuntime.submitWindField() 传给 MapLibreMap.submitRasterArraySourceHostField(),JNI NativeMapView::submitRasterArraySourceHostField 把 Java byte[] 复制为 C++ vector<char>,再调用 RasterArraySource::submitHostField();Core adapter 再复制解码为 float vector。因此当前 ownership 是同步、三次宿主/核心内存持有,而非 zero-copy。

Timeline / Runtime Window

RasterArraySource::submitHostField() 首帧 pending、第二帧原子建立 Source-owned RasterArrayTimelineRuntime T0/T1;后续按 validTime/generation 单调 append,容量 8。RasterArrayTimelineRuntime 输出 immutable T0/T1 + MIX,暂停不推进。RenderWeatherColorLayer 与 RenderRasterParticleLayer 都取同一 Source timeline;正常 overlap rollover 保持 simulationRebuild=false、trailCleared=false,无 overlap 才 reset。invalid/gap 由 timeline 状态 fail-closed。

Field Renderer 与 speedMps 链路

WeatherColorStop.speedMps 位于 C++ weather_color_stop.hpp,Android WeatherRuntime.ColorStop、Kotlin native bridge 和 generated TurboModule 均仍使用该内部 ABI;RN .2 已将公开 FieldColorStop.value 薄转换为 speedMps。当前 shader 默认 0..30 m/s palette,stop 值也按 speed 解释。因此 V3 必须新增明确 value source,不能以有无 scalar 猜测。

WeatherV2 输入核对

nsft.py / field_pmtiles.py 证实 NSFT PMTiles wm_grid_257、NW origin(row north→south、column west→east)、同 zoom tile 257 样本。Wind 与 current 都写物理 U/V;wind.py、tide.py 计算 speed 为 sqrt(u²+v²)。Rain 写 rain_mm_h + valid;虽 decoder 有 precipitation_type,encode_rain_tile() 未写它。Wave 写 height_m、period_s 和 unit_to_u/v;waves.py 将 from 转 to 后归一化,非 m/s。target_time 由实际任务时间写入 header,不能推定小时 cadence。任务书给出的事实与代码一致。

直接结论

V3 应保留现有 Source-owned timeline、两个独立 renderer 和 overlap reuse 的行为,但将单个 velocity snapshot 升级为一个快照的 optional scalar、optional vector、shared validity 三资源。业务名称、单位换算、NSFT/PMTiles、tile 拼接、provider/缓存必须停在 NavSea 侧。