refactor(M03): extract terrain chunk LOD planner
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
class_name TerrainChunkLodPlanner
|
||||
extends RefCounted
|
||||
|
||||
## Pure linear desired-state planner for parsed ADT chunk records.
|
||||
|
||||
const POLICY_SCRIPT := preload("res://src/render/terrain/terrain_chunk_lod_policy.gd")
|
||||
const GODOT_WORLD_POSITION_SCRIPT := preload("res://src/domain/coordinates/godot_world_position.gd")
|
||||
|
||||
|
||||
## Maps source chunk indices to LOD 0/1/2 using horizontal distance from the
|
||||
## typed focus to each chunk center. Empty/out-of-range chunks remain absent.
|
||||
func plan(
|
||||
chunks: Array,
|
||||
focus_position: RefCounted,
|
||||
policy: RefCounted
|
||||
) -> Dictionary:
|
||||
if (
|
||||
focus_position == null
|
||||
or focus_position.get_script() != GODOT_WORLD_POSITION_SCRIPT
|
||||
or policy == null
|
||||
or policy.get_script() != POLICY_SCRIPT
|
||||
or not bool(policy.get("is_enabled"))
|
||||
):
|
||||
return {}
|
||||
|
||||
var chunk_size_units := float(policy.get("chunk_size_units"))
|
||||
var lod0_radius_squared := (float(policy.get("lod0_radius_chunks")) * chunk_size_units) ** 2
|
||||
var lod1_radius_squared := (float(policy.get("lod1_radius_chunks")) * chunk_size_units) ** 2
|
||||
var lod2_radius_squared := (float(policy.get("lod2_radius_chunks")) * chunk_size_units) ** 2
|
||||
var focus_x_units := float(focus_position.get("x_units"))
|
||||
var focus_z_units := float(focus_position.get("z_units"))
|
||||
var desired_lods: Dictionary = {}
|
||||
|
||||
for chunk_id in range(chunks.size()):
|
||||
var chunk: Dictionary = chunks[chunk_id]
|
||||
if chunk.is_empty():
|
||||
continue
|
||||
var origin: Vector3 = chunk.get("origin", Vector3.ZERO)
|
||||
var center_x_units := origin.x + chunk_size_units * 0.5
|
||||
var center_z_units := origin.z + chunk_size_units * 0.5
|
||||
var delta_x_units := center_x_units - focus_x_units
|
||||
var delta_z_units := center_z_units - focus_z_units
|
||||
var distance_squared_units := (
|
||||
delta_x_units * delta_x_units + delta_z_units * delta_z_units
|
||||
)
|
||||
if distance_squared_units <= lod0_radius_squared:
|
||||
desired_lods[chunk_id] = 0
|
||||
elif distance_squared_units <= lod1_radius_squared:
|
||||
desired_lods[chunk_id] = 1
|
||||
elif distance_squared_units <= lod2_radius_squared:
|
||||
desired_lods[chunk_id] = 2
|
||||
|
||||
return desired_lods
|
||||
@@ -0,0 +1 @@
|
||||
uid://x8simqkfctqw
|
||||
@@ -0,0 +1,45 @@
|
||||
class_name TerrainChunkLodPolicy
|
||||
extends RefCounted
|
||||
|
||||
## Immutable snapshot of the streamer's chunk-terrain LOD configuration.
|
||||
|
||||
var is_enabled: bool:
|
||||
get:
|
||||
return _is_enabled
|
||||
|
||||
var lod0_radius_chunks: int:
|
||||
get:
|
||||
return _lod0_radius_chunks
|
||||
|
||||
var lod1_radius_chunks: int:
|
||||
get:
|
||||
return _lod1_radius_chunks
|
||||
|
||||
var lod2_radius_chunks: int:
|
||||
get:
|
||||
return _lod2_radius_chunks
|
||||
|
||||
var chunk_size_units: float:
|
||||
get:
|
||||
return _chunk_size_units
|
||||
|
||||
var _is_enabled: bool
|
||||
var _lod0_radius_chunks: int
|
||||
var _lod1_radius_chunks: int
|
||||
var _lod2_radius_chunks: int
|
||||
var _chunk_size_units: float
|
||||
|
||||
|
||||
## Captures one renderer configuration snapshot for a deterministic plan.
|
||||
func _init(
|
||||
is_enabled_value: bool,
|
||||
lod0_radius_chunks_value: int,
|
||||
lod1_radius_chunks_value: int,
|
||||
lod2_radius_chunks_value: int,
|
||||
chunk_size_units_value: float
|
||||
) -> void:
|
||||
_is_enabled = is_enabled_value
|
||||
_lod0_radius_chunks = lod0_radius_chunks_value
|
||||
_lod1_radius_chunks = lod1_radius_chunks_value
|
||||
_lod2_radius_chunks = lod2_radius_chunks_value
|
||||
_chunk_size_units = chunk_size_units_value
|
||||
@@ -0,0 +1 @@
|
||||
uid://dmwi83dp52pa8
|
||||
Reference in New Issue
Block a user