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/
Using java Syntax Highlighting
public final void renderBillboards(Billboard billboard, Vector3f renderPositions[], GLColor renderColors[],
int start, int numBillboards)
{
gl.glClientActiveTexture(GL_TEXTURE0);
gl.glEnable(GL_TEXTURE_2D);
gl.glEnableClientState(GL_VERTEX_ARRAY);
gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
gl.glBlendFunc(billboard.blendSource, billboard.blendDest);
gl.glBindTexture(GL_TEXTURE_2D, billboard.texture.id);
gl.glDepthMask(false);
gl.glEnable(GL_BLEND);
gl.glVertexPointer(3, GL_FLOAT, 0, billboard.vertexBuffer.getReadBuffer());
gl.glTexCoordPointer(2, GL_FLOAT, 0, billboard.textureBuffer.getReadBuffer());
for (int cntr = start, end = start + numBillboards; cntr < end ; cntr++)
{
GLColor color = renderColors[cntr];
gl.glColor4f(color.red, color.green, color.blue, color.alpha);
gl.glPushMatrix();
gl.glMultMatrixf(VectorMath.getInverseMatrix(matrixFloatArray, billboard.eyePosition, renderPositions[cntr]), 0);
gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
}
gl.glColor4f(1, 1, 1, 1);
gl.glDisable(GL_BLEND);
gl.glDepthMask(true);
gl.glDisable(GL_TEXTURE_2D);
gl.glDisableClientState(GL_VERTEX_ARRAY);
gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
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.
Using java Syntax Highlighting
public class Billboard
{
public VectorBuffer3f vertexBuffer;
public VectorBuffer2f textureBuffer;
// Billboard variables
public float width, height;
public int halfWidth, halfHeight;
public float texCoordX, texCoordY;
public float texCoordW, texCoordH;
public Vector3f eyePosition = new Vector3f();
// Shared variables
public Texture texture;
public int blendSource;
public int blendDest;
// Used in derived classes
protected Billboard() {}
public Billboard(Texture texture, int blendSource, int blendDest)
{
this(texture, blendSource, blendDest, texture.width, texture.height);
}
public Billboard(Texture texture, int blendSource, int blendDest, int width, int height)
{
this.texture = texture;
this.blendSource = blendSource;
this.blendDest = blendDest;
this.width = width;
this.height = height;
vertexBuffer = new VectorBuffer3f(4, true, true);
textureBuffer = new VectorBuffer2f(4, true, true);
halfWidth = width / 2;
halfHeight = height / 2;
texCoordX = 0f;
texCoordY = 0f;
texCoordW = 1.0f;
texCoordH = 1.0f;
vertexBuffer.put(-halfWidth, -halfHeight, 0);
vertexBuffer.put(-halfWidth + width, -halfHeight, 0);
vertexBuffer.put(-halfWidth, -halfHeight + height, 0);
vertexBuffer.put(-halfWidth + width, -halfHeight + height, 0);
vertexBuffer.rewindWrite();
textureBuffer.put(texCoordX, texCoordY);
textureBuffer.put(texCoordX + texCoordW, texCoordY);
textureBuffer.put(texCoordX, texCoordY + texCoordH);
textureBuffer.put(texCoordX + texCoordW, texCoordY + texCoordH);
textureBuffer.rewindWrite();
}
}
Parsed in 0.036 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.
Using java Syntax Highlighting
// Gets the inverse matrix matrix between eye and position
public static float[] getInverseMatrix(float matrix[], Vector3f eye, Vector3f position)
{
// Reset X axis
tempVector1.x = 0;
tempVector1.y = 0;
tempVector1.z = 0;
// Reset Y axis
tempVector2.x = 0;
tempVector2.y = 1f;
tempVector2.z = 0;
// Set Z axis to position
tempVector3.x = position.x;
tempVector3.y = position.y;
tempVector3.z = position.z;
// Sub eye
tempVector3.x -= eye.x;
tempVector3.y -= eye.y;
tempVector3.z -= eye.z;
tempVector3.normalize();
tempVector1.cross(tempVector2, tempVector3);
tempVector1.normalize();
tempVector2.cross(tempVector1, tempVector3);
tempVector2.normalize();
tempVector2.scale(-1f);
matrix[0] = tempVector1.x;
matrix[1] = tempVector1.y;
matrix[2] = tempVector1.z;
matrix[12] = position.x;
matrix[4] = tempVector2.x;
matrix[5] = tempVector2.y;
matrix[6] = tempVector2.z;
matrix[13] = position.y;
matrix[8] = tempVector3.x;
matrix[9] = tempVector3.y;
matrix[10] = tempVector3.z;
matrix[14] = position.z;
matrix[15] = 1.0f;
return matrix;
}
Parsed in 0.037 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.
Using java Syntax Highlighting
public final void renderBillboardsQuick(Billboard billboard, Vector3f renderPositions[], int start,
int numBillboards)
{
gl.glClientActiveTexture(GL_TEXTURE0);
gl.glEnable(GL_TEXTURE_2D);
gl.glEnableClientState(GL_VERTEX_ARRAY);
gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
gl.glBlendFunc(billboard.blendSource, billboard.blendDest);
gl.glBindTexture(GL_TEXTURE_2D, billboard.texture.id);
gl.glDepthMask(false);
gl.glEnable(GL_BLEND);
gl.glVertexPointer(3, GL_FLOAT, 0, billboard.vertexBuffer.getReadBuffer());
gl.glTexCoordPointer(2, GL_FLOAT, 0, billboard.textureBuffer.getReadBuffer());
// Get the inverse matrix from the 1st billboard position
VectorMath.getInverseMatrix(matrixFloatArray, billboard.eyePosition, renderPositions[start]);
for (int cntr = start, end = start + numBillboards; cntr < end ; cntr++)
{
gl.glPushMatrix();
Vector3f position = renderPositions[cntr];
matrixFloatArray[12] = position.x;
matrixFloatArray[13] = position.y;
matrixFloatArray[14] = position.z;
gl.glMultMatrixf(matrixFloatArray, 0);
gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
}
gl.glDisable(GL_BLEND);
gl.glDepthMask(true);
gl.glDisable(GL_TEXTURE_2D);
gl.glDisableClientState(GL_VERTEX_ARRAY);
gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Parsed in 0.039 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!