refactor(M03): extract M2 runtime rebuild classifier

This commit is contained in:
2026-07-17 10:01:29 +04:00
parent 324e64dd6e
commit 19ca8f48e8
9 changed files with 600 additions and 52 deletions
+11 -51
View File
@@ -60,6 +60,9 @@ const M2_PLACEMENT_GROUPER_SCRIPT := preload(
const M2_BUILD_BATCH_PLANNER_SCRIPT := preload(
"res://src/render/m2/m2_build_batch_planner.gd"
)
const M2_RUNTIME_MESH_REBUILD_CLASSIFIER_SCRIPT := preload(
"res://src/render/m2/m2_runtime_mesh_rebuild_classifier.gd"
)
const STREAMING_TARGET_PLANNER_SCRIPT := preload("res://src/render/streaming/streaming_target_planner.gd")
const STREAMING_TARGET_POLICY_SCRIPT := preload("res://src/render/streaming/streaming_target_policy.gd")
const RENDER_BUDGET_SCHEDULER_SCRIPT := preload("res://src/render/streaming/render_budget_scheduler.gd")
@@ -247,10 +250,12 @@ var _m2_unique_placement_registry := (
var _m2_placement_transform_resolver := M2_PLACEMENT_TRANSFORM_RESOLVER_SCRIPT.new()
var _m2_placement_grouper := M2_PLACEMENT_GROUPER_SCRIPT.new()
var _m2_build_batch_planner := M2_BUILD_BATCH_PLANNER_SCRIPT.new()
var _m2_runtime_mesh_rebuild_classifier := (
M2_RUNTIME_MESH_REBUILD_CLASSIFIER_SCRIPT.new()
)
var _m2_mesh_cache: Dictionary = {}
var _m2_mesh_load_requests: Dictionary = {}
var _m2_mesh_finalize_queue: Array = []
var _m2_runtime_rebuild_required_cache: Dictionary = {}
var _m2_animation_load_requests: Dictionary = {}
var _m2_animation_finalize_queue: Array = []
var _wmo_build_jobs: Dictionary = {}
@@ -2342,7 +2347,7 @@ func _wait_for_tile_tasks() -> void:
ResourceLoader.load_threaded_get(path)
_m2_mesh_load_requests.clear()
_m2_mesh_finalize_queue.clear()
_m2_runtime_rebuild_required_cache.clear()
_m2_runtime_mesh_rebuild_classifier.clear()
for pending in _m2_animation_load_requests.values():
var path: String = String(pending.get("path", ""))
@@ -2993,7 +2998,7 @@ func _clear_streamed_world() -> void:
_m2_unique_placement_registry.clear()
_m2_mesh_load_requests.clear()
_m2_mesh_finalize_queue.clear()
_m2_runtime_rebuild_required_cache.clear()
_m2_runtime_mesh_rebuild_classifier.clear()
_m2_animation_load_requests.clear()
_m2_animation_finalize_queue.clear()
_wmo_build_jobs.clear()
@@ -4645,7 +4650,9 @@ func _prepare_m2_mesh_for_runtime(normalized_rel: String, mesh: Mesh) -> Mesh:
if int(mesh.get_meta("wow_m2_material_refresh_version", 0)) >= M2_MATERIAL_REFRESH_VERSION:
return mesh
var data := _load_m2_raw_data_for_refresh(normalized_rel)
if data.is_empty() or not _m2_raw_data_needs_runtime_mesh_rebuild(normalized_rel, data):
if data.is_empty() or not _m2_runtime_mesh_rebuild_classifier.needs_runtime_mesh_rebuild(
normalized_rel,
data):
mesh.set_meta("wow_m2_material_refresh_version", M2_MATERIAL_REFRESH_VERSION)
return mesh
var rebuilt := _rebuild_m2_mesh_from_data(data)
@@ -4679,53 +4686,6 @@ func _load_m2_raw_data_for_refresh(normalized_rel: String) -> Dictionary:
return data if data is Dictionary else {}
func _m2_raw_data_needs_runtime_mesh_rebuild(normalized_rel: String, data: Dictionary) -> bool:
if _m2_runtime_rebuild_required_cache.has(normalized_rel):
return bool(_m2_runtime_rebuild_required_cache[normalized_rel])
var needs_rebuild := _m2_raw_data_has_billboards(data) or _m2_raw_data_has_uv_rotation(data)
_m2_runtime_rebuild_required_cache[normalized_rel] = needs_rebuild
return needs_rebuild
func _m2_raw_data_has_billboards(data: Dictionary) -> bool:
for batch_variant in data.get("batches", []):
if not (batch_variant is Dictionary):
continue
var batch: Dictionary = batch_variant
if bool(batch.get("has_billboard", false)) or int(batch.get("billboard_vertex_count", 0)) > 0:
return true
return false
func _m2_raw_data_has_uv_rotation(data: Dictionary) -> bool:
var transforms: Array = data.get("texture_transforms", [])
if transforms.is_empty():
return false
var combos: PackedInt32Array = data.get("texture_transform_combos", PackedInt32Array())
if combos.is_empty():
return false
for batch_variant in data.get("batches", []):
if not (batch_variant is Dictionary):
continue
var batch: Dictionary = batch_variant
var texture_count := maxi(1, int(batch.get("texture_count", 1)))
var base_combo := int(batch.get("texture_transform_combo_index", -1))
for stage in mini(texture_count, 4):
var combo_index := base_combo + stage
if combo_index < 0 or combo_index >= combos.size():
continue
var transform_index := int(combos[combo_index])
if transform_index < 0 or transform_index >= transforms.size():
continue
var transform: Dictionary = transforms[transform_index] if transforms[transform_index] is Dictionary else {}
var rotation: Vector4 = transform.get("rotation", Vector4(1.0, 0.0, 0.0, 1.0))
if not rotation.is_equal_approx(Vector4(1.0, 0.0, 0.0, 1.0)):
return true
if absf(float(transform.get("rotation_speed", 0.0))) > 0.000001:
return true
return false
func _rebuild_m2_mesh_from_data(data: Dictionary) -> Mesh:
if data.is_empty():
return null