summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/TransformMatrix.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/utils/TransformMatrix.h')
-rw-r--r--xbmc/utils/TransformMatrix.h246
1 files changed, 246 insertions, 0 deletions
diff --git a/xbmc/utils/TransformMatrix.h b/xbmc/utils/TransformMatrix.h
new file mode 100644
index 0000000..34c2092
--- /dev/null
+++ b/xbmc/utils/TransformMatrix.h
@@ -0,0 +1,246 @@
1/*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#include "utils/Color.h"
12
13#include <algorithm>
14#include <math.h>
15#include <memory>
16#include <string.h>
17
18#ifdef __GNUC__
19// under gcc, inline will only take place if optimizations are applied (-O). this will force inline even with optimizations.
20#define XBMC_FORCE_INLINE __attribute__((always_inline))
21#else
22#define XBMC_FORCE_INLINE
23#endif
24
25class TransformMatrix
26{
27public:
28 TransformMatrix()
29 {
30 Reset();
31 };
32 void Reset()
33 {
34 m[0][0] = 1.0f; m[0][1] = m[0][2] = m[0][3] = 0.0f;
35 m[1][0] = m[1][2] = m[1][3] = 0.0f; m[1][1] = 1.0f;
36 m[2][0] = m[2][1] = m[2][3] = 0.0f; m[2][2] = 1.0f;
37 alpha = 1.0f;
38 identity = true;
39 };
40 static TransformMatrix CreateTranslation(float transX, float transY, float transZ = 0)
41 {
42 TransformMatrix translation;
43 translation.SetTranslation(transX, transY, transZ);
44 return translation;
45 }
46 void SetTranslation(float transX, float transY, float transZ)
47 {
48 m[0][1] = m[0][2] = 0.0f; m[0][0] = 1.0f; m[0][3] = transX;
49 m[1][0] = m[1][2] = 0.0f; m[1][1] = 1.0f; m[1][3] = transY;
50 m[2][0] = m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = transZ;
51 alpha = 1.0f;
52 identity = (transX == 0 && transY == 0 && transZ == 0);
53 }
54 static TransformMatrix CreateScaler(float scaleX, float scaleY, float scaleZ = 1.0f)
55 {
56 TransformMatrix scaler;
57 scaler.m[0][0] = scaleX;
58 scaler.m[1][1] = scaleY;
59 scaler.m[2][2] = scaleZ;
60 scaler.identity = (scaleX == 1 && scaleY == 1 && scaleZ == 1);
61 return scaler;
62 };
63 void SetScaler(float scaleX, float scaleY, float centerX, float centerY)
64 {
65 // Trans(centerX,centerY,centerZ)*Scale(scaleX,scaleY,scaleZ)*Trans(-centerX,-centerY,-centerZ)
66 float centerZ = 0.0f, scaleZ = 1.0f;
67 m[0][0] = scaleX; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = centerX*(1-scaleX);
68 m[1][0] = 0.0f; m[1][1] = scaleY; m[1][2] = 0.0f; m[1][3] = centerY*(1-scaleY);
69 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = scaleZ; m[2][3] = centerZ*(1-scaleZ);
70 alpha = 1.0f;
71 identity = (scaleX == 1 && scaleY == 1);
72 };
73 void SetXRotation(float angle, float y, float z, float ar = 1.0f)
74 { // angle about the X axis, centered at y,z where our coordinate system has aspect ratio ar.
75 // Trans(0,y,z)*Scale(1,1/ar,1)*RotateX(angle)*Scale(ar,1,1)*Trans(0,-y,-z);
76 float c = cos(angle); float s = sin(angle);
77 m[0][0] = ar; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
78 m[1][0] = 0.0f; m[1][1] = c/ar; m[1][2] = -s/ar; m[1][3] = (-y*c+s*z)/ar + y;
79 m[2][0] = 0.0f; m[2][1] = s; m[2][2] = c; m[2][3] = (-y*s-c*z) + z;
80 alpha = 1.0f;
81 identity = (angle == 0);
82 }
83 void SetYRotation(float angle, float x, float z, float ar = 1.0f)
84 { // angle about the Y axis, centered at x,z where our coordinate system has aspect ratio ar.
85 // Trans(x,0,z)*Scale(1/ar,1,1)*RotateY(angle)*Scale(ar,1,1)*Trans(-x,0,-z);
86 float c = cos(angle); float s = sin(angle);
87 m[0][0] = c; m[0][1] = 0.0f; m[0][2] = -s/ar; m[0][3] = -x*c + s*z/ar + x;
88 m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
89 m[2][0] = ar*s; m[2][1] = 0.0f; m[2][2] = c; m[2][3] = -ar*x*s - c*z + z;
90 alpha = 1.0f;
91 identity = (angle == 0);
92 }
93 static TransformMatrix CreateZRotation(float angle, float x, float y, float ar = 1.0f)
94 { // angle about the Z axis, centered at x,y where our coordinate system has aspect ratio ar.
95 // Trans(x,y,0)*Scale(1/ar,1,1)*RotateZ(angle)*Scale(ar,1,1)*Trans(-x,-y,0)
96 TransformMatrix rot;
97 rot.SetZRotation(angle, x, y, ar);
98 return rot;
99 }
100 void SetZRotation(float angle, float x, float y, float ar = 1.0f)
101 { // angle about the Z axis, centered at x,y where our coordinate system has aspect ratio ar.
102 // Trans(x,y,0)*Scale(1/ar,1,1)*RotateZ(angle)*Scale(ar,1,1)*Trans(-x,-y,0)
103 float c = cos(angle); float s = sin(angle);
104 m[0][0] = c; m[0][1] = -s/ar; m[0][2] = 0.0f; m[0][3] = -x*c + s*y/ar + x;
105 m[1][0] = s*ar; m[1][1] = c; m[1][2] = 0.0f; m[1][3] = -ar*x*s - c*y + y;
106 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
107 alpha = 1.0f;
108 identity = (angle == 0);
109 }
110 static TransformMatrix CreateFader(float a)
111 {
112 TransformMatrix fader;
113 fader.SetFader(a);
114 return fader;
115 }
116 void SetFader(float a)
117 {
118 m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
119 m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
120 m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
121 alpha = a;
122 identity = (a == 1.0f);
123 }
124
125 // multiplication operators
126 const TransformMatrix &operator *=(const TransformMatrix &right)
127 {
128 if (right.identity)
129 return *this;
130 if (identity)
131 {
132 *this = right;
133 return *this;
134 }
135 float t00 = m[0][0] * right.m[0][0] + m[0][1] * right.m[1][0] + m[0][2] * right.m[2][0];
136 float t01 = m[0][0] * right.m[0][1] + m[0][1] * right.m[1][1] + m[0][2] * right.m[2][1];
137 float t02 = m[0][0] * right.m[0][2] + m[0][1] * right.m[1][2] + m[0][2] * right.m[2][2];
138 m[0][3] = m[0][0] * right.m[0][3] + m[0][1] * right.m[1][3] + m[0][2] * right.m[2][3] + m[0][3];
139 m[0][0] = t00; m[0][1] = t01; m[0][2] = t02;
140 t00 = m[1][0] * right.m[0][0] + m[1][1] * right.m[1][0] + m[1][2] * right.m[2][0];
141 t01 = m[1][0] * right.m[0][1] + m[1][1] * right.m[1][1] + m[1][2] * right.m[2][1];
142 t02 = m[1][0] * right.m[0][2] + m[1][1] * right.m[1][2] + m[1][2] * right.m[2][2];
143 m[1][3] = m[1][0] * right.m[0][3] + m[1][1] * right.m[1][3] + m[1][2] * right.m[2][3] + m[1][3];
144 m[1][0] = t00; m[1][1] = t01; m[1][2] = t02;
145 t00 = m[2][0] * right.m[0][0] + m[2][1] * right.m[1][0] + m[2][2] * right.m[2][0];
146 t01 = m[2][0] * right.m[0][1] + m[2][1] * right.m[1][1] + m[2][2] * right.m[2][1];
147 t02 = m[2][0] * right.m[0][2] + m[2][1] * right.m[1][2] + m[2][2] * right.m[2][2];
148 m[2][3] = m[2][0] * right.m[0][3] + m[2][1] * right.m[1][3] + m[2][2] * right.m[2][3] + m[2][3];
149 m[2][0] = t00; m[2][1] = t01; m[2][2] = t02;
150 alpha *= right.alpha;
151 identity = false;
152 return *this;
153 }
154
155 TransformMatrix operator *(const TransformMatrix &right) const
156 {
157 if (right.identity)
158 return *this;
159 if (identity)
160 return right;
161 TransformMatrix result;
162 result.m[0][0] = m[0][0] * right.m[0][0] + m[0][1] * right.m[1][0] + m[0][2] * right.m[2][0];
163 result.m[0][1] = m[0][0] * right.m[0][1] + m[0][1] * right.m[1][1] + m[0][2] * right.m[2][1];
164 result.m[0][2] = m[0][0] * right.m[0][2] + m[0][1] * right.m[1][2] + m[0][2] * right.m[2][2];
165 result.m[0][3] = m[0][0] * right.m[0][3] + m[0][1] * right.m[1][3] + m[0][2] * right.m[2][3] + m[0][3];
166 result.m[1][0] = m[1][0] * right.m[0][0] + m[1][1] * right.m[1][0] + m[1][2] * right.m[2][0];
167 result.m[1][1] = m[1][0] * right.m[0][1] + m[1][1] * right.m[1][1] + m[1][2] * right.m[2][1];
168 result.m[1][2] = m[1][0] * right.m[0][2] + m[1][1] * right.m[1][2] + m[1][2] * right.m[2][2];
169 result.m[1][3] = m[1][0] * right.m[0][3] + m[1][1] * right.m[1][3] + m[1][2] * right.m[2][3] + m[1][3];
170 result.m[2][0] = m[2][0] * right.m[0][0] + m[2][1] * right.m[1][0] + m[2][2] * right.m[2][0];
171 result.m[2][1] = m[2][0] * right.m[0][1] + m[2][1] * right.m[1][1] + m[2][2] * right.m[2][1];
172 result.m[2][2] = m[2][0] * right.m[0][2] + m[2][1] * right.m[1][2] + m[2][2] * right.m[2][2];
173 result.m[2][3] = m[2][0] * right.m[0][3] + m[2][1] * right.m[1][3] + m[2][2] * right.m[2][3] + m[2][3];
174 result.alpha = alpha * right.alpha;
175 result.identity = false;
176 return result;
177 }
178
179 inline void TransformPosition(float &x, float &y, float &z) const XBMC_FORCE_INLINE
180 {
181 float newX = m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3];
182 float newY = m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3];
183 z = m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3];
184 y = newY;
185 x = newX;
186 }
187
188 inline void TransformPositionUnscaled(float &x, float &y, float &z) const XBMC_FORCE_INLINE
189 {
190 float n;
191 // calculate the norm of the transformed (but not translated) vectors involved
192 n = sqrt(m[0][0]*m[0][0] + m[0][1]*m[0][1] + m[0][2]*m[0][2]);
193 float newX = (m[0][0] * x + m[0][1] * y + m[0][2] * z)/n + m[0][3];
194 n = sqrt(m[1][0]*m[1][0] + m[1][1]*m[1][1] + m[1][2]*m[1][2]);
195 float newY = (m[1][0] * x + m[1][1] * y + m[1][2] * z)/n + m[1][3];
196 n = sqrt(m[2][0]*m[2][0] + m[2][1]*m[2][1] + m[2][2]*m[2][2]);
197 float newZ = (m[2][0] * x + m[2][1] * y + m[2][2] * z)/n + m[2][3];
198 z = newZ;
199 y = newY;
200 x = newX;
201 }
202
203 inline void InverseTransformPosition(float &x, float &y) const XBMC_FORCE_INLINE
204 { // used for mouse - no way to find z
205 x -= m[0][3]; y -= m[1][3];
206 float detM = m[0][0]*m[1][1] - m[0][1]*m[1][0];
207 float newX = (m[1][1] * x - m[0][1] * y)/detM;
208 y = (-m[1][0] * x + m[0][0] * y)/detM;
209 x = newX;
210 }
211
212 inline float TransformXCoord(float x, float y, float z) const XBMC_FORCE_INLINE
213 {
214 return m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3];
215 }
216
217 inline float TransformYCoord(float x, float y, float z) const XBMC_FORCE_INLINE
218 {
219 return m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3];
220 }
221
222 inline float TransformZCoord(float x, float y, float z) const XBMC_FORCE_INLINE
223 {
224 return m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3];
225 }
226
227 inline UTILS::Color TransformAlpha(UTILS::Color color) const XBMC_FORCE_INLINE
228 {
229 return static_cast<UTILS::Color>(color * alpha);
230 }
231
232 float m[3][4];
233 float alpha;
234 bool identity;
235};
236
237inline bool operator==(const TransformMatrix &a, const TransformMatrix &b)
238{
239 return a.alpha == b.alpha && ((a.identity && b.identity) ||
240 (!a.identity && !b.identity && std::equal(&a.m[0][0], &a.m[0][0] + sizeof (a.m) / sizeof (a.m[0][0]), &b.m[0][0])));
241}
242
243inline bool operator!=(const TransformMatrix &a, const TransformMatrix &b)
244{
245 return !operator==(a, b);
246}