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.WorldRenderer;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.BlockPos;
import net.minecraft.world.IBlockAccess;

// Helper for net.mnecraft.client.renderer.WorldRenderer

public class SVertexBuilder {
	
	/** 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;
	
	public SVertexBuilder() {
		entityData = new long[10];
		entityDataIndex = 0;
		entityData[entityDataIndex] = 0;
	}

	public static void initVertexBuilder(WorldRenderer wrr) {
		Dummy.put_worldRenderer_sVertexBuilder(wrr, new SVertexBuilder());
	}

	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, WorldRenderer wrr) {
		Block block = blockState.getBlock();
		int blockID = Block.getIdFromBlock(block);
		int renderType = block.getRenderType();
		int meta = block.getMetaFromState(blockState);
		//SMCLog.finest("push");
		int dataLo = ((renderType&65535)<<16)+(blockID&65535);
		int dataHi = (meta&65535);
		Dummy.get_worldRenderer_sVertexBuilder(wrr).pushEntity((((long)dataHi)<<32)+dataLo);
		//SMCLog.finest("end push");
	}
	public static void popEntity(WorldRenderer wrr) {
		//SMCLog.finest("pop");
		Dummy.get_worldRenderer_sVertexBuilder(wrr).popEntity();
		//SMCLog.finest("end pop");
	}
	public static boolean popEntity(boolean value, WorldRenderer wrr) {
		//SMCLog.finest("pop");
		Dummy.get_worldRenderer_sVertexBuilder(wrr).popEntity();
		//SMCLog.finest("end pop");
		return value;
	}
	
	public static void endSetVertexFormat(WorldRenderer wrr) {
		SVertexBuilder svb = Dummy.get_worldRenderer_sVertexBuilder(wrr);
		VertexFormat vf = wrr.getVertexFormat();
		svb.vertexSize = vf.getNextOffset() / 4;
		svb.hasNormal  = vf.hasNormal();
		svb.hasTangent = svb.hasNormal;;
		svb.hasUV      = vf.hasElementOffset(0);
		svb.offsetNormal = svb.hasNormal? vf.getNormalOffset()/4 : 0;
		svb.offsetUV     = svb.hasUV? vf.getElementOffsetById(0)/4 : 0;
		svb.offsetUVCenter = 8;
	}
	
	public static void beginAddVertex(WorldRenderer wrr) {
		if (Dummy.get_worldRenderer_vertexCount(wrr)==0) {
			endSetVertexFormat(wrr);
		}
	}
	public static void endAddVertex(WorldRenderer wrr) {
		SVertexBuilder svb = Dummy.get_worldRenderer_sVertexBuilder(wrr);
		if (svb.vertexSize == SVertexFormat.vertexSizeBlock) {
			// ShadersMod calculate normal and mid UV
			if (Dummy.get_worldRenderer_drawMode(wrr) == GL11.GL_QUADS && Dummy.get_worldRenderer_vertexCount(wrr) % 4==0)
			{
				svb.calcNormal(wrr,Dummy.get_worldRenderer_rawBufferIndex(wrr)-4*svb.vertexSize);
			}
			long eData = svb.entityData[svb.entityDataIndex];
			int pos = Dummy.get_worldRenderer_rawBufferIndex(wrr)-SVertexFormat.vertexSizeBlock+SVertexFormat.offsetEntity;
			Dummy.get_worldRenderer_rawIntBuffer(wrr).put(pos  ,(int)(eData    ));
			Dummy.get_worldRenderer_rawIntBuffer(wrr).put(pos+1,(int)(eData>>32));
		}
	}
	public static void beginAddVertexData(WorldRenderer wrr,int[] data) {
		if (Dummy.get_worldRenderer_vertexCount(wrr)==0) {
			endSetVertexFormat(wrr);
		}
		SVertexBuilder svb = Dummy.get_worldRenderer_sVertexBuilder(wrr);
		if (svb.vertexSize == SVertexFormat.vertexSizeBlock) {
			long eData = svb.entityData[svb.entityDataIndex];
			for (int pos=SVertexFormat.offsetEntity; pos+1<data.length; pos+=SVertexFormat.vertexSizeBlock) {
				data[pos  ] = (int)(eData    );
				data[pos+1] = (int)(eData>>32);
			}
		}
	}
	public static void endAddVertexData(WorldRenderer wrr) {
		SVertexBuilder svb = Dummy.get_worldRenderer_sVertexBuilder(wrr);
		if (svb.vertexSize == SVertexFormat.vertexSizeBlock) {
			// ShadersMod calculate normal and mid UV
			if (Dummy.get_worldRenderer_drawMode(wrr) == GL11.GL_QUADS && Dummy.get_worldRenderer_vertexCount(wrr) % 4==0)
			{
				svb.calcNormal(wrr,Dummy.get_worldRenderer_rawBufferIndex(wrr)-4*svb.vertexSize);
			}
		}
	}
	public void calcNormal(WorldRenderer wrr, int baseIndex) {
		SVertexBuilder svb = this;
		FloatBuffer floatBuffer = Dummy.get_worldRenderer_rawFloatBuffer(wrr);
		IntBuffer intBuffer = Dummy.get_worldRenderer_rawIntBuffer(wrr);
		int rbi = Dummy.get_worldRenderer_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);
		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;
		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 calcNormalAll(WorldRenderer wrr) {
//		if (wrr.vertexFormat.hasNormal())
//		{
//			// ShadersMod calculate normal and mid UV
//			if (wrr.drawMode==GL11.GL_QUADS && wrr.vertexCount%4==0)
//			{
//				SVertexBuilder svb = wrr.sVertexBuilder;
//				svb.endSetVertexFormat(wrr);
//				int indexEnd = wrr.vertexCount*svb.vertexSize;
//				int index;
//				for (index=0; index < indexEnd; index+=svb.vertexSize*4)
//					svb.calcNormal(wrr,index);
//			}
//		}
//	}

	public static void calcNormalChunkLayer(WorldRenderer wrr) {
		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)
			{
				SVertexBuilder 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, WorldRenderer wrr) {
		if (count != 0) {
			VertexFormat vf = wrr.getVertexFormat();
			int vertexSizeByte = vf.getNextOffset();
			if (vertexSizeByte == SVertexFormat.vertexSizeBlock*4) {
				ByteBuffer bb = wrr.getByteBuffer();
				bb.position(SVertexFormat.offsetMidTexCoord*4);
				GL20.glVertexAttribPointer(Shaders.midTexCoordAttrib, 2, GL11.GL_FLOAT, false, vertexSizeByte, bb);
				bb.position(SVertexFormat.offsetTangent*4);
				GL20.glVertexAttribPointer(Shaders.tangentAttrib, 4, GL11.GL_SHORT, false, vertexSizeByte, bb);
				bb.position(SVertexFormat.offsetEntity*4);
				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(WorldRenderer wrr) {
		wrr.setVertexFormat(SVertexFormat.defVertexFormatTextured);
	}

}

	

//	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");
//	}
//
