docs: freeze V3 scalar vector field contract
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
# 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 侧。
|
||||
Reference in New Issue
Block a user