Kiwano Engine v1.3.x
Matrix.hpp
1// Copyright (c) 2016-2018 Kiwano - Nomango
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21#pragma once
22#include <algorithm>
23#include <kiwano/math/Rect.hpp>
24#include <kiwano/math/Vec2.hpp>
25
26namespace kiwano
27{
28namespace math
29{
30template <typename _Ty, typename _Lty, typename _Rty>
31struct MatrixMultiply;
32
33template <typename _Ty>
35{
36 using ValueType = _Ty;
39
40 union
41 {
42 struct
43 {
44 _Ty m[6]; // m[3][2]
45 };
46
47 struct
48 {
49 _Ty _11, _12, _21, _22, _31, _32;
50 };
51 };
52
54 : _11(1.f)
55 , _12(0.f)
56 , _21(0.f)
57 , _22(1.f)
58 , _31(0.f)
59 , _32(0.f)
60 {
61 }
62
63 Matrix3x2T(ValueType _11, ValueType _12, ValueType _21, ValueType _22, ValueType _31, ValueType _32)
64 : _11(_11)
65 , _12(_12)
66 , _21(_21)
67 , _22(_22)
68 , _31(_31)
69 , _32(_32)
70 {
71 }
72
73 explicit Matrix3x2T(const ValueType* p)
74 {
75 for (int i = 0; i < 6; i++)
76 m[i] = p[i];
77 }
78
79 Matrix3x2T(const Matrix3x2T& other)
80 : _11(other._11)
81 , _12(other._12)
82 , _21(other._21)
83 , _22(other._22)
84 , _31(other._31)
85 , _32(other._32)
86 {
87 }
88
89 KGE_SUPPRESS_WARNING_PUSH
90 KGE_SUPPRESS_WARNING(26495) // ignore warning "always initialize member variables"
91
92 template <typename _MTy>
93 Matrix3x2T(const _MTy& other)
94 {
95 for (int i = 0; i < 6; i++)
96 m[i] = other[i];
97 }
98
99 KGE_SUPPRESS_WARNING_POP
100
101 inline ValueType operator[](uint32_t index) const
102 {
103 return m[index];
104 }
105
106 inline ValueType& operator[](uint32_t index)
107 {
108 return m[index];
109 }
110
111 inline Matrix3x2T& operator=(const Matrix3x2T& other)
112 {
113 for (int i = 0; i < 6; i++)
114 m[i] = other[i];
115 return (*this);
116 }
117
118 template <typename _Lty, typename _Rty>
119 inline Matrix3x2T& operator=(const MatrixMultiply<ValueType, _Lty, _Rty>& other)
120 {
121 Matrix3x2T result(other);
122 (*this) = result;
123 return (*this);
124 }
125
126 inline Matrix3x2T& operator*=(const Matrix3x2T& other)
127 {
128 return operator=((*this) * other);
129 }
130
131 inline void Identity()
132 {
133 _11 = 1.f;
134 _12 = 0.f;
135 _21 = 0.f;
136 _22 = 1.f;
137 _31 = 0.f;
138 _32 = 0.f;
139 }
140
141 inline bool IsIdentity() const
142 {
143 return _11 == 1.f && _12 == 0.f && _21 == 0.f && _22 == 1.f && _31 == 0.f && _32 == 0.f;
144 }
145
146 inline Matrix3x2T Invert() const
147 {
148 ValueType det = 1.f / Determinant();
149 return Matrix3x2T(det * _22, -det * _12, -det * _21, det * _11, det * (_21 * _32 - _22 * _31),
150 det * (_12 * _31 - _11 * _32));
151 }
152
153 inline bool IsInvertible() const
154 {
155 return 0 != Determinant();
156 }
157
158 inline ValueType Determinant() const
159 {
160 return (_11 * _22) - (_12 * _21);
161 }
162
163 inline Vec2Type Transform(const Vec2Type& v) const
164 {
165 return Vec2Type(v.x * _11 + v.y * _21 + _31, v.x * _12 + v.y * _22 + _32);
166 }
167
168 RectType Transform(const RectType& rect) const
169 {
170 Vec2Type top_left = Transform(rect.GetLeftTop());
171 Vec2Type top_right = Transform(rect.GetRightTop());
172 Vec2Type bottom_left = Transform(rect.GetLeftBottom());
173 Vec2Type bottom_right = Transform(rect.GetRightBottom());
174
175 ValueType left = std::min(std::min(top_left.x, top_right.x), std::min(bottom_left.x, bottom_right.x));
176 ValueType right = std::max(std::max(top_left.x, top_right.x), std::max(bottom_left.x, bottom_right.x));
177 ValueType top = std::min(std::min(top_left.y, top_right.y), std::min(bottom_left.y, bottom_right.y));
178 ValueType bottom = std::max(std::max(top_left.y, top_right.y), std::max(bottom_left.y, bottom_right.y));
179
180 return RectType{ left, top, right, bottom };
181 }
182
183 inline void Translate(const Vec2Type& v)
184 {
185 _31 += _11 * v.x + _21 * v.y;
186 _32 += _12 * v.x + _22 * v.y;
187 }
188
189 static inline Matrix3x2T Translation(const Vec2Type& v)
190 {
191 return Matrix3x2T(1.f, 0.f, 0.f, 1.f, v.x, v.y);
192 }
193
194 static inline Matrix3x2T Scaling(const Vec2Type& v)
195 {
196 return Matrix3x2T(v.x, 0.f, 0.f, v.y, 0.f, 0.f);
197 }
198
199 static inline Matrix3x2T Scaling(const Vec2Type& v, const Vec2Type& center)
200 {
201 return Matrix3x2T(v.x, 0.f, 0.f, v.y, center.x - v.x * center.x, center.y - v.y * center.y);
202 }
203
204 static inline Matrix3x2T Rotation(ValueType angle)
205 {
206 ValueType s = math::Sin(angle);
207 ValueType c = math::Cos(angle);
208 return Matrix3x2T(c, s, -s, c, 0.f, 0.f);
209 }
210
211 static inline Matrix3x2T Rotation(ValueType angle, const Vec2Type& center)
212 {
213 ValueType s = math::Sin(angle);
214 ValueType c = math::Cos(angle);
215 return Matrix3x2T(c, s, -s, c, center.x * (1 - c) + center.y * s, center.y * (1 - c) - center.x * s);
216 }
217
218 static inline Matrix3x2T SRT(const Vec2Type& trans, const Vec2Type& scale, ValueType angle)
219 {
220 ValueType s = math::Sin(angle);
221 ValueType c = math::Cos(angle);
222 return Matrix3x2T(c * scale.x, s * scale.x, -s * scale.y, c * scale.y, trans.x, trans.y);
223 }
224
225 static inline Matrix3x2T Skewing(const Vec2Type& angle)
226 {
227 ValueType tx = math::Tan(angle.x);
228 ValueType ty = math::Tan(angle.y);
229 return Matrix3x2T(1.f, -ty, -tx, 1.f, 0.f, 0.f);
230 }
231
232 static inline Matrix3x2T Skewing(const Vec2Type& angle, const Vec2Type& center)
233 {
234 ValueType tx = math::Tan(angle.x);
235 ValueType ty = math::Tan(angle.y);
236 return Matrix3x2T(1.f, -ty, -tx, 1.f, center.y * tx, center.x * ty);
237 }
238};
239
240// Use template expression to optimize matrix multiply
241template <typename _Ty, typename _Lty, typename _Rty>
243{
244 const _Lty& lhs;
245 const _Rty& rhs;
246
247 MatrixMultiply(const _Lty& lhs, const _Rty& rhs)
248 : lhs(lhs)
249 , rhs(rhs)
250 {
251 }
252
253 inline _Ty operator[](uint32_t index) const
254 {
255 switch (index)
256 {
257 case 0:
258 return lhs[0] * rhs[0] + lhs[1] * rhs[2];
259 case 1:
260 return lhs[0] * rhs[1] + lhs[1] * rhs[3];
261 case 2:
262 return lhs[2] * rhs[0] + lhs[3] * rhs[2];
263 case 3:
264 return lhs[2] * rhs[1] + lhs[3] * rhs[3];
265 case 4:
266 return lhs[4] * rhs[0] + lhs[5] * rhs[2] + rhs[4];
267 case 5:
268 return lhs[4] * rhs[1] + lhs[5] * rhs[3] + rhs[5];
269 default:
270 return 0.f;
271 }
272 }
273};
274
275template <typename _Ty>
277 const Matrix3x2T<_Ty>& rhs)
278{
280}
281
282template <typename _Ty, typename _Lty, typename _Rty>
283inline MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>
284operator*(const MatrixMultiply<_Ty, _Lty, _Rty>& lhs, const Matrix3x2T<_Ty>& rhs)
285{
286 return MatrixMultiply<_Ty, MatrixMultiply<_Ty, _Lty, _Rty>, Matrix3x2T<_Ty>>(lhs, rhs);
287}
288} // namespace math
289} // namespace kiwano
Definition: Matrix.hpp:35
Definition: Matrix.hpp:243
Definition: Rect.hpp:30