1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 #include "Matrix.h" 16 #include <string.h> 17 #include <cmath> 18 19 #define LOG_TAG "CTS_OPENGL" 20 #define LOG_NDEBUG 0 21 #include "android/log.h" 22 23 Matrix::Matrix() { 24 identity(); 25 } 26 27 Matrix::Matrix(const Matrix& src) { 28 loadWith(src); 29 } 30 31 void Matrix::print(const char* label) { 32 __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%c", *label); 33 for (int i = 0; i < 4; i++) { 34 const float* d = &(mData[i * 4]); 35 __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%f %f %f %f\n", d[0], d[1], d[2], d[3]); 36 } 37 } 38 39 bool Matrix::equals(const Matrix& src) { 40 bool equals = true; 41 const float* d = src.mData; 42 for (int i = 0; i < MATRIX_SIZE && equals; i++) { 43 if (mData[i] != d[i]) { 44 equals = false; 45 } 46 } 47 return equals; 48 } 49 50 void Matrix::loadWith(const Matrix& src) { 51 memcpy(mData, src.mData, MATRIX_SIZE * sizeof(float)); 52 } 53 54 void Matrix::identity() { 55 mData[0] = 1.0f; 56 mData[1] = 0.0f; 57 mData[2] = 0.0f; 58 mData[3] = 0.0f; 59 60 mData[4] = 0.0f; 61 mData[5] = 1.0f; 62 mData[6] = 0.0f; 63 mData[7] = 0.0f; 64 65 mData[8] = 0.0f; 66 mData[9] = 0.0f; 67 mData[10] = 1.0f; 68 mData[11] = 0.0f; 69 70 mData[12] = 0.0f; 71 mData[13] = 0.0f; 72 mData[14] = 0.0f; 73 mData[15] = 1.0f; 74 } 75 76 void Matrix::translate(float x, float y, float z) { 77 Matrix* m = newTranslate(x, y, z); 78 Matrix* temp = new Matrix(*this); 79 if (m != NULL && temp != NULL) { 80 multiply(*temp, *m); 81 } 82 delete m; 83 delete temp; 84 } 85 86 void Matrix::scale(float x, float y, float z) { 87 Matrix* m = newScale(x, y, z); 88 Matrix* temp = new Matrix(*this); 89 if (m != NULL && temp != NULL) { 90 multiply(*temp, *m); 91 } 92 delete m; 93 delete temp; 94 } 95 96 void Matrix::rotate(float radians, float x, float y, float z) { 97 Matrix* m = newRotate(radians, x, y, z); 98 Matrix* temp = new Matrix(*this); 99 if (m != NULL && temp != NULL) { 100 multiply(*temp, *m); 101 } 102 delete m; 103 delete temp; 104 } 105 106 void Matrix::multiply(const Matrix& l, const Matrix& r) { 107 float const* const lhs = l.mData; 108 float const* const rhs = r.mData; 109 for (int i = 0; i < 4; i++) { 110 const int i4 = i * 4; 111 float x = 0; 112 float y = 0; 113 float z = 0; 114 float w = 0; 115 116 for (int j = 0; j < 4; j++) { 117 const int j4 = j * 4; 118 const float e = rhs[i4 + j]; 119 x += lhs[j4 + 0] * e; 120 y += lhs[j4 + 1] * e; 121 z += lhs[j4 + 2] * e; 122 w += lhs[j4 + 3] * e; 123 } 124 125 mData[i4 + 0] = x; 126 mData[i4 + 1] = y; 127 mData[i4 + 2] = z; 128 mData[i4 + 3] = w; 129 } 130 } 131 132 Matrix* Matrix::newLookAt(float eyeX, float eyeY, float eyeZ, float centerX, 133 float centerY, float centerZ, float upX, float upY, float upZ) { 134 Matrix* m = new Matrix(); 135 if (m != NULL) { 136 // See the OpenGL GLUT documentation for gluLookAt for a description 137 // of the algorithm. We implement it in a straightforward way: 138 139 float fx = centerX - eyeX; 140 float fy = centerY - eyeY; 141 float fz = centerZ - eyeZ; 142 143 // Normalize f 144 float rlf = 1.0f / (float) sqrt(fx * fx + fy * fy + fz * fz); 145 fx *= rlf; 146 fy *= rlf; 147 fz *= rlf; 148 149 // compute s = f x up (x means "cross product") 150 float sx = fy * upZ - fz * upY; 151 float sy = fz * upX - fx * upZ; 152 float sz = fx * upY - fy * upX; 153 154 // and normalize s 155 float rls = 1.0f / (float) sqrt(sx * sx + sy * sy + sz * sz); 156 sx *= rls; 157 sy *= rls; 158 sz *= rls; 159 160 // compute u = s x f 161 float ux = sy * fz - sz * fy; 162 float uy = sz * fx - sx * fz; 163 float uz = sx * fy - sy * fx; 164 165 float* d = m->mData; 166 d[0] = sx; 167 d[1] = ux; 168 d[2] = -fx; 169 d[3] = 0.0f; 170 171 d[4] = sy; 172 d[5] = uy; 173 d[6] = -fy; 174 d[7] = 0.0f; 175 176 d[8] = sz; 177 d[9] = uz; 178 d[10] = -fz; 179 d[11] = 0.0f; 180 181 d[12] = 0.0f; 182 d[13] = 0.0f; 183 d[14] = 0.0f; 184 d[15] = 1.0f; 185 186 m->translate(-eyeX, -eyeY, -eyeZ); 187 } 188 return m; 189 } 190 191 Matrix* Matrix::newFrustum(float left, float right, float bottom, float top, 192 float near, float far) { 193 const float r_width = 1.0f / (right - left); 194 const float r_height = 1.0f / (top - bottom); 195 const float r_depth = 1.0f / (near - far); 196 const float x = 2.0f * (near * r_width); 197 const float y = 2.0f * (near * r_height); 198 const float A = (right + left) * r_width; 199 const float B = (top + bottom) * r_height; 200 const float C = (far + near) * r_depth; 201 const float D = 2.0f * (far * near * r_depth); 202 Matrix* m = new Matrix(); 203 if (m != NULL) { 204 float* d = m->mData; 205 d[0] = x; 206 d[5] = y; 207 d[8] = A; 208 d[9] = B; 209 d[10] = C; 210 d[14] = D; 211 d[11] = -1.0f; 212 d[1] = 0.0f; 213 d[2] = 0.0f; 214 d[3] = 0.0f; 215 d[4] = 0.0f; 216 d[6] = 0.0f; 217 d[7] = 0.0f; 218 d[12] = 0.0f; 219 d[13] = 0.0f; 220 d[15] = 0.0f; 221 } 222 return m; 223 } 224 225 Matrix* Matrix::newTranslate(float x, float y, float z) { 226 Matrix* m = new Matrix(); 227 if (m != NULL) { 228 float* d = m->mData; 229 d[12] = x; 230 d[13] = y; 231 d[14] = z; 232 } 233 return m; 234 } 235 Matrix* Matrix::newScale(float x, float y, float z) { 236 Matrix* m = new Matrix(); 237 if (m != NULL) { 238 float* d = m->mData; 239 d[0] = x; 240 d[5] = y; 241 d[10] = z; 242 } 243 return m; 244 } 245 Matrix* Matrix::newRotate(float radians, float x, float y, float z) { 246 Matrix* m = new Matrix(); 247 if (m != NULL) { 248 float* d = m->mData; 249 d[3] = 0; 250 d[7] = 0; 251 d[11] = 0; 252 d[12] = 0; 253 d[13] = 0; 254 d[14] = 0; 255 d[15] = 1; 256 float s = (float) sinf(radians); 257 float c = (float) cosf(radians); 258 if (1.0f == x && 0.0f == y && 0.0f == z) { 259 d[5] = c; 260 d[10] = c; 261 d[6] = s; 262 d[9] = -s; 263 d[1] = 0; 264 d[2] = 0; 265 d[4] = 0; 266 d[8] = 0; 267 d[0] = 1; 268 } else if (0.0f == x && 1.0f == y && 0.0f == z) { 269 d[0] = c; 270 d[10] = c; 271 d[8] = s; 272 d[2] = -s; 273 d[1] = 0; 274 d[4] = 0; 275 d[6] = 0; 276 d[9] = 0; 277 d[5] = 1; 278 } else if (0.0f == x && 0.0f == y && 1.0f == z) { 279 d[0] = c; 280 d[5] = c; 281 d[1] = s; 282 d[4] = -s; 283 d[2] = 0; 284 d[6] = 0; 285 d[8] = 0; 286 d[9] = 0; 287 d[10] = 1; 288 } else { 289 float len = sqrt((x * x) + (y * y) + (z * z)); 290 if (1.0f != len) { 291 float recipLen = 1.0f / len; 292 x *= recipLen; 293 y *= recipLen; 294 z *= recipLen; 295 } 296 float nc = 1.0f - c; 297 float xy = x * y; 298 float yz = y * z; 299 float zx = z * x; 300 float xs = x * s; 301 float ys = y * s; 302 float zs = z * s; 303 d[0] = x * x * nc + c; 304 d[4] = xy * nc - zs; 305 d[8] = zx * nc + ys; 306 d[1] = xy * nc + zs; 307 d[5] = y * y * nc + c; 308 d[9] = yz * nc - xs; 309 d[2] = zx * nc - ys; 310 d[6] = yz * nc + xs; 311 d[10] = z * z * nc + c; 312 } 313 } 314 return m; 315 } 316 317 void Matrix::multiplyVector(float* result, const Matrix& lhs, 318 const float* rhs) { 319 const float* d = lhs.mData; 320 const float x = rhs[0]; 321 const float y = rhs[1]; 322 const float z = rhs[2]; 323 const float w = rhs[3]; 324 for (int i = 0; i < 4; i++) { 325 const int j = i * 4; 326 result[i] = d[j + 0] * x + d[j + 1] * y + d[j + 2] * z + d[j + 3] * w; 327 } 328 } 329