package shadersmod.client;

public class SBakedQuad {
	
	static final int vertexSize    = 14;
	static final int offsetPos     =  0;
	static final int offsetUV      =  4;
	static final int offsetNormal  =  7;
	static final int offsetMidUV   =  8;
	static final int offsetTangent = 10;
	static final int offsetEntity  = 12;
	
	public static int[] onMakeQuadData(int[] vertexData) {
		float v0x,v0y,v0z,v0u,v0v, v1x,v1y,v1z,v1u,v1v, v2x,v2y,v2z,v2u,v2v, v3x,v3y,v3z,v3u,v3v;
		v0x = Float.intBitsToFloat(vertexData[0*vertexSize+offsetPos+0]);
		v0y = Float.intBitsToFloat(vertexData[0*vertexSize+offsetPos+1]);
		v0z = Float.intBitsToFloat(vertexData[0*vertexSize+offsetPos+2]);
		v0u = Float.intBitsToFloat(vertexData[0*vertexSize+offsetUV +0]);
		v0v = Float.intBitsToFloat(vertexData[0*vertexSize+offsetUV +1]);
		v1x = Float.intBitsToFloat(vertexData[1*vertexSize+offsetPos+0]);
		v1y = Float.intBitsToFloat(vertexData[1*vertexSize+offsetPos+1]);
		v1z = Float.intBitsToFloat(vertexData[1*vertexSize+offsetPos+2]);
		v1u = Float.intBitsToFloat(vertexData[1*vertexSize+offsetUV +0]);
		v1v = Float.intBitsToFloat(vertexData[1*vertexSize+offsetUV +1]);
		v2x = Float.intBitsToFloat(vertexData[2*vertexSize+offsetPos+0]);
		v2y = Float.intBitsToFloat(vertexData[2*vertexSize+offsetPos+1]);
		v2z = Float.intBitsToFloat(vertexData[2*vertexSize+offsetPos+2]);
		v2u = Float.intBitsToFloat(vertexData[2*vertexSize+offsetUV +0]);
		v2v = Float.intBitsToFloat(vertexData[2*vertexSize+offsetUV +1]);
		v3x = Float.intBitsToFloat(vertexData[3*vertexSize+offsetPos+0]);
		v3y = Float.intBitsToFloat(vertexData[3*vertexSize+offsetPos+1]);
		v3z = Float.intBitsToFloat(vertexData[3*vertexSize+offsetPos+2]);
		v3u = Float.intBitsToFloat(vertexData[3*vertexSize+offsetUV +0]);
		v3v = Float.intBitsToFloat(vertexData[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;
		vertexData[0*vertexSize+offsetNormal] = packedNormal;
		vertexData[1*vertexSize+offsetNormal] = packedNormal;
		vertexData[2*vertexSize+offsetNormal] = packedNormal;
		vertexData[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);
		vertexData[0*vertexSize+offsetTangent+0] = packedTan1xy;
		vertexData[0*vertexSize+offsetTangent+1] = packedTan1zw;
		vertexData[1*vertexSize+offsetTangent+0] = packedTan1xy;
		vertexData[1*vertexSize+offsetTangent+1] = packedTan1zw;
		vertexData[2*vertexSize+offsetTangent+0] = packedTan1xy;
		vertexData[2*vertexSize+offsetTangent+1] = packedTan1zw;
		vertexData[3*vertexSize+offsetTangent+0] = packedTan1xy;
		vertexData[3*vertexSize+offsetTangent+1] = packedTan1zw;
		
		// save midTexCoord
		float midU = (v0u+v1u+v2u+v3u)/4;
		float midV = (v0v+v1v+v2v+v3v)/4;
		vertexData[0*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[0*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		vertexData[1*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[1*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		vertexData[2*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[2*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		vertexData[3*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[3*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		
		return vertexData;
	}
	
	public static void onRemapQuad(int[] vertexData) {
		float v0u,v0v, v1u,v1v, v2u,v2v, v3u,v3v;
		v0u = Float.intBitsToFloat(vertexData[0*vertexSize+offsetUV +0]);
		v0v = Float.intBitsToFloat(vertexData[0*vertexSize+offsetUV +1]);
		v1u = Float.intBitsToFloat(vertexData[1*vertexSize+offsetUV +0]);
		v1v = Float.intBitsToFloat(vertexData[1*vertexSize+offsetUV +1]);
		v2u = Float.intBitsToFloat(vertexData[2*vertexSize+offsetUV +0]);
		v2v = Float.intBitsToFloat(vertexData[2*vertexSize+offsetUV +1]);
		v3u = Float.intBitsToFloat(vertexData[3*vertexSize+offsetUV +0]);
		v3v = Float.intBitsToFloat(vertexData[3*vertexSize+offsetUV +1]);
		
		float midU = (v0u+v1u+v2u+v3u)/4;
		float midV = (v0v+v1v+v2v+v3v)/4;
		vertexData[0*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[0*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		vertexData[1*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[1*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		vertexData[2*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[2*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		vertexData[3*vertexSize+offsetMidUV+0] = Float.floatToRawIntBits(midU);
		vertexData[3*vertexSize+offsetMidUV+1] = Float.floatToRawIntBits(midV);
		
	}
}
