diff options
Diffstat (limited to 'xbmc/utils/TransformMatrix.h')
| -rw-r--r-- | xbmc/utils/TransformMatrix.h | 246 |
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 | |||
| 25 | class TransformMatrix | ||
| 26 | { | ||
| 27 | public: | ||
| 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 | |||
| 237 | inline 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 | |||
| 243 | inline bool operator!=(const TransformMatrix &a, const TransformMatrix &b) | ||
| 244 | { | ||
| 245 | return !operator==(a, b); | ||
| 246 | } | ||
