/** * Copyright 2010 Per-Erik Bergman (per-erik.bergman@jayway.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alarmclocksnoozers.runnershigh; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; import android.graphics.Bitmap; import android.opengl.GLUtils; /** * Mesh is a base class for 3D objects making it easier to create and maintain * new primitives. * * @author Per-Erik Bergman (per-erik.bergman@jayway.com) * */ public class Mesh { // Our vertex buffer. private FloatBuffer mVerticesBuffer = null; // Our index buffer. private ShortBuffer mIndicesBuffer = null; // Our UV texture buffer. private FloatBuffer mTextureBuffer; // New variable. // Our texture id. private int mTextureId = -1; // New variable. // The bitmap we want to load as a texture. private Bitmap mBitmap; // New variable. // Indicates if we need to load the texture. private boolean mShouldLoadTexture = false; // New variable. private int mWrapS; private int mWrapT; private ByteBuffer byteBuf; // The number of indices. private int mNumOfIndices = -1; // Flat Color private final float[] mRGBA = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; // Smooth Colors private FloatBuffer mColorBuffer = null; // Translate params. public float x = 0; public float y = 0; public float z = 0; // Rotate params. public float rx = 0; public float ry = 0; public float rz = 0; public boolean shouldBeDrawn = true; /** * Render the mesh. * * @param gl * the OpenGL context to render to. */ public void draw(GL10 gl) { if (!shouldBeDrawn) return; gl.glPushMatrix(); // Counter-clockwise winding. gl.glFrontFace(GL10.GL_CCW); // Enable face culling. gl.glEnable(GL10.GL_CULL_FACE); // What faces to remove with the face culling. gl.glCullFace(GL10.GL_BACK); // Enabled the vertices buffer for writing and to be used during // rendering. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // Specifies the location and data format of an array of vertex // coordinates to use when rendering. gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVerticesBuffer); // Set flat color gl.glColor4f(mRGBA[0], mRGBA[1], mRGBA[2], mRGBA[3]); // Smooth color if (mColorBuffer != null) { // Enable the color array buffer to be used during rendering. gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer); } // New part... if (mShouldLoadTexture) { loadGLTexture(gl); mShouldLoadTexture = false; } if (mTextureId != -1 && mTextureBuffer != null) { gl.glEnable(GL10.GL_TEXTURE_2D); // Enable the texture state gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Point to our buffers gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer); gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId); } // ... end new part. gl.glTranslatef(x, y, z); gl.glRotatef(rx, 1, 0, 0); gl.glRotatef(ry, 0, 1, 0); gl.glRotatef(rz, 0, 0, 1); // Point out the where the color buffer is. gl.glDrawElements(GL10.GL_TRIANGLES, mNumOfIndices, GL10.GL_UNSIGNED_SHORT, mIndicesBuffer); // Disable the vertices buffer. gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // New part... if (mTextureId != -1 && mTextureBuffer != null) { gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); } // ... end new part. // Disable face culling. gl.glDisable(GL10.GL_CULL_FACE); gl.glPopMatrix(); } /** * Set the vertices. * * @param vertices */ protected void setVertices(float[] vertices) { // a float is 4 bytes, therefore we multiply the number if // vertices with 4. ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); mVerticesBuffer = vbb.asFloatBuffer(); mVerticesBuffer.put(vertices); mVerticesBuffer.position(0); } /** * Set the indices. * * @param indices */ protected void setIndices(short[] indices) { // short is 2 bytes, therefore we multiply the number if // vertices with 2. ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); ibb.order(ByteOrder.nativeOrder()); mIndicesBuffer = ibb.asShortBuffer(); mIndicesBuffer.put(indices); mIndicesBuffer.position(0); mNumOfIndices = indices.length; } /** * Set the texture coordinates. * * @param textureCoords */ protected void setTextureCoordinates(float[] textureCoords) { // float is 4 bytes, therefore we multiply the number if // vertices with 4. byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4); byteBuf.order(ByteOrder.nativeOrder()); mTextureBuffer = byteBuf.asFloatBuffer(); mTextureBuffer.put(textureCoords); mTextureBuffer.position(0); } /** * Set one flat color on the mesh. * * @param red * @param green * @param blue * @param alpha */ protected void setColor(float red, float green, float blue, float alpha) { mRGBA[0] = red; mRGBA[1] = green; mRGBA[2] = blue; mRGBA[3] = alpha; } /** * Set the colors * * @param colors */ protected void setColors(float[] colors) { // float has 4 bytes. ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4); cbb.order(ByteOrder.nativeOrder()); mColorBuffer = cbb.asFloatBuffer(); mColorBuffer.put(colors); mColorBuffer.position(0); } /** * Set the bitmap to load into a texture. * * @param bitmap */ public void loadBitmap(Bitmap bitmap) { this.mBitmap = bitmap; mShouldLoadTexture = true; mWrapS = GL10.GL_CLAMP_TO_EDGE; mWrapT = GL10.GL_CLAMP_TO_EDGE; } public void loadBitmap(Bitmap bitmap, int wrapS, int wrapT) { this.mBitmap = bitmap; mShouldLoadTexture = true; mWrapS = wrapS; mWrapT = wrapT; } /** * Loads the texture. * * @param gl */ private void loadGLTexture(GL10 gl) { // New function // Generate one texture pointer... int[] textures = new int[1]; gl.glGenTextures(1, textures, 0); mTextureId = textures[0]; gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); if ( gl instanceof GL11 ) { gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE); } // ...and bind it to our array gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId); // Create Nearest Filtered Texture gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST); // Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, mWrapS); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, mWrapT); // Use the Android GLUtils to specify a two-dimensional texture image // from our bitmap GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0); } }