1 /* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef UI_MAT4_H 18 #define UI_MAT4_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 23 #include <ui/vec4.h> 24 #include <utils/String8.h> 25 26 #define TMAT_IMPLEMENTATION 27 #include <ui/TMatHelpers.h> 28 29 #define PURE __attribute__((pure)) 30 31 namespace android { 32 // ------------------------------------------------------------------------------------- 33 34 template <typename T> 35 class tmat44 : public TVecUnaryOperators<tmat44, T>, 36 public TVecComparisonOperators<tmat44, T>, 37 public TVecAddOperators<tmat44, T>, 38 public TMatProductOperators<tmat44, T>, 39 public TMatSquareFunctions<tmat44, T>, 40 public TMatDebug<tmat44, T> 41 { 42 public: 43 enum no_init { NO_INIT }; 44 typedef T value_type; 45 typedef T& reference; 46 typedef T const& const_reference; 47 typedef size_t size_type; 48 typedef tvec4<T> col_type; 49 typedef tvec4<T> row_type; 50 51 // size of a column (i.e.: number of rows) 52 enum { COL_SIZE = col_type::SIZE }; 53 static inline size_t col_size() { return COL_SIZE; } 54 55 // size of a row (i.e.: number of columns) 56 enum { ROW_SIZE = row_type::SIZE }; 57 static inline size_t row_size() { return ROW_SIZE; } 58 static inline size_t size() { return row_size(); } // for TVec*<> 59 60 private: 61 62 /* 63 * <-- N columns --> 64 * 65 * a00 a10 a20 ... aN0 ^ 66 * a01 a11 a21 ... aN1 | 67 * a02 a12 a22 ... aN2 M rows 68 * ... | 69 * a0M a1M a2M ... aNM v 70 * 71 * COL_SIZE = M 72 * ROW_SIZE = N 73 * m[0] = [a00 a01 a02 ... a01M] 74 */ 75 76 col_type mValue[ROW_SIZE]; 77 78 public: 79 // array access 80 inline col_type const& operator [] (size_t i) const { return mValue[i]; } 81 inline col_type& operator [] (size_t i) { return mValue[i]; } 82 83 T const* asArray() const { return &mValue[0][0]; } 84 85 // ----------------------------------------------------------------------- 86 // we don't provide copy-ctor and operator= on purpose 87 // because we want the compiler generated versions 88 89 /* 90 * constructors 91 */ 92 93 // leaves object uninitialized. use with caution. 94 explicit tmat44(no_init) { } 95 96 // initialize to identity 97 tmat44(); 98 99 // initialize to Identity*scalar. 100 template<typename U> 101 explicit tmat44(U v); 102 103 // sets the diagonal to the passed vector 104 template <typename U> 105 explicit tmat44(const tvec4<U>& rhs); 106 107 // construct from another matrix of the same size 108 template <typename U> 109 explicit tmat44(const tmat44<U>& rhs); 110 111 // construct from 4 column vectors 112 template <typename A, typename B, typename C, typename D> 113 tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3); 114 115 // construct from 16 scalars 116 template < 117 typename A, typename B, typename C, typename D, 118 typename E, typename F, typename G, typename H, 119 typename I, typename J, typename K, typename L, 120 typename M, typename N, typename O, typename P> 121 tmat44( A m00, B m01, C m02, D m03, 122 E m10, F m11, G m12, H m13, 123 I m20, J m21, K m22, L m23, 124 M m30, N m31, O m32, P m33); 125 126 // construct from a C array 127 template <typename U> 128 explicit tmat44(U const* rawArray); 129 130 /* 131 * helpers 132 */ 133 134 static tmat44 ortho(T left, T right, T bottom, T top, T near, T far); 135 136 static tmat44 frustum(T left, T right, T bottom, T top, T near, T far); 137 138 template <typename A, typename B, typename C> 139 static tmat44 lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up); 140 141 template <typename A> 142 static tmat44 translate(const tvec4<A>& t); 143 144 template <typename A> 145 static tmat44 scale(const tvec4<A>& s); 146 147 template <typename A, typename B> 148 static tmat44 rotate(A radian, const tvec3<B>& about); 149 }; 150 151 // ---------------------------------------------------------------------------------------- 152 // Constructors 153 // ---------------------------------------------------------------------------------------- 154 155 /* 156 * Since the matrix code could become pretty big quickly, we don't inline most 157 * operations. 158 */ 159 160 template <typename T> 161 tmat44<T>::tmat44() { 162 mValue[0] = col_type(1,0,0,0); 163 mValue[1] = col_type(0,1,0,0); 164 mValue[2] = col_type(0,0,1,0); 165 mValue[3] = col_type(0,0,0,1); 166 } 167 168 template <typename T> 169 template <typename U> 170 tmat44<T>::tmat44(U v) { 171 mValue[0] = col_type(v,0,0,0); 172 mValue[1] = col_type(0,v,0,0); 173 mValue[2] = col_type(0,0,v,0); 174 mValue[3] = col_type(0,0,0,v); 175 } 176 177 template<typename T> 178 template<typename U> 179 tmat44<T>::tmat44(const tvec4<U>& v) { 180 mValue[0] = col_type(v.x,0,0,0); 181 mValue[1] = col_type(0,v.y,0,0); 182 mValue[2] = col_type(0,0,v.z,0); 183 mValue[3] = col_type(0,0,0,v.w); 184 } 185 186 // construct from 16 scalars 187 template<typename T> 188 template < 189 typename A, typename B, typename C, typename D, 190 typename E, typename F, typename G, typename H, 191 typename I, typename J, typename K, typename L, 192 typename M, typename N, typename O, typename P> 193 tmat44<T>::tmat44( A m00, B m01, C m02, D m03, 194 E m10, F m11, G m12, H m13, 195 I m20, J m21, K m22, L m23, 196 M m30, N m31, O m32, P m33) { 197 mValue[0] = col_type(m00, m01, m02, m03); 198 mValue[1] = col_type(m10, m11, m12, m13); 199 mValue[2] = col_type(m20, m21, m22, m23); 200 mValue[3] = col_type(m30, m31, m32, m33); 201 } 202 203 template <typename T> 204 template <typename U> 205 tmat44<T>::tmat44(const tmat44<U>& rhs) { 206 for (size_t r=0 ; r<row_size() ; r++) 207 mValue[r] = rhs[r]; 208 } 209 210 template <typename T> 211 template <typename A, typename B, typename C, typename D> 212 tmat44<T>::tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3) { 213 mValue[0] = v0; 214 mValue[1] = v1; 215 mValue[2] = v2; 216 mValue[3] = v3; 217 } 218 219 template <typename T> 220 template <typename U> 221 tmat44<T>::tmat44(U const* rawArray) { 222 for (size_t r=0 ; r<row_size() ; r++) 223 for (size_t c=0 ; c<col_size() ; c++) 224 mValue[r][c] = *rawArray++; 225 } 226 227 // ---------------------------------------------------------------------------------------- 228 // Helpers 229 // ---------------------------------------------------------------------------------------- 230 231 template <typename T> 232 tmat44<T> tmat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) { 233 tmat44<T> m; 234 m[0][0] = 2 / (right - left); 235 m[1][1] = 2 / (top - bottom); 236 m[2][2] = -2 / (far - near); 237 m[3][0] = -(right + left) / (right - left); 238 m[3][1] = -(top + bottom) / (top - bottom); 239 m[3][2] = -(far + near) / (far - near); 240 return m; 241 } 242 243 template <typename T> 244 tmat44<T> tmat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) { 245 tmat44<T> m; 246 T A = (right + left) / (right - left); 247 T B = (top + bottom) / (top - bottom); 248 T C = (far + near) / (far - near); 249 T D = (2 * far * near) / (far - near); 250 m[0][0] = (2 * near) / (right - left); 251 m[1][1] = (2 * near) / (top - bottom); 252 m[2][0] = A; 253 m[2][1] = B; 254 m[2][2] = C; 255 m[2][3] =-1; 256 m[3][2] = D; 257 m[3][3] = 0; 258 return m; 259 } 260 261 template <typename T> 262 template <typename A, typename B, typename C> 263 tmat44<T> tmat44<T>::lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up) { 264 tvec3<T> L(normalize(center - eye)); 265 tvec3<T> S(normalize( cross(L, up) )); 266 tvec3<T> U(cross(S, L)); 267 return tmat44<T>( 268 tvec4<T>( S, 0), 269 tvec4<T>( U, 0), 270 tvec4<T>(-L, 0), 271 tvec4<T>(-eye, 1)); 272 } 273 274 template <typename T> 275 template <typename A> 276 tmat44<T> tmat44<T>::translate(const tvec4<A>& t) { 277 tmat44<T> r; 278 r[3] = t; 279 return r; 280 } 281 282 template <typename T> 283 template <typename A> 284 tmat44<T> tmat44<T>::scale(const tvec4<A>& s) { 285 tmat44<T> r; 286 r[0][0] = s[0]; 287 r[1][1] = s[1]; 288 r[2][2] = s[2]; 289 r[3][3] = s[3]; 290 return r; 291 } 292 293 template <typename T> 294 template <typename A, typename B> 295 tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) { 296 tmat44<T> rotation; 297 T* r = const_cast<T*>(rotation.asArray()); 298 T c = cos(radian); 299 T s = sin(radian); 300 if (about.x==1 && about.y==0 && about.z==0) { 301 r[5] = c; r[10]= c; 302 r[6] = s; r[9] = -s; 303 } else if (about.x==0 && about.y==1 && about.z==0) { 304 r[0] = c; r[10]= c; 305 r[8] = s; r[2] = -s; 306 } else if (about.x==0 && about.y==0 && about.z==1) { 307 r[0] = c; r[5] = c; 308 r[1] = s; r[4] = -s; 309 } else { 310 tvec3<B> nabout = normalize(about); 311 B x = nabout.x; 312 B y = nabout.y; 313 B z = nabout.z; 314 T nc = 1 - c; 315 T xy = x * y; 316 T yz = y * z; 317 T zx = z * x; 318 T xs = x * s; 319 T ys = y * s; 320 T zs = z * s; 321 r[ 0] = x*x*nc + c; r[ 4] = xy*nc - zs; r[ 8] = zx*nc + ys; 322 r[ 1] = xy*nc + zs; r[ 5] = y*y*nc + c; r[ 9] = yz*nc - xs; 323 r[ 2] = zx*nc - ys; r[ 6] = yz*nc + xs; r[10] = z*z*nc + c; 324 } 325 return rotation; 326 } 327 328 // ---------------------------------------------------------------------------------------- 329 // Arithmetic operators outside of class 330 // ---------------------------------------------------------------------------------------- 331 332 /* We use non-friend functions here to prevent the compiler from using 333 * implicit conversions, for instance of a scalar to a vector. The result would 334 * not be what the caller expects. 335 * 336 * Also note that the order of the arguments in the inner loop is important since 337 * it determines the output type (only relevant when T != U). 338 */ 339 340 // matrix * vector, result is a vector of the same type than the input vector 341 template <typename T, typename U> 342 typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) { 343 typename tmat44<U>::col_type result; 344 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 345 result += rv[r]*lv[r]; 346 return result; 347 } 348 349 // vector * matrix, result is a vector of the same type than the input vector 350 template <typename T, typename U> 351 typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) { 352 typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT); 353 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 354 result[r] = dot(rv, lv[r]); 355 return result; 356 } 357 358 // matrix * scalar, result is a matrix of the same type than the input matrix 359 template <typename T, typename U> 360 tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) { 361 tmat44<T> result(tmat44<T>::NO_INIT); 362 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 363 result[r] = lv[r]*rv; 364 return result; 365 } 366 367 // scalar * matrix, result is a matrix of the same type than the input matrix 368 template <typename T, typename U> 369 tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) { 370 tmat44<T> result(tmat44<T>::NO_INIT); 371 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 372 result[r] = lv[r]*rv; 373 return result; 374 } 375 376 // ---------------------------------------------------------------------------------------- 377 378 /* FIXME: this should go into TMatSquareFunctions<> but for some reason 379 * BASE<T>::col_type is not accessible from there (???) 380 */ 381 template<typename T> 382 typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) { 383 return matrix::diag(m); 384 } 385 386 // ---------------------------------------------------------------------------------------- 387 388 typedef tmat44<float> mat4; 389 390 // ---------------------------------------------------------------------------------------- 391 }; // namespace android 392 393 #undef PURE 394 395 #endif /* UI_MAT4_H */ 396