QuadrilateralInCamera.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using o0.Geometry2D;
  5. using o0.Geometry2D.Float;
  6. using UnityEngine;
  7. namespace ZIM.Unity
  8. {
  9. // 屏幕识别使用,记录摄像机画面内的四边形
  10. public class QuadrilateralInCamera
  11. {
  12. public Vector CameraSize;
  13. public OrdinalQuadrilateral Quad;
  14. // 固定的顶点顺序: 左下,右下,左上,右上
  15. public QuadrilateralInCamera(Vector2 a, Vector2 b, Vector2 c, Vector2 d, Vector2 cameraSize)
  16. {
  17. CameraSize = cameraSize.o0Vector();
  18. Quad = new OrdinalQuadrilateral(a.o0Vector(), b.o0Vector(), c.o0Vector(), d.o0Vector());
  19. }
  20. // 固定的顶点顺序: 左下,右下,左上,右上
  21. public QuadrilateralInCamera(Vector a, Vector b, Vector c, Vector d, Vector cameraSize)
  22. {
  23. CameraSize = cameraSize;
  24. Quad = new OrdinalQuadrilateral(a, b, c, d);
  25. }
  26. // 固定的顶点顺序: 左下,右下,左上,右上
  27. public QuadrilateralInCamera(IEnumerable<Vector> enumable, Vector cameraSize)
  28. {
  29. CameraSize = cameraSize;
  30. Quad = new OrdinalQuadrilateral(enumable);
  31. }
  32. // 固定的顶点顺序: 左下,右下,左上,右上
  33. public QuadrilateralInCamera(IEnumerable<Vector2> enumable, Vector cameraSize)
  34. {
  35. CameraSize = cameraSize;
  36. Quad = new OrdinalQuadrilateral(enumable.Select((i => i.o0Vector())));
  37. }
  38. public QuadrilateralInCamera(OrdinalQuadrilateral quad, Vector cameraSize)
  39. {
  40. CameraSize = cameraSize;
  41. Quad = quad;
  42. }
  43. public string SizeString => $"({CameraSize.x}, {CameraSize.y})";
  44. public string QuadString => $"[({Quad.A.x}, {Quad.A.y}), ({Quad.B.x}, {Quad.B.y}), ({Quad.C.x}, {Quad.C.y}), ({Quad.D.x}, {Quad.D.y})]";
  45. public override string ToString() => $"CameraSize: {SizeString}, Vertices: {QuadString}";
  46. // 需要标准化的坐标(即数值范围0-1)时使用,会自动根据当前的CameraSize转换
  47. private List<Vector> ScreenVertexListNormalized
  48. {
  49. get
  50. {
  51. return new List<Vector> {
  52. Quad.A / CameraSize,
  53. Quad.B / CameraSize,
  54. Quad.C / CameraSize,
  55. Quad.D / CameraSize
  56. };
  57. }
  58. set
  59. {
  60. for (int i = 0; i < Quad.Count; i++)
  61. Quad[i] = value[i] * CameraSize;
  62. }
  63. }
  64. // 这里是标准化坐标(即数值范围0-1)
  65. public List<Vector2> GetUnityVertexNormalizedList()
  66. {
  67. return new List<Vector2>() {
  68. new Vector2(Quad.A.x / CameraSize.x, Quad.A.y / CameraSize.y),
  69. new Vector2(Quad.B.x / CameraSize.x, Quad.B.y / CameraSize.y),
  70. new Vector2(Quad.C.x / CameraSize.x, Quad.C.y / CameraSize.y),
  71. new Vector2(Quad.D.x / CameraSize.x, Quad.D.y / CameraSize.y)
  72. };
  73. }
  74. // 线段顺序: 下、右、上、左
  75. public Line[] GetLines() => new Line[4]
  76. {
  77. new Line(Quad.A, Quad.B),
  78. new Line(Quad.B, Quad.D),
  79. new Line(Quad.C, Quad.D),
  80. new Line(Quad.A, Quad.C)
  81. };
  82. // 摄像机分辨率变化时调用
  83. public void ReSize(Vector sizeNew, AspectRatioSetting viewAspectRatioSetting)
  84. {
  85. if (CameraSize != sizeNew)
  86. {
  87. float ratio;
  88. Func<Vector, Vector> Translate;
  89. List<Vector> vertices;
  90. switch (viewAspectRatioSetting)
  91. {
  92. case AspectRatioSetting.FixedAll:
  93. var scale = new Vector(sizeNew.x / CameraSize.x, sizeNew.y / CameraSize.y);
  94. CameraSize = sizeNew;
  95. for (int i = 0; i < Quad.Count; i++)
  96. Quad[i] *= scale;
  97. break;
  98. case AspectRatioSetting.FixedHeight:
  99. var wOld = CameraSize.x / CameraSize.y; // 宽度比高度
  100. var wNew = sizeNew.x / sizeNew.y;
  101. ratio = wOld / wNew;
  102. Translate = (v) =>
  103. {
  104. var x = v.x - 0.5f;
  105. return new Vector(x * ratio + 0.5f, v.y);
  106. };
  107. vertices = ScreenVertexListNormalized;
  108. for (int i = 0; i < vertices.Count; i++)
  109. vertices[i] = Translate(vertices[i]);
  110. CameraSize = sizeNew; // 这里要先设置Size
  111. ScreenVertexListNormalized = vertices;
  112. break;
  113. case AspectRatioSetting.FixedWidth:
  114. var hOld = CameraSize.y / CameraSize.x; // 高度比宽度
  115. var hNew = sizeNew.y / sizeNew.x;
  116. ratio = hOld / hNew;
  117. Translate = (v) =>
  118. {
  119. var y = v.y - 0.5f;
  120. return new Vector(v.x, y * ratio + 0.5f);
  121. };
  122. vertices = ScreenVertexListNormalized;
  123. for (int i = 0; i < vertices.Count; i++)
  124. vertices[i] = Translate(vertices[i]);
  125. CameraSize = sizeNew;
  126. ScreenVertexListNormalized = vertices;
  127. break;
  128. }
  129. }
  130. }
  131. // 四边形是否完整的在屏幕内
  132. public bool IsQuadComplete()
  133. {
  134. if (Quad.A.x < Quad.B.x && Quad.A.y < Quad.C.y && Quad.B.y < Quad.D.y && Quad.C.x < Quad.D.x && Quad.A.x > 0 && Quad.A.y > 0 &&
  135. Quad.B.x < CameraSize.x && Quad.B.y > 0 && Quad.C.x > 0 && Quad.C.y < CameraSize.y && Quad.D.x < CameraSize.x && Quad.D.y < CameraSize.y)
  136. return true;
  137. return false;
  138. }
  139. }
  140. }