2 * Copyright 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <sys/types.h>
24 #include <utils/String8.h>
26 #define TMAT_IMPLEMENTATION
27 #include <ui/TMatHelpers.h>
29 #define PURE __attribute__((pure))
32 // -------------------------------------------------------------------------------------
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>
43 enum no_init { NO_INIT };
46 typedef T const& const_reference;
47 typedef size_t size_type;
48 typedef tvec4<T> col_type;
49 typedef tvec4<T> row_type;
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; }
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*<>
65 * a00 a10 a20 ... aN0 ^
66 * a01 a11 a21 ... aN1 |
67 * a02 a12 a22 ... aN2 M rows
69 * a0M a1M a2M ... aNM v
73 * m[0] = [a00 a01 a02 ... a01M]
76 col_type mValue[ROW_SIZE];
80 inline col_type const& operator [] (size_t i) const { return mValue[i]; }
81 inline col_type& operator [] (size_t i) { return mValue[i]; }
83 T const* asArray() const { return &mValue[0][0]; }
85 // -----------------------------------------------------------------------
86 // we don't provide copy-ctor and operator= on purpose
87 // because we want the compiler generated versions
93 // leaves object uninitialized. use with caution.
94 explicit tmat44(no_init) { }
96 // initialize to identity
99 // initialize to Identity*scalar.
101 explicit tmat44(U v);
103 // sets the diagonal to the passed vector
104 template <typename U>
105 explicit tmat44(const tvec4<U>& rhs);
107 // construct from another matrix of the same size
108 template <typename U>
109 explicit tmat44(const tmat44<U>& rhs);
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);
115 // construct from 16 scalars
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);
126 // construct from a C array
127 template <typename U>
128 explicit tmat44(U const* rawArray);
134 static tmat44 ortho(T left, T right, T bottom, T top, T near, T far);
136 static tmat44 frustum(T left, T right, T bottom, T top, T near, T far);
138 template <typename A, typename B, typename C>
139 static tmat44 lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up);
141 template <typename A>
142 static tmat44 translate(const tvec4<A>& t);
144 template <typename A>
145 static tmat44 scale(const tvec4<A>& s);
147 template <typename A, typename B>
148 static tmat44 rotate(A radian, const tvec3<B>& about);
151 // ----------------------------------------------------------------------------------------
153 // ----------------------------------------------------------------------------------------
156 * Since the matrix code could become pretty big quickly, we don't inline most
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);
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);
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);
186 // construct from 16 scalars
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);
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++)
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) {
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++;
227 // ----------------------------------------------------------------------------------------
229 // ----------------------------------------------------------------------------------------
231 template <typename T>
232 tmat44<T> tmat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
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);
243 template <typename T>
244 tmat44<T> tmat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
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);
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));
274 template <typename T>
275 template <typename A>
276 tmat44<T> tmat44<T>::translate(const tvec4<A>& t) {
282 template <typename T>
283 template <typename A>
284 tmat44<T> tmat44<T>::scale(const tvec4<A>& s) {
293 template <typename T>
294 template <typename A, typename B>
295 tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) {
297 T* r = const_cast<T*>(rotation.asArray());
300 if (about.x==1 && about.y==0 && about.z==0) {
303 } else if (about.x==0 && about.y==1 && about.z==0) {
306 } else if (about.x==0 && about.y==0 && about.z==1) {
310 tvec3<B> nabout = normalize(about);
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;
327 // ----------------------------------------------------------------------------------------
328 // Arithmetic operators outside of class
329 // ----------------------------------------------------------------------------------------
331 /* We use non-friend functions here to prevent the compiler from using
332 * implicit conversions, for instance of a scalar to a vector. The result would
333 * not be what the caller expects.
335 * Also note that the order of the arguments in the inner loop is important since
336 * it determines the output type (only relevant when T != U).
339 // matrix * vector, result is a vector of the same type than the input vector
340 template <typename T, typename U>
341 typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) {
342 typename tmat44<U>::col_type result;
343 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
344 result += rv[r]*lv[r];
348 // vector * matrix, result is a vector of the same type than the input vector
349 template <typename T, typename U>
350 typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) {
351 typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT);
352 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
353 result[r] = dot(rv, lv[r]);
357 // matrix * scalar, result is a matrix of the same type than the input matrix
358 template <typename T, typename U>
359 tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) {
360 tmat44<T> result(tmat44<T>::NO_INIT);
361 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
362 result[r] = lv[r]*rv;
366 // scalar * matrix, result is a matrix of the same type than the input matrix
367 template <typename T, typename U>
368 tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) {
369 tmat44<T> result(tmat44<T>::NO_INIT);
370 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
371 result[r] = lv[r]*rv;
375 // ----------------------------------------------------------------------------------------
377 /* FIXME: this should go into TMatSquareFunctions<> but for some reason
378 * BASE<T>::col_type is not accessible from there (???)
381 typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
382 return matrix::diag(m);
385 // ----------------------------------------------------------------------------------------
387 typedef tmat44<float> mat4;
389 // ----------------------------------------------------------------------------------------
390 }; // namespace android
394 #endif /* UI_MAT4_H */