Draw a Bitmap using OpenGL

Problems with Canvas, OpenGL, etc...

Draw a Bitmap using OpenGL

Postby underminedsk » Tue Jun 08, 2010 9:18 pm

Hi all,

I am trying to draw a bitmap to the screen from a particular perspective using openGL. I have the 4x4 matrix T which specifies how the bitmap is oriented in 3D space, but I am unsure how to draw png files using OpenGLes.

Can someone provide me with a quick sample of code that shows how to do this, or link me to a good example on the web?

Thanks!
underminedsk
Developer
Developer
 
Posts: 26
Joined: Tue Mar 02, 2010 3:36 am

Top

Re: Draw a Bitmap using OpenGL

Postby ShadowKntSDS » Tue Jun 08, 2010 10:54 pm

You best bet is draw the bitmap to a quad and map you bitmap to it as a texture. You can then manipulate the quad using your transforms. I'll see if i can find a quick demo. SpriteMethodTest (google example code) has several methods for doing this.
ShadowKntSDS
Junior Developer
Junior Developer
 
Posts: 15
Joined: Wed Apr 28, 2010 10:29 pm

Re: Draw a Bitmap using OpenGL

Postby IronChef253 » Sat Jun 19, 2010 7:14 am

I got mine working today e.g. bitmap applied to a quad. It works very nicely although I have problems animating it.

I will copy below. You need two main pieces: A quad with a texture applied to it (in my case R.drawable.smurf). Remember that the image dimensions MUST be a power of four for things to work.

Below I have copied most of what you need to get this working: A "Run" activity that launches things, a "Quad" claass that textures a quad and a class to do all the fun rendering things (this is based on the NeHe 6 tutorial).


Code: Select all
package com.nea.nehe.lesson06;

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

/**
* The initial Android Activity, setting and initiating
* the OpenGL ES Renderer Class @see Lesson06.java
*
* @author Savas Ziplies (nea/INsanityDesign)
*/
public class Run extends Activity {

   /** The OpenGL View */
   private GLSurfaceView glSurface;

   /**
    * Initiate the OpenGL View and set our own
    * Renderer (@see Lesson06.java)
    */
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      //Create an Instance with this Activity
      glSurface = new GLSurfaceView(this);
      //Set our own Renderer and hand the renderer this Activity Context
      glSurface.setRenderer(new Lesson06(this));
      //Set the GLSurface as View to this Activity
      setContentView(glSurface);
   }

   /**
    * Remember to resume the glSurface
    */
   @Override
   protected void onResume() {
      super.onResume();
      glSurface.onResume();
   }

   /**
    * Also pause the glSurface
    */
   @Override
   protected void onPause() {
      super.onPause();
      glSurface.onPause();
   }
   
}






Code: Select all

package com.nea.nehe.lesson06;

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

import android.content.Context;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;

/**
* This is a port of the {@link http://nehe.gamedev.net} OpenGL
* tutorials to the Android 1.5 OpenGL ES platform. Thanks to
* NeHe and all contributors for their great tutorials and great
* documentation. This source should be used together with the
* textual explanations made at {@link http://nehe.gamedev.net}.
* The code is based on the original Visual C++ code with all
* comments made. It has been altered and extended to meet the
* Android requirements. The Java code has according comments.
*
* If you use this code or find it helpful, please visit and send
* a shout to the author under {@link http://www.insanitydesign.com/}
*
* @DISCLAIMER
* This source and the whole package comes without warranty. It may or may
* not harm your computer or cell phone. Please use with care. Any damage
* cannot be related back to the author. The source has been tested on a
* virtual environment and scanned for viruses and has passed all tests.
*
*
* This is an interpretation of "Lesson 06: Texture Mapping"
* for the Google Android platform.
*
* @author Savas Ziplies (nea/INsanityDesign)
*/
public class Lesson06 implements Renderer {
   
   /** Cube instance */
   private Cube cube;   
   
   
   private Quad quad;
   
   /* Rotation values for all axis */
   private float xrot;            //X Rotation ( NEW )
   private float yrot;            //Y Rotation ( NEW )
   private float zrot;            //Z Rotation ( NEW )
   
   /** The Activity Context ( NEW ) */
   private Context context;
   
   /**
    * Instance the Cube object and set
    * the Activity Context handed over
    */
   public Lesson06(Context context) {
      this.context = context;
      
      quad = new Quad();
   }

   /**
    * The Surface is created/init()
    */
   public void onSurfaceCreated(GL10 gl, EGLConfig config) {      
      //Load the texture for the cube once during Surface creation

      quad.loadGLTexture(gl, this.context);


      
      gl.glEnable(GL10.GL_TEXTURE_2D);         //Enable Texture Mapping ( NEW )
      gl.glShadeModel(GL10.GL_SMOOTH);          //Enable Smooth Shading
      gl.glClearColor(1.0f, 1.0f, 0.0f, 0.0f);    //Yellow Background
      gl.glClearDepthf(1.0f);                //Depth Buffer Setup
      gl.glEnable(GL10.GL_DEPTH_TEST);          //Enables Depth Testing
      gl.glDepthFunc(GL10.GL_LEQUAL);          //The Type Of Depth Testing To Do
      gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); //enable transparency
      gl.glEnable(GL10.GL_BLEND); //enable transparency blending
      
      //Really Nice Perspective Calculations
      gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
   }

   /**
    * Here we do our drawing
    */
   public void onDrawFrame(GL10 gl) {
      //Clear Screen And Depth Buffer
      gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);   
      gl.glLoadIdentity();               //Reset The Current Modelview Matrix
      
      //Drawing
      gl.glTranslatef(0.0f, 0.0f, -5.0f);      //Move 5 units into the screen
      gl.glScalef(0.8f, 0.8f, 0.8f);          //Scale the Cube to 80 percent, otherwise it would be too large for the screen
      
      //Rotate around the axis based on the rotation matrix (rotation, x, y, z)
      gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);   //X
      gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);   //Y
      gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);   //Z
            

      quad.draw(gl);                  //Draw the Cube   
      
      //Change rotation factors (nice rotation)
      xrot += 0.3f;
      yrot += 0.2f;
      zrot += 0.4f;
   }

   /**
    * If the surface changes, reset the view
    */
   public void onSurfaceChanged(GL10 gl, int width, int height) {
      if(height == 0) {                   //Prevent A Divide By Zero By
         height = 1;                   //Making Height Equal One
      }

      gl.glViewport(0, 0, width, height);    //Reset The Current Viewport
      gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
      gl.glLoadIdentity();                //Reset The Projection Matrix

      //Calculate The Aspect Ratio Of The Window
      GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);

      gl.glMatrixMode(GL10.GL_MODELVIEW);    //Select The Modelview Matrix
      gl.glLoadIdentity();                //Reset The Modelview Matrix
   }
}








Code: Select all
package com.nea.nehe.lesson06;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

/**
* This class is an object representation of
* a Cube containing the vertex information,
* texture coordinates, the vertex indices
* and drawing functionality, which is called
* by the renderer.
*
* @author Savas Ziplies (nea/INsanityDesign)
*/
public class Quad {

   /** The buffer holding the vertices */
   private FloatBuffer vertexBuffer;
   /** The buffer holding the texture coordinates */
   private FloatBuffer textureBuffer;
   /** The buffer holding the indices */
   private ByteBuffer indexBuffer;
   
   /** Our texture pointer */
   private int[] textures = new int[1];

   /**
    * The initial vertex definitio
    *
    * Note that each face is defined, even
    * if indices are available, because
    * of the texturing we want to achieve
    */   
    private float vertices[] = {
                   //Vertices according to faces
                   -1.0f, -1.0f, 1.0f, //Vertex 0
                   1.0f, -1.0f, 1.0f,  //v1
                   -1.0f, 1.0f, 1.0f,  //v2
                   1.0f, 1.0f, 1.0f,   //v3
                                 };
   
    /** The initial texture coordinates (u, v) */   
    private float texture[] = {          
                   //Mapping coordinates for the vertices
                   0.0f, 0.0f,
                   0.0f, .25f,
                   .25f, 0.0f,
                   .25f, .25f,
                                  };
       
    /** The initial indices definition */   
    private byte indices[] = {
                   //Faces definition
                   0,1,3, 0,3,2,          //Face front
                                  };

   /**
    * The Quad constructor.
    *
    * Initiate the buffers.
    */
   public Quad() {
      //
      ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
      byteBuf.order(ByteOrder.nativeOrder());
      vertexBuffer = byteBuf.asFloatBuffer();
      vertexBuffer.put(vertices);
      vertexBuffer.position(0);

      //
      byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
      byteBuf.order(ByteOrder.nativeOrder());
      textureBuffer = byteBuf.asFloatBuffer();
      textureBuffer.put(texture);
      textureBuffer.position(0);

      //
      indexBuffer = ByteBuffer.allocateDirect(indices.length);
      indexBuffer.put(indices);
      indexBuffer.position(0);
   }

   /**
    * The object own drawing function.
    * Called from the renderer to redraw this instance
    * with possible changes in values.
    *
    * @param gl - The GL Context
    */
   public void draw(GL10 gl) {
      //Bind our only previously generated texture in this case
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
      
      //Point to our buffers
      gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

      //Set the face rotation
      gl.glFrontFace(GL10.GL_CCW);
      
      //Enable the vertex and texture state
      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
      gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
      
      //Draw the vertices as triangles, based on the Index Buffer information
      gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);      
      
      //Disable the client state before leaving
      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
   }
   
   
   /**
    * Load the textures
    *
    * @param gl - The GL Context
    * @param context - The Activity context
    */
   public void loadGLTexture(GL10 gl, Context context) {
      //Get the texture from the Android resource directory
      InputStream is = context.getResources().openRawResource(R.drawable.smurf_sprite);
      Bitmap bitmap = null;
      try {
         //BitmapFactory is an Android graphics utility for images
         bitmap = BitmapFactory.decodeStream(is);

      } finally {
         //Always clear and close
         try {
            is.close();
            is = null;
         } catch (IOException e) {
         }
      }

      //Generate one texture pointer...
      gl.glGenTextures(1, textures, 0);
      //...and bind it to our array
      gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
      
      //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_LINEAR);

      //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
      gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
      
      //Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
      GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
      
      //Clean up
      bitmap.recycle();
   }
}


IronChef253
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sun Jun 13, 2010 6:51 am

Re: Draw a Bitmap using OpenGL

Postby IronChef253 » Sat Jun 19, 2010 7:17 am

One minor detail I wanted to mention. If you view the NeHe Tutorial 6, it is basically the same as mine except it is using a cube. In order to reduce the cube to a single surface, I just removed all the vertexes except those required to develop a square polygon on which to apply my texture.

If you see errant references to cubes, its because the source renders a cube as the example. Thanks.
IronChef253
Junior Developer
Junior Developer
 
Posts: 11
Joined: Sun Jun 13, 2010 6:51 am

Top

Return to Android 2D/3D Graphics - OpenGL Problems

Who is online

Users browsing this forum: No registered users and 5 guests