説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

olcPGEX_Graphics2D.cpp 7.1KB

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