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