Ei kuvausta
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

olcPGEX_Graphics2D.cpp 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include "olcPGEX_Graphics2D.h"
  2. namespace olc
  3. {
  4. void GFX2D::DrawSprite(olc::Sprite *sprite, olc::GFX2D::Transform2D &transform, bool centered)
  5. {
  6. if (sprite == nullptr)
  7. return;
  8. // Work out bounding rectangle of sprite
  9. float ex=-1, ey=-1;
  10. float sx, sy;
  11. float px, py;
  12. float x0 = 0;
  13. float y0 = 0;
  14. if (centered)
  15. {
  16. x0 += sprite->width / 2;
  17. y0 += sprite->height / 2;
  18. }
  19. transform.Forward(-x0, -y0, sx, sy);
  20. px = sx; py = sy;
  21. sx = std::min(sx, px); sy = std::min(sy, py);
  22. ex = std::max(ex, px); ey = std::max(ey, py);
  23. transform.Forward((float)sprite->width-x0, (float)sprite->height-y0, px, py);
  24. sx = std::min(sx, px); sy = std::min(sy, py);
  25. ex = std::max(ex, px); ey = std::max(ey, py);
  26. transform.Forward(-x0, (float)sprite->height-y0, px, py);
  27. sx = std::min(sx, px); sy = std::min(sy, py);
  28. ex = std::max(ex, px); ey = std::max(ey, py);
  29. transform.Forward((float)sprite->width-x0, -y0, px, py);
  30. sx = std::min(sx, px); sy = std::min(sy, py);
  31. ex = std::max(ex, px); ey = std::max(ey, py);
  32. // Perform inversion of transform if required
  33. transform.Invert();
  34. if (ex < sx)
  35. std::swap(ex, sx);
  36. if (ey < sy)
  37. std::swap(ey, sy);
  38. // Iterate through render space, and sample Sprite from suitable texel location
  39. for (float i = sx; i < ex; i++)
  40. {
  41. for (float j = sy; j < ey; j++)
  42. {
  43. float ox, oy;
  44. transform.Backward(i, j, ox, oy);
  45. pge->Draw((int32_t)i, (int32_t)j, sprite->GetPixel((int32_t)(x0+ox+0.5f), (int32_t)(y0+oy+0.5f)));
  46. }
  47. }
  48. }
  49. void GFX2D::DrawPartialSprite(olc::Sprite *sprite, int32_t x0, int32_t y0, int32_t w, int32_t h, olc::GFX2D::Transform2D &transform, bool centered)
  50. {
  51. if (sprite == nullptr)
  52. return;
  53. // Work out bounding rectangle of sprite
  54. float ex=-1, ey=-1;
  55. float sx, sy;
  56. float px, py;
  57. float xOff = 0;
  58. float yOff = 0;
  59. if (centered)
  60. {
  61. xOff += w / 2;
  62. yOff += h / 2;
  63. }
  64. transform.Forward(-xOff, -yOff, sx, sy);
  65. px = sx; py = sy;
  66. sx = std::min(sx, px); sy = std::min(sy, py);
  67. ex = std::max(ex, px); ey = std::max(ey, py);
  68. transform.Forward((float)w-xOff, (float)h-yOff, px, py);
  69. sx = std::min(sx, px); sy = std::min(sy, py);
  70. ex = std::max(ex, px); ey = std::max(ey, py);
  71. transform.Forward(-xOff, (float)h-yOff, px, py);
  72. sx = std::min(sx, px); sy = std::min(sy, py);
  73. ex = std::max(ex, px); ey = std::max(ey, py);
  74. transform.Forward((float)w-xOff, -yOff, px, py);
  75. sx = std::min(sx, px); sy = std::min(sy, py);
  76. ex = std::max(ex, px); ey = std::max(ey, py);
  77. // Perform inversion of transform if required
  78. transform.Invert();
  79. if (ex < sx)
  80. std::swap(ex, sx);
  81. if (ey < sy)
  82. std::swap(ey, sy);
  83. // Iterate through render space, and sample Sprite from suitable texel location
  84. for (float i = sx; i < ex; i++)
  85. {
  86. for (float j = sy; j < ey; j++)
  87. {
  88. float ox, oy;
  89. transform.Backward(i, j, ox, oy);
  90. int32_t xx = (int32_t)(xOff+x0+ox+0.5f);
  91. int32_t yy = (int32_t)(yOff+y0+oy+0.5f);
  92. if (xx >= x0 && xx < x0 + w && yy >= y0 && yy < y0 + h)
  93. pge->Draw((int32_t)i, (int32_t)j, sprite->GetPixel(xx, yy));
  94. }
  95. }
  96. }
  97. olc::GFX2D::Transform2D::Transform2D()
  98. {
  99. Reset();
  100. }
  101. void olc::GFX2D::Transform2D::Reset()
  102. {
  103. nTargetMatrix = 0;
  104. nSourceMatrix = 1;
  105. bDirty = true;
  106. // Columns Then Rows
  107. // Matrices 0 & 1 are used as swaps in Transform accumulation
  108. matrix[0][0][0] = 1.0f; matrix[0][1][0] = 0.0f; matrix[0][2][0] = 0.0f;
  109. matrix[0][0][1] = 0.0f; matrix[0][1][1] = 1.0f; matrix[0][2][1] = 0.0f;
  110. matrix[0][0][2] = 0.0f; matrix[0][1][2] = 0.0f; matrix[0][2][2] = 1.0f;
  111. matrix[1][0][0] = 1.0f; matrix[1][1][0] = 0.0f; matrix[1][2][0] = 0.0f;
  112. matrix[1][0][1] = 0.0f; matrix[1][1][1] = 1.0f; matrix[1][2][1] = 0.0f;
  113. matrix[1][0][2] = 0.0f; matrix[1][1][2] = 0.0f; matrix[1][2][2] = 1.0f;
  114. // Matrix 2 is a cache matrix to hold the immediate transform operation
  115. // Matrix 3 is a cache matrix to hold the inverted transform
  116. }
  117. void olc::GFX2D::Transform2D::Multiply()
  118. {
  119. for (int c = 0; c < 3; c++)
  120. {
  121. for (int r = 0; r < 3; r++)
  122. {
  123. matrix[nTargetMatrix][c][r] = matrix[2][0][r] * matrix[nSourceMatrix][c][0] +
  124. matrix[2][1][r] * matrix[nSourceMatrix][c][1] +
  125. matrix[2][2][r] * matrix[nSourceMatrix][c][2];
  126. }
  127. }
  128. std::swap(nTargetMatrix, nSourceMatrix);
  129. bDirty = true; // Any transform multiply dirties the inversion
  130. }
  131. void olc::GFX2D::Transform2D::Rotate(float fTheta)
  132. {
  133. // Construct Rotation Matrix
  134. matrix[2][0][0] = cosf(fTheta); matrix[2][1][0] = sinf(fTheta); matrix[2][2][0] = 0.0f;
  135. matrix[2][0][1] = -sinf(fTheta); matrix[2][1][1] = cosf(fTheta); matrix[2][2][1] = 0.0f;
  136. matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
  137. Multiply();
  138. }
  139. void olc::GFX2D::Transform2D::Scale(float sx, float sy)
  140. {
  141. // Construct Scale Matrix
  142. matrix[2][0][0] = sx; matrix[2][1][0] = 0.0f; matrix[2][2][0] = 0.0f;
  143. matrix[2][0][1] = 0.0f; matrix[2][1][1] = sy; matrix[2][2][1] = 0.0f;
  144. matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
  145. Multiply();
  146. }
  147. void olc::GFX2D::Transform2D::Shear(float sx, float sy)
  148. {
  149. // Construct Shear Matrix
  150. matrix[2][0][0] = 1.0f; matrix[2][1][0] = sx; matrix[2][2][0] = 0.0f;
  151. matrix[2][0][1] = sy; matrix[2][1][1] = 1.0f; matrix[2][2][1] = 0.0f;
  152. matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
  153. Multiply();
  154. }
  155. void olc::GFX2D::Transform2D::Translate(float ox, float oy)
  156. {
  157. // Construct Translate Matrix
  158. matrix[2][0][0] = 1.0f; matrix[2][1][0] = 0.0f; matrix[2][2][0] = ox;
  159. matrix[2][0][1] = 0.0f; matrix[2][1][1] = 1.0f; matrix[2][2][1] = oy;
  160. matrix[2][0][2] = 0.0f; matrix[2][1][2] = 0.0f; matrix[2][2][2] = 1.0f;
  161. Multiply();
  162. }
  163. void olc::GFX2D::Transform2D::Perspective(float ox, float oy)
  164. {
  165. // Construct Translate Matrix
  166. matrix[2][0][0] = 1.0f; matrix[2][1][0] = 0.0f; matrix[2][2][0] = 0.0f;
  167. matrix[2][0][1] = 0.0f; matrix[2][1][1] = 1.0f; matrix[2][2][1] = 0.0f;
  168. matrix[2][0][2] = ox; matrix[2][1][2] = oy; matrix[2][2][2] = 1.0f;
  169. Multiply();
  170. }
  171. void olc::GFX2D::Transform2D::Forward(float in_x, float in_y, float &out_x, float &out_y)
  172. {
  173. out_x = in_x * matrix[nSourceMatrix][0][0] + in_y * matrix[nSourceMatrix][1][0] + matrix[nSourceMatrix][2][0];
  174. out_y = in_x * matrix[nSourceMatrix][0][1] + in_y * matrix[nSourceMatrix][1][1] + matrix[nSourceMatrix][2][1];
  175. float out_z = in_x * matrix[nSourceMatrix][0][2] + in_y * matrix[nSourceMatrix][1][2] + matrix[nSourceMatrix][2][2];
  176. if (out_z != 0)
  177. {
  178. out_x /= out_z;
  179. out_y /= out_z;
  180. }
  181. }
  182. void olc::GFX2D::Transform2D::Backward(float in_x, float in_y, float &out_x, float &out_y)
  183. {
  184. out_x = in_x * matrix[3][0][0] + in_y * matrix[3][1][0] + matrix[3][2][0];
  185. out_y = in_x * matrix[3][0][1] + in_y * matrix[3][1][1] + matrix[3][2][1];
  186. float out_z = in_x * matrix[3][0][2] + in_y * matrix[3][1][2] + matrix[3][2][2];
  187. if (out_z != 0)
  188. {
  189. out_x /= out_z;
  190. out_y /= out_z;
  191. }
  192. }
  193. void olc::GFX2D::Transform2D::Invert()
  194. {
  195. if (bDirty) // Obviously costly so only do if needed
  196. {
  197. float det = matrix[nSourceMatrix][0][0] * (matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][1][2] * matrix[nSourceMatrix][2][1]) -
  198. matrix[nSourceMatrix][1][0] * (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][2][1] * matrix[nSourceMatrix][0][2]) +
  199. matrix[nSourceMatrix][2][0] * (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][0][2]);
  200. float idet = 1.0f / det;
  201. matrix[3][0][0] = (matrix[nSourceMatrix][1][1] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][1][2] * matrix[nSourceMatrix][2][1]) * idet;
  202. matrix[3][1][0] = (matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][1][0] * matrix[nSourceMatrix][2][2]) * idet;
  203. matrix[3][2][0] = (matrix[nSourceMatrix][1][0] * matrix[nSourceMatrix][2][1] - matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][1][1]) * idet;
  204. matrix[3][0][1] = (matrix[nSourceMatrix][2][1] * matrix[nSourceMatrix][0][2] - matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][2]) * idet;
  205. matrix[3][1][1] = (matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][2][2] - matrix[nSourceMatrix][2][0] * matrix[nSourceMatrix][0][2]) * idet;
  206. matrix[3][2][1] = (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][2][0] - matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][2][1]) * idet;
  207. matrix[3][0][2] = (matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][2] - matrix[nSourceMatrix][0][2] * matrix[nSourceMatrix][1][1]) * idet;
  208. matrix[3][1][2] = (matrix[nSourceMatrix][0][2] * matrix[nSourceMatrix][1][0] - matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][1][2]) * idet;
  209. matrix[3][2][2] = (matrix[nSourceMatrix][0][0] * matrix[nSourceMatrix][1][1] - matrix[nSourceMatrix][0][1] * matrix[nSourceMatrix][1][0]) * idet;
  210. bDirty = false;
  211. }
  212. }
  213. }