test(M00): add renderer coordinate calibration
Work-Package: M00-QAR-COORD-CALIBRATION-001 Agent: sindo-main-codex Tests: coordinate probe, M00 dry-run, coordination and documentation gates Fidelity: five build 12340 camera points round-trip within 0.000015 units
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
"name": "elwynn_terrain_overview",
|
||||
"coverage": ["terrain"],
|
||||
"camera": [16680.0, 180.0, 26220.0],
|
||||
"reference_wow_camera": [-9153.334, 386.666, 180.0],
|
||||
"target": [16800.0, 62.0, 26400.0],
|
||||
"player": [16800.0, 58.0, 26400.0],
|
||||
"time_hours": 13.0
|
||||
@@ -51,6 +52,7 @@
|
||||
"name": "elwynn_adt_boundary",
|
||||
"coverage": ["adt_boundary"],
|
||||
"camera": [17020.0, 105.0, 26590.0],
|
||||
"reference_wow_camera": [-9523.334, 46.666, 105.0],
|
||||
"target": [17066.666, 62.0, 26666.666],
|
||||
"player": [17060.0, 58.0, 26660.0],
|
||||
"time_hours": 13.0
|
||||
@@ -59,6 +61,7 @@
|
||||
"name": "goldshire_dense_m2",
|
||||
"coverage": ["dense_m2"],
|
||||
"camera": [16956.666, 150.0, 26466.666],
|
||||
"reference_wow_camera": [-9400.0, 110.0, 150.0],
|
||||
"target": [17015.0, 62.0, 26525.0],
|
||||
"player": [17015.0, 58.0, 26525.0],
|
||||
"time_hours": 13.0
|
||||
@@ -67,6 +70,7 @@
|
||||
"name": "goldshire_inn_large_wmo",
|
||||
"coverage": ["large_wmo"],
|
||||
"camera": [17013.666, 72.0, 26451.666],
|
||||
"reference_wow_camera": [-9385.0, 53.0, 72.0],
|
||||
"target": [17042.27, 66.0, 26530.91],
|
||||
"player": [17042.27, 58.0, 26530.91],
|
||||
"time_hours": 13.0
|
||||
@@ -75,6 +79,7 @@
|
||||
"name": "elwynn_waterfall_liquid",
|
||||
"coverage": ["liquid"],
|
||||
"camera": [16481.666, 190.0, 26366.666],
|
||||
"reference_wow_camera": [-9300.0, 585.0, 190.0],
|
||||
"target": [16518.84, 68.0, 26427.27],
|
||||
"player": [16518.84, 55.0, 26427.27],
|
||||
"time_hours": 13.0
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
extends SceneTree
|
||||
|
||||
## Verifies observed build 12340 camera coordinates against the current renderer
|
||||
## WoW X/Y/Z to Godot X/Y/Z convention. This diagnostic does not define the
|
||||
## future M01 production CoordinateMapper contract.
|
||||
|
||||
const MANIFEST_PATH := "res://src/tools/render_baseline_manifest.json"
|
||||
const WOW_WORLD_CENTER := 17066.666
|
||||
const MAXIMUM_POSITION_ERROR := 0.002
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
var manifest := _load_manifest()
|
||||
if manifest.is_empty():
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var failures: Array[String] = []
|
||||
var calibrated_count := 0
|
||||
var maximum_round_trip_error := 0.0
|
||||
for checkpoint_variant in manifest.get("checkpoints", []):
|
||||
if not (checkpoint_variant is Dictionary):
|
||||
continue
|
||||
var checkpoint: Dictionary = checkpoint_variant
|
||||
var reference_wow_camera_variant = checkpoint.get("reference_wow_camera", null)
|
||||
if not (reference_wow_camera_variant is Array):
|
||||
continue
|
||||
var reference_wow_camera: Array = reference_wow_camera_variant
|
||||
var checkpoint_name := String(checkpoint.get("name", "checkpoint"))
|
||||
if reference_wow_camera.size() != 3:
|
||||
failures.append("%s reference_wow_camera must contain three coordinates" % checkpoint_name)
|
||||
continue
|
||||
var expected_godot_camera := _array_to_vector3(checkpoint.get("camera", []))
|
||||
var reference_wow_position := _array_to_vector3(reference_wow_camera)
|
||||
var mapped_godot_position := _wow_to_godot(reference_wow_position)
|
||||
var round_trip_wow_position := _godot_to_wow(mapped_godot_position)
|
||||
var mapping_error := mapped_godot_position.distance_to(expected_godot_camera)
|
||||
var round_trip_error := round_trip_wow_position.distance_to(reference_wow_position)
|
||||
maximum_round_trip_error = maxf(maximum_round_trip_error, maxf(mapping_error, round_trip_error))
|
||||
if mapping_error > MAXIMUM_POSITION_ERROR:
|
||||
failures.append("%s maps %.6f units away from manifest camera" % [checkpoint_name, mapping_error])
|
||||
if round_trip_error > MAXIMUM_POSITION_ERROR:
|
||||
failures.append("%s round-trip error is %.6f" % [checkpoint_name, round_trip_error])
|
||||
calibrated_count += 1
|
||||
|
||||
if calibrated_count < 5:
|
||||
failures.append("expected at least five build 12340 camera calibrations, found %d" % calibrated_count)
|
||||
if not failures.is_empty():
|
||||
for failure in failures:
|
||||
push_error("RENDER_COORDINATE_CALIBRATION: %s" % failure)
|
||||
quit(1)
|
||||
return
|
||||
print("RENDER_COORDINATE_CALIBRATION PASS points=%d maximum_error=%.6f" % [calibrated_count, maximum_round_trip_error])
|
||||
quit(0)
|
||||
|
||||
|
||||
func _wow_to_godot(wow_position: Vector3) -> Vector3:
|
||||
return Vector3(
|
||||
WOW_WORLD_CENTER - wow_position.y,
|
||||
wow_position.z,
|
||||
WOW_WORLD_CENTER - wow_position.x
|
||||
)
|
||||
|
||||
|
||||
func _godot_to_wow(godot_position: Vector3) -> Vector3:
|
||||
return Vector3(
|
||||
WOW_WORLD_CENTER - godot_position.z,
|
||||
WOW_WORLD_CENTER - godot_position.x,
|
||||
godot_position.y
|
||||
)
|
||||
|
||||
|
||||
func _array_to_vector3(value_variant) -> Vector3:
|
||||
if not (value_variant is Array) or value_variant.size() != 3:
|
||||
return Vector3.ZERO
|
||||
return Vector3(float(value_variant[0]), float(value_variant[1]), float(value_variant[2]))
|
||||
|
||||
|
||||
func _load_manifest() -> Dictionary:
|
||||
var manifest_file := FileAccess.open(MANIFEST_PATH, FileAccess.READ)
|
||||
if manifest_file == null:
|
||||
push_error("Cannot open renderer baseline manifest: %s" % MANIFEST_PATH)
|
||||
return {}
|
||||
var parsed = JSON.parse_string(manifest_file.get_as_text())
|
||||
if not (parsed is Dictionary):
|
||||
push_error("Renderer baseline manifest is not a JSON object")
|
||||
return {}
|
||||
return parsed
|
||||
Reference in New Issue
Block a user