Home | History | Annotate | Download | only in graphics
      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