Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2007 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 package com.cooliris.media;
     18 
     19 import android.opengl.Matrix;
     20 
     21 import java.nio.FloatBuffer;
     22 import java.nio.IntBuffer;
     23 
     24 /**
     25  * A matrix stack, similar to OpenGL ES's internal matrix stack.
     26  */
     27 public class MatrixStack {
     28     public MatrixStack() {
     29         commonInit(DEFAULT_MAX_DEPTH);
     30     }
     31 
     32     public MatrixStack(int maxDepth) {
     33         commonInit(maxDepth);
     34     }
     35 
     36     private void commonInit(int maxDepth) {
     37         mMatrix = new float[maxDepth * MATRIX_SIZE];
     38         mTemp = new float[MATRIX_SIZE * 2];
     39         glLoadIdentity();
     40     }
     41 
     42     public void apply(float[] mCoordsIn, float[] mCoordsOut) {
     43         Matrix.multiplyMV(mCoordsOut, 0, mMatrix, mTop, mCoordsIn, 0);
     44     }
     45 
     46     public void glFrustumf(float left, float right, float bottom, float top, float near, float far) {
     47         Matrix.frustumM(mMatrix, mTop, left, right, bottom, top, near, far);
     48     }
     49 
     50     public void glFrustumx(int left, int right, int bottom, int top, int near, int far) {
     51         glFrustumf(fixedToFloat(left), fixedToFloat(right), fixedToFloat(bottom), fixedToFloat(top), fixedToFloat(near),
     52                 fixedToFloat(far));
     53     }
     54 
     55     public void glLoadIdentity() {
     56         Matrix.setIdentityM(mMatrix, mTop);
     57     }
     58 
     59     public void glLoadMatrixf(float[] m, int offset) {
     60         System.arraycopy(m, offset, mMatrix, mTop, MATRIX_SIZE);
     61     }
     62 
     63     public void glLoadMatrixf(FloatBuffer m) {
     64         m.get(mMatrix, mTop, MATRIX_SIZE);
     65     }
     66 
     67     public void glLoadMatrixx(int[] m, int offset) {
     68         for (int i = 0; i < MATRIX_SIZE; i++) {
     69             mMatrix[mTop + i] = fixedToFloat(m[offset + i]);
     70         }
     71     }
     72 
     73     public void glLoadMatrixx(IntBuffer m) {
     74         for (int i = 0; i < MATRIX_SIZE; i++) {
     75             mMatrix[mTop + i] = fixedToFloat(m.get());
     76         }
     77     }
     78 
     79     public void glMultMatrixf(float[] m, int offset) {
     80         System.arraycopy(mMatrix, mTop, mTemp, 0, MATRIX_SIZE);
     81         Matrix.multiplyMM(mMatrix, mTop, mTemp, 0, m, offset);
     82     }
     83 
     84     public void glMultMatrixf(FloatBuffer m) {
     85         m.get(mTemp, MATRIX_SIZE, MATRIX_SIZE);
     86         glMultMatrixf(mTemp, MATRIX_SIZE);
     87     }
     88 
     89     public void glMultMatrixx(int[] m, int offset) {
     90         for (int i = 0; i < MATRIX_SIZE; i++) {
     91             mTemp[MATRIX_SIZE + i] = fixedToFloat(m[offset + i]);
     92         }
     93         glMultMatrixf(mTemp, MATRIX_SIZE);
     94     }
     95 
     96     public void glMultMatrixx(IntBuffer m) {
     97         for (int i = 0; i < MATRIX_SIZE; i++) {
     98             mTemp[MATRIX_SIZE + i] = fixedToFloat(m.get());
     99         }
    100         glMultMatrixf(mTemp, MATRIX_SIZE);
    101     }
    102 
    103     public void glOrthof(float left, float right, float bottom, float top, float near, float far) {
    104         Matrix.orthoM(mMatrix, mTop, left, right, bottom, top, near, far);
    105     }
    106 
    107     public void glOrthox(int left, int right, int bottom, int top, int near, int far) {
    108         glOrthof(fixedToFloat(left), fixedToFloat(right), fixedToFloat(bottom), fixedToFloat(top), fixedToFloat(near),
    109                 fixedToFloat(far));
    110     }
    111 
    112     public void glPopMatrix() {
    113         preflight_adjust(-1);
    114         adjust(-1);
    115     }
    116 
    117     public void glPushMatrix() {
    118         preflight_adjust(1);
    119         System.arraycopy(mMatrix, mTop, mMatrix, mTop + MATRIX_SIZE, MATRIX_SIZE);
    120         adjust(1);
    121     }
    122 
    123     public void glRotatef(float angle, float x, float y, float z) {
    124         Matrix.setRotateM(mTemp, 0, angle, x, y, z);
    125         System.arraycopy(mMatrix, mTop, mTemp, MATRIX_SIZE, MATRIX_SIZE);
    126         Matrix.multiplyMM(mMatrix, mTop, mTemp, MATRIX_SIZE, mTemp, 0);
    127     }
    128 
    129     public void glRotatex(int angle, int x, int y, int z) {
    130         glRotatef(angle, fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
    131     }
    132 
    133     public void glScalef(float x, float y, float z) {
    134         Matrix.scaleM(mMatrix, mTop, x, y, z);
    135     }
    136 
    137     public void glScalex(int x, int y, int z) {
    138         glScalef(fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
    139     }
    140 
    141     public void glTranslatef(float x, float y, float z) {
    142         Matrix.translateM(mMatrix, mTop, x, y, z);
    143     }
    144 
    145     public void glTranslatex(int x, int y, int z) {
    146         glTranslatef(fixedToFloat(x), fixedToFloat(y), fixedToFloat(z));
    147     }
    148 
    149     public void getMatrix(float[] dest, int offset) {
    150         System.arraycopy(mMatrix, mTop, dest, offset, MATRIX_SIZE);
    151     }
    152 
    153     private float fixedToFloat(int x) {
    154         return x * (1.0f / 65536.0f);
    155     }
    156 
    157     private void preflight_adjust(int dir) {
    158         int newTop = mTop + dir * MATRIX_SIZE;
    159         if (newTop < 0) {
    160             throw new IllegalArgumentException("stack underflow");
    161         }
    162         if (newTop + MATRIX_SIZE > mMatrix.length) {
    163             throw new IllegalArgumentException("stack overflow");
    164         }
    165     }
    166 
    167     private void adjust(int dir) {
    168         mTop += dir * MATRIX_SIZE;
    169     }
    170 
    171     private final static int DEFAULT_MAX_DEPTH = 32;
    172     private final static int MATRIX_SIZE = 16;
    173     private float[] mMatrix;
    174     private int mTop;
    175     private float[] mTemp;
    176 }
    177