Merge pull request #4687 from ruuk/textboxgettext
[vuplus_xbmc] / xbmc / guilib / TransformMatrix.h
1 #pragma once
2
3 /*
4  *      Copyright (C) 2005-2013 Team XBMC
5  *      http://xbmc.org
6  *
7  *  This Program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  This Program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with XBMC; see the file COPYING.  If not, see
19  *  <http://www.gnu.org/licenses/>.
20  *
21  */
22
23 #include <math.h>
24 #include <memory>
25 #include <string.h>
26 #include <stdint.h>
27
28 #ifdef __GNUC__
29 // under gcc, inline will only take place if optimizations are applied (-O). this will force inline even whith optimizations.
30 #define XBMC_FORCE_INLINE __attribute__((always_inline))
31 #else
32 #define XBMC_FORCE_INLINE
33 #endif
34
35 typedef uint32_t color_t;
36
37 class TransformMatrix
38 {
39 public:
40   TransformMatrix()
41   {
42     Reset();
43   };
44   void Reset()
45   {
46     m[0][0] = 1.0f; m[0][1] = m[0][2] = m[0][3] = 0.0f;
47     m[1][0] = m[1][2] = m[1][3] = 0.0f; m[1][1] = 1.0f;
48     m[2][0] = m[2][1] = m[2][3] = 0.0f; m[2][2] = 1.0f;
49     alpha = 1.0f;
50     identity = true;
51   };
52   static TransformMatrix CreateTranslation(float transX, float transY, float transZ = 0)
53   {
54     TransformMatrix translation;
55     translation.SetTranslation(transX, transY, transZ);
56     return translation;
57   }
58   void SetTranslation(float transX, float transY, float transZ)
59   {
60     m[0][1] = m[0][2] = 0.0f; m[0][0] = 1.0f; m[0][3] = transX;
61     m[1][0] = m[1][2] = 0.0f; m[1][1] = 1.0f; m[1][3] = transY;
62     m[2][0] = m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = transZ;
63     alpha = 1.0f;
64     identity = (transX == 0 && transY == 0 && transZ == 0);
65   }
66   static TransformMatrix CreateScaler(float scaleX, float scaleY, float scaleZ = 1.0f)
67   {
68     TransformMatrix scaler;
69     scaler.m[0][0] = scaleX;
70     scaler.m[1][1] = scaleY;
71     scaler.m[2][2] = scaleZ;
72     scaler.identity = (scaleX == 1 && scaleY == 1 && scaleZ == 1);
73     return scaler;
74   };
75   void SetScaler(float scaleX, float scaleY, float centerX, float centerY)
76   {
77     // Trans(centerX,centerY,centerZ)*Scale(scaleX,scaleY,scaleZ)*Trans(-centerX,-centerY,-centerZ)
78     float centerZ = 0.0f, scaleZ = 1.0f;
79     m[0][0] = scaleX;  m[0][1] = 0.0f;    m[0][2] = 0.0f;    m[0][3] = centerX*(1-scaleX);
80     m[1][0] = 0.0f;    m[1][1] = scaleY;  m[1][2] = 0.0f;    m[1][3] = centerY*(1-scaleY);
81     m[2][0] = 0.0f;    m[2][1] = 0.0f;    m[2][2] = scaleZ;  m[2][3] = centerZ*(1-scaleZ);
82     alpha = 1.0f;
83     identity = (scaleX == 1 && scaleY == 1);
84   };
85   void SetXRotation(float angle, float y, float z, float ar = 1.0f)
86   { // angle about the X axis, centered at y,z where our coordinate system has aspect ratio ar.
87     // Trans(0,y,z)*Scale(1,1/ar,1)*RotateX(angle)*Scale(ar,1,1)*Trans(0,-y,-z);
88     float c = cos(angle); float s = sin(angle);
89     m[0][0] = ar;    m[0][1] = 0.0f;  m[0][2] = 0.0f;   m[0][3] = 0.0f;
90     m[1][0] = 0.0f;  m[1][1] = c/ar;  m[1][2] = -s/ar;  m[1][3] = (-y*c+s*z)/ar + y;
91     m[2][0] = 0.0f;  m[2][1] = s;     m[2][2] = c;      m[2][3] = (-y*s-c*z) + z;
92     alpha = 1.0f;
93     identity = (angle == 0);
94   }
95   void SetYRotation(float angle, float x, float z, float ar = 1.0f)
96   { // angle about the Y axis, centered at x,z where our coordinate system has aspect ratio ar.
97     // Trans(x,0,z)*Scale(1/ar,1,1)*RotateY(angle)*Scale(ar,1,1)*Trans(-x,0,-z);
98     float c = cos(angle); float s = sin(angle);
99     m[0][0] = c;     m[0][1] = 0.0f;  m[0][2] = -s/ar;  m[0][3] = -x*c + s*z/ar + x;
100     m[1][0] = 0.0f;  m[1][1] = 1.0f;  m[1][2] = 0.0f;   m[1][3] = 0.0f;
101     m[2][0] = ar*s;  m[2][1] = 0.0f;  m[2][2] = c;      m[2][3] = -ar*x*s - c*z + z;
102     alpha = 1.0f;
103     identity = (angle == 0);
104   }
105   static TransformMatrix CreateZRotation(float angle, float x, float y, float ar = 1.0f)
106   { // angle about the Z axis, centered at x,y where our coordinate system has aspect ratio ar.
107     // Trans(x,y,0)*Scale(1/ar,1,1)*RotateZ(angle)*Scale(ar,1,1)*Trans(-x,-y,0)
108     TransformMatrix rot;
109     rot.SetZRotation(angle, x, y, ar);
110     return rot;
111   }
112   void SetZRotation(float angle, float x, float y, float ar = 1.0f)
113   { // angle about the Z axis, centered at x,y where our coordinate system has aspect ratio ar.
114     // Trans(x,y,0)*Scale(1/ar,1,1)*RotateZ(angle)*Scale(ar,1,1)*Trans(-x,-y,0)
115     float c = cos(angle); float s = sin(angle);
116     m[0][0] = c;     m[0][1] = -s/ar;  m[0][2] = 0.0f;  m[0][3] = -x*c + s*y/ar + x;
117     m[1][0] = s*ar;  m[1][1] = c;      m[1][2] = 0.0f;  m[1][3] = -ar*x*s - c*y + y;
118     m[2][0] = 0.0f;  m[2][1] = 0.0f;   m[2][2] = 1.0f;  m[2][3] = 0.0f;
119     alpha = 1.0f;
120     identity = (angle == 0);
121   }
122   static TransformMatrix CreateFader(float a)
123   {
124     TransformMatrix fader;
125     fader.SetFader(a);
126     return fader;
127   }
128   void SetFader(float a)
129   {
130     m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
131     m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
132     m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
133     alpha = a;
134     identity = (a == 1.0f);
135   }
136
137   // multiplication operators
138   const TransformMatrix &operator *=(const TransformMatrix &right)
139   {
140     if (right.identity)
141       return *this;
142     if (identity)
143     {
144       *this = right;
145       return *this;
146     }
147     float t00 = m[0][0] * right.m[0][0] + m[0][1] * right.m[1][0] + m[0][2] * right.m[2][0];
148     float t01 = m[0][0] * right.m[0][1] + m[0][1] * right.m[1][1] + m[0][2] * right.m[2][1];
149     float t02 = m[0][0] * right.m[0][2] + m[0][1] * right.m[1][2] + m[0][2] * right.m[2][2];
150     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];
151     m[0][0] = t00; m[0][1] = t01; m[0][2] = t02;
152     t00 = m[1][0] * right.m[0][0] + m[1][1] * right.m[1][0] + m[1][2] * right.m[2][0];
153     t01 = m[1][0] * right.m[0][1] + m[1][1] * right.m[1][1] + m[1][2] * right.m[2][1];
154     t02 = m[1][0] * right.m[0][2] + m[1][1] * right.m[1][2] + m[1][2] * right.m[2][2];
155     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];
156     m[1][0] = t00; m[1][1] = t01; m[1][2] = t02;
157     t00 = m[2][0] * right.m[0][0] + m[2][1] * right.m[1][0] + m[2][2] * right.m[2][0];
158     t01 = m[2][0] * right.m[0][1] + m[2][1] * right.m[1][1] + m[2][2] * right.m[2][1];
159     t02 = m[2][0] * right.m[0][2] + m[2][1] * right.m[1][2] + m[2][2] * right.m[2][2];
160     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];
161     m[2][0] = t00; m[2][1] = t01; m[2][2] = t02;
162     alpha *= right.alpha;
163     identity = false;
164     return *this;
165   }
166
167   TransformMatrix operator *(const TransformMatrix &right) const
168   {
169     if (right.identity)
170       return *this;
171     if (identity)
172       return right;
173     TransformMatrix result;
174     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];
175     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];
176     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];
177     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];
178     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];
179     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];
180     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];
181     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];
182     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];
183     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];
184     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];
185     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];
186     result.alpha = alpha * right.alpha;
187     result.identity = false;
188     return result;
189   }
190
191   inline void TransformPosition(float &x, float &y, float &z) const XBMC_FORCE_INLINE
192   {
193     float newX = m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3];
194     float newY = m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3];
195     z = m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3];
196     y = newY;
197     x = newX;
198   }
199
200   inline void TransformPositionUnscaled(float &x, float &y, float &z) const XBMC_FORCE_INLINE
201   {
202     float n;
203     // calculate the norm of the transformed (but not translated) vectors involved
204     n = sqrt(m[0][0]*m[0][0] + m[0][1]*m[0][1] + m[0][2]*m[0][2]);
205     float newX = (m[0][0] * x + m[0][1] * y + m[0][2] * z)/n + m[0][3];
206     n = sqrt(m[1][0]*m[1][0] + m[1][1]*m[1][1] + m[1][2]*m[1][2]);
207     float newY = (m[1][0] * x + m[1][1] * y + m[1][2] * z)/n + m[1][3];
208     n = sqrt(m[2][0]*m[2][0] + m[2][1]*m[2][1] + m[2][2]*m[2][2]);
209     float newZ = (m[2][0] * x + m[2][1] * y + m[2][2] * z)/n + m[2][3];
210     z = newZ;
211     y = newY;
212     x = newX;
213   }
214
215   inline void InverseTransformPosition(float &x, float &y) const XBMC_FORCE_INLINE
216   { // used for mouse - no way to find z
217     x -= m[0][3]; y -= m[1][3];
218     float detM = m[0][0]*m[1][1] - m[0][1]*m[1][0];
219     float newX = (m[1][1] * x - m[0][1] * y)/detM;
220     y = (-m[1][0] * x + m[0][0] * y)/detM;
221     x = newX;
222   }
223
224   inline float TransformXCoord(float x, float y, float z) const XBMC_FORCE_INLINE
225   {
226     return m[0][0] * x + m[0][1] * y + m[0][2] * z + m[0][3];
227   }
228
229   inline float TransformYCoord(float x, float y, float z) const XBMC_FORCE_INLINE
230   {
231     return m[1][0] * x + m[1][1] * y + m[1][2] * z + m[1][3];
232   }
233
234   inline float TransformZCoord(float x, float y, float z) const XBMC_FORCE_INLINE
235   {
236     return m[2][0] * x + m[2][1] * y + m[2][2] * z + m[2][3];
237   }
238
239   inline color_t TransformAlpha(color_t colour) const XBMC_FORCE_INLINE
240   {
241     return (color_t)(colour * alpha);
242   }
243
244   float m[3][4];
245   float alpha;
246   bool identity;
247 };