package shadersmod.client;

//import static org.lwjgl.opengl.ARBVertexShader.glDisableVertexAttribArrayARB;
//import static org.lwjgl.opengl.ARBVertexShader.glEnableVertexAttribArrayARB;
//import static org.lwjgl.opengl.ARBVertexShader.glVertexAttribPointerARB;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Arrays;

//import org.lwjgl.opengl.ARBVertexBufferObject;
//import org.lwjgl.opengl.EXTFramebufferObject;
//import org.lwjgl.opengl.EXTVertexShader;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;

import shadersmod.common.SMCLog;

import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;

// Helper for net.minecraft.client.renderer.BufferBuilder

public class SVertexBuffer {
	
//	/** size of vertex / size of int */
//	int vertexSize;
//	int offsetNormal;
//	int offsetUV;
//	int offsetUVCenter;
//	boolean hasNormal;
//	boolean hasTangent;
//	boolean hasUV;
//	boolean hasUVCenter;
	long[] entityData;
	int entityDataIndex;
	boolean calcNormalEnabled;
	
	public SVertexBuffer() {
		entityData = new long[10];
		entityDataIndex = 0;
		entityData[0] = 0;
		calcNormalEnabled = false;
	}

	public static void onVertexBufferInit(BufferBuilder vb) {
		Dummy.put_vertexBuffer_sVertexBuffer(vb, new SVertexBuffer());
	}
	
	public static void onVertexBufferBegin(BufferBuilder vb) {
	}

	public static void enableCalcNormal(BufferBuilder vb) {
		SVertexBuffer svb = Dummy.get_vertexBuffer_sVertexBuffer(vb);
		svb.calcNormalEnabled = true;
	}

	public static void onVertexBufferReset(BufferBuilder vb) {
		SVertexBuffer svb = Dummy.get_vertexBuffer_sVertexBuffer(vb);
		svb.entityDataIndex = 0;
		svb.entityData[0] = 0;
		//svb.calcNormalEnabled = false;
	}
	
	public void pushEntity(long data) {
		++entityDataIndex;
		entityData[entityDataIndex] = data;
		//SMCLog.finest("i %d",entityDataIndex);
	}
	
	public void popEntity() {
		entityData[entityDataIndex] = 0;
		--entityDataIndex;
		//SMCLog.finest("i %d",entityDataIndex);
	}
	
	public static void pushEntity(IBlockState blockState, BlockPos blockPos, IBlockAccess blockAccess, BufferBuilder wrr) {
		Block block = blockState.getBlock();
		int blockID = Block.getIdFromBlock(block);
		int renderType = block.getRenderType(block.getDefaultState()).ordinal();
		int meta = block.getMetaFromState(blockState);
		//SMCLog.finest("push");
		int dataLo = ((renderType&65535)<<16)+(blockID&65535);
		int dataHi = (meta&65535);
		Dummy.get_vertexBuffer_sVertexBuffer(wrr).pushEntity((((long)dataHi)<<32)+dataLo);
		//SMCLog.finest("end push");
	}
	public static void popEntity(BufferBuilder wrr) {
		//SMCLog.finest("pop");
		Dummy.get_vertexBuffer_sVertexBuffer(wrr).popEntity();
		//SMCLog.finest("end pop");
	}
	public static boolean popEntity(boolean value, BufferBuilder wrr) {
		//SMCLog.finest("pop");
		Dummy.get_vertexBuffer_sVertexBuffer(wrr).popEntity();
		//SMCLog.finest("end pop");
		return value;
	}

	public static void beginAddVertexData(BufferBuilder vb,int[] data) {
		VertexFormat vertexFormat = vb.getVertexFormat();
		if (Dummy.get_vertexFormat_entityElementOffset(vertexFormat) > 0) {
			SVertexBuffer svb = Dummy.get_vertexBuffer_sVertexBuffer(vb);
			long eData = svb.entityData[svb.entityDataIndex];
			for (int pos=Dummy.get_vertexFormat_entityElementOffset(vertexFormat)/4;
					pos+1<data.length;
					pos+=SVertexFormat.vertexSizeBlock) {
				data[pos  ] = (int)(eData    );
				data[pos+1] = (int)(eData>>32);
			}
		}
	}
	public static void endAddVertexData(BufferBuilder vb) {
//		SVertexBuffer svb = Dummy.get_vertexBuffer_sVertexBuffer(vb);
//		VertexFormat vertexFormat = vb.getVertexFormat(); 
//		if (vertexFormat.getIntegerSize() == SVertexFormat.vertexSizeBlock) {
//			if (Dummy.get_vertexBuffer_drawMode(vb) == GL11.GL_QUADS && (Dummy.get_vertexBuffer_vertexCount(vb) % 4)==0)
//			{
//				calcNormal(vb, (vb.getVertexCount()-4) * vertexFormat.getIntegerSize());
//			}
//		}
	}
	public static void endEndVertex(BufferBuilder vb) {
		VertexFormat vertexFormat = vb.getVertexFormat(); 
		if (Dummy.get_vertexBuffer_vertexElementIndex(vb) != 0) {
			Dummy.put_vertexBuffer_vertexElementIndex(vb, 0);
			Dummy.put_vertexBuffer_vertexElement(vb,vertexFormat.getElement(0));
			SVertexBuffer svb = Dummy.get_vertexBuffer_sVertexBuffer(vb);
			if (Dummy.get_vertexFormat_entityElementOffset(vertexFormat)>0) {
				long eData = svb.entityData[svb.entityDataIndex];
				int pos = (vb.getVertexCount()-1) * vertexFormat.getIntegerSize()
						+ Dummy.get_vertexFormat_entityElementOffset(vertexFormat)/4;
				Dummy.get_vertexBuffer_rawIntBuffer(vb).put(pos  ,(int)(eData    ));
				Dummy.get_vertexBuffer_rawIntBuffer(vb).put(pos+1,(int)(eData>>32));
			}
			if (svb.calcNormalEnabled && 
					(vb.getVertexCount() & 3)==0 && vb.getDrawMode()==GL11.GL_QUADS 
					) {
				calcNormal(vb, (vb.getVertexCount()-4) * vertexFormat.getIntegerSize());
			}
		}
	}
	
	public static void calcNormal(BufferBuilder vb, int baseIndex) {
		VertexFormat vertexFormat = vb.getVertexFormat();
		FloatBuffer floatBuffer = Dummy.get_vertexBuffer_rawFloatBuffer(vb);
		IntBuffer intBuffer = Dummy.get_vertexBuffer_rawIntBuffer(vb);
		int vertexSize = vertexFormat.getIntegerSize();
		int offsetUV   = vertexFormat.getUvOffsetById(0)/4;
		int offsetNormal = vertexFormat.getNormalOffset()/4;
		int offsetTangent = Dummy.get_vertexFormat_tangentElementOffset(vertexFormat)/4;
		int offsetMidUV  = Dummy.get_vertexFormat_miduvElementOffset(vertexFormat)/4;
		float v0x,v0y,v0z,v0u,v0v, v1x,v1y,v1z,v1u,v1v, v2x,v2y,v2z,v2u,v2v, v3x,v3y,v3z,v3u,v3v;
		v0x = floatBuffer.get(baseIndex+0*vertexSize  );
		v0y = floatBuffer.get(baseIndex+0*vertexSize+1);
		v0z = floatBuffer.get(baseIndex+0*vertexSize+2);
		v0u = floatBuffer.get(baseIndex+0*vertexSize+offsetUV  );
		v0v = floatBuffer.get(baseIndex+0*vertexSize+offsetUV+1);
		v1x = floatBuffer.get(baseIndex+1*vertexSize  );
		v1y = floatBuffer.get(baseIndex+1*vertexSize+1);
		v1z = floatBuffer.get(baseIndex+1*vertexSize+2);
		v1u = floatBuffer.get(baseIndex+1*vertexSize+offsetUV  );
		v1v = floatBuffer.get(baseIndex+1*vertexSize+offsetUV+1);
		v2x = floatBuffer.get(baseIndex+2*vertexSize  );
		v2y = floatBuffer.get(baseIndex+2*vertexSize+1);
		v2z = floatBuffer.get(baseIndex+2*vertexSize+2);
		v2u = floatBuffer.get(baseIndex+2*vertexSize+offsetUV  );
		v2v = floatBuffer.get(baseIndex+2*vertexSize+offsetUV+1);
		v3x = floatBuffer.get(baseIndex+3*vertexSize  );
		v3y = floatBuffer.get(baseIndex+3*vertexSize+1);
		v3z = floatBuffer.get(baseIndex+3*vertexSize+2);
		v3u = floatBuffer.get(baseIndex+3*vertexSize+offsetUV  );
		v3v = floatBuffer.get(baseIndex+3*vertexSize+offsetUV+1);

		// calculate normal
		float x1, y1, z1, x2, y2, z2, u1, v1, u2, v2;
		x1 = v2x - v0x;
		y1 = v2y - v0y;
		z1 = v2z - v0z;
		x2 = v3x - v1x;
		y2 = v3y - v1y;
		z2 = v3z - v1z;
		float vnx = y1 * z2 - y2 * z1;
		float vny = z1 * x2 - z2 * x1;
		float vnz = x1 * y2 - x2 * y1;
		float lensq = vnx * vnx + vny * vny + vnz * vnz;
		float mult = (lensq != 0.0) ? (float) (1f / Math.sqrt(lensq)) : 1f;
		vnx *= mult;
		vny *= mult;
		vnz *= mult;
		
		// calculate tangent
		float tanX, tanY, tanZ;
		x1 = v1x - v0x;
		y1 = v1y - v0y;
		z1 = v1z - v0z;
		u1 = v1u - v0u;
		v1 = v1v - v0v;
		x2 = v2x - v0x;
		y2 = v2y - v0y;
		z2 = v2z - v0z;
		u2 = v2u - v0u;
		v2 = v2v - v0v;
		float d = u1 * v2 - u2 * v1;
		float r = (d != 0.0f) ? (1f / d) : 1f;
		float tan1x = (v2 * x1 - v1 * x2) * r;
		float tan1y = (v2 * y1 - v1 * y2) * r;
		float tan1z = (v2 * z1 - v1 * z2) * r;
		float tan2x = (u1 * x2 - u2 * x1) * r;
		float tan2y = (u1 * y2 - u2 * y1) * r;
		float tan2z = (u1 * z2 - u2 * z1) * r;
		lensq = tan1x * tan1x + tan1y * tan1y + tan1z * tan1z;
		mult = (lensq != 0.0) ? (float) (1f / Math.sqrt(lensq))	: 1f;
		tan1x *= mult;
		tan1y *= mult;
		tan1z *= mult;
		lensq = tan2x * tan2x + tan2y * tan2y + tan2z * tan2z;
		mult = (lensq != 0.0) ? (float) (1f / Math.sqrt(lensq))	: 1f;
		tan2x *= mult;
		tan2y *= mult;
		tan2z *= mult;
		float tan3x = vnz * tan1y - vny * tan1z;
		float tan3y = vnx * tan1z - vnz * tan1x;
		float tan3z = vny * tan1x - vnx * tan1y;
		float tan1w = (tan2x * tan3x + tan2y * tan3y + tan2z * tan3z < 0) ? -1f : 1f;
		
		// save normal
		int bnx = ((int)(vnx*127))&255;
		int bny = ((int)(vny*127))&255;
		int bnz = ((int)(vnz*127))&255;
		int packedNormal = (bnz<<16)+(bny<<8)+bnx;
		intBuffer.put(baseIndex+0*vertexSize+offsetNormal,packedNormal);
		intBuffer.put(baseIndex+1*vertexSize+offsetNormal,packedNormal);
		intBuffer.put(baseIndex+2*vertexSize+offsetNormal,packedNormal);
		intBuffer.put(baseIndex+3*vertexSize+offsetNormal,packedNormal);
		
		// save tangent
		int packedTan1xy = ((int)(tan1x*32767)&65535) + (((int)(tan1y*32767)&65535)<<16);
		int packedTan1zw = ((int)(tan1z*32767)&65535) + (((int)(tan1w*32767)&65535)<<16);
		intBuffer.put(baseIndex+0*vertexSize+offsetTangent  ,packedTan1xy);
		intBuffer.put(baseIndex+0*vertexSize+offsetTangent+1,packedTan1zw);
		intBuffer.put(baseIndex+1*vertexSize+offsetTangent  ,packedTan1xy);
		intBuffer.put(baseIndex+1*vertexSize+offsetTangent+1,packedTan1zw);
		intBuffer.put(baseIndex+2*vertexSize+offsetTangent  ,packedTan1xy);
		intBuffer.put(baseIndex+2*vertexSize+offsetTangent+1,packedTan1zw);
		intBuffer.put(baseIndex+3*vertexSize+offsetTangent  ,packedTan1xy);
		intBuffer.put(baseIndex+3*vertexSize+offsetTangent+1,packedTan1zw);
		
		// save midTexCoord
		int midU = Float.floatToRawIntBits( (v0u+v1u+v2u+v3u)/4 );
		int midV = Float.floatToRawIntBits( (v0v+v1v+v2v+v3v)/4 );
		intBuffer.put(baseIndex+0*vertexSize+offsetMidUV  ,midU);
		intBuffer.put(baseIndex+0*vertexSize+offsetMidUV+1,midV);
		intBuffer.put(baseIndex+1*vertexSize+offsetMidUV  ,midU);
		intBuffer.put(baseIndex+1*vertexSize+offsetMidUV+1,midV);
		intBuffer.put(baseIndex+2*vertexSize+offsetMidUV  ,midU);
		intBuffer.put(baseIndex+2*vertexSize+offsetMidUV+1,midV);
		intBuffer.put(baseIndex+3*vertexSize+offsetMidUV  ,midU);
		intBuffer.put(baseIndex+3*vertexSize+offsetMidUV+1,midV);
	}
	
//	public void calcNormal_old(BufferBuilder wrr, int baseIndex) {
//		SVertexBuffer svb = this;
//		FloatBuffer floatBuffer = Dummy.get_vertexBuffer_rawFloatBuffer(wrr);
//		IntBuffer intBuffer = Dummy.get_vertexBuffer_rawIntBuffer(wrr);
//		int rbi = Dummy.get_vertexBuffer_rawBufferIndex(wrr);
//		float v0x,v0y,v0z,v0u,v0v, v1x,v1y,v1z,v1u,v1v, v2x,v2y,v2z,v2u,v2v, v3x,v3y,v3z,v3u,v3v;
//		v0x = floatBuffer.get(baseIndex+0*vertexSize  );
//		v0y = floatBuffer.get(baseIndex+0*vertexSize+1);
//		v0z = floatBuffer.get(baseIndex+0*vertexSize+2);
//		v0u = floatBuffer.get(baseIndex+0*vertexSize+offsetUV  );
//		v0v = floatBuffer.get(baseIndex+0*vertexSize+offsetUV+1);
//		v1x = floatBuffer.get(baseIndex+1*vertexSize  );
//		v1y = floatBuffer.get(baseIndex+1*vertexSize+1);
//		v1z = floatBuffer.get(baseIndex+1*vertexSize+2);
//		v1u = floatBuffer.get(baseIndex+1*vertexSize+offsetUV  );
//		v1v = floatBuffer.get(baseIndex+1*vertexSize+offsetUV+1);
//		v2x = floatBuffer.get(baseIndex+2*vertexSize  );
//		v2y = floatBuffer.get(baseIndex+2*vertexSize+1);
//		v2z = floatBuffer.get(baseIndex+2*vertexSize+2);
//		v2u = floatBuffer.get(baseIndex+2*vertexSize+offsetUV  );
//		v2v = floatBuffer.get(baseIndex+2*vertexSize+offsetUV+1);
//		v3x = floatBuffer.get(baseIndex+3*vertexSize  );
//		v3y = floatBuffer.get(baseIndex+3*vertexSize+1);
//		v3z = floatBuffer.get(baseIndex+3*vertexSize+2);
//		v3u = floatBuffer.get(baseIndex+3*vertexSize+offsetUV  );
//		v3v = floatBuffer.get(baseIndex+3*vertexSize+offsetUV+1);
//
//		// calculate normal
//		float x1, y1, z1, x2, y2, z2, u1, v1, u2, v2;
//		x1 = v2x - v0x;
//		y1 = v2y - v0y;
//		z1 = v2z - v0z;
//		x2 = v3x - v1x;
//		y2 = v3y - v1y;
//		z2 = v3z - v1z;
//		float vnx = y1 * z2 - y2 * z1;
//		float vny = z1 * x2 - z2 * x1;
//		float vnz = x1 * y2 - x2 * y1;
//		float lensq = vnx * vnx + vny * vny + vnz * vnz;
//		float mult = (lensq != 0.0) ? (float) (1f / Math.sqrt(lensq)) : 1f;
//		vnx *= mult;
//		vny *= mult;
//		vnz *= mult;
//		
//		// calculate tangent
//		float tanX, tanY, tanZ;
//		x1 = v1x - v0x;
//		y1 = v1y - v0y;
//		z1 = v1z - v0z;
//		u1 = v1u - v0u;
//		v1 = v1v - v0v;
//		x2 = v2x - v0x;
//		y2 = v2y - v0y;
//		z2 = v2z - v0z;
//		u2 = v2u - v0u;
//		v2 = v2v - v0v;
//		float d = u1 * v2 - u2 * v1;
//		float r = (d != 0.0f) ? (1f / d) : 1f;
//		float tan1x = (v2 * x1 - v1 * x2) * r;
//		float tan1y = (v2 * y1 - v1 * y2) * r;
//		float tan1z = (v2 * z1 - v1 * z2) * r;
//		float tan2x = (u1 * x2 - u2 * x1) * r;
//		float tan2y = (u1 * y2 - u2 * y1) * r;
//		float tan2z = (u1 * z2 - u2 * z1) * r;
//		lensq = tan1x * tan1x + tan1y * tan1y + tan1z * tan1z;
//		mult = (lensq != 0.0) ? (float) (1f / Math.sqrt(lensq))	: 1f;
//		tan1x *= mult;
//		tan1y *= mult;
//		tan1z *= mult;
//		lensq = tan2x * tan2x + tan2y * tan2y + tan2z * tan2z;
//		mult = (lensq != 0.0) ? (float) (1f / Math.sqrt(lensq))	: 1f;
//		tan2x *= mult;
//		tan2y *= mult;
//		tan2z *= mult;
//		float tan3x = vnz * tan1y - vny * tan1z;
//		float tan3y = vnx * tan1z - vnz * tan1x;
//		float tan3z = vny * tan1x - vnx * tan1y;
//		float tan1w = (tan2x * tan3x + tan2y * tan3y + tan2z * tan3z < 0) ? -1f : 1f;
//		
//		// save normal
//		int bnx = ((int)(vnx*127))&255;
//		int bny = ((int)(vny*127))&255;
//		int bnz = ((int)(vnz*127))&255;
//		int packedNormal = (bnz<<16)+(bny<<8)+bnx;
//		intBuffer.put(baseIndex+0*vertexSize+offsetNormal,packedNormal);
//		intBuffer.put(baseIndex+1*vertexSize+offsetNormal,packedNormal);
//		intBuffer.put(baseIndex+2*vertexSize+offsetNormal,packedNormal);
//		intBuffer.put(baseIndex+3*vertexSize+offsetNormal,packedNormal);
//		
//		// save tangent
//		int packedTan1xy = ((int)(tan1x*32767)&65535) + (((int)(tan1y*32767)&65535)<<16);
//		int packedTan1zw = ((int)(tan1z*32767)&65535) + (((int)(tan1w*32767)&65535)<<16);
////TODO: offsetTangent
////		intBuffer.put(baseIndex+0*vertexSize+SVertexFormat.offsetTangent  ,packedTan1xy);
////		intBuffer.put(baseIndex+0*vertexSize+SVertexFormat.offsetTangent+1,packedTan1zw);
////		intBuffer.put(baseIndex+1*vertexSize+SVertexFormat.offsetTangent  ,packedTan1xy);
////		intBuffer.put(baseIndex+1*vertexSize+SVertexFormat.offsetTangent+1,packedTan1zw);
////		intBuffer.put(baseIndex+2*vertexSize+SVertexFormat.offsetTangent  ,packedTan1xy);
////		intBuffer.put(baseIndex+2*vertexSize+SVertexFormat.offsetTangent+1,packedTan1zw);
////		intBuffer.put(baseIndex+3*vertexSize+SVertexFormat.offsetTangent  ,packedTan1xy);
////		intBuffer.put(baseIndex+3*vertexSize+SVertexFormat.offsetTangent+1,packedTan1zw);
//		
//		// save midTexCoord
//		float midU = (v0u+v1u+v2u+v3u)/4;
//		float midV = (v0v+v1v+v2v+v3v)/4;
////TODO: offsetMidTexCoord
////		floatBuffer.put(baseIndex+0*vertexSize+SVertexFormat.offsetMidTexCoord  ,midU);
////		floatBuffer.put(baseIndex+0*vertexSize+SVertexFormat.offsetMidTexCoord+1,midV);
////		floatBuffer.put(baseIndex+1*vertexSize+SVertexFormat.offsetMidTexCoord  ,midU);
////		floatBuffer.put(baseIndex+1*vertexSize+SVertexFormat.offsetMidTexCoord+1,midV);
////		floatBuffer.put(baseIndex+2*vertexSize+SVertexFormat.offsetMidTexCoord  ,midU);
////		floatBuffer.put(baseIndex+2*vertexSize+SVertexFormat.offsetMidTexCoord+1,midV);
////		floatBuffer.put(baseIndex+3*vertexSize+SVertexFormat.offsetMidTexCoord  ,midU);
////		floatBuffer.put(baseIndex+3*vertexSize+SVertexFormat.offsetMidTexCoord+1,midV);
//	}

	public static void calcNormalChunkLayer(BufferBuilder wrr) {
//TODO:
//		if (wrr.getVertexFormat().hasNormal())
//		{
//			// ShadersMod calculate normal and mid UV
//			if (Dummy.get_worldRenderer_drawMode(wrr)==GL11.GL_QUADS && Dummy.get_worldRenderer_vertexCount(wrr)%4==0)
//			{
//				SVertexBuffer svb = Dummy.get_worldRenderer_sVertexBuilder(wrr);
//				svb.endSetVertexFormat(wrr);
//				int indexEnd = Dummy.get_worldRenderer_vertexCount(wrr)*svb.vertexSize;
//				int index;
//				for (index=0; index < indexEnd; index+=svb.vertexSize*4)
//					svb.calcNormal(wrr,index);
//			}
//		}
	}

	//public static void calcNormal(WorldRenderer wrr, int[] var4) {
	//	// TODO Auto-generated method stub
	//}

	public static void drawArrays(int drawMode, int first, int count, BufferBuilder vb) {
		if (count != 0) {
			VertexFormat vf = vb.getVertexFormat();
			int vertexSizeByte = vf.getNextOffset();
			if (vertexSizeByte == SVertexFormat.vertexSizeBlock*4) {
				ByteBuffer bb = vb.getByteBuffer();
				bb.position(Dummy.get_vertexFormat_miduvElementOffset(vf));
				GL20.glVertexAttribPointer(Shaders.midTexCoordAttrib, 2, GL11.GL_FLOAT, false, vertexSizeByte, bb);
				bb.position(Dummy.get_vertexFormat_tangentElementOffset(vf));
				GL20.glVertexAttribPointer(Shaders.tangentAttrib, 4, GL11.GL_SHORT, false, vertexSizeByte, bb);
				bb.position(Dummy.get_vertexFormat_entityElementOffset(vf));
				GL20.glVertexAttribPointer(Shaders.entityAttrib, 3, GL11.GL_SHORT, false, vertexSizeByte, bb);
				bb.position(0);
				GL20.glEnableVertexAttribArray(Shaders.midTexCoordAttrib);
				GL20.glEnableVertexAttribArray(Shaders.tangentAttrib);
				GL20.glEnableVertexAttribArray(Shaders.entityAttrib);
				GL11.glDrawArrays(drawMode, first, count);
				GL20.glDisableVertexAttribArray(Shaders.midTexCoordAttrib);
				GL20.glDisableVertexAttribArray(Shaders.tangentAttrib);
				GL20.glDisableVertexAttribArray(Shaders.entityAttrib);
			} else {
				GL11.glDrawArrays(drawMode, first, count);
			}
		}
	}
	
	public static void startTexturedQuad(BufferBuilder vb) {
	}

}

	

//	public static int finishDrawing(WorldRenderer tess) {
//        if (!tess.isDrawing)
//        {
//            throw new IllegalStateException("Not building");
//        }
//        else
//        {
//            tess.isDrawing = false;
//            if (tess.drawMode == GL11.GL_QUADS && tess.vertexCount % 4 != 0) {
//            	SMCLog.warning("%s", "bad vertexCount");
//            }
//            int voffset = 0;
//            int realDrawMode = tess.drawMode;
//            while (voffset < tess.vertexCount)
//            {
//                int vcount;
//                vcount = Math.min(tess.vertexCount - voffset, tess.byteBuffer.capacity() / (vertexStride*4));
//                if (realDrawMode == GL11.GL_QUADS)
//                	vcount = vcount /4 *4;
//                tess.rawFloatBuffer.clear();
//                tess.shortBuffer.clear();
//                tess.rawIntBuffer.clear();
//                tess.rawIntBuffer.put(tess.rawBuffer, voffset * vertexStride, vcount * vertexStride);
//                tess.byteBuffer.position(0);
//                tess.byteBuffer.limit(vcount * (vertexStride * 4));
//                voffset += vcount;
//
//                if (tess.hasTexture)
//                {
//                    tess.rawFloatBuffer.position(3);
//                    GL11.glTexCoordPointer(2, (vertexStride * 4), tess.rawFloatBuffer);
//                    GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//                }
//                if (tess.hasBrightness)
//                {
//                    OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit);
//                    tess.shortBuffer.position(6*2);
//                    GL11.glTexCoordPointer(2, (vertexStride * 4), tess.shortBuffer);
//                    GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//                    OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit);
//                }
//                if (tess.hasColor)
//                {
//                    tess.byteBuffer.position(5*4);
//                    GL11.glColorPointer(4, true, (vertexStride * 4), tess.byteBuffer);
//                    GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
//                }
//                if (tess.hasNormals)
//                {
//                    tess.rawFloatBuffer.position(9);
//                    GL11.glNormalPointer((vertexStride * 4), tess.rawFloatBuffer);
//                    GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
//                }
//                tess.rawFloatBuffer.position(0);
//                GL11.glVertexPointer(3, (vertexStride * 4), tess.rawFloatBuffer);
//                SVertexBuilder.preDrawArray(tess);
//                
//                GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
//                GL11.glDrawArrays(realDrawMode, 0, vcount);
//            }
//            // end loop
//
//            GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
//            SVertexBuilder.postDrawArray(tess);
//            if (tess.hasTexture)
//            {
//                GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//            }
//            if (tess.hasBrightness)
//            {
//                OpenGlHelper.setClientActiveTexture(OpenGlHelper.lightmapTexUnit);
//                GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//                OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit);
//            }
//            if (tess.hasColor)
//            {
//                GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
//            }
//            if (tess.hasNormals)
//            {
//                GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
//            }
//
//            int n = tess.rawBufferIndex * 4;
//            tess.reset();
//            return n;
//        }
//	}
//
//	public static void preDrawArray(WorldRenderer tess)
//	{
//		//Shaders.checkGLError("preDrawArray");
//		if (Shaders.useMultiTexCoord3Attrib && tess.hasTexture)
//		{
//			GL13.glClientActiveTexture(GL13.GL_TEXTURE3); 
//			GL11.glTexCoordPointer(2, (vertexStride * 4), (FloatBuffer)tess.rawFloatBuffer.position(16));
//			GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//			GL13.glClientActiveTexture(GL13.GL_TEXTURE0); 
//		}
//		if (Shaders.useMidTexCoordAttrib && tess.hasTexture)
//		{
//			glVertexAttribPointerARB(Shaders.midTexCoordAttrib, 2, false, vertexStride*4, (FloatBuffer)tess.rawFloatBuffer.position(16));
//			glEnableVertexAttribArrayARB(Shaders.midTexCoordAttrib);
//		}
//		if (Shaders.useTangentAttrib && tess.hasTexture)
//		{
//			glVertexAttribPointerARB(Shaders.tangentAttrib, 4, false, vertexStride*4, (FloatBuffer)tess.rawFloatBuffer.position(12));
//			glEnableVertexAttribArrayARB(Shaders.tangentAttrib);
//		}
//		if (Shaders.useEntityAttrib)
//		{
//			glVertexAttribPointerARB(Shaders.entityAttrib, 3, false, false, vertexStride*4, (ShortBuffer)tess.shortBuffer.position(7*2));
//			glEnableVertexAttribArrayARB(Shaders.entityAttrib);
//		}
//		//Shaders.checkGLError("preDrawArray");
//	}
//	public static void preDrawArrayVBO(WorldRenderer tess)
//	{
//		//Shaders.checkGLError("preDrawArray");
//		if (Shaders.useMultiTexCoord3Attrib && tess.hasTexture)
//		{
//			GL13.glClientActiveTexture(GL13.GL_TEXTURE3); 
//			GL11.glTexCoordPointer(2, GL11.GL_FLOAT, (vertexStride * 4), 16*4L);
//			GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//			GL13.glClientActiveTexture(GL13.GL_TEXTURE0); 
//		}
//		if (Shaders.useMidTexCoordAttrib && tess.hasTexture)
//		{
//			glVertexAttribPointerARB(Shaders.midTexCoordAttrib, 2, GL11.GL_FLOAT, false, vertexStride*4, 16*4L);
//			glEnableVertexAttribArrayARB(Shaders.midTexCoordAttrib);
//		}
//		if (Shaders.useTangentAttrib && tess.hasTexture)
//		{
//			glVertexAttribPointerARB(Shaders.tangentAttrib, 4, GL11.GL_FLOAT, false, vertexStride*4, 12*4L);
//			glEnableVertexAttribArrayARB(Shaders.tangentAttrib);
//		}
//		if (Shaders.useEntityAttrib)
//		{
//			glVertexAttribPointerARB(Shaders.entityAttrib, 3, GL11.GL_SHORT, false, vertexStride*4, 7*4L);
//			glEnableVertexAttribArrayARB(Shaders.entityAttrib);
//		}
//		//Shaders.checkGLError("preDrawArray");
//	}
//
//	public static void postDrawArray(WorldRenderer tess)
//	{
//		//Shaders.checkGLError("postDrawArray");
//		if (Shaders.useEntityAttrib)
//		{
//			glDisableVertexAttribArrayARB(Shaders.entityAttrib);
//		}
//		if (Shaders.useMidTexCoordAttrib && tess.hasTexture)
//		{
//			glDisableVertexAttribArrayARB(Shaders.midTexCoordAttrib);
//		}
//		if (Shaders.useTangentAttrib && tess.hasTexture)
//		{
//			glDisableVertexAttribArrayARB(Shaders.tangentAttrib);
//		}
//		if (Shaders.useMultiTexCoord3Attrib && tess.hasTexture)
//		{
//			GL13.glClientActiveTexture(GL13.GL_TEXTURE3); 
//			GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
//			GL13.glClientActiveTexture(GL13.GL_TEXTURE0); 
//		}
//		//Shaders.checkGLError("postDrawArray");
//	}
//
