Recipe Drawing 3D Images

Android supports the Open Graphics Library for Embedded Systems (OpenGL ES).This recipe, based on an Android API Demo, shows how to create a three-dimensional pyramid shape using this library and have it bounce around the screen and spin as it reflects off the edges. The main activity requires two separate support classes: one to define the shape shown in Listing 5.17 and one to render the shape shown in Listing 5.18.

Listing 5.17 src/com/cookbook/open_gl/Pyramid.java package com.cookbook.open_gl;

import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

class Pyramid {

public Pyramid() {

int one = 0x10000;

/* square base and point top to make a pyramid */ int vertices[] = {

-one,

-one,

-one,

-one,

one,

-one,

one,

one,

-one,

one,

-one,

-one

0, 0,

one

one, 0, one, one, one, 0, one, one, one, 0, one, one, one, 0, one, one, one, one, one, one

/* triangles of the vertices above to build the shape */ byte indices[] = {

// Buffers to be passed to gl*Pointer() functions

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);

vbb.order(ByteOrder.nativeOrder());

mVertexBuffer = vbb.asIntBuffer();

mVertexBuffer.put(vertices);

mVertexBuffer.position(0);

ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);

cbb.order(ByteOrder.nativeOrder());

mColorBuffer = cbb.asIntBuffer();

mColorBuffer.put(colors);

mColorBuffer.position(0);

mIndexBuffer = ByteBuffer.allocateDirect(indices.length);

mlndexBuffer.put(indices);

mIndexBuffer.position(0);

public void draw(GL10 gl) {

gl.glFrontFace(GL10.GL_CW);

gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer); gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer); gl.glDrawElements(GL10.GL_TRIANGLES, 18, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);

private IntBuffer mVertexBuffer; private IntBuffer mColorBuffer; private ByteBuffer mIndexBuffer;

Note the pyramid has five vertices: four in a square base and one as the raised pointy top. It is important the vertices are in an order that can be traversed by a line across the figure (not just randomly listed).The center of the shape is at the origin (0, 0, 0).

The five colors in RGBA form correspond with the vertices; the base vertices are defined as purple and the top vertex as white. The library gradates the colors to fill in the shape. Different colors or shading help provide a three-dimensional look.

The main draw() method is defined for triangle elements.The square base can be made of two triangles and each upper side is a triangle, which leads to 6 total triangles or 18 indices.The pyramid is shown in two different perspectives as it bounces around in Figure 5.5.

OpenGIExample

DpenGIExample

Figure 5.5 The rotating, bouncing pyramid created with OpenGL ES.

Then a separate class can be created to extend GLSurfaceView.Renderer to render this pyramid using the OpenGL ES library, as shown in Listing 5.18.Three methods need to be implemented:

■ onSurfaceCreated()—One-time initialization of the OpenGL framework

■ onSurfaceChanged()—Sets the projection at start-up or when the viewport is resized

■ onDrawFrame()—Draws the graphic image every frame Listing 5.18 src/com/cookbook/open_gl/PyramidRenderer.java package com.cookbook.open_gl;

import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;

* Render a tumbling Pyramid */

class PyramidRenderer implements GLSurfaceView.Renderer {

public PyramidRenderer(boolean useTranslucentBackground) { mTranslucentBackground = useTranslucentBackground; mPyramid = new Pyramid();

public void onDrawFrame(GL1O gl) { /* clear the screen */

gl.glClear(GL1O.GL_COLOR_BUFFER_BIT | GL1O.GL_DEPTH_BUFFER_BIT);

gl.glMatrixMode(GL1O.GL_MODELVIEW);

gl.glLoadIdentity();

gl.glTranslatef(mCenter[O], mCenter[1], mCenter[2]); gl.glRotatef(mAngle, 0, 1, 0);

gl.glEnableClientState(GL1O.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL1O.GL_COLOR_ARRAY);

mPyramid.draw(gl);

mAngle += mAngleDelta;

/* draw it bouncing off the walls */ mCenter[O] += mVel[O]; mCenter[1] += mVel[1];

if(Math.abs(mCenter[O])>4.Of) { mVel[O] = -mVel[O];

if(Math.abs(mCenter[1])>6.Of) { mVel[1] = -mVel[1];

public void onSurfaceChanged(GL1O gl, int width, int height) { gl.glViewport(O, O, width, height);

/* Set a new projection when the viewport is resized */ float ratio = (float) width / height;

gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity();

public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glDisable(GL10.GL_DITHER);

/* one-time OpenGL initialization */ gl.glHint(GL10.GL_PERSPECTIVE_C0RRECTI0N_HINT, GL10.GL_FASTEST);

if (mTranslucentBackground) { gl.glClearColor(0,0,0,0); } else {

gl.glClearColor(1,1,1,1);

gl.glEnable(GL10.GL_CULL_FACE);

gl.glShadeModel(GL10.GL_SM00TH);

gl.glEnable(GL10.GL_DEPTH_TEST);

private boolean mTranslucentBackground;

private Pyramid mPyramid;

private float mAngle, mAngleDelta=0;

private float mVel[]={0.025f, 0.03535227f, 0f};

The dynamics of the bouncing ball are captured in the onDrawFrame() method.The screen is cleared for the new image, and then the pyramid center is set to mCenter[] .The screen is defined as the origin, so the starting point of (0, 0, -10) sets the shape back from right up against the screen. At each update, the shape is rotated by mAngleDelta and translates by mVel[] .The mVel in the x- and y-direction are set differently enough to provide a nice diversity of bouncing around the walls.When the shape reaches the edge of the screen, the velocity sign is switched to have it bounce back.

Finally, the main activity must set the content view to the OpenGL ES object, as shown in Listing 5.19.The shape movement can be paused and resumed along with the activity.

Listing 5.19 src/com/cookbook/open_gl/OpenGlExample.java package com.cookbook.open_gl;

import android.app.Activity; import android.opengl.GLSurfaceView;

import android.os.Bundle;

/* Wrapper activity demonstrating the use of GLSurfaceView, a view

* that uses OpenGL drawing into a dedicated surface. */ public class OpenGlExample extends Activity {

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

// Set our Preview view as the Activity content mGLSurfaceView = new GLSurfaceView(this); mGLSurfaceView.setRenderer(new PyramidRenderer(true)); setContentView(mGLSurfaceView);

^Override protected void onResume() { super.onResume(); mGLSurfaceView.onResume();

^Override protected void onPause() { super.onPause(); mGLSurfaceView.onPause();

private GLSurfaceView mGLSurfaceView;

This page intentionally left blank

Character Building Thought Power

Character Building Thought Power

Character-Building Thought Power by Ralph Waldo Trine. Ralph draws a distinct line between bad and good habits. In this book, every effort is made by the writer to explain what comprises good habits and why every one needs it early in life. It draws the conclusion that habits nurtured in early life concretize into impulses in future for the good or bad of the subject.

Get My Free Ebook


Responses

  • semrawit abaalom
    How to draw 3d images in android?
    6 years ago

Post a comment