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