feat: add runtime particle field updates

This commit is contained in:
OpenAI Codex
2026-09-03 18:26:13 +08:00
parent 7af12e7d62
commit 45502a53f4
12 changed files with 346 additions and 15 deletions

View File

@@ -105,10 +105,7 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
findViewById<Button>(R.id.validationParticle65536).setOnClickListener { setParticleCount(PARTICLE_COUNT_65536) }
findViewById<Button>(R.id.validationParticle1048576).setOnClickListener { setParticleCount(PARTICLE_COUNT_1048576) }
findViewById<Button>(R.id.validationAdvanceWindow).setOnClickListener {
timeWindowMode = true
fixtureMode = FIXTURE_UNIFORM_NORTH
timeMix = 0.0f
if (this::maplibreMap.isInitialized) loadValidationStyle(active, enabled, "ADVANCE")
if (this::maplibreMap.isInitialized) advanceRuntimeFieldWindow()
}
findViewById<Button>(R.id.validationDateline).setOnClickListener {
maplibreMap.cameraPosition = CameraPosition.Builder().target(LatLng(0.0, 179.0)).zoom(2.0).build()
@@ -196,6 +193,26 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
Log.i(TAG, "ParticleGPU: event=PARTICLE_COUNT_APPLIED requestedParticleCount=$requestedParticleCount effectiveParticleCount=$particleCount styleEpoch=$styleLoadEpoch")
}
private fun advanceRuntimeFieldWindow() {
val rejectReason = when {
!styleReady -> "STYLE_LOADING"
!enabled -> "DISABLED"
!timeWindowMode -> "TIME_WINDOW_OFF"
else -> null
}
if (rejectReason != null) {
Log.i(TAG, "ParticleField: event=FIELD_WINDOW_UPDATE_REJECTED reason=$rejectReason styleEpoch=$styleLoadEpoch")
return
}
Log.i(TAG, "ParticleField: event=FIELD_WINDOW_UPDATE_REQUEST sourceId=$PARTICLE_SOURCE_ID styleEpoch=$styleLoadEpoch")
if (!maplibreMap.advanceRasterArraySourceFieldWindow(PARTICLE_SOURCE_ID)) {
Log.i(TAG, "ParticleField: event=FIELD_WINDOW_UPDATE_REJECTED reason=CORE_SOURCE_REJECTED styleEpoch=$styleLoadEpoch")
return
}
status.text = statusText()
Log.i(TAG, "ParticleField: event=FIELD_WINDOW_UPDATE_APPLIED styleEpoch=$styleLoadEpoch")
}
private fun statusText(): String {
val mask = when (maskMode) {
MASK_OCEAN_A -> "OCEAN A"
@@ -204,7 +221,7 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
}
val runtime = if (enabled) if (active) "ACTIVE" else "STATIC" else "DISABLED"
val fields = if (timeWindowMode) {
"T0 EAST · T1 NORTH"
"RUNTIME WINDOW"
} else if (fixtureMode == FIXTURE_UNIFORM_NORTH) {
"NORTH"
} else {
@@ -239,7 +256,13 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
"field": "asset://integration/particle-fixtures/$fixtureId/field.f32",
"next-fixture": "$nextFixtureId",
"next-metadata": "asset://integration/particle-fixtures/$nextFixtureId/metadata.json",
"next-field": "asset://integration/particle-fixtures/$nextFixtureId/field.f32"
"next-field": "asset://integration/particle-fixtures/$nextFixtureId/field.f32",
"runtime-fields": [
{"fixture":"vortex","metadata":"asset://integration/particle-fixtures/vortex/metadata.json",
"field":"asset://integration/particle-fixtures/vortex/field.f32"},
{"fixture":"nodata","metadata":"asset://integration/particle-fixtures/nodata/metadata.json",
"field":"asset://integration/particle-fixtures/nodata/field.f32"}
]
},
"validation-point": {
"type": "geojson",
@@ -292,6 +315,7 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
private const val STATE_PARTICLE_COUNT = "particle_validation.particle_count"
private const val STATE_TIME_WINDOW = "particle_validation.time_window"
private const val PARTICLE_LAYER_ID = "particle-raster-core"
private const val PARTICLE_SOURCE_ID = "particle-fixture"
private const val MASK_GLOBAL = 0
private const val MASK_OCEAN_A = 1
private const val MASK_OCEAN_B = 2

View File

@@ -25,7 +25,7 @@
<string name="particle_validation_uniform_east">UNIFORM EAST</string>
<string name="particle_validation_uniform_north">UNIFORM NORTH</string>
<string name="particle_validation_time_window">T0 EAST / T1 NORTH</string>
<string name="particle_validation_advance_window">ADVANCE B→C</string>
<string name="particle_validation_advance_window">ADVANCE WINDOW</string>
<string name="particle_validation_mix_0">MIX 0%</string>
<string name="particle_validation_mix_50">MIX 50%</string>
<string name="particle_validation_mix_100">MIX 100%</string>