Transform.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #include "Transform.h"
  8. #include <cmath>
  9. namespace facebook {
  10. namespace react {
  11. Transform Transform::Identity() {
  12. return {};
  13. }
  14. Transform Transform::Perspective(Float perspective) {
  15. auto transform = Transform{};
  16. transform.matrix[11] = -1.0 / perspective;
  17. return transform;
  18. }
  19. Transform Transform::Scale(Float factorX, Float factorY, Float factorZ) {
  20. auto transform = Transform{};
  21. transform.matrix[0] = factorX;
  22. transform.matrix[5] = factorY;
  23. transform.matrix[10] = factorZ;
  24. return transform;
  25. }
  26. Transform Transform::Translate(Float x, Float y, Float z) {
  27. auto transform = Transform{};
  28. transform.matrix[12] = x;
  29. transform.matrix[13] = y;
  30. transform.matrix[14] = z;
  31. return transform;
  32. }
  33. Transform Transform::Skew(Float x, Float y) {
  34. auto transform = Transform{};
  35. transform.matrix[4] = std::tan(x);
  36. transform.matrix[1] = std::tan(y);
  37. return transform;
  38. }
  39. Transform Transform::RotateX(Float radians) {
  40. auto transform = Transform{};
  41. transform.matrix[5] = std::cos(radians);
  42. transform.matrix[6] = std::sin(radians);
  43. transform.matrix[9] = -std::sin(radians);
  44. transform.matrix[10] = std::cos(radians);
  45. return transform;
  46. }
  47. Transform Transform::RotateY(Float radians) {
  48. auto transform = Transform{};
  49. transform.matrix[0] = std::cos(radians);
  50. transform.matrix[2] = -std::sin(radians);
  51. transform.matrix[8] = std::sin(radians);
  52. transform.matrix[10] = std::cos(radians);
  53. return transform;
  54. }
  55. Transform Transform::RotateZ(Float radians) {
  56. auto transform = Transform{};
  57. transform.matrix[0] = std::cos(radians);
  58. transform.matrix[1] = std::sin(radians);
  59. transform.matrix[4] = -std::sin(radians);
  60. transform.matrix[5] = std::cos(radians);
  61. return transform;
  62. }
  63. Transform Transform::Rotate(Float x, Float y, Float z) {
  64. auto transform = Transform{};
  65. if (x != 0) {
  66. transform = transform * Transform::RotateX(x);
  67. }
  68. if (y != 0) {
  69. transform = transform * Transform::RotateY(y);
  70. }
  71. if (z != 0) {
  72. transform = transform * Transform::RotateZ(z);
  73. }
  74. return transform;
  75. }
  76. bool Transform::operator==(Transform const &rhs) const {
  77. for (auto i = 0; i < 16; i++) {
  78. if (matrix[i] != rhs.matrix[i]) {
  79. return false;
  80. }
  81. }
  82. return true;
  83. }
  84. bool Transform::operator!=(Transform const &rhs) const {
  85. return !(*this == rhs);
  86. }
  87. Transform Transform::operator*(Transform const &rhs) const {
  88. if (*this == Transform::Identity()) {
  89. return rhs;
  90. }
  91. const auto &lhs = *this;
  92. auto result = Transform{};
  93. auto lhs00 = lhs.matrix[0], lhs01 = lhs.matrix[1], lhs02 = lhs.matrix[2],
  94. lhs03 = lhs.matrix[3], lhs10 = lhs.matrix[4], lhs11 = lhs.matrix[5],
  95. lhs12 = lhs.matrix[6], lhs13 = lhs.matrix[7], lhs20 = lhs.matrix[8],
  96. lhs21 = lhs.matrix[9], lhs22 = lhs.matrix[10], lhs23 = lhs.matrix[11],
  97. lhs30 = lhs.matrix[12], lhs31 = lhs.matrix[13], lhs32 = lhs.matrix[14],
  98. lhs33 = lhs.matrix[15];
  99. auto rhs0 = rhs.matrix[0], rhs1 = rhs.matrix[1], rhs2 = rhs.matrix[2],
  100. rhs3 = rhs.matrix[3];
  101. result.matrix[0] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
  102. result.matrix[1] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
  103. result.matrix[2] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
  104. result.matrix[3] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;
  105. rhs0 = rhs.matrix[4];
  106. rhs1 = rhs.matrix[5];
  107. rhs2 = rhs.matrix[6];
  108. rhs3 = rhs.matrix[7];
  109. result.matrix[4] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
  110. result.matrix[5] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
  111. result.matrix[6] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
  112. result.matrix[7] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;
  113. rhs0 = rhs.matrix[8];
  114. rhs1 = rhs.matrix[9];
  115. rhs2 = rhs.matrix[10];
  116. rhs3 = rhs.matrix[11];
  117. result.matrix[8] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
  118. result.matrix[9] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
  119. result.matrix[10] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
  120. result.matrix[11] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;
  121. rhs0 = rhs.matrix[12];
  122. rhs1 = rhs.matrix[13];
  123. rhs2 = rhs.matrix[14];
  124. rhs3 = rhs.matrix[15];
  125. result.matrix[12] = rhs0 * lhs00 + rhs1 * lhs10 + rhs2 * lhs20 + rhs3 * lhs30;
  126. result.matrix[13] = rhs0 * lhs01 + rhs1 * lhs11 + rhs2 * lhs21 + rhs3 * lhs31;
  127. result.matrix[14] = rhs0 * lhs02 + rhs1 * lhs12 + rhs2 * lhs22 + rhs3 * lhs32;
  128. result.matrix[15] = rhs0 * lhs03 + rhs1 * lhs13 + rhs2 * lhs23 + rhs3 * lhs33;
  129. return result;
  130. }
  131. Float &Transform::at(int i, int j) {
  132. return matrix[(i * 4) + j];
  133. }
  134. Float const &Transform::at(int i, int j) const {
  135. return matrix[(i * 4) + j];
  136. }
  137. Point operator*(Point const &point, Transform const &transform) {
  138. if (transform == Transform::Identity()) {
  139. return point;
  140. }
  141. auto result = transform * Vector{point.x, point.y, 0, 1};
  142. return {result.x, result.y};
  143. }
  144. Rect operator*(Rect const &rect, Transform const &transform) {
  145. auto centre = rect.getCenter();
  146. auto a = Point{rect.origin.x, rect.origin.y} - centre;
  147. auto b = Point{rect.getMaxX(), rect.origin.y} - centre;
  148. auto c = Point{rect.getMaxX(), rect.getMaxY()} - centre;
  149. auto d = Point{rect.origin.x, rect.getMaxY()} - centre;
  150. auto vectorA = transform * Vector{a.x, a.y, 0, 1};
  151. auto vectorB = transform * Vector{b.x, b.y, 0, 1};
  152. auto vectorC = transform * Vector{c.x, c.y, 0, 1};
  153. auto vectorD = transform * Vector{d.x, d.y, 0, 1};
  154. Point transformedA{vectorA.x + centre.x, vectorA.y + centre.y};
  155. Point transformedB{vectorB.x + centre.x, vectorB.y + centre.y};
  156. Point transformedC{vectorC.x + centre.x, vectorC.y + centre.y};
  157. Point transformedD{vectorD.x + centre.x, vectorD.y + centre.y};
  158. return Rect::boundingRect(
  159. transformedA, transformedB, transformedC, transformedD);
  160. }
  161. Vector operator*(Transform const &transform, Vector const &vector) {
  162. return {
  163. vector.x * transform.at(0, 0) + vector.y * transform.at(1, 0) +
  164. vector.z * transform.at(2, 0) + vector.w * transform.at(3, 0),
  165. vector.x * transform.at(0, 1) + vector.y * transform.at(1, 1) +
  166. vector.z * transform.at(2, 1) + vector.w * transform.at(3, 1),
  167. vector.x * transform.at(0, 2) + vector.y * transform.at(1, 2) +
  168. vector.z * transform.at(2, 2) + vector.w * transform.at(3, 2),
  169. vector.x * transform.at(0, 3) + vector.y * transform.at(1, 3) +
  170. vector.z * transform.at(2, 3) + vector.w * transform.at(3, 3),
  171. };
  172. }
  173. Size operator*(Size const &size, Transform const &transform) {
  174. if (transform == Transform::Identity()) {
  175. return size;
  176. }
  177. auto result = Size{};
  178. result.width = transform.at(0, 0) * size.width;
  179. result.height = transform.at(1, 1) * size.height;
  180. return result;
  181. }
  182. } // namespace react
  183. } // namespace facebook