BsRect2I.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include "BsRect2I.h"
  2. #include "BsVector2I.h"
  3. #include "BsMatrix4.h"
  4. #include "BsMath.h"
  5. namespace BansheeEngine
  6. {
  7. const Rect2I Rect2I::EMPTY = Rect2I();
  8. Rect2I::Rect2I()
  9. :x(0), y(0), width(0), height(0)
  10. { }
  11. Rect2I::Rect2I(int _x, int _y, int _width, int _height)
  12. :x(_x), y(_y), width(_width), height(_height)
  13. { }
  14. bool Rect2I::contains(const Vector2I& point) const
  15. {
  16. if(point.x >= x && point.x < (x + width))
  17. {
  18. if(point.y >= y && point.y < (y + height))
  19. return true;
  20. }
  21. return false;
  22. }
  23. bool Rect2I::overlaps(const Rect2I& other) const
  24. {
  25. INT32 otherRight = other.x + other.width;
  26. INT32 myRight = x + width;
  27. INT32 otherBottom = other.y + other.height;
  28. INT32 myBottom = y + height;
  29. if(x < otherRight && myRight > other.x &&
  30. y < otherBottom && myBottom > other.y)
  31. return true;
  32. return false;
  33. }
  34. void Rect2I::encapsulate(const Rect2I& other)
  35. {
  36. int myRight = x + width;
  37. int myBottom = y + height;
  38. int otherRight = other.x + other.width;
  39. int otherBottom = other.y + other.height;
  40. if(other.x < x)
  41. x = other.x;
  42. if(other.y < y)
  43. y = other.y;
  44. if(otherRight > myRight)
  45. width = otherRight - x;
  46. else
  47. width = myRight - x;
  48. if(otherBottom > myBottom)
  49. height = otherBottom - y;
  50. else
  51. height = myBottom - y;
  52. }
  53. void Rect2I::clip(const Rect2I& clipRect)
  54. {
  55. int newLeft = std::max(x, clipRect.x);
  56. int newTop = std::max(y, clipRect.y);
  57. int newRight = std::min(x + width, clipRect.x + clipRect.width);
  58. int newBottom = std::min(y + height, clipRect.y + clipRect.height);
  59. x = std::min(newLeft, newRight);
  60. y = std::min(newTop, newBottom);
  61. width = std::max(0, newRight - newLeft);
  62. height = std::max(0, newBottom - newTop);
  63. }
  64. void Rect2I::cut(const Rect2I& cutRect, Vector<Rect2I>& pieces)
  65. {
  66. UINT32 initialPieces = (UINT32)pieces.size();
  67. // Cut horizontal
  68. if (cutRect.x > x && cutRect.x < (x + width))
  69. {
  70. Rect2I leftPiece;
  71. leftPiece.x = x;
  72. leftPiece.width = cutRect.x - x;
  73. leftPiece.y = y;
  74. leftPiece.height = height;
  75. pieces.push_back(leftPiece);
  76. }
  77. if ((cutRect.x + cutRect.width) > x && (cutRect.x + cutRect.width) < (x + width))
  78. {
  79. Rect2I rightPiece;
  80. rightPiece.x = cutRect.x + cutRect.width;
  81. rightPiece.width = (x + width) - (cutRect.x + cutRect.width);
  82. rightPiece.y = y;
  83. rightPiece.height = height;
  84. pieces.push_back(rightPiece);
  85. }
  86. // Cut vertical
  87. INT32 cutLeft = std::min(std::max(x, cutRect.x), x + width);
  88. INT32 cutRight = std::max(std::min(x + width, cutRect.x + cutRect.width), x);
  89. if (cutLeft != cutRight)
  90. {
  91. if (cutRect.y > y && cutRect.y < (y + height))
  92. {
  93. Rect2I topPiece;
  94. topPiece.y = y;
  95. topPiece.height = cutRect.y - y;
  96. topPiece.x = cutLeft;
  97. topPiece.width = cutRight - cutLeft;
  98. pieces.push_back(topPiece);
  99. }
  100. if ((cutRect.y + cutRect.height) > y && (cutRect.y + cutRect.height) < (y + height))
  101. {
  102. Rect2I bottomPiece;
  103. bottomPiece.y = cutRect.y + cutRect.height;
  104. bottomPiece.height = (y + height) - (cutRect.y + cutRect.height);
  105. bottomPiece.x = cutLeft;
  106. bottomPiece.width = cutRight - cutLeft;
  107. pieces.push_back(bottomPiece);
  108. }
  109. }
  110. // No cut
  111. if (initialPieces == (UINT32)pieces.size())
  112. {
  113. if (cutRect.x <= x && (cutRect.x + cutRect.width) >= (x + width) &&
  114. cutRect.y <= y && (cutRect.y + cutRect.height) >= (y + height))
  115. {
  116. // Cut rectangle completely encompasses this one
  117. }
  118. else
  119. pieces.push_back(*this); // Cut rectangle doesn't even touch this one
  120. }
  121. }
  122. void Rect2I::cut(const Vector<Rect2I>& cutRects, Vector<Rect2I>& pieces)
  123. {
  124. Vector<Rect2I> tempPieces[2];
  125. UINT32 bufferIdx = 0;
  126. tempPieces[0].push_back(*this);
  127. for (auto& cutRect : cutRects)
  128. {
  129. UINT32 currentBufferIdx = bufferIdx;
  130. bufferIdx = (bufferIdx + 1) % 2;
  131. tempPieces[bufferIdx].clear();
  132. for (auto& rect : tempPieces[currentBufferIdx])
  133. rect.cut(cutRect, tempPieces[bufferIdx]);
  134. }
  135. pieces = tempPieces[bufferIdx];
  136. }
  137. void Rect2I::transform(const Matrix4& matrix)
  138. {
  139. Vector4 verts[4];
  140. verts[0] = Vector4((float)x, (float)y, 0.0f, 1.0f);
  141. verts[1] = Vector4((float)x + width, (float)y, 0.0f, 1.0f);
  142. verts[2] = Vector4((float)x, (float)y + height, 0.0f, 1.0f);
  143. verts[3] = Vector4((float)x + width, (float)y + height, 0.0f, 1.0f);
  144. for(UINT32 i = 0; i < 4; i++)
  145. verts[i] = matrix.multiply(verts[i]);
  146. float minX = std::numeric_limits<float>::max();
  147. float maxX = std::numeric_limits<float>::min();
  148. float minY = std::numeric_limits<float>::max();
  149. float maxY = std::numeric_limits<float>::min();
  150. for(UINT32 i = 0; i < 4; i++)
  151. {
  152. if(verts[i].x < minX)
  153. minX = verts[i].x;
  154. if(verts[i].y < minY)
  155. minY = verts[i].y;
  156. if(verts[i].x > maxX)
  157. maxX = verts[i].x;
  158. if(verts[i].y > maxY)
  159. maxY = verts[i].y;
  160. }
  161. x = Math::floorToInt(minX);
  162. y = Math::floorToInt(minY);
  163. width = Math::ceilToInt(maxX) - x;
  164. height = Math::ceilToInt(maxY) - y;
  165. }
  166. }