Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2008 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.example.android.apis.graphics;
     18 
     19 import static android.opengl.GLES10.*;
     20 
     21 import java.io.IOException;
     22 import java.io.InputStream;
     23 import java.nio.ByteBuffer;
     24 import java.nio.ByteOrder;
     25 import java.nio.FloatBuffer;
     26 import java.nio.ShortBuffer;
     27 
     28 import javax.microedition.khronos.egl.EGLConfig;
     29 import javax.microedition.khronos.opengles.GL10;
     30 
     31 import android.content.Context;
     32 import android.graphics.Bitmap;
     33 import android.graphics.BitmapFactory;
     34 import android.opengl.GLSurfaceView;
     35 import android.opengl.GLU;
     36 import android.opengl.GLUtils;
     37 import android.os.SystemClock;
     38 
     39 import com.example.android.apis.R;
     40 
     41 /**
     42  * A GLSurfaceView.Renderer that uses the Android-specific
     43  * android.opengl.GLESXXX static OpenGL ES APIs. The static APIs
     44  * expose more of the OpenGL ES features than the
     45  * javax.microedition.khronos.opengles APIs, and also
     46  * provide a programming model that is closer to the C OpenGL ES APIs, which
     47  * may make it easier to reuse code and documentation written for the
     48  * C OpenGL ES APIs.
     49  *
     50  */
     51 public class StaticTriangleRenderer implements GLSurfaceView.Renderer{
     52 
     53     public interface TextureLoader {
     54         /**
     55          * Load a texture into the currently bound OpenGL texture.
     56          */
     57         void load(GL10 gl);
     58     }
     59 
     60     public StaticTriangleRenderer(Context context) {
     61         init(context, new RobotTextureLoader());
     62     }
     63 
     64     public StaticTriangleRenderer(Context context, TextureLoader loader) {
     65         init(context, loader);
     66     }
     67 
     68     private void init(Context context, TextureLoader loader) {
     69         mContext = context;
     70         mTriangle = new Triangle();
     71         mTextureLoader = loader;
     72     }
     73 
     74     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
     75         /*
     76          * By default, OpenGL enables features that improve quality
     77          * but reduce performance. One might want to tweak that
     78          * especially on software renderer.
     79          */
     80         glDisable(GL_DITHER);
     81 
     82         /*
     83          * Some one-time OpenGL initialization can be made here
     84          * probably based on features of this particular context
     85          */
     86         glHint(GL_PERSPECTIVE_CORRECTION_HINT,
     87                 GL_FASTEST);
     88 
     89         glClearColor(.5f, .5f, .5f, 1);
     90         glShadeModel(GL_SMOOTH);
     91         glEnable(GL_DEPTH_TEST);
     92         glEnable(GL_TEXTURE_2D);
     93 
     94         /*
     95          * Create our texture. This has to be done each time the
     96          * surface is created.
     97          */
     98 
     99         int[] textures = new int[1];
    100         glGenTextures(1, textures, 0);
    101 
    102         mTextureID = textures[0];
    103         glBindTexture(GL_TEXTURE_2D, mTextureID);
    104 
    105         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
    106                 GL_NEAREST);
    107         glTexParameterf(GL_TEXTURE_2D,
    108                 GL_TEXTURE_MAG_FILTER,
    109                 GL_LINEAR);
    110 
    111         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
    112                 GL_CLAMP_TO_EDGE);
    113         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
    114                 GL_CLAMP_TO_EDGE);
    115 
    116         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
    117                 GL_REPLACE);
    118         mTextureLoader.load(gl);
    119     }
    120 
    121     public void onDrawFrame(GL10 gl) {
    122         /*
    123          * By default, OpenGL enables features that improve quality
    124          * but reduce performance. One might want to tweak that
    125          * especially on software renderer.
    126          */
    127         glDisable(GL_DITHER);
    128 
    129         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
    130                 GL_MODULATE);
    131 
    132         /*
    133          * Usually, the first thing one might want to do is to clear
    134          * the screen. The most efficient way of doing this is to use
    135          * glClear().
    136          */
    137 
    138         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    139 
    140         /*
    141          * Now we're ready to draw some 3D objects
    142          */
    143 
    144         glMatrixMode(GL_MODELVIEW);
    145         glLoadIdentity();
    146 
    147         GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    148 
    149         glEnableClientState(GL_VERTEX_ARRAY);
    150         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    151 
    152         glActiveTexture(GL_TEXTURE0);
    153         glBindTexture(GL_TEXTURE_2D, mTextureID);
    154         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
    155                 GL_REPEAT);
    156         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
    157                 GL_REPEAT);
    158 
    159         long time = SystemClock.uptimeMillis() % 4000L;
    160         float angle = 0.090f * ((int) time);
    161 
    162         glRotatef(angle, 0, 0, 1.0f);
    163 
    164         mTriangle.draw(gl);
    165     }
    166 
    167     public void onSurfaceChanged(GL10 gl, int w, int h) {
    168         glViewport(0, 0, w, h);
    169 
    170         /*
    171         * Set our projection matrix. This doesn't have to be done
    172         * each time we draw, but usually a new projection needs to
    173         * be set when the viewport is resized.
    174         */
    175 
    176         float ratio = (float) w / h;
    177         glMatrixMode(GL_PROJECTION);
    178         glLoadIdentity();
    179         glFrustumf(-ratio, ratio, -1, 1, 3, 7);
    180     }
    181 
    182     private Context mContext;
    183     private Triangle mTriangle;
    184     private int mTextureID;
    185     private TextureLoader mTextureLoader;
    186 
    187     private class RobotTextureLoader implements TextureLoader {
    188         public void load(GL10 gl) {
    189             InputStream is = mContext.getResources().openRawResource(
    190                     R.raw.robot);
    191             Bitmap bitmap;
    192             try {
    193                 bitmap = BitmapFactory.decodeStream(is);
    194             } finally {
    195                 try {
    196                     is.close();
    197                 } catch (IOException e) {
    198                     // Ignore.
    199                 }
    200             }
    201 
    202             GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
    203             bitmap.recycle();
    204         }
    205     }
    206 
    207     static class Triangle {
    208         public Triangle() {
    209 
    210             // Buffers to be passed to gl*Pointer() functions
    211             // must be direct, i.e., they must be placed on the
    212             // native heap where the garbage collector cannot
    213             // move them.
    214             //
    215             // Buffers with multi-byte datatypes (e.g., short, int, float)
    216             // must have their byte order set to native order
    217 
    218             ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4);
    219             vbb.order(ByteOrder.nativeOrder());
    220             mFVertexBuffer = vbb.asFloatBuffer();
    221 
    222             ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
    223             tbb.order(ByteOrder.nativeOrder());
    224             mTexBuffer = tbb.asFloatBuffer();
    225 
    226             ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2);
    227             ibb.order(ByteOrder.nativeOrder());
    228             mIndexBuffer = ibb.asShortBuffer();
    229 
    230             // A unit-sided equilateral triangle centered on the origin.
    231             float[] coords = {
    232                     // X, Y, Z
    233                     -0.5f, -0.25f, 0,
    234                      0.5f, -0.25f, 0,
    235                      0.0f,  0.559016994f, 0
    236             };
    237 
    238             for (int i = 0; i < VERTS; i++) {
    239                 for(int j = 0; j < 3; j++) {
    240                     mFVertexBuffer.put(coords[i*3+j] * 2.0f);
    241                 }
    242             }
    243 
    244             for (int i = 0; i < VERTS; i++) {
    245                 for(int j = 0; j < 2; j++) {
    246                     mTexBuffer.put(coords[i*3+j] * 2.0f + 0.5f);
    247                 }
    248             }
    249 
    250             for(int i = 0; i < VERTS; i++) {
    251                 mIndexBuffer.put((short) i);
    252             }
    253 
    254             mFVertexBuffer.position(0);
    255             mTexBuffer.position(0);
    256             mIndexBuffer.position(0);
    257         }
    258 
    259         public void draw(GL10 gl) {
    260             glFrontFace(GL_CCW);
    261             glVertexPointer(3, GL_FLOAT, 0, mFVertexBuffer);
    262             glEnable(GL_TEXTURE_2D);
    263             glTexCoordPointer(2, GL_FLOAT, 0, mTexBuffer);
    264             glDrawElements(GL_TRIANGLE_STRIP, VERTS,
    265                     GL_UNSIGNED_SHORT, mIndexBuffer);
    266         }
    267 
    268         private final static int VERTS = 3;
    269 
    270         private FloatBuffer mFVertexBuffer;
    271         private FloatBuffer mTexBuffer;
    272         private ShortBuffer mIndexBuffer;
    273     }
    274 }
    275