Simple Vertex-Array Immediate drawer

Hello everyone!

I just made a immediate-mode style Vertex-Array drawer, and thought some of you might find it useful.

Here it is (Only depency is LWJGL):


import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

/**
 This class is distributed under the WTFPL-License!
 Do with it what you want!
 Its free!
**/
public class ImmediateDrawerVA {
	
	public static final ImmediateDrawerVA tessellator = new ImmediateDrawerVA();
	
	FloatBuffer vertexBuffer;
	FloatBuffer colorBuffer;
	FloatBuffer textureBuffer;
	
	int vertexCount = 0;
	int drawMode = -1;
	
	float r = 1;
	float g = 1;
	float b = 1;
	
	float offX = 0;
	float offY = 0;
	float offZ = 0;
	
	float s = 0;
	float t = 0;
	
	boolean useColor = false;
	boolean useUV = false;
	
	boolean isDrawing = false;
	
	
	private ImmediateDrawerVA(){
		this.vertexBuffer = BufferUtils.createFloatBuffer(1024 * 1024);
		this.colorBuffer = BufferUtils.createFloatBuffer(1024 * 1024);
		this.textureBuffer = BufferUtils.createFloatBuffer(1024 * 1024);
		this.reset();
	}
	
	/**
	 * Starts drawing.
	 * 
	 * @param mode The OpenGL Geometry Mode to use for this draw.
	 * @throws RuntimeException If the ImmediateDrawer was already drawing.
	 **/
	public void startDrawing(int mode){
		
		if(this.isDrawing)
			throw new RuntimeException("Tessellator is already drawing!");
		
		this.reset();
		this.drawMode = mode;
		this.isDrawing = true;
	}
	
	/**
	 * Sets the UV-Coordinates for the next vertex to draw. (Has to be called in between start/stop!)
	 **/
	public void setUV(float u, float v){
		this.s = u;
		this.t = v;
		this.useUV = true;
	}
	
	/**
	 * Sets the Color for the next vertex to draw. (Has to be called in between start/stop!)
	 **/
	public void setColor(float r,float g,float b){
		this.r = r;
		this.g = g;
		this.b = b;
		this.useColor = true;
	}
	
	/**
	 * Sets the Position-Offset for the next vertex to draw. (Has to be called in between start/stop!)
	 **/
	public void setVertexOffset(float x, float y, float z){
		this.offX = x;
		this.offY = y;
		this.offZ = z;
	}
	
	/**
	 * Draws a vertex with a UV-Coordinate. (Has to be called in between start/stop!)
	 * 
	 * @param x The x-position of the vertex.
	 * @param y The y-position of the vertex.
	 * @param z The z-position of the vertex.
	 * 
	 * @param u The u-texCoord of the vertex.
	 * @param v The v-texCoord of the vertex.
	 **/
	public void drawVertWithUV(float x, float y, float z, float u, float v){
		this.setUV(u,v);
		this.drawVert(x,y,z);
	}
	
	/**
	 * Draws a vertex. (Has to be called in between start/stop!)
	 * 
	 * @param x The x-position of the vertex.
	 * @param y The y-position of the vertex.
	 * @param z The z-position of the vertex.
	 **/
	public void drawVert(float x, float y, float z){
		this.vertexBuffer.put(x + this.offX);
		this.vertexBuffer.put(y + this.offY);
		this.vertexBuffer.put(z + this.offZ);
		
		this.colorBuffer.put(this.r);
		this.colorBuffer.put(this.g);
		this.colorBuffer.put(this.b);
		
		this.textureBuffer.put(this.s);
		this.textureBuffer.put(this.t);
		
		this.vertexCount++;
	}
	
	/**
	 * Stops drawing.
	 **/
	public void stopDrawing(){
		if(this.vertexCount == 0){
			this.reset();
			return;
		}
		
		this.vertexBuffer.rewind();
		this.colorBuffer.rewind();
		this.textureBuffer.rewind();
		
		GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glVertexPointer(3, /* stride */3 << 2, this.vertexBuffer);
		
		if(this.useColor){
			GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
			GL11.glColorPointer(3, /* stride */3 << 2, this.colorBuffer);
		}
		
		if(this.useUV){
			GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
			GL11.glTexCoordPointer(2, /* stride */2 << 2, this.textureBuffer);
		}
		
		GL11.glDrawArrays(this.drawMode, 0, this.vertexCount);
		
		GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
		
		if(this.useColor)
			GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
		
		if(this.useUV)
			GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		
		this.reset();
	}
	
	// Do NOT call this method directly!
	private void reset() {
		this.vertexCount = 0;
		this.drawMode = -1;
		this.offX = 0;
		this.offY = 0;
		this.offZ = 0;
		this.r = 1;
		this.g = 1;
		this.b = 1;
		this.s = 0;
		this.t = 0;
		this.useColor = false;
		this.useUV = false;
		this.isDrawing = false;
		
		this.vertexBuffer.clear();
		this.colorBuffer.clear();
		this.textureBuffer.clear();
	}

	/**
	 * Returns true if this tessellator is drawing, false if not.
	 **/
	public boolean isDrawing() {
		return this.isDrawing;
	}
	
}

And this is how you use it:


ImmediateDrawerVA tess = ImmediateDrawerVA.instance;

tess.startDrawing(GL11.GL_QUADS);
 tess.setColor(1, 1, 1);
  tess.drawVertWithUV(0, 0, 0, 0, 0);
  tess.drawVertWithUV(1, 0, 0, 0, 0);
 tess.setColor(0, 0, 0);
  tess.drawVertWithUV(1, 1, 0, 0, 0);
  tess.drawVertWithUV(0, 1, 0, 0, 0);
tess.stopDrawing();

This class should work instantly and without any problems.
Its mostly useful to LWJGL newbies and everyone who is wondering how the heck to use these Vertex-Array’s.

If I made some mistake in the rendering code, or you find a bug, please tell me, as I want to use this class in my applications.

  • Longor1996

Why not keeping the same naming style than in OpenGL like in this class (from JOGL, build-in)?

Yeah, about that:
I was in an IRC today, and showed some friends the class, and they immdiately told me that this is not a Tessellator, but rather an immediate drawer.
I renamed all the stuff in the class so it fits its name again.

It is an immediate drawer: ImmediateDrawerVA

  • Longor1996