feat: add GPU particle time interpolation
This commit is contained in:
@@ -22,12 +22,16 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
private var enabled = true
|
||||
private var maskMode = MASK_GLOBAL
|
||||
private var fixtureMode = FIXTURE_UNIFORM_EAST
|
||||
private var timeMix = 0.0f
|
||||
private var timeWindowMode = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
active = savedInstanceState?.getBoolean(STATE_ACTIVE, true) ?: true
|
||||
enabled = savedInstanceState?.getBoolean(STATE_ENABLED, true) ?: true
|
||||
maskMode = savedInstanceState?.getInt(STATE_MASK_MODE, MASK_GLOBAL) ?: MASK_GLOBAL
|
||||
fixtureMode = savedInstanceState?.getInt(STATE_FIXTURE_MODE, FIXTURE_UNIFORM_EAST) ?: FIXTURE_UNIFORM_EAST
|
||||
timeMix = savedInstanceState?.getFloat(STATE_TIME_MIX, 0.0f) ?: 0.0f
|
||||
timeWindowMode = savedInstanceState?.getBoolean(STATE_TIME_WINDOW, false) ?: false
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.i(
|
||||
TAG,
|
||||
@@ -72,13 +76,30 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
if (this::maplibreMap.isInitialized) setValidationProperties(active = active, maskMode = MASK_OCEAN_B)
|
||||
}
|
||||
findViewById<Button>(R.id.validationUniformEast).setOnClickListener {
|
||||
timeWindowMode = false
|
||||
fixtureMode = FIXTURE_UNIFORM_EAST
|
||||
if (this::maplibreMap.isInitialized) loadValidationStyle(active, enabled)
|
||||
}
|
||||
findViewById<Button>(R.id.validationUniformNorth).setOnClickListener {
|
||||
timeWindowMode = false
|
||||
fixtureMode = FIXTURE_UNIFORM_NORTH
|
||||
if (this::maplibreMap.isInitialized) loadValidationStyle(active, enabled)
|
||||
}
|
||||
findViewById<Button>(R.id.validationTimeWindow).setOnClickListener {
|
||||
timeWindowMode = true
|
||||
fixtureMode = FIXTURE_UNIFORM_EAST
|
||||
timeMix = 0.0f
|
||||
if (this::maplibreMap.isInitialized) loadValidationStyle(active, enabled)
|
||||
}
|
||||
findViewById<Button>(R.id.validationMix0).setOnClickListener { setTimeMix(0.0f) }
|
||||
findViewById<Button>(R.id.validationMix50).setOnClickListener { setTimeMix(0.5f) }
|
||||
findViewById<Button>(R.id.validationMix100).setOnClickListener { setTimeMix(1.0f) }
|
||||
findViewById<Button>(R.id.validationAdvanceWindow).setOnClickListener {
|
||||
timeWindowMode = true
|
||||
fixtureMode = FIXTURE_UNIFORM_NORTH
|
||||
timeMix = 0.0f
|
||||
if (this::maplibreMap.isInitialized) loadValidationStyle(active, enabled)
|
||||
}
|
||||
findViewById<Button>(R.id.validationDateline).setOnClickListener {
|
||||
maplibreMap.cameraPosition = CameraPosition.Builder().target(LatLng(0.0, 179.0)).zoom(2.0).build()
|
||||
Log.i(TAG, "ParticleValidation30_03: DATELINE preset center=0,179 zoom=2")
|
||||
@@ -116,6 +137,20 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
Log.i(TAG, "ParticleRender: property update active=$active maskMode=$maskMode fixtureMode=$fixtureMode")
|
||||
}
|
||||
|
||||
private fun setTimeMix(value: Float) {
|
||||
timeMix = value.coerceIn(0.0f, 1.0f)
|
||||
val layer = maplibreMap.style?.getLayer(PARTICLE_LAYER_ID)
|
||||
if (layer == null || !enabled || !timeWindowMode) {
|
||||
timeWindowMode = true
|
||||
fixtureMode = FIXTURE_UNIFORM_EAST
|
||||
loadValidationStyle(active, enabled)
|
||||
return
|
||||
}
|
||||
layer.setProperties(PaintPropertyValue("raster-particle-time-mix", timeMix))
|
||||
status.text = "40-02 T0 east / T1 north timeMix=$timeMix"
|
||||
Log.i(TAG, "ParticleGPU: test timeMix=$timeMix; expect no Field upload or simulation rebuild")
|
||||
}
|
||||
|
||||
private fun statusText(): String = when {
|
||||
!enabled -> getString(R.string.particle_validation_disabled_status)
|
||||
maskMode == MASK_OCEAN_A -> getString(R.string.particle_validation_ocean_a_status)
|
||||
@@ -126,9 +161,15 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
|
||||
private fun validationStyle(active: Boolean, enabled: Boolean): String {
|
||||
val fixtureId = fixtureId()
|
||||
val nextFixtureId = if (timeWindowMode) {
|
||||
if (fixtureMode == FIXTURE_UNIFORM_NORTH) "vortex" else "uniform-north"
|
||||
} else {
|
||||
fixtureId
|
||||
}
|
||||
val particleLayer = if (enabled) {
|
||||
"""{"id":"particle-raster-core","type":"raster-particle","source":"particle-fixture",
|
||||
"paint":{"raster-particle-active":$active,"raster-particle-mask-mode":$maskMode}},"""
|
||||
"paint":{"raster-particle-active":$active,"raster-particle-mask-mode":$maskMode,
|
||||
"raster-particle-time-mix":$timeMix}},"""
|
||||
} else {
|
||||
""
|
||||
}
|
||||
@@ -141,7 +182,10 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
"type": "raster-array",
|
||||
"fixture": "$fixtureId",
|
||||
"metadata": "asset://integration/particle-fixtures/$fixtureId/metadata.json",
|
||||
"field": "asset://integration/particle-fixtures/$fixtureId/field.f32"
|
||||
"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"
|
||||
},
|
||||
"validation-point": {
|
||||
"type": "geojson",
|
||||
@@ -172,6 +216,8 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
outState.putBoolean(STATE_ENABLED, enabled)
|
||||
outState.putInt(STATE_MASK_MODE, maskMode)
|
||||
outState.putInt(STATE_FIXTURE_MODE, fixtureMode)
|
||||
outState.putFloat(STATE_TIME_MIX, timeMix)
|
||||
outState.putBoolean(STATE_TIME_WINDOW, timeWindowMode)
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
@@ -187,6 +233,8 @@ class ParticleCoreLayerValidationActivity : AppCompatActivity() {
|
||||
private const val STATE_ENABLED = "particle_validation.enabled"
|
||||
private const val STATE_MASK_MODE = "particle_validation.mask_mode"
|
||||
private const val STATE_FIXTURE_MODE = "particle_validation.fixture_mode"
|
||||
private const val STATE_TIME_MIX = "particle_validation.time_mix"
|
||||
private const val STATE_TIME_WINDOW = "particle_validation.time_window"
|
||||
private const val PARTICLE_LAYER_ID = "particle-raster-core"
|
||||
private const val MASK_GLOBAL = 0
|
||||
private const val MASK_OCEAN_A = 1
|
||||
|
||||
@@ -44,6 +44,53 @@
|
||||
android:text="@string/particle_validation_uniform_north" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/validationTimeWindow"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/particle_validation_time_window" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/validationAdvanceWindow"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/particle_validation_advance_window" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/validationMix0"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/particle_validation_mix_0" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/validationMix50"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/particle_validation_mix_50" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/validationMix100"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/particle_validation_mix_100" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<string name="particle_validation_world_wrap">WORLD WRAP</string>
|
||||
<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_mix_0">MIX 0%</string>
|
||||
<string name="particle_validation_mix_50">MIX 50%</string>
|
||||
<string name="particle_validation_mix_100">MIX 100%</string>
|
||||
<string name="particle_validation_global_active_status">40-01 GLOBAL ACTIVE: offline field simulation and current-frame composite.</string>
|
||||
<string name="particle_validation_global_static_status">40-01 GLOBAL STATIC: zero-step bootstrap and frozen composite.</string>
|
||||
<string name="particle_validation_ocean_a_status">40-01 OCEAN_ONLY_A: shared coastal-mask consumer.</string>
|
||||
|
||||
Reference in New Issue
Block a user