Home | History | Annotate | Download | only in RenderUtils
      1 /*
      2  * Copyright (C) 2016 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 package com.android.cts.verifier.sensors.sixdof.Renderer.RenderUtils;
     17 
     18 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.MATRIX_4X4;
     19 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.X;
     20 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.Y;
     21 import static com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils.Z;
     22 
     23 import android.opengl.Matrix;
     24 
     25 import com.android.cts.verifier.sensors.sixdof.Utils.MathsUtils;
     26 
     27 
     28 /**
     29  * Utility class to manage the calculation of a Model Matrix from the translation and quaternion
     30  * arrays obtained from an PoseData object.
     31  */
     32 public class ModelMatrixCalculator {
     33 
     34     protected static final int MATRIX_4X4_TRANSLATION_X = 12;
     35     protected static final int MATRIX_4X4_TRANSLATION_Y = 13;
     36     protected static final int MATRIX_4X4_TRANSLATION_Z = 14;
     37 
     38     public static final float[] TANGO_TO_OPENGL = new float[]{1.0f, 0.0f, 0.0f, 0.0f,
     39             0.0f, 0.0f, -1.0f, 0.0f,
     40             0.0f, 1.0f, 0.0f, 0.0f,
     41             0.0f, 0.0f, 0.0f, 1.0f};
     42 
     43     protected float[] mModelMatrix = new float[MATRIX_4X4];
     44 
     45     // Set these to identity matrix.
     46     protected float[] mDevice2IMUMatrix = new float[]{1.0f, 0.0f, 0.0f, 0.0f,
     47             0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
     48             1.0f};
     49     protected float[] mColorCamera2IMUMatrix = new float[]{1.0f, 0.0f, 0.0f,
     50             0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
     51             0.0f, 1.0f};
     52     protected float[] mOpengl2ColorCameraMatrix = new float[]{1.0f, 0.0f, 0.0f,
     53             0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
     54             0.0f, 1.0f};
     55 
     56     protected int mToRotate = 0;
     57 
     58     public ModelMatrixCalculator(int toRotate) {
     59         Matrix.setIdentityM(mModelMatrix, 0);
     60         mToRotate = toRotate;
     61     }
     62 
     63     /**
     64      * Calculates a new model matrix, taking into account extrinsics and the latest pose
     65      * data.
     66      *
     67      * @param translationInOpenGlCoordinates latest translation from pose data in OpenGl coordinate
     68      *                                       system.
     69      * @param quaternion                     latest rotation from pose data.
     70      * @return the new model matrix.
     71      */
     72     protected float[] calculateModelMatrix(float[] translationInOpenGlCoordinates,
     73                                            float[] quaternion) {
     74         float[] newModelMatrix = new float[MATRIX_4X4];
     75 
     76         // Calculate an initial matrix with extrinsics taken into account.
     77         float[] imu2OpenGlMatrix = new float[MATRIX_4X4];
     78         Matrix.setIdentityM(imu2OpenGlMatrix, 0);
     79         Matrix.multiplyMM(imu2OpenGlMatrix, 0, mColorCamera2IMUMatrix, 0,
     80                 mOpengl2ColorCameraMatrix, 0);
     81         float[] invertedDevice2ImuMatrix = new float[MATRIX_4X4];
     82         Matrix.setIdentityM(invertedDevice2ImuMatrix, 0);
     83         Matrix.invertM(invertedDevice2ImuMatrix, 0, mDevice2IMUMatrix, 0);
     84         float[] extrinsicsBasedMatrix = new float[MATRIX_4X4];
     85         Matrix.setIdentityM(extrinsicsBasedMatrix, 0);
     86         Matrix.multiplyMM(extrinsicsBasedMatrix, 0, invertedDevice2ImuMatrix, 0,
     87                 imu2OpenGlMatrix, 0);
     88 
     89         // Do any translations that need to be done before rotating. Only used for the Cone offset.
     90         float[] requiredTranslations = getRequiredTranslations();
     91         Matrix.translateM(extrinsicsBasedMatrix, 0, requiredTranslations[X], requiredTranslations[Y],
     92                 requiredTranslations[Z]);
     93 
     94         // Rotate based on rotation pose data.
     95         float[] quaternionMatrix = new float[MATRIX_4X4];
     96         Matrix.setIdentityM(quaternionMatrix, 0);
     97         quaternionMatrix = MathsUtils.quaternionMatrixOpenGL(quaternion);
     98         float[] rotatedMatrix = new float[MATRIX_4X4];
     99         float[] deviceOrientationMatrix = new float[MATRIX_4X4];
    100         Matrix.setIdentityM(rotatedMatrix, 0);
    101         Matrix.setIdentityM(newModelMatrix, 0);
    102         Matrix.setIdentityM(deviceOrientationMatrix, 0);
    103         Matrix.multiplyMM(rotatedMatrix, 0, quaternionMatrix, 0,
    104                 extrinsicsBasedMatrix, 0);
    105         Matrix.multiplyMM(deviceOrientationMatrix, 0, TANGO_TO_OPENGL, 0,
    106                 rotatedMatrix, 0);
    107 
    108         Matrix.multiplyMM(newModelMatrix, 0, deviceOrientationMatrix, 0,
    109                 MathsUtils.getDeviceOrientationMatrix(mToRotate), 0);
    110 
    111         // Finally, add the translations from the pose data.
    112         newModelMatrix[MATRIX_4X4_TRANSLATION_X] += translationInOpenGlCoordinates[X];
    113         newModelMatrix[MATRIX_4X4_TRANSLATION_Y] += translationInOpenGlCoordinates[Y];
    114         newModelMatrix[MATRIX_4X4_TRANSLATION_Z] += translationInOpenGlCoordinates[Z];
    115 
    116         return newModelMatrix;
    117     }
    118 
    119     /**
    120      * Updates the model matrix (rotation and translation).
    121      *
    122      * @param translation a three-element array of translation data.
    123      * @param quaternion  a four-element array of rotation data.
    124      */
    125     public void updateModelMatrix(float[] translation, float[] quaternion) {
    126         float[] convertedTranslation = MathsUtils.convertToOpenGlCoordinates(translation, mToRotate);
    127         mModelMatrix = calculateModelMatrix(convertedTranslation, quaternion);
    128     }
    129 
    130     public void setDevice2IMUMatrix(float[] translation, float[] quaternion) {
    131         mDevice2IMUMatrix = MathsUtils.quaternionMatrixOpenGL(quaternion);
    132         mDevice2IMUMatrix[MATRIX_4X4_TRANSLATION_X] = translation[X];
    133         mDevice2IMUMatrix[MATRIX_4X4_TRANSLATION_Y] = translation[Y];
    134         mDevice2IMUMatrix[MATRIX_4X4_TRANSLATION_Z] = translation[Z];
    135     }
    136 
    137     public void setColorCamera2IMUMatrix(float[] translation, float[] quaternion) {
    138         mOpengl2ColorCameraMatrix = new float[]{1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
    139                 -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
    140                 1.0f};
    141         mColorCamera2IMUMatrix = MathsUtils.quaternionMatrixOpenGL(quaternion);
    142         mColorCamera2IMUMatrix[MATRIX_4X4_TRANSLATION_X] = translation[X];
    143         mColorCamera2IMUMatrix[MATRIX_4X4_TRANSLATION_Y] = translation[Y];
    144         mColorCamera2IMUMatrix[MATRIX_4X4_TRANSLATION_Z] = translation[Z];
    145     }
    146 
    147     public float[] getModelMatrix() {
    148         return mModelMatrix;
    149     }
    150 
    151     /**
    152      * Translations that need to be done before rotating. Used for calculating the CONE_OFFSET.
    153      *
    154      * @return no translation.
    155      */
    156     protected float[] getRequiredTranslations() {
    157         return new float[]{0.0f, 0.0f, 0.0f};
    158     }
    159 }
    160