//transparency.cpp
//sort and draw all transparent polygons

#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <stdlib.h>
#include "fileio.h"
#include "vectors.h"
#include "environment.h"
#include "transparency.h"
#include "entities.h"
#include "textures.h"
#include "renderframe.h"
#include "config.h"
#include "gameframe.h"
#include "gameinitexit.h"
#include "text.h"
#include "sky.h"

//an index used to sort transparent polygons
typedef struct{
	float distance;
	int poly;
}tTransparentPolyDistSort;


float gTunnelFactor=0;
float gBlurMapFactor=0;
float gGlowFactor=0;
float gShineFactor=1;
int gGhostShine=false;

#define kMaxTransparentPolys 16384 //maximum number of transparent polygons in scene
#define kMaxMaterialStorage 1024
tPolyMaterial *gMaterialStorage;
tTransparentPoly *gTranparentPolys; //transparent poly buffer
tTransparentPolyDistSort *gPolyDistance; //transparent poly index
int gTransparentPolyCount=0; //transparent polygons currently used
int gMaterialStorageCount=0;

void InitTransparency()
{
	gMaterialStorage=(tPolyMaterial*)malloc(sizeof(tPolyMaterial)*kMaxMaterialStorage);
	gTranparentPolys=(tTransparentPoly*)malloc(sizeof(tTransparentPoly)*kMaxTransparentPolys);
	gPolyDistance=(tTransparentPolyDistSort*)malloc(sizeof(tTransparentPolyDistSort)*kMaxTransparentPolys);
}

//returns a pointer to an unused tTransparentPoly which needs to be filled with data
//and increments the transparent polygon count
tTransparentPoly* GetNextTransparentPoly(int allocateMaterial)
{
	if(gTransparentPolyCount<kMaxTransparentPolys)
	{
		if(allocateMaterial)
			if(gMaterialStorageCount<kMaxMaterialStorage)
				gTranparentPolys[gTransparentPolyCount].mat=gMaterialStorage+gMaterialStorageCount++;
			else
				return NULL;
		gTranparentPolys[gTransparentPolyCount].textureSet=0;
		gTranparentPolys[gTransparentPolyCount].ghost=0;
		gTranparentPolys[gTransparentPolyCount].glow=gGlowFactor;
		gTranparentPolys[gTransparentPolyCount].blur=gBlurMapFactor;
		gTransparentPolyCount++;
		return gTranparentPolys+gTransparentPolyCount-1;
	}
	else
		return NULL;
}

//setup OpenGL to use the properties of the material passed in mat
int UseMaterial(tPolyMaterial *mat,int allowTransparency,int textureSet)
{
	GLfloat specularReflectance[4];
	GLfloat ambientReflectance[4];
	GLfloat diffuseReflectance[4];
	GLfloat emission[4]={0,0,0,1};

	*(tVector3*)specularReflectance=mat->specular;
	*(tVector3*)ambientReflectance=mat->ambient;
	*(tVector3*)diffuseReflectance=mat->diffuse;
	
	specularReflectance[3]=1;
	ambientReflectance[3]=1;
	diffuseReflectance[3]=1;
	
	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuseReflectance);
	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambientReflectance);
	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specularReflectance);
	glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,mat->shininess);
	if(mat->flags&kMaterialEnableGlow)
	{
		emission[0]=gGlowFactor;
		emission[1]=gGlowFactor*0.3;
	}
	if(mat->flags&kMaterialEnableShine)
	{
		emission[0]=gShineFactor*gEnvironment->spotLightColor.x;
		emission[1]=gShineFactor*gEnvironment->spotLightColor.y;
		emission[2]=gShineFactor*gEnvironment->spotLightColor.z;
	}
	if(gGhostShine)
	{
		emission[0]=1.5;
		emission[1]=1.5;
		emission[2]=1.5;
	}
	glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,emission);
	if(mat->flags&kMaterialDisableLighting)
		glDisable(GL_LIGHTING);
	else
		glEnable(GL_LIGHTING);

	TexturesSelectTex(FileGetIndexedReference(mat->texRef,textureSet));
/*	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	if(mat->flags&kMaterialMoveUVs)
		glTranslatef(kFrameTime*gFrameCount,kFrameTime*gFrameCount,0);
	glMatrixMode(GL_MODELVIEW);*/
	
	if(mat->flags&kMaterialDisableWrap)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	}
	else if(mat->flags&kMaterialDisableWrapS)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	}
	else if(mat->flags&kMaterialDisableWrapT)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	}
	else 	
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	}


	if(mat->flags&kMaterialBothSides)
		glDisable(GL_CULL_FACE);
	else
		glEnable(GL_CULL_FACE);	
	
	
	if(gEnvironment->environmentMapping)
		if(mat->flags&kMaterialSphereMap){
			if(TexturesSelectTextureUnit(1))
			{
			#ifndef __TARGET_TOOLAPP	

				if(gMapEnv)
					if(gMapEnv->spheremap)
						TexturesSelectTex(gMapEnv->spheremap);
					else		
						TexturesSelectTex(gEnvironment->spheremap);
				else		
			#endif
					TexturesSelectTex(gEnvironment->spheremap);
				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
				glEnable(GL_TEXTURE_GEN_S);
				glEnable(GL_TEXTURE_GEN_T);	
				glMatrixMode(GL_TEXTURE);
				tMatrix4 m;
				MatrixCopy(gTransformDir,m);
				
				glLoadMatrixf((float*)m);		
				glMatrixMode(GL_MODELVIEW);
				if(gEnvironment->environmentMapping==kEnvironmentMappingSphereInterpolate)
				{
#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
#define GL_MODULATE_ADD_ATI 0x8744
				/*	GLfloat color[4]={1,1,1,gEnvironment->environmentMapIntensity*gEnvironmentMapFactor};
					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INTERPOLATE_ARB);	
					glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_CONSTANT_ARB);	
					glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SRC_ALPHA);	
					glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,color);	*/
					GLfloat color[4]={1,1,1,0.5};
					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_MODULATE_ADD_ATI);	
					//glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INTERPOLATE_ARB);	
					glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_TEXTURE);	
					glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR);	
					glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PREVIOUS_ARB);	
					glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SRC_COLOR);	
					glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_PREVIOUS_ARB);	
					glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SRC_ALPHA);	
					
					//glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,color);
				}
				else
				{
					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_ADD_SIGNED_ARB);	
				}
				TexturesSelectTextureUnit(0);
			}
		}
	else {
		if(TexturesSelectTextureUnit(1)){
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_TEXTURE_3D);
			glDisable(GL_TEXTURE_GEN_S);
			glDisable(GL_TEXTURE_GEN_T);
			TexturesSelectTextureUnit(0);
		}
	}

#ifndef __TARGET_TOOLAPP	
	int enableLightMap=false;
	if(gMapEnv)
		if(gMapEnv->lightMap)
			if((!gMapEnv->lightMap2)||((mat->flags&kMaterialSphereMap)&&!gTunnelFactor))
				if(TexturesSelectTextureUnit(2))
				{
					TexturesSelectTex(gMapEnv->lightMap);
					glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
					glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_MODULATE);						

					glEnable(GL_TEXTURE_GEN_S);
					glEnable(GL_TEXTURE_GEN_T);
					glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);	
					glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);	
					if(gMapEnv->lightMapBotRight.x!=gMapEnv->lightMapTopLeft.x)
					{
						GLfloat xPlane[]={1.0f/(gMapEnv->lightMapBotRight.x-gMapEnv->lightMapTopLeft.x),0.0f,0.0f,(gTransformPos.x-gMapEnv->lightMapTopLeft.x+gFrameCount*kFrameTime*gMapEnv->lightMapSpeed.x)/(gMapEnv->lightMapBotRight.x-gMapEnv->lightMapTopLeft.x)};
						glTexGenfv(GL_S,GL_OBJECT_PLANE,xPlane);	
					}
					if(gMapEnv->lightMapBotRight.y!=gMapEnv->lightMapTopLeft.y)
					{
						GLfloat yPlane[]={0.0f,0.0f,1.0f/(gMapEnv->lightMapBotRight.y-gMapEnv->lightMapTopLeft.y),(gTransformPos.z-gMapEnv->lightMapTopLeft.y+gFrameCount*kFrameTime*gMapEnv->lightMapSpeed.y)/(gMapEnv->lightMapBotRight.y-gMapEnv->lightMapTopLeft.y)};
						glTexGenfv(GL_T,GL_OBJECT_PLANE,yPlane);	
					}
					glMatrixMode(GL_TEXTURE);
					glLoadIdentity();
					glMatrixMode(GL_MODELVIEW);
					enableLightMap=true;
					TexturesSelectTextureUnit(0);
				}
	if(!enableLightMap)
		if(TexturesSelectTextureUnit(2))
		{
			glDisable(GL_TEXTURE_2D);
			TexturesSelectTextureUnit(0);
		}
	
#endif

	if(allowTransparency)
	{
		if(mat->flags&kMaterialUseAlphaChannel)
		{
			//glColor4f(1,1,1,0.5);
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		//	glEnable(GL_ALPHA_TEST);									
		//	glAlphaFunc(GL_GREATER,0.0);
		}
		else{
		//	glDisable(GL_ALPHA_TEST);
			glDisable(GL_BLEND);
		}
		if(mat->flags&kMaterialAlphaTest)
		{
			glEnable(GL_ALPHA_TEST);									
			glAlphaFunc(GL_GREATER,0.5);
		}
		else
			glDisable(GL_ALPHA_TEST);
	}
	if(TexturesSelectTextureUnit(3))
	{
		glDisable(GL_TEXTURE_2D);
		TexturesSelectTextureUnit(0);
	}
	return mat->flags&kMaterialUseAlphaChannel;
}

//setup OpenGL to use the properties of the material passed in mat
void UseMaterial2(tPolyMaterial *mat,tPolyMaterial *mat2,int textureSet)
{
	GLfloat specularReflectance[4];
	GLfloat ambientReflectance[4];
	GLfloat diffuseReflectance[4];
	GLfloat emission[4]={0,0,0,1};

	*(tVector3*)specularReflectance=mat->specular;
	*(tVector3*)ambientReflectance=mat->ambient;
	*(tVector3*)diffuseReflectance=mat->diffuse;
	
	specularReflectance[3]=1;
	ambientReflectance[3]=1;
	diffuseReflectance[3]=1;
	
	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuseReflectance);
	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambientReflectance);
	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specularReflectance);
	glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,mat->shininess);
	if(mat->flags&kMaterialEnableGlow)
	{
		emission[0]=gGlowFactor;
		emission[1]=gGlowFactor*0.3;
	}
	if(mat->flags&kMaterialEnableShine)
	{
		emission[0]=gShineFactor*gEnvironment->spotLightColor.x;
		emission[1]=gShineFactor*gEnvironment->spotLightColor.y;
		emission[2]=gShineFactor*gEnvironment->spotLightColor.z;
	}
	glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,emission);
	if(mat->flags&kMaterialDisableLighting)
		glDisable(GL_LIGHTING);
	else
		glEnable(GL_LIGHTING);

	TexturesSelectTex(FileGetIndexedReference(mat->texRef,textureSet));
	
	if(mat->flags&kMaterialDisableWrap)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	}
	else if(mat->flags&kMaterialDisableWrapS)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	}
	else if(mat->flags&kMaterialDisableWrapT)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
	}
	else 	
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	}

	if(mat->flags&kMaterialBothSides)
		glDisable(GL_CULL_FACE);
	else
		glEnable(GL_CULL_FACE);	
	
	
	if(gConfig->stencil){
		if(TexturesSelectTextureUnit(1))
		{
			glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
			glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_MODULATE);	
			glDisable(GL_TEXTURE_GEN_S);
			glDisable(GL_TEXTURE_GEN_T);
			glMatrixMode(GL_TEXTURE);
			glEnable(GL_TEXTURE_2D);
			glLoadIdentity();
			glMatrixMode(GL_MODELVIEW);
			if(!gLightning)
			{
				TexturesSelectTex(FileGetIndexedReference(mat2->texRef,gEnvironment->envFlags));
				if(mat2->flags&kMaterialDisableWrap)
				{
					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
				}
				else 	
				{
					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
					glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
				}
			}
			else
				TexturesSelectTex(FileGetReference("null.raw"));			
			TexturesSelectTextureUnit(0);
		}
	}
	else
	{
		glEnable(GL_LIGHTING);
		if(TexturesSelectTextureUnit(1))
		{
			glDisable(GL_TEXTURE_2D);
			TexturesSelectTextureUnit(0);
		}
	}	

#ifndef __TARGET_TOOLAPP	
	if(gMapEnv)
		if(gMapEnv->lightMap2)
		{
			if(TexturesSelectTextureUnit(2))
			{
				if(!gLightning)
					TexturesSelectTex(gMapEnv->lightMap2);
				else
					TexturesSelectTex(FileGetReference("null.raw"));			
				glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
				glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_MODULATE);	
				glEnable(GL_TEXTURE_GEN_S);
				glEnable(GL_TEXTURE_GEN_T);
				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);	
				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);	
				GLfloat xPlane[]={1/(gMapEnv->lightMap2BotRight.x-gMapEnv->lightMap2TopLeft.x),0,0,(gTransformPos.x-gMapEnv->lightMap2TopLeft.x+gFrameCount*kFrameTime*gMapEnv->lightMap2Speed.x)/(gMapEnv->lightMap2BotRight.x-gMapEnv->lightMap2TopLeft.x)};
				glTexGenfv(GL_S,GL_OBJECT_PLANE,xPlane);	
				GLfloat yPlane[]={0,0,1/(gMapEnv->lightMap2BotRight.y-gMapEnv->lightMap2TopLeft.y),(gTransformPos.z-gMapEnv->lightMap2TopLeft.y+gFrameCount*kFrameTime*gMapEnv->lightMap2Speed.y)/(gMapEnv->lightMap2BotRight.y-gMapEnv->lightMap2TopLeft.y)};
				glTexGenfv(GL_T,GL_OBJECT_PLANE,yPlane);	
				glMatrixMode(GL_TEXTURE);
				glLoadIdentity();
				glMatrixMode(GL_MODELVIEW);
				TexturesSelectTextureUnit(0);
			}
		}
		else if(gMapEnv->lightMap)
			if(TexturesSelectTextureUnit(2))
			{
				if(!gLightning)
					TexturesSelectTex(gMapEnv->lightMap);
				else
					TexturesSelectTex(FileGetReference("null.raw"));			
				glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
				glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_MODULATE);	
				glEnable(GL_TEXTURE_GEN_S);
				glEnable(GL_TEXTURE_GEN_T);
				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);	
				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);	
				GLfloat xPlane[]={1/(gMapEnv->lightMapBotRight.x-gMapEnv->lightMapTopLeft.x),0,0,(gTransformPos.x-gMapEnv->lightMapTopLeft.x+gFrameCount*kFrameTime*gMapEnv->lightMapSpeed.x)/(gMapEnv->lightMapBotRight.x-gMapEnv->lightMapTopLeft.x)};
				glTexGenfv(GL_S,GL_OBJECT_PLANE,xPlane);	
				GLfloat yPlane[]={0,0,1/(gMapEnv->lightMapBotRight.y-gMapEnv->lightMapTopLeft.y),(gTransformPos.z-gMapEnv->lightMapTopLeft.y+gFrameCount*kFrameTime*gMapEnv->lightMapSpeed.y)/(gMapEnv->lightMapBotRight.y-gMapEnv->lightMapTopLeft.y)};
				glTexGenfv(GL_T,GL_OBJECT_PLANE,yPlane);	
				glMatrixMode(GL_TEXTURE);
				glLoadIdentity();
				glMatrixMode(GL_MODELVIEW);
				TexturesSelectTextureUnit(0);
			}
#endif
		if(mat->flags&kMaterialSphereMap&&gEnvironment->particlesAmount){
			if(TexturesSelectTextureUnit(3))
			{
				TexturesSelectTex(FileGetReference("rainreflection.pct"));
				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
				glEnable(GL_TEXTURE_GEN_S);
				glEnable(GL_TEXTURE_GEN_T);	
				glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
				glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INTERPOLATE_ARB);	
				glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_PREVIOUS_ARB);	
				glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SRC_ALPHA);	

				TexturesSelectTextureUnit(0);
			}
		} else if(TexturesSelectTextureUnit(3))
		{
			glDisable(GL_TEXTURE_2D);
			TexturesSelectTextureUnit(0);
		}	
}

int UseGhostMaterial(tPolyMaterial *mat,int textureSet)
{
	GLfloat specularReflectance[4];
	GLfloat ambientReflectance[4];
	GLfloat diffuseReflectance[4];

	*(tVector3*)specularReflectance=mat->specular;
	*(tVector3*)ambientReflectance=mat->ambient;
	*(tVector3*)diffuseReflectance=mat->diffuse;
	
	specularReflectance[3]=1;
	ambientReflectance[3]=1;
	diffuseReflectance[3]=1;
	
	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuseReflectance);
	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambientReflectance);
	glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specularReflectance);
	
	
	glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,mat->shininess);

	TexturesSelectTex(FileGetIndexedReference(mat->texRef,textureSet));
	
	if(mat->flags&kMaterialDisableWrap)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
	}
	else if(mat->flags&kMaterialDisableWrapS)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	}
	else if(mat->flags&kMaterialDisableWrapT)
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
	}
	else 	
	{
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
	}

	glDisable(GL_CULL_FACE);
	
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE0_ARB);

	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE,GL_ONE);

	return true;
}

//compare function used to sort the polygon index by the Z-Distance from the camera
int PolyTableCompare(tTransparentPolyDistSort *a,tTransparentPolyDistSort *b)
{
	float diff=(a->distance)-(b->distance);
	if(diff==0) return 0;
	else return sign(diff);
}

//calculates the z-distance from the camera for each polygon index value
void PolyTableDepthSetup(tVector3 *clipPlanes)
{
	tVector3 camZ=-*MatrixGetZVector(gCameraEntity->dir);
	for(int i=0;i<gTransparentPolyCount;i++)
	{
		tTransparentPoly* p=gTranparentPolys+i;
		//we simply use the sum of the three vertices for comparison
		tVector3 center=(p->v[0].vertex+p->v[1].vertex+p->v[2].vertex)*(1.0f/3.0f);
		
		if(clipPlanes)
			if(ClipPointDistanced(clipPlanes,&center,20.0f))
				gPolyDistance[i].distance=-10000.0f;
			else
				gPolyDistance[i].distance=(center-gCameraEntity->pos)*camZ;
		else
			gPolyDistance[i].distance=(center-gCameraEntity->pos)*camZ;
		gPolyDistance[i].poly=i;
	}
}

void DrawTransparentPolys(tVector3 *clipPlanes)
{
	glPushAttrib(GL_LIGHTING_BIT+GL_TEXTURE_BIT+GL_POLYGON_BIT+GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	PolyTableDepthSetup(clipPlanes);
	SetupWorldTranslation();
	//depth-sort the polygons
	qsort(gPolyDistance,gTransparentPolyCount,sizeof(tTransparentPolyDistSort),(int (*)(const void *, const void *))&PolyTableCompare);

	//draw all the polygons
	int texture=-1;
	int textureSet=-1;
	int ghost=0;
	int i=0;
	
	for(;i<gTransparentPolyCount&&gPolyDistance[i].distance==-10000.0f;i++);
	for(;i<gTransparentPolyCount;i++)
	{
		int polyIndex=gPolyDistance[i].poly;
		//if the texture isn't currently selected, then select it
		if(texture!=gTranparentPolys[polyIndex].mat->texRef||textureSet!=gTranparentPolys[polyIndex].textureSet||ghost!=gTranparentPolys[polyIndex].ghost||gGlowFactor!=gTranparentPolys[polyIndex].glow)
		{
			gGlowFactor=gTranparentPolys[polyIndex].glow;
			if(gTranparentPolys[polyIndex].ghost)
				UseGhostMaterial(gTranparentPolys[polyIndex].mat,gTranparentPolys[polyIndex].textureSet);
			else
				UseMaterial(gTranparentPolys[polyIndex].mat,true,gTranparentPolys[polyIndex].textureSet);
				
			glDepthMask(!(gTranparentPolys[polyIndex].mat->flags&kMaterialDisableShadow));
			texture=gTranparentPolys[polyIndex].mat->texRef;
			textureSet=gTranparentPolys[polyIndex].textureSet;
			ghost=gTranparentPolys[polyIndex].ghost;
		}

		glBegin(GL_TRIANGLES);
		for(int v=0;v<3;v++)
		{
			glNormal3fv(&gTranparentPolys[polyIndex].v[v].normal.x);
			glTexCoord3f(gTranparentPolys[polyIndex].v[v].texel.x,gTranparentPolys[polyIndex].v[v].texel.y,0.25+0.5*gTranparentPolys[polyIndex].blur);
	//		glTexCoord3f(gTranparentPolys[polyIndex].v[v].texel.x,gTranparentPolys[polyIndex].v[v].texel.y,0.75);
			glVertex3fv(&gTranparentPolys[polyIndex].v[v].vertex.x);
		}	
		glEnd();
	}
	
	//reset transparent polygon count
	gTransparentPolyCount=0;
	gMaterialStorageCount=0;

	glDisable(GL_BLEND);
	if(TexturesSelectTextureUnit(1)){
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_3D);
		glDisable(GL_TEXTURE_GEN_S);
		glDisable(GL_TEXTURE_GEN_T);
		TexturesSelectTextureUnit(0);
	}
		
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	glPopAttrib();	
}