alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (CubeMapActivity.java)

This example Android source code file (CubeMapActivity.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

activity, android, char_size, drawing, float_size, gl10, gl11, gl11extensionpack, glsurfaceview, graphics, grid, illegalargumentexception, io, nio, opengl, override, renderer, string, vertex_normal_buffer_index_offset, vertex_size

The CubeMapActivity.java Android example source code

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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.example.android.apis.graphics;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;
import javax.microedition.khronos.opengles.GL11ExtensionPack;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.util.Log;

import com.example.android.apis.R;

/**
 * Demonstrate how to use the OES_texture_cube_map extension, available on some
 * high-end OpenGL ES 1.x GPUs.
 */
public class CubeMapActivity extends Activity {
    private GLSurfaceView mGLSurfaceView;
    private class Renderer implements GLSurfaceView.Renderer {
        private boolean mContextSupportsCubeMap;
        private Grid mGrid;
        private int mCubeMapTextureID;
        private boolean mUseTexGen = false;
        private float mAngle;

        public void onDrawFrame(GL10 gl) {
            checkGLError(gl);
            if (mContextSupportsCubeMap) {
                gl.glClearColor(0,0,1,0);
            } else {
                // Current context doesn't support cube maps.
                // Indicate this by drawing a red background.
                gl.glClearColor(1,0,0,0);
            }
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
            gl.glEnable(GL10.GL_DEPTH_TEST);
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();

            GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
            gl.glRotatef(mAngle,        0, 1, 0);
            gl.glRotatef(mAngle*0.25f,  1, 0, 0);

            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

            checkGLError(gl);

            if (mContextSupportsCubeMap) {
                gl.glActiveTexture(GL10.GL_TEXTURE0);
                checkGLError(gl);
                gl.glEnable(GL11ExtensionPack.GL_TEXTURE_CUBE_MAP);
                checkGLError(gl);
                gl.glBindTexture(GL11ExtensionPack.GL_TEXTURE_CUBE_MAP, mCubeMapTextureID);
                checkGLError(gl);
                GL11ExtensionPack gl11ep = (GL11ExtensionPack) gl;
                gl11ep.glTexGeni(GL11ExtensionPack.GL_TEXTURE_GEN_STR,
                        GL11ExtensionPack.GL_TEXTURE_GEN_MODE,
                        GL11ExtensionPack.GL_REFLECTION_MAP);
                checkGLError(gl);
                gl.glEnable(GL11ExtensionPack.GL_TEXTURE_GEN_STR);
                checkGLError(gl);
                gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_DECAL);
            }

            checkGLError(gl);
            mGrid.draw(gl);

            if (mContextSupportsCubeMap) {
                gl.glDisable(GL11ExtensionPack.GL_TEXTURE_GEN_STR);
            }
            checkGLError(gl);

            mAngle += 1.2f;
        }

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            checkGLError(gl);
            gl.glViewport(0, 0, width, height);
            float ratio = (float) width / height;
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
            checkGLError(gl);
        }

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            checkGLError(gl);
            // This test needs to be done each time a context is created,
            // because different contexts may support different extensions.
            mContextSupportsCubeMap = checkIfContextSupportsCubeMap(gl);

            mGrid = generateTorusGrid(gl, 60, 60, 3.0f, 0.75f);

            if (mContextSupportsCubeMap) {
                int[] cubeMapResourceIds = new int[]{
                        R.raw.skycubemap0, R.raw.skycubemap1, R.raw.skycubemap2,
                        R.raw.skycubemap3, R.raw.skycubemap4, R.raw.skycubemap5};
                mCubeMapTextureID = generateCubeMap(gl, cubeMapResourceIds);
            }
            checkGLError(gl);
        }

        private int generateCubeMap(GL10 gl, int[] resourceIds) {
            checkGLError(gl);
            int[] ids = new int[1];
            gl.glGenTextures(1, ids, 0);
            int cubeMapTextureId = ids[0];
            gl.glBindTexture(GL11ExtensionPack.GL_TEXTURE_CUBE_MAP, cubeMapTextureId);
            gl.glTexParameterf(GL11ExtensionPack.GL_TEXTURE_CUBE_MAP,
                    GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
            gl.glTexParameterf(GL11ExtensionPack.GL_TEXTURE_CUBE_MAP,
                    GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

            for (int face = 0; face < 6; face++) {
                InputStream is = getResources().openRawResource(resourceIds[face]);
                Bitmap bitmap;
                try {
                    bitmap = BitmapFactory.decodeStream(is);
                } finally {
                    try {
                        is.close();
                    } catch(IOException e) {
                        Log.e("CubeMap", "Could not decode texture for face " + Integer.toString(face));
                    }
                }
                GLUtils.texImage2D(GL11ExtensionPack.GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0,
                        bitmap, 0);
                bitmap.recycle();
            }
            checkGLError(gl);
            return cubeMapTextureId;
        }

        private Grid generateTorusGrid(GL gl, int uSteps, int vSteps, float majorRadius, float minorRadius) {
            Grid grid = new Grid(uSteps + 1, vSteps + 1);
            for (int j = 0; j <= vSteps; j++) {
                double angleV = Math.PI * 2 * j / vSteps;
                float cosV = (float) Math.cos(angleV);
                float sinV = (float) Math.sin(angleV);
                for (int i = 0; i <= uSteps; i++) {
                    double angleU = Math.PI * 2 * i / uSteps;
                    float cosU = (float) Math.cos(angleU);
                    float sinU = (float) Math.sin(angleU);
                    float d = majorRadius+minorRadius*cosU;
                    float x = d*cosV;
                    float y = d*(-sinV);
                    float z = minorRadius * sinU;

                    float nx = cosV * cosU;
                    float ny = -sinV * cosU;
                    float nz = sinU;

                    float length = (float) Math.sqrt(nx*nx + ny*ny + nz*nz);
                    nx /= length;
                    ny /= length;
                    nz /= length;

                    grid.set(i, j, x, y, z, nx, ny, nz);
                }
            }
            grid.createBufferObjects(gl);
            return grid;
        }

        private boolean checkIfContextSupportsCubeMap(GL10 gl) {
            return checkIfContextSupportsExtension(gl, "GL_OES_texture_cube_map");
        }

        /**
         * This is not the fastest way to check for an extension, but fine if
         * we are only checking for a few extensions each time a context is created.
         * @param gl
         * @param extension
         * @return true if the extension is present in the current context.
         */
        private boolean checkIfContextSupportsExtension(GL10 gl, String extension) {
            String extensions = " " + gl.glGetString(GL10.GL_EXTENSIONS) + " ";
            // The extensions string is padded with spaces between extensions, but not
            // necessarily at the beginning or end. For simplicity, add spaces at the
            // beginning and end of the extensions string and the extension string.
            // This means we can avoid special-case checks for the first or last
            // extension, as well as avoid special-case checks when an extension name
            // is the same as the first part of another extension name.
            return extensions.indexOf(" " + extension + " ") >= 0;
        }
    }

    /** A grid is a topologically rectangular array of vertices.
     *
     * This grid class is customized for the vertex data required for this
     * example.
     *
     * The vertex and index data are held in VBO objects because on most
     * GPUs VBO objects are the fastest way of rendering static vertex
     * and index data.
     *
     */

    private static class Grid {
        // Size of vertex data elements in bytes:
        final static int FLOAT_SIZE = 4;
        final static int CHAR_SIZE = 2;

        // Vertex structure:
        // float x, y, z;
        // float nx, ny, nx;

        final static int VERTEX_SIZE = 6 * FLOAT_SIZE;
        final static int VERTEX_NORMAL_BUFFER_INDEX_OFFSET = 3;

        private int mVertexBufferObjectId;
        private int mElementBufferObjectId;

        // These buffers are used to hold the vertex and index data while
        // constructing the grid. Once createBufferObjects() is called
        // the buffers are nulled out to save memory.

        private ByteBuffer mVertexByteBuffer;
        private FloatBuffer mVertexBuffer;
        private CharBuffer mIndexBuffer;

        private int mW;
        private int mH;
        private int mIndexCount;

        public Grid(int w, int h) {
            if (w < 0 || w >= 65536) {
                throw new IllegalArgumentException("w");
            }
            if (h < 0 || h >= 65536) {
                throw new IllegalArgumentException("h");
            }
            if (w * h >= 65536) {
                throw new IllegalArgumentException("w * h >= 65536");
            }

            mW = w;
            mH = h;
            int size = w * h;

            mVertexByteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * size)
            .order(ByteOrder.nativeOrder());
            mVertexBuffer = mVertexByteBuffer.asFloatBuffer();

            int quadW = mW - 1;
            int quadH = mH - 1;
            int quadCount = quadW * quadH;
            int indexCount = quadCount * 6;
            mIndexCount = indexCount;
            mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount)
            .order(ByteOrder.nativeOrder()).asCharBuffer();

            /*
             * Initialize triangle list mesh.
             *
             *     [0]-----[  1] ...
             *      |    /   |
             *      |   /    |
             *      |  /     |
             *     [w]-----[w+1] ...
             *      |       |
             *
             */

            {
                int i = 0;
                for (int y = 0; y < quadH; y++) {
                    for (int x = 0; x < quadW; x++) {
                        char a = (char) (y * mW + x);
                        char b = (char) (y * mW + x + 1);
                        char c = (char) ((y + 1) * mW + x);
                        char d = (char) ((y + 1) * mW + x + 1);

                        mIndexBuffer.put(i++, a);
                        mIndexBuffer.put(i++, c);
                        mIndexBuffer.put(i++, b);

                        mIndexBuffer.put(i++, b);
                        mIndexBuffer.put(i++, c);
                        mIndexBuffer.put(i++, d);
                    }
                }
            }
        }

        public void set(int i, int j, float x, float y, float z, float nx, float ny, float nz) {
            if (i < 0 || i >= mW) {
                throw new IllegalArgumentException("i");
            }
            if (j < 0 || j >= mH) {
                throw new IllegalArgumentException("j");
            }

            int index = mW * j + i;

            mVertexBuffer.position(index * VERTEX_SIZE / FLOAT_SIZE);
            mVertexBuffer.put(x);
            mVertexBuffer.put(y);
            mVertexBuffer.put(z);
            mVertexBuffer.put(nx);
            mVertexBuffer.put(ny);
            mVertexBuffer.put(nz);
        }

        public void createBufferObjects(GL gl) {
            checkGLError(gl);
            // Generate a the vertex and element buffer IDs
            int[] vboIds = new int[2];
            GL11 gl11 = (GL11) gl;
            gl11.glGenBuffers(2, vboIds, 0);
            mVertexBufferObjectId = vboIds[0];
            mElementBufferObjectId = vboIds[1];

            // Upload the vertex data
            gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertexBufferObjectId);
            mVertexByteBuffer.position(0);
            gl11.glBufferData(GL11.GL_ARRAY_BUFFER, mVertexByteBuffer.capacity(), mVertexByteBuffer, GL11.GL_STATIC_DRAW);

            gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mElementBufferObjectId);
            mIndexBuffer.position(0);
            gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer.capacity() * CHAR_SIZE, mIndexBuffer, GL11.GL_STATIC_DRAW);

            // We don't need the in-memory data any more
            mVertexBuffer = null;
            mVertexByteBuffer = null;
            mIndexBuffer = null;
            checkGLError(gl);
        }

        public void draw(GL10 gl) {
            checkGLError(gl);
            GL11 gl11 = (GL11) gl;

            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

            gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertexBufferObjectId);
            gl11.glVertexPointer(3, GL10.GL_FLOAT, VERTEX_SIZE, 0);

            gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
            gl11.glNormalPointer(GL10.GL_FLOAT, VERTEX_SIZE, VERTEX_NORMAL_BUFFER_INDEX_OFFSET * FLOAT_SIZE);

            gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mElementBufferObjectId);
            gl11.glDrawElements(GL10.GL_TRIANGLES, mIndexCount, GL10.GL_UNSIGNED_SHORT, 0);
            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
            gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
            gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
            gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
            checkGLError(gl);
        }
    }

    static void checkGLError(GL gl) {
        int error = ((GL10) gl).glGetError();
        if (error != GL10.GL_NO_ERROR) {
            throw new RuntimeException("GLError 0x" + Integer.toHexString(error));
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create our surface view and set it as the content of our
        // Activity
        mGLSurfaceView = new GLSurfaceView(this);
        mGLSurfaceView.setRenderer(new Renderer());
        setContentView(mGLSurfaceView);
    }

    @Override
    protected void onResume() {
        // Ideally a game should implement onResume() and onPause()
        // to take appropriate action when the activity looses focus
        super.onResume();
        mGLSurfaceView.onResume();
    }

    @Override
    protected void onPause() {
        // Ideally a game should implement onResume() and onPause()
        // to take appropriate action when the activity looses focus
        super.onPause();
        mGLSurfaceView.onPause();
    }
}

Other Android examples (source code examples)

Here is a short list of links related to this Android CubeMapActivity.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.