mat4.h revision 595ea77f6bdb5e9d0ddd3305da7a44b56f326b2c
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 31namespace android { 32// ------------------------------------------------------------------------------------- 33 34template <typename T> 35class tmat44 : public TVecUnaryOperators<tmat44, T>, 36 public TVecComparisonOperators<tmat44, T> 37{ 38public: 39 enum no_init { NO_INIT }; 40 typedef T value_type; 41 typedef T& reference; 42 typedef T const& const_reference; 43 typedef size_t size_type; 44 typedef tvec4<T> col_type; 45 typedef tvec4<T> row_type; 46 47 // size of a column (i.e.: number of rows) 48 enum { COL_SIZE = col_type::SIZE }; 49 static inline size_t col_size() { return COL_SIZE; } 50 51 // size of a row (i.e.: number of columns) 52 enum { ROW_SIZE = row_type::SIZE }; 53 static inline size_t row_size() { return ROW_SIZE; } 54 static inline size_t size() { return row_size(); } // for TVec*<> 55 56private: 57 58 /* 59 * <-- N columns --> 60 * 61 * a00 a10 a20 ... aN0 ^ 62 * a01 a11 a21 ... aN1 | 63 * a02 a12 a22 ... aN2 M rows 64 * ... | 65 * a0M a1M a2M ... aNM v 66 * 67 * COL_SIZE = M 68 * ROW_SIZE = N 69 * m[0] = [a00 a01 a02 ... a01M] 70 */ 71 72 col_type mValue[ROW_SIZE]; 73 74public: 75 // array access 76 inline col_type const& operator [] (size_t i) const { return mValue[i]; } 77 inline col_type& operator [] (size_t i) { return mValue[i]; } 78 79 T const* asArray() const { return &mValue[0][0]; } 80 81 // ----------------------------------------------------------------------- 82 // we don't provide copy-ctor and operator= on purpose 83 // because we want the compiler generated versions 84 85 /* 86 * constructors 87 */ 88 89 // leaves object uninitialized. use with caution. 90 explicit tmat44(no_init) { } 91 92 // initialize to identity 93 tmat44(); 94 95 // initialize to Identity*scalar. 96 template<typename U> 97 explicit tmat44(U v); 98 99 // sets the diagonal to the passed vector 100 template <typename U> 101 explicit tmat44(const tvec4<U>& rhs); 102 103 // construct from another matrix of the same size 104 template <typename U> 105 explicit tmat44(const tmat44<U>& rhs); 106 107 // construct from 4 column vectors 108 template <typename A, typename B, typename C, typename D> 109 tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3); 110 111 // construct from a C array 112 template <typename U> 113 explicit tmat44(U const* rawArray); 114 115 /* 116 * helpers 117 */ 118 119 static tmat44 ortho(T left, T right, T bottom, T top, T near, T far); 120 121 static tmat44 frustum(T left, T right, T bottom, T top, T near, T far); 122 123 template <typename A, typename B, typename C> 124 static tmat44 lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up); 125 126 template <typename A> 127 static tmat44 translate(const tvec4<A>& t); 128 129 template <typename A> 130 static tmat44 scale(const tvec4<A>& s); 131 132 template <typename A, typename B> 133 static tmat44 rotate(A radian, const tvec3<B>& about); 134 135 136 /* 137 * Compound assignment arithmetic operators 138 */ 139 140 // add another matrix of the same size 141 template <typename U> 142 tmat44& operator += (const tmat44<U>& v); 143 144 // subtract another matrix of the same size 145 template <typename U> 146 tmat44& operator -= (const tmat44<U>& v); 147 148 // multiply by a scalar 149 template <typename U> 150 tmat44& operator *= (U v); 151 152 // divide by a scalar 153 template <typename U> 154 tmat44& operator /= (U v); 155 156 /* 157 * debugging 158 */ 159 160 String8 asString() const; 161}; 162 163// ---------------------------------------------------------------------------------------- 164// Constructors 165// ---------------------------------------------------------------------------------------- 166 167/* 168 * Since the matrix code could become pretty big quickly, we don't inline most 169 * operations. 170 */ 171 172template <typename T> 173tmat44<T>::tmat44() { 174 mValue[0] = col_type(1,0,0,0); 175 mValue[1] = col_type(0,1,0,0); 176 mValue[2] = col_type(0,0,1,0); 177 mValue[3] = col_type(0,0,0,1); 178} 179 180template <typename T> 181template <typename U> 182tmat44<T>::tmat44(U v) { 183 mValue[0] = col_type(v,0,0,0); 184 mValue[1] = col_type(0,v,0,0); 185 mValue[2] = col_type(0,0,v,0); 186 mValue[3] = col_type(0,0,0,v); 187} 188 189template<typename T> 190template<typename U> 191tmat44<T>::tmat44(const tvec4<U>& v) { 192 mValue[0] = col_type(v.x,0,0,0); 193 mValue[1] = col_type(0,v.y,0,0); 194 mValue[2] = col_type(0,0,v.z,0); 195 mValue[3] = col_type(0,0,0,v.w); 196} 197 198template <typename T> 199template <typename U> 200tmat44<T>::tmat44(const tmat44<U>& rhs) { 201 for (size_t r=0 ; r<row_size() ; r++) 202 mValue[r] = rhs[r]; 203} 204 205template <typename T> 206template <typename A, typename B, typename C, typename D> 207tmat44<T>::tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3) { 208 mValue[0] = v0; 209 mValue[1] = v1; 210 mValue[2] = v2; 211 mValue[3] = v3; 212} 213 214template <typename T> 215template <typename U> 216tmat44<T>::tmat44(U const* rawArray) { 217 for (size_t r=0 ; r<row_size() ; r++) 218 for (size_t c=0 ; c<col_size() ; c++) 219 mValue[r][c] = *rawArray++; 220} 221 222// ---------------------------------------------------------------------------------------- 223// Helpers 224// ---------------------------------------------------------------------------------------- 225 226template <typename T> 227tmat44<T> tmat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) { 228 tmat44<T> m; 229 m[0][0] = 2 / (right - left); 230 m[1][1] = 2 / (top - bottom); 231 m[2][2] = -2 / (far - near); 232 m[3][0] = -(right + left) / (right - left); 233 m[3][1] = -(top + bottom) / (top - bottom); 234 m[3][2] = -(far + near) / (far - near); 235 return m; 236} 237 238template <typename T> 239tmat44<T> tmat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) { 240 tmat44<T> m; 241 T A = (right + left) / (right - left); 242 T B = (top + bottom) / (top - bottom); 243 T C = (far + near) / (far - near); 244 T D = (2 * far * near) / (far - near); 245 m[0][0] = (2 * near) / (right - left); 246 m[1][1] = (2 * near) / (top - bottom); 247 m[2][0] = A; 248 m[2][1] = B; 249 m[2][2] = C; 250 m[2][3] =-1; 251 m[3][2] = D; 252 m[3][3] = 0; 253 return m; 254} 255 256template <typename T> 257template <typename A, typename B, typename C> 258tmat44<T> tmat44<T>::lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up) { 259 tvec3<T> L(normalize(center - eye)); 260 tvec3<T> S(normalize( cross(L, up) )); 261 tvec3<T> U(cross(S, L)); 262 return tmat44<T>( 263 tvec4<T>( S, 0), 264 tvec4<T>( U, 0), 265 tvec4<T>(-L, 0), 266 tvec4<T>(-eye, 1)); 267} 268 269template <typename T> 270template <typename A> 271tmat44<T> tmat44<T>::translate(const tvec4<A>& t) { 272 tmat44<T> r; 273 r[3] = t; 274 return r; 275} 276 277template <typename T> 278template <typename A> 279tmat44<T> tmat44<T>::scale(const tvec4<A>& s) { 280 tmat44<T> r; 281 r[0][0] = s[0]; 282 r[1][1] = s[1]; 283 r[2][2] = s[2]; 284 r[3][3] = s[3]; 285 return r; 286} 287 288template <typename T> 289template <typename A, typename B> 290tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) { 291 tmat44<T> rotation; 292 T* r = const_cast<T*>(rotation.asArray()); 293 T c = cos(radian); 294 T s = sin(radian); 295 if (about.x==1 && about.y==0 && about.z==0) { 296 r[5] = c; r[10]= c; 297 r[6] = s; r[9] = -s; 298 } else if (about.x==0 && about.y==1 && about.z==0) { 299 r[0] = c; r[10]= c; 300 r[8] = s; r[2] = -s; 301 } else if (about.x==0 && about.y==0 && about.z==1) { 302 r[0] = c; r[5] = c; 303 r[1] = s; r[4] = -s; 304 } else { 305 tvec3<B> nabout = normalize(about); 306 B x = nabout.x; 307 B y = nabout.y; 308 B z = nabout.z; 309 T nc = 1 - c; 310 T xy = x * y; 311 T yz = y * z; 312 T zx = z * x; 313 T xs = x * s; 314 T ys = y * s; 315 T zs = z * s; 316 r[ 0] = x*x*nc + c; r[ 4] = xy*nc - zs; r[ 8] = zx*nc + ys; 317 r[ 1] = xy*nc + zs; r[ 5] = y*y*nc + c; r[ 9] = yz*nc - xs; 318 r[ 2] = zx*nc - ys; r[ 6] = yz*nc + xs; r[10] = z*z*nc + c; 319 } 320} 321 322// ---------------------------------------------------------------------------------------- 323// Compound assignment arithmetic operators 324// ---------------------------------------------------------------------------------------- 325 326template <typename T> 327template <typename U> 328tmat44<T>& tmat44<T>::operator += (const tmat44<U>& v) { 329 for (size_t r=0 ; r<row_size() ; r++) 330 mValue[r] += v[r]; 331 return *this; 332} 333 334template <typename T> 335template <typename U> 336tmat44<T>& tmat44<T>::operator -= (const tmat44<U>& v) { 337 for (size_t r=0 ; r<row_size() ; r++) 338 mValue[r] -= v[r]; 339 return *this; 340} 341 342template <typename T> 343template <typename U> 344tmat44<T>& tmat44<T>::operator *= (U v) { 345 for (size_t r=0 ; r<row_size() ; r++) 346 mValue[r] *= v; 347 return *this; 348} 349 350template <typename T> 351template <typename U> 352tmat44<T>& tmat44<T>::operator /= (U v) { 353 for (size_t r=0 ; r<row_size() ; r++) 354 mValue[r] /= v; 355 return *this; 356} 357 358// ---------------------------------------------------------------------------------------- 359// Arithmetic operators outside of class 360// ---------------------------------------------------------------------------------------- 361 362/* We use non-friend functions here to prevent the compiler from using 363 * implicit conversions, for instance of a scalar to a vector. The result would 364 * not be what the caller expects. 365 * 366 * Also note that the order of the arguments in the inner loop is important since 367 * it determines the output type (only relevant when T != U). 368 */ 369 370// matrix + matrix, result is a matrix of the same type than the lhs matrix 371template <typename T, typename U> 372tmat44<T> PURE operator +(const tmat44<T>& lhs, const tmat44<U>& rhs) { 373 tmat44<T> result(tmat44<T>::NO_INIT); 374 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 375 result[r] = lhs[r] + rhs[r]; 376 return result; 377} 378 379// matrix - matrix, result is a matrix of the same type than the lhs matrix 380template <typename T, typename U> 381tmat44<T> PURE operator -(const tmat44<T>& lhs, const tmat44<U>& rhs) { 382 tmat44<T> result(tmat44<T>::NO_INIT); 383 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 384 result[r] = lhs[r] - rhs[r]; 385 return result; 386} 387 388// matrix * vector, result is a vector of the same type than the input vector 389template <typename T, typename U> 390typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) { 391 typename tmat44<U>::col_type result; 392 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 393 result += rv[r]*lv[r]; 394 return result; 395} 396 397// vector * matrix, result is a vector of the same type than the input vector 398template <typename T, typename U> 399typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) { 400 typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT); 401 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 402 result[r] = dot(rv, lv[r]); 403 return result; 404} 405 406// matrix * scalar, result is a matrix of the same type than the input matrix 407template <typename T, typename U> 408tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) { 409 tmat44<T> result(tmat44<T>::NO_INIT); 410 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 411 result[r] = lv[r]*rv; 412 return result; 413} 414 415// scalar * matrix, result is a matrix of the same type than the input matrix 416template <typename T, typename U> 417tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) { 418 tmat44<T> result(tmat44<T>::NO_INIT); 419 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++) 420 result[r] = lv[r]*rv; 421 return result; 422} 423 424// matrix * matrix, result is a matrix of the same type than the lhs matrix 425template <typename T, typename U> 426tmat44<T> PURE operator *(const tmat44<T>& lhs, const tmat44<U>& rhs) { 427 return matrix::multiply< tmat44<T> >(lhs, rhs); 428} 429 430// ---------------------------------------------------------------------------------------- 431// Functions 432// ---------------------------------------------------------------------------------------- 433 434// inverse a matrix 435template <typename T> 436tmat44<T> PURE inverse(const tmat44<T>& m) { 437 return matrix::inverse(m); 438} 439 440template <typename T> 441tmat44<T> PURE transpose(const tmat44<T>& m) { 442 return matrix::transpose(m); 443} 444 445template <typename T> 446T PURE trace(const tmat44<T>& m) { 447 return matrix::trace(m); 448} 449 450template <typename T> 451tvec4<T> PURE diag(const tmat44<T>& m) { 452 return matrix::diag(m); 453} 454 455// ---------------------------------------------------------------------------------------- 456// Debugging 457// ---------------------------------------------------------------------------------------- 458 459template <typename T> 460String8 tmat44<T>::asString() const { 461 return matrix::asString(*this); 462} 463 464// ---------------------------------------------------------------------------------------- 465 466typedef tmat44<float> mat4; 467 468// ---------------------------------------------------------------------------------------- 469}; // namespace android 470 471#undef PURE 472 473#endif /* UI_MAT4_H */ 474