| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- using UnityEngine;
- using UnityEngine.UI;
- using TMPro;
- using LightGlue.Unity.Game;
- using LightGlue.Unity.Networking;
- namespace LightGlue.Unity.Roma.UI
- {
- /// <summary>
- /// Roma 场景结果显示 UI(兼容旧 LightGlueManager / 新 RomaManager)。
- /// - 优先绑定 LightGlueManager(旧场景)
- /// - 若不存在则绑定 RomaManager(新场景)
- /// </summary>
- public sealed class RomaResultUIController : MonoBehaviour
- {
- [Header("结果来源(可留空自动查找)")]
- public LightGlueManager lightGlueManager;
- public RomaManager romaManager;
- [Header("UI显示组件(可选)")]
- [Tooltip("综合状态文本(推荐绑定一个 Text 或 TMP_Text 之一)")]
- public Text statusText;
- public TMP_Text statusTmpText;
- [Tooltip("结果有效性状态文本(显示Valid/Invalid)")]
- public Text isValidText;
- [Tooltip("匹配点数量文本")]
- public Text numMatchesText;
- [Tooltip("内点比例文本")]
- public Text inliersRatioText;
- [Tooltip("相机位置X坐标文本")]
- public Text cameraXText;
- [Tooltip("相机位置Y坐标文本")]
- public Text cameraYText;
- [Header("显示设置")]
- [Range(1, 60)]
- public int updateRate = 10;
- public bool showInvalidResults = true;
- public string invalidResultText = "等待有效结果...";
- [Header("格式")]
- [Tooltip("是否按 RomaBridge 日志格式输出到 statusText/statusTmpText")]
- public bool useRomaBridgeLogFormat = true;
- private float _updateInterval;
- private float _lastUpdateTime;
- private LightGlueResult _latestResult;
- private bool _hasResult;
- private enum SourceType { None, LightGlueManager, RomaManager }
- private SourceType _source;
- private void Start()
- {
- _updateInterval = 1.0f / Mathf.Max(1, updateRate);
- _lastUpdateTime = Time.time;
- BindSource();
- }
- private void BindSource()
- {
- if (lightGlueManager == null)
- lightGlueManager = LightGlueManager.Instance;
- if (lightGlueManager != null)
- {
- _source = SourceType.LightGlueManager;
- lightGlueManager.OnResultUpdated += OnResultUpdated;
- if (lightGlueManager.HasLatestResult)
- OnResultUpdated(lightGlueManager.LatestResult);
- return;
- }
- if (romaManager == null)
- romaManager = RomaManager.Instance;
- if (romaManager != null)
- {
- _source = SourceType.RomaManager;
- romaManager.OnResultUpdated += OnResultUpdated;
- if (romaManager.HasLatestResult)
- OnResultUpdated(romaManager.LatestResult);
- return;
- }
- _source = SourceType.None;
- Debug.LogError("[RomaResultUI] 未找到 LightGlueManager / RomaManager,无法获取算法结果。");
- }
- private void Update()
- {
- if (Time.time - _lastUpdateTime < _updateInterval)
- return;
- _lastUpdateTime = Time.time;
- if (!_hasResult)
- {
- if (!showInvalidResults)
- ClearUI();
- return;
- }
- UpdateUI(_latestResult);
- }
- private void UpdateUI(LightGlueResult result)
- {
- if (isValidText != null)
- {
- if (result.IsValid)
- {
- isValidText.text = "状态: 有效";
- isValidText.color = Color.green;
- }
- else
- {
- isValidText.text = "状态: 无效";
- isValidText.color = Color.red;
- }
- }
- if (numMatchesText != null)
- numMatchesText.text = $"匹配点: {result.NumMatches}";
- if (inliersRatioText != null)
- inliersRatioText.text = $"内点比例: {result.InliersRatio:P1}";
- if (cameraXText != null)
- cameraXText.text = result.IsValid ? $"相机X: {result.CameraPosition.x:F1}" : "相机X: --";
- if (cameraYText != null)
- cameraYText.text = result.IsValid ? $"相机Y: {result.CameraPosition.y:F1}" : "相机Y: --";
- string msg = BuildStatusText(result);
- if (statusText != null)
- {
- statusText.text = msg;
- statusText.color = result.IsValid ? Color.white : Color.yellow;
- }
- if (statusTmpText != null)
- {
- statusTmpText.text = msg;
- statusTmpText.color = result.IsValid ? Color.white : Color.yellow;
- }
- }
- private string BuildStatusText(LightGlueResult result)
- {
- if (!result.IsValid && showInvalidResults && !useRomaBridgeLogFormat)
- return $"无效 | 匹配:{result.NumMatches} | {invalidResultText}";
- if (!useRomaBridgeLogFormat)
- {
- if (result.IsValid)
- return $"有效 | 匹配:{result.NumMatches} | 内点:{result.InliersRatio:P1} | 位置:({result.CameraPosition.x:F1}, {result.CameraPosition.y:F1})";
- return invalidResultText;
- }
- // 对齐你在 Console 里看到的格式:[RomaBridge] Result: valid=0 matches=500 inliers=0.000 x=0.0 y=0.0
- string prefix = _source == SourceType.LightGlueManager ? "[LightGlue]" : "[RomaBridge]";
- int valid = result.IsValid ? 1 : 0;
- return $"{prefix} Result: valid={valid} matches={result.NumMatches} inliers={result.InliersRatio:F3} x={result.CameraPosition.x:F1} y={result.CameraPosition.y:F1}";
- }
- private void ClearUI()
- {
- if (isValidText != null) isValidText.text = "状态: --";
- if (numMatchesText != null) numMatchesText.text = "匹配点: --";
- if (inliersRatioText != null) inliersRatioText.text = "内点比例: --";
- if (cameraXText != null) cameraXText.text = "相机X: --";
- if (cameraYText != null) cameraYText.text = "相机Y: --";
- if (statusText != null)
- {
- statusText.text = invalidResultText;
- statusText.color = Color.gray;
- }
- if (statusTmpText != null)
- {
- statusTmpText.text = invalidResultText;
- statusTmpText.color = Color.gray;
- }
- }
- private void OnResultUpdated(LightGlueResult result)
- {
- _latestResult = result;
- _hasResult = true;
- }
- private void OnDestroy()
- {
- if (lightGlueManager != null)
- lightGlueManager.OnResultUpdated -= OnResultUpdated;
- if (romaManager != null)
- romaManager.OnResultUpdated -= OnResultUpdated;
- }
- }
- }
|