Home | History | Annotate | Download | only in globaltime
      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.android.globaltime;
     18 
     19 import java.nio.Buffer;
     20 import java.nio.ByteBuffer;
     21 import java.nio.ByteOrder;
     22 import java.nio.IntBuffer;
     23 import java.nio.ShortBuffer;
     24 
     25 import javax.microedition.khronos.opengles.GL10;
     26 
     27 /**
     28  * An abstract superclass for various three-dimensional objects to be drawn
     29  * using OpenGL ES.  Each subclass is responsible for setting up NIO buffers
     30  * containing vertices, texture coordinates, colors, normals, and indices.
     31  * The {@link #draw(GL10)} method draws the object to the given OpenGL context.
     32  */
     33 public abstract class Shape {
     34 
     35     public static final int INT_BYTES = 4;
     36     public static final int SHORT_BYTES = 2;
     37 
     38     public static final float DEGREES_TO_RADIANS = (float) Math.PI / 180.0f;
     39     public static final float PI = (float) Math.PI;
     40     public static final float TWO_PI = (float) (2.0 * Math.PI);
     41     public static final float PI_OVER_TWO = (float) (Math.PI / 2.0);
     42 
     43     protected int mPrimitive;
     44     protected int mIndexDatatype;
     45 
     46     protected boolean mEmitTextureCoordinates;
     47     protected boolean mEmitNormals;
     48     protected boolean mEmitColors;
     49 
     50     protected IntBuffer mVertexBuffer;
     51     protected IntBuffer mTexcoordBuffer;
     52     protected IntBuffer mColorBuffer;
     53     protected IntBuffer mNormalBuffer;
     54     protected Buffer mIndexBuffer;
     55     protected int mNumIndices = -1;
     56 
     57     /**
     58      * Constructs a Shape.
     59      *
     60      * @param primitive a GL primitive type understood by glDrawElements,
     61      * such as GL10.GL_TRIANGLES
     62      * @param indexDatatype the GL datatype for the  index buffer, such as
     63      * GL10.GL_UNSIGNED_SHORT
     64      * @param emitTextureCoordinates true to enable use of the texture
     65      * coordinate buffer
     66      * @param emitNormals true to enable use of the normal buffer
     67      * @param emitColors true to enable use of the color buffer
     68      */
     69     protected Shape(int primitive,
     70         int indexDatatype,
     71         boolean emitTextureCoordinates,
     72         boolean emitNormals,
     73         boolean emitColors) {
     74         mPrimitive = primitive;
     75         mIndexDatatype = indexDatatype;
     76         mEmitTextureCoordinates = emitTextureCoordinates;
     77         mEmitNormals = emitNormals;
     78         mEmitColors = emitColors;
     79     }
     80 
     81     /**
     82      * Converts the given floating-point value to fixed-point.
     83      */
     84     public static int toFixed(float x) {
     85         return (int) (x * 65536.0);
     86     }
     87 
     88     /**
     89      * Converts the given fixed-point value to floating-point.
     90      */
     91     public static float toFloat(int x) {
     92         return (float) (x / 65536.0);
     93     }
     94 
     95     /**
     96      * Computes the cross-product of two vectors p and q and places
     97      * the result in out.
     98      */
     99     public static void cross(float[] p, float[] q, float[] out) {
    100         out[0] = p[1] * q[2] - p[2] * q[1];
    101         out[1] = p[2] * q[0] - p[0] * q[2];
    102         out[2] = p[0] * q[1] - p[1] * q[0];
    103     }
    104 
    105     /**
    106      * Returns the length of a vector, given as three floats.
    107      */
    108     public static float length(float vx, float vy, float vz) {
    109         return (float) Math.sqrt(vx * vx + vy * vy + vz * vz);
    110     }
    111 
    112     /**
    113      * Returns the length of a vector, given as an array of three floats.
    114      */
    115     public static float length(float[] v) {
    116         return length(v[0], v[1], v[2]);
    117     }
    118 
    119     /**
    120      * Normalizes the given vector of three floats to have length == 1.0.
    121      * Vectors with length zero are unaffected.
    122      */
    123     public static void normalize(float[] v) {
    124         float length = length(v);
    125         if (length != 0.0f) {
    126             float norm = 1.0f / length;
    127             v[0] *= norm;
    128             v[1] *= norm;
    129             v[2] *= norm;
    130         }
    131     }
    132 
    133     /**
    134      * Returns the number of triangles associated with this shape.
    135      */
    136     public int getNumTriangles() {
    137         if (mPrimitive == GL10.GL_TRIANGLES) {
    138             return mIndexBuffer.capacity() / 3;
    139         } else if (mPrimitive == GL10.GL_TRIANGLE_STRIP) {
    140             return mIndexBuffer.capacity() - 2;
    141         }
    142         return 0;
    143     }
    144 
    145     /**
    146      * Copies the given data into the instance
    147      * variables mVertexBuffer, mTexcoordBuffer, mNormalBuffer, mColorBuffer,
    148      * and mIndexBuffer.
    149      *
    150      * @param vertices an array of fixed-point vertex coordinates
    151      * @param texcoords an array of fixed-point texture coordinates
    152      * @param normals an array of fixed-point normal vector coordinates
    153      * @param colors an array of fixed-point color channel values
    154      * @param indices an array of short indices
    155      */
    156     public void allocateBuffers(int[] vertices, int[] texcoords, int[] normals,
    157         int[] colors, short[] indices) {
    158         allocate(vertices, texcoords, normals, colors);
    159 
    160         ByteBuffer ibb =
    161             ByteBuffer.allocateDirect(indices.length * SHORT_BYTES);
    162         ibb.order(ByteOrder.nativeOrder());
    163         ShortBuffer shortIndexBuffer = ibb.asShortBuffer();
    164         shortIndexBuffer.put(indices);
    165         shortIndexBuffer.position(0);
    166         this.mIndexBuffer = shortIndexBuffer;
    167     }
    168 
    169     /**
    170      * Copies the given data into the instance
    171      * variables mVertexBuffer, mTexcoordBuffer, mNormalBuffer, mColorBuffer,
    172      * and mIndexBuffer.
    173      *
    174      * @param vertices an array of fixed-point vertex coordinates
    175      * @param texcoords an array of fixed-point texture coordinates
    176      * @param normals an array of fixed-point normal vector coordinates
    177      * @param colors an array of fixed-point color channel values
    178      * @param indices an array of int indices
    179      */
    180     public void allocateBuffers(int[] vertices, int[] texcoords, int[] normals,
    181         int[] colors, int[] indices) {
    182         allocate(vertices, texcoords, normals, colors);
    183 
    184         ByteBuffer ibb =
    185             ByteBuffer.allocateDirect(indices.length * INT_BYTES);
    186         ibb.order(ByteOrder.nativeOrder());
    187         IntBuffer intIndexBuffer = ibb.asIntBuffer();
    188         intIndexBuffer.put(indices);
    189         intIndexBuffer.position(0);
    190         this.mIndexBuffer = intIndexBuffer;
    191     }
    192 
    193     /**
    194      * Allocate the vertex, texture coordinate, normal, and color buffer.
    195      */
    196     private void allocate(int[] vertices, int[] texcoords, int[] normals,
    197         int[] colors) {
    198         ByteBuffer vbb =
    199             ByteBuffer.allocateDirect(vertices.length * INT_BYTES);
    200         vbb.order(ByteOrder.nativeOrder());
    201         mVertexBuffer = vbb.asIntBuffer();
    202         mVertexBuffer.put(vertices);
    203         mVertexBuffer.position(0);
    204 
    205         if ((texcoords != null) && mEmitTextureCoordinates) {
    206             ByteBuffer tbb =
    207                 ByteBuffer.allocateDirect(texcoords.length * INT_BYTES);
    208             tbb.order(ByteOrder.nativeOrder());
    209             mTexcoordBuffer = tbb.asIntBuffer();
    210             mTexcoordBuffer.put(texcoords);
    211             mTexcoordBuffer.position(0);
    212         }
    213 
    214         if ((normals != null) && mEmitNormals) {
    215             ByteBuffer nbb =
    216                 ByteBuffer.allocateDirect(normals.length * INT_BYTES);
    217             nbb.order(ByteOrder.nativeOrder());
    218             mNormalBuffer = nbb.asIntBuffer();
    219             mNormalBuffer.put(normals);
    220             mNormalBuffer.position(0);
    221         }
    222 
    223         if ((colors != null) && mEmitColors) {
    224             ByteBuffer cbb =
    225                 ByteBuffer.allocateDirect(colors.length * INT_BYTES);
    226             cbb.order(ByteOrder.nativeOrder());
    227             mColorBuffer = cbb.asIntBuffer();
    228             mColorBuffer.put(colors);
    229             mColorBuffer.position(0);
    230         }
    231     }
    232 
    233     /**
    234      * Draws the shape to the given OpenGL ES 1.0 context.  Texture coordinates,
    235      * normals, and colors are emitted according the the preferences set for
    236      * this shape.
    237      */
    238     public void draw(GL10 gl) {
    239         gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
    240         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    241 
    242         if (mEmitTextureCoordinates) {
    243             gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    244             gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mTexcoordBuffer);
    245             gl.glEnable(GL10.GL_TEXTURE_2D);
    246         } else {
    247             gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    248             gl.glDisable(GL10.GL_TEXTURE_2D);
    249         }
    250 
    251         if (mEmitNormals) {
    252             gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
    253             gl.glNormalPointer(GL10.GL_FIXED, 0, mNormalBuffer);
    254         } else {
    255             gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
    256         }
    257 
    258         if (mEmitColors) {
    259             gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    260             gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
    261         } else {
    262             gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
    263         }
    264 
    265         gl.glDrawElements(mPrimitive,
    266                           mNumIndices > 0 ? mNumIndices : mIndexBuffer.capacity(),
    267                           mIndexDatatype,
    268                           mIndexBuffer);
    269     }
    270 }
    271