Gamedev Framework (gf)  0.2.0
A C++11 framework for 2D games
Transform.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_TRANSFORM_H
22 #define GF_TRANSFORM_H
23 
24 #include <cmath>
25 
26 #include "Matrix.h"
27 #include "Portability.h"
28 #include "Rect.h"
29 #include "Vector.h"
30 
31 namespace gf {
32 #ifndef DOXYGEN_SHOULD_SKIP_THIS
33 inline namespace v1 {
34 #endif
35 
36  // https://en.wikipedia.org/wiki/Homogeneous_coordinates
37 
38  /**
39  * @ingroup core
40  * @brief Apply an affine transformation to a 2D point.
41  *
42  * @param mat The transformation matrix
43  * @param point The point to transform
44  * @return The transformed point
45  */
46  inline
47  Vector2f transform(const Matrix3f& mat, Vector2f point) {
48  Vector3f homogeneousPoint{point, 1.0f};
49  Vector3f result = mat * homogeneousPoint;
50  return result.xy;
51  }
52 
53  /**
54  * @ingroup core
55  * @brief Apply an affine transformaton to a rectangle
56  *
57  * The resulting rectangle is axis-aligned
58  *
59  * @param mat The transformation matrix
60  * @param rect The rectangle to transform
61  * @return The transformed rectangle
62  */
63  GF_API RectF transform(const Matrix3f& mat, const RectF& rect);
64 
65 
66  /**
67  * @ingroup core
68  * @brief Identity transform
69  *
70  * @return The identity matrix
71  */
72  constexpr Matrix3f identityTransform() {
73  return Matrix3f(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
74  }
75 
76  /**
77  * @ingroup core
78  * @brief Get a translation matrix
79  *
80  * @param offset The offset of the translation
81  * @return A translation by `offset`
82  */
83  inline
84  Matrix3f translation(Vector2f offset) {
85  return Matrix3f{
86  1.0f, 0.0f, offset.x,
87  0.0f, 1.0f, offset.y,
88  0.0f, 0.0f, 1.0f
89  };
90  }
91 
92  /**
93  * @ingroup core
94  * @brief Combine the current transform with a translation
95  *
96  * @param mat The current transform
97  * @param offset The offset of the translation
98  */
99  GF_API void translate(Matrix3f& mat, Vector2f offset);
100 
101  /**
102  * @ingroup core
103  * @brief Get a rotation matrix
104  *
105  * @param angle The angle of the rotation (in radians)
106  * @return A rotation of `angle` radians
107  */
108  inline
109  Matrix3f rotation(float angle) {
110  float cos = std::cos(angle);
111  float sin = std::sin(angle);
112  return Matrix3f{
113  cos, -sin, 0.0f,
114  sin, cos, 0.0f,
115  0.0f, 0.0f, 1.0f
116  };
117  }
118 
119  /**
120  * @ingroup core
121  * @brief Get a rotation matrix
122  *
123  * @param angle The angle of the rotation (in radians)
124  * @param center The center of the rotation
125  * @return A rotation of `angle` radians of origin `center`
126  */
127  inline
128  Matrix3f rotation(float angle, Vector2f center) {
129  float cos = std::cos(angle);
130  float sin = std::sin(angle);
131  return Matrix3f{
132  cos, -sin, center.x * (1 - cos) + center.y * sin,
133  sin, cos, center.y * (1 - cos) - center.x * sin,
134  0.0f, 0.0f, 1.0f
135  };
136  }
137 
138  /**
139  * @ingroup core
140  * @brief Combine the current transform with a rotation
141  *
142  * @param mat The current transform
143  * @param angle The angle of the rotation (in radians)
144  */
145  GF_API void rotate(Matrix3f& mat, float angle);
146 
147  /**
148  * @ingroup core
149  * @brief Combine the current transform with a rotation
150  *
151  * @param mat The current transform
152  * @param angle The angle of the rotation (in radians)
153  * @param center The center of the rotation
154  */
155  GF_API void rotate(Matrix3f& mat, float angle, Vector2f center);
156 
157  /**
158  * @ingroup core
159  * @brief Get a scaling matrix
160  *
161  * @param factor The scaling factor
162  * @return A scaling by `factor`
163  */
164  inline
165  Matrix3f scaling(Vector2f factor) {
166  return Matrix3f{
167  factor.x, 0.0f, 0.0f,
168  0.0f, factor.y, 0.0f,
169  0.0f, 0.0f, 1.0f
170  };
171  }
172 
173  /**
174  * @ingroup core
175  * @brief Get a scaling matrix
176  *
177  * @param factor The scaling factor
178  * @param center The center of the scaling
179  * @return A scaling by `factor` of origin `center`
180  */
181  inline
182  Matrix3f scaling(Vector2f factor, Vector2f center) {
183  return Matrix3f{
184  factor.x, 0.0f, center.x * (1.0f - factor.x),
185  0.0f, factor.y, center.y * (1.0f - factor.y),
186  0.0f, 0.0f, 1.0f
187  };
188  }
189 
190  /**
191  * @ingroup core
192  * @brief Combine the current transform with a scaling
193  *
194  * @param mat The current transform
195  * @param factor The scaling factor
196  */
197  GF_API void scale(Matrix3f& mat, Vector2f factor);
198 
199  /**
200  * @ingroup core
201  * @brief Combine the current transform with a scaling
202  *
203  * @param mat The current transform
204  * @param factor The scaling factor
205  * @param center The center of the scaling
206  */
207  GF_API void scale(Matrix3f& mat, Vector2f factor, Vector2f center);
208 
209 #ifndef DOXYGEN_SHOULD_SKIP_THIS
210 }
211 #endif
212 }
213 
214 #endif // GF_TRANSFORM_H
Vector2f transform(const Matrix3f &mat, Vector2f point)
Apply an affine transformation to a 2D point.
Definition: Transform.h:47
void scale(Matrix3f &mat, Vector2f factor)
Combine the current transform with a scaling.
Matrix3f rotation(float angle, Vector2f center)
Get a rotation matrix.
Definition: Transform.h:128
Matrix3f scaling(Vector2f factor)
Get a scaling matrix.
Definition: Transform.h:165
Vector< T, S1 > operator*(const Matrix< T, S1, S2 > &lhs, const Vector< T, S2 > &rhs)
Matrix-vector multiplication.
Definition: Matrix.h:566
Matrix3f scaling(Vector2f factor, Vector2f center)
Get a scaling matrix.
Definition: Transform.h:182
void scale(Matrix3f &mat, Vector2f factor, Vector2f center)
Combine the current transform with a scaling.
Definition: Action.h:34
Matrix3f rotation(float angle)
Get a rotation matrix.
Definition: Transform.h:109
void rotate(Matrix3f &mat, float angle)
Combine the current transform with a rotation.
Matrix3f translation(Vector2f offset)
Get a translation matrix.
Definition: Transform.h:84
void translate(Matrix3f &mat, Vector2f offset)
Combine the current transform with a translation.
RectF transform(const Matrix3f &mat, const RectF &rect)
Apply an affine transformaton to a rectangle.
constexpr Matrix(T xx, T xy, T xz, T yx, T yy, T yz, T zx, T zy, T zz)
Constructor that takes all the elements.
Definition: Matrix.h:219
constexpr Vector(Vector< T, 2 > xy, T z)
Constructor that takes a 2D vector and a z component.
Definition: Vector.h:606
void rotate(Matrix3f &mat, float angle, Vector2f center)
Combine the current transform with a rotation.
#define GF_API
Definition: Portability.h:35
constexpr Matrix3f identityTransform()
Identity transform.
Definition: Transform.h:72