ScreenMap.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using o0.Geometry2D.Float;
  2. using System;
  3. using UnityEngine;
  4. namespace ZIM.Unity
  5. {
  6. // 摄像机的取景画面的纵横比设置(取景画面纵横比是否会根据分辨率变化)
  7. public enum AspectRatioSetting
  8. {
  9. FixedAll, // 高度和宽度都不变
  10. FixedHeight, // 高度固定
  11. FixedWidth, // 宽度固定
  12. }
  13. // 记录屏幕的位置,QuadInCamera表示屏幕4个点在摄像机画面中的坐标
  14. // TransformToScreen可将摄像机空间的点映射到屏幕空间,反之用TransformToCamera
  15. public class ScreenMap
  16. {
  17. public static AspectRatioSetting ViewAspectRatioSetting = AspectRatioSetting.FixedHeight;// 默认取景画面的高度保持不变,宽度随着分辨率变化
  18. public Rect QuadRect { get; private set; }
  19. public Vector2 UVSize { get; private set; } // UV代表屏幕空间的坐标,UVSize代表屏幕坐标的取值范围
  20. public bool Active;
  21. QuadrilateralInCamera quadInCamera; // 记录的分辨率和识别时的分辨率可能不同
  22. public QuadrilateralInCamera QuadInCamera
  23. {
  24. get => quadInCamera;
  25. set
  26. {
  27. quadInCamera = value;
  28. InitByQuad();
  29. }
  30. }
  31. // 当分辨率不同时,刷新分辨率并返回true,否则返回false
  32. public bool RefreshCameraSize(Vector2 sizeNew) => RefreshCameraSize(sizeNew.o0Vector());
  33. public bool RefreshCameraSize(Vector sizeNew)
  34. {
  35. if (QuadInCamera != null && QuadInCamera.CameraSize != sizeNew)
  36. {
  37. UnityEngine.Debug.Log("[ScreenMap]根据分辨率映射: from " + QuadInCamera.SizeString + " to " + sizeNew);
  38. QuadInCamera.ReSize(sizeNew, ViewAspectRatioSetting);
  39. InitByQuad();
  40. return true;
  41. }
  42. return false;
  43. }
  44. private void InitByQuad()
  45. {
  46. if (QuadInCamera != null)
  47. {
  48. var quad = QuadInCamera.Quad;
  49. var x = Math.Min((quad.A - quad.B).Length, (quad.C - quad.D).Length);
  50. var y = Math.Min((quad.A - quad.C).Length, (quad.B - quad.D).Length);
  51. UVSize = new Vector2(x, y);
  52. perspective = new ZIMPerspectiveTransform(quad, new OrdinalQuadrilateral(new Vector(0, 0), new Vector(x, 0), new Vector(0, y), new Vector(x, y)));
  53. var aabb = quad.AABBRect();
  54. QuadRect = new Rect(aabb.Item1.x, aabb.Item1.y, aabb.Item2.x - aabb.Item1.x, aabb.Item2.y - aabb.Item1.y);
  55. Debug.Log("[ScreenMap] 应用屏幕识别数据");
  56. //Debug.Log("QuadRect:" + QuadRect);
  57. Active = true;
  58. }
  59. else
  60. {
  61. Active = false;
  62. }
  63. }
  64. private ZIMPerspectiveTransform perspective;
  65. public ScreenMap()
  66. {
  67. }
  68. public ScreenMap(QuadrilateralInCamera quad)
  69. {
  70. QuadInCamera = quad;
  71. }
  72. public bool UVInScreen(Vector2 v)
  73. {
  74. return Active ? v.x > 0 && v.x < UVSize.x && v.y > 0 && v.y < UVSize.y : true;
  75. }
  76. // UV归一化到[0, 1]范围,仅用于输出最终结果
  77. public Vector2 UVNormalized(Vector2 location)
  78. {
  79. return Active ?
  80. new Vector2(location.x / UVSize.x, location.y / UVSize.y) :
  81. new Vector2(location.x / ScreenLocate.Main.CameraSize.x, location.y / ScreenLocate.Main.CameraSize.y);
  82. }
  83. public Vector2 TransformToScreen(Vector2 vIn)
  84. {
  85. if (Active)
  86. {
  87. var v = perspective.Transform(vIn.x, vIn.y);
  88. return new Vector2(v.x, v.y);
  89. }
  90. else
  91. {
  92. return vIn;
  93. }
  94. }
  95. public Vector2 TransformToCamera(Vector2 vIn)
  96. {
  97. if (Active)
  98. {
  99. var v = perspective.TransformInverse(vIn.x, vIn.y);
  100. return new Vector2(v.x, v.y);
  101. }
  102. else
  103. {
  104. return vIn;
  105. }
  106. }
  107. }
  108. }