Billboard in Android

Tutorials concerning the OpenGL® ES cross-platform API for full-function 2D and 3D graphics on the Google-Android platform.

Billboard in Android

Postby arachnospore » Wed Apr 21, 2010 3:00 pm

Hi,

I'm looking for any information on billboarding techniques for openGL es, there's plenty for openGL but sadly with the reduced functionality (for lack of a better word) in es I can't apply those techniques. Otherwise the problem is rotating images in 3D space so they always face the camera. Any help, tutorials or sample code would be greatly appreciated.

Cheers
Put on some golf shoes man or we'll never leave this place alive!
arachnospore
Junior Developer
Junior Developer
 
Posts: 11
Joined: Wed Nov 04, 2009 8:44 pm

Top

Postby MichaelEGR » Wed Apr 21, 2010 4:26 pm

I can provide code I use with TyphonRT and hopefully it will be helpful. I will be releasing TyphonRT really soon, so perhaps drop me an email at the contact address here:
http://www.typhon4android.org/


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.    public final void renderBillboards(Billboard billboard, Vector3f renderPositions[], GLColor renderColors[],
  3.  
  4.     int start, int numBillboards)
  5.  
  6.    {
  7.  
  8.       gl.glClientActiveTexture(GL_TEXTURE0);
  9.  
  10.       gl.glEnable(GL_TEXTURE_2D);
  11.  
  12.       gl.glEnableClientState(GL_VERTEX_ARRAY);
  13.  
  14.       gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  15.  
  16.  
  17.  
  18.       gl.glBlendFunc(billboard.blendSource, billboard.blendDest);
  19.  
  20.       gl.glBindTexture(GL_TEXTURE_2D, billboard.texture.id);
  21.  
  22.  
  23.  
  24.       gl.glDepthMask(false);
  25.  
  26.  
  27.  
  28.       gl.glEnable(GL_BLEND);
  29.  
  30.  
  31.  
  32.       gl.glVertexPointer(3, GL_FLOAT, 0, billboard.vertexBuffer.getReadBuffer());
  33.  
  34.       gl.glTexCoordPointer(2, GL_FLOAT, 0, billboard.textureBuffer.getReadBuffer());
  35.  
  36.  
  37.  
  38.       for (int cntr = start, end = start + numBillboards; cntr < end ; cntr++)
  39.  
  40.       {
  41.  
  42.          GLColor color = renderColors[cntr];
  43.  
  44.          gl.glColor4f(color.red, color.green, color.blue, color.alpha);
  45.  
  46.          gl.glPushMatrix();
  47.  
  48.          gl.glMultMatrixf(VectorMath.getInverseMatrix(matrixFloatArray, billboard.eyePosition, renderPositions[cntr]), 0);
  49.  
  50.          gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  51.  
  52.          gl.glPopMatrix();
  53.  
  54.       }
  55.  
  56.  
  57.  
  58.       gl.glColor4f(1, 1, 1, 1);
  59.  
  60.  
  61.  
  62.       gl.glDisable(GL_BLEND);
  63.  
  64.  
  65.  
  66.       gl.glDepthMask(true);
  67.  
  68.  
  69.  
  70.       gl.glDisable(GL_TEXTURE_2D);
  71.  
  72.       gl.glDisableClientState(GL_VERTEX_ARRAY);
  73.  
  74.       gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  75.  
  76.    }
  77.  
  78.  
  79.  
  80.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


Here is the Billboard class. Essentially it takes a Texture reference which is another class in TyphonRT that stores a loaded texture. VectorBuffer2f and VectorBuffer3f are also TyphonRT classes, but they are essentially NIO FloatBuffers.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class Billboard
  3.  
  4. {
  5.  
  6.    public VectorBuffer3f vertexBuffer;
  7.  
  8.    public VectorBuffer2f textureBuffer;
  9.  
  10.  
  11.  
  12.    // Billboard variables
  13.  
  14.    public float width, height;
  15.  
  16.    public int halfWidth, halfHeight;
  17.  
  18.  
  19.  
  20.    public float texCoordX, texCoordY;
  21.  
  22.    public float texCoordW, texCoordH;
  23.  
  24.  
  25.  
  26.    public Vector3f eyePosition = new Vector3f();
  27.  
  28.  
  29.  
  30.    // Shared variables
  31.  
  32.    public Texture texture;
  33.  
  34.    public int blendSource;
  35.  
  36.    public int blendDest;
  37.  
  38.  
  39.  
  40.    // Used in derived classes
  41.  
  42.    protected Billboard() {}
  43.  
  44.  
  45.  
  46.    public Billboard(Texture texture, int blendSource, int blendDest)
  47.  
  48.    {
  49.  
  50.       this(texture, blendSource, blendDest, texture.width, texture.height);
  51.  
  52.    }
  53.  
  54.  
  55.  
  56.    public Billboard(Texture texture, int blendSource, int blendDest, int width, int height)
  57.  
  58.    {
  59.  
  60.       this.texture = texture;
  61.  
  62.       this.blendSource = blendSource;
  63.  
  64.       this.blendDest = blendDest;
  65.  
  66.       this.width = width;
  67.  
  68.       this.height = height;
  69.  
  70.  
  71.  
  72.       vertexBuffer = new VectorBuffer3f(4, true, true);
  73.  
  74.       textureBuffer = new VectorBuffer2f(4, true, true);
  75.  
  76.  
  77.  
  78.       halfWidth = width / 2;
  79.  
  80.       halfHeight = height / 2;
  81.  
  82.  
  83.  
  84.       texCoordX = 0f;
  85.  
  86.       texCoordY = 0f;
  87.  
  88.       texCoordW = 1.0f;
  89.  
  90.       texCoordH = 1.0f;
  91.  
  92.  
  93.  
  94.       vertexBuffer.put(-halfWidth, -halfHeight, 0);
  95.  
  96.       vertexBuffer.put(-halfWidth + width, -halfHeight, 0);
  97.  
  98.       vertexBuffer.put(-halfWidth, -halfHeight + height, 0);
  99.  
  100.       vertexBuffer.put(-halfWidth + width, -halfHeight + height, 0);
  101.  
  102.       vertexBuffer.rewindWrite();
  103.  
  104.  
  105.  
  106.       textureBuffer.put(texCoordX, texCoordY);
  107.  
  108.       textureBuffer.put(texCoordX + texCoordW, texCoordY);
  109.  
  110.       textureBuffer.put(texCoordX, texCoordY + texCoordH);
  111.  
  112.       textureBuffer.put(texCoordX + texCoordW, texCoordY + texCoordH);
  113.  
  114.       textureBuffer.rewindWrite();
  115.  
  116.    }
  117.  
  118. }
  119.  
  120.  
Parsed in 0.038 seconds, using GeSHi 1.0.8.4


The remaining method to calculate Billboard rotation is VectorMath. I am using a Vector API that is a modified javax.vecmath library.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.    // Gets the inverse matrix matrix between eye and position
  3.  
  4.    public static float[] getInverseMatrix(float matrix[], Vector3f eye, Vector3f position)
  5.  
  6.    {
  7.  
  8.       // Reset X axis
  9.  
  10.       tempVector1.x = 0;
  11.  
  12.       tempVector1.y = 0;
  13.  
  14.       tempVector1.z = 0;
  15.  
  16.  
  17.  
  18.       // Reset Y axis
  19.  
  20.       tempVector2.x = 0;
  21.  
  22.       tempVector2.y = 1f;
  23.  
  24.       tempVector2.z = 0;
  25.  
  26.  
  27.  
  28.       // Set Z axis to position
  29.  
  30.       tempVector3.x = position.x;
  31.  
  32.       tempVector3.y = position.y;
  33.  
  34.       tempVector3.z = position.z;
  35.  
  36.  
  37.  
  38.       // Sub eye
  39.  
  40.       tempVector3.x -= eye.x;
  41.  
  42.       tempVector3.y -= eye.y;
  43.  
  44.       tempVector3.z -= eye.z;
  45.  
  46.  
  47.  
  48.       tempVector3.normalize();
  49.  
  50.  
  51.  
  52.       tempVector1.cross(tempVector2, tempVector3);
  53.  
  54.       tempVector1.normalize();
  55.  
  56.       tempVector2.cross(tempVector1, tempVector3);
  57.  
  58.       tempVector2.normalize();
  59.  
  60.       tempVector2.scale(-1f);
  61.  
  62.  
  63.  
  64.       matrix[0] = tempVector1.x;
  65.  
  66.       matrix[1] = tempVector1.y;
  67.  
  68.       matrix[2] = tempVector1.z;
  69.  
  70.       matrix[12] = position.x;
  71.  
  72.       matrix[4] = tempVector2.x;
  73.  
  74.       matrix[5] = tempVector2.y;
  75.  
  76.       matrix[6] = tempVector2.z;
  77.  
  78.       matrix[13] = position.y;
  79.  
  80.       matrix[8] = tempVector3.x;
  81.  
  82.       matrix[9] = tempVector3.y;
  83.  
  84.       matrix[10] = tempVector3.z;
  85.  
  86.       matrix[14] = position.z;
  87.  
  88.       matrix[15] = 1.0f;
  89.  
  90.  
  91.  
  92.       return matrix;
  93.  
  94.    }
  95.  
  96.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


The following is a shortcut of sorts that only calculates the inverse matrix for the first billboard. It updates the matrix for billboard positions in each iteration instead of calculating the inverse matrix for each billboard. It can be helpful if all billboards are in a particular direction from the eye / camera.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.    public final void renderBillboardsQuick(Billboard billboard, Vector3f renderPositions[], int start,
  3.  
  4.     int numBillboards)
  5.  
  6.    {
  7.  
  8.       gl.glClientActiveTexture(GL_TEXTURE0);
  9.  
  10.       gl.glEnable(GL_TEXTURE_2D);
  11.  
  12.       gl.glEnableClientState(GL_VERTEX_ARRAY);
  13.  
  14.       gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  15.  
  16.  
  17.  
  18.       gl.glBlendFunc(billboard.blendSource, billboard.blendDest);
  19.  
  20.       gl.glBindTexture(GL_TEXTURE_2D, billboard.texture.id);
  21.  
  22.  
  23.  
  24.       gl.glDepthMask(false);
  25.  
  26.  
  27.  
  28.       gl.glEnable(GL_BLEND);
  29.  
  30.  
  31.  
  32.       gl.glVertexPointer(3, GL_FLOAT, 0, billboard.vertexBuffer.getReadBuffer());
  33.  
  34.       gl.glTexCoordPointer(2, GL_FLOAT, 0, billboard.textureBuffer.getReadBuffer());
  35.  
  36.  
  37.  
  38.       // Get the inverse matrix from the 1st billboard position
  39.  
  40.       VectorMath.getInverseMatrix(matrixFloatArray, billboard.eyePosition, renderPositions[start]);
  41.  
  42.  
  43.  
  44.       for (int cntr = start, end = start + numBillboards; cntr < end ; cntr++)
  45.  
  46.       {
  47.  
  48.          gl.glPushMatrix();
  49.  
  50.          Vector3f position = renderPositions[cntr];
  51.  
  52.          matrixFloatArray[12] = position.x;
  53.  
  54.          matrixFloatArray[13] = position.y;
  55.  
  56.          matrixFloatArray[14] = position.z;
  57.  
  58.          gl.glMultMatrixf(matrixFloatArray, 0);
  59.  
  60.          gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  61.  
  62.          gl.glPopMatrix();
  63.  
  64.       }
  65.  
  66.  
  67.  
  68.       gl.glDisable(GL_BLEND);
  69.  
  70.       gl.glDepthMask(true);
  71.  
  72.  
  73.  
  74.       gl.glDisable(GL_TEXTURE_2D);
  75.  
  76.       gl.glDisableClientState(GL_VERTEX_ARRAY);
  77.  
  78.       gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  79.  
  80.    }
  81.  
  82.  
Parsed in 0.040 seconds, using GeSHi 1.0.8.4


There are also other variations to take into account that you can use a luminance texture and apply a GLColor to modulate the billboard with but that will all be available with the TyphonRT launch.

Good luck!
Founder & Principal Architect; EGR Software LLC
http://www.typhonrt.org
http://www.egrsoftware.com
User avatar
MichaelEGR
Senior Developer
Senior Developer
 
Posts: 147
Joined: Thu Jan 21, 2010 5:30 am
Location: San Francisco, CA

Top

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

Who is online

Users browsing this forum: No registered users and 6 guests