//tracks.cpp
//draw tire tracks on the road

#include <OpenGL/gl.h>
#include "textures.h"
#include "fileio.h"
#include "vectors.h"
#include "renderframe.h"
#include "gamemem.h"
#include "network.h"
#include "tracks.h"
#include "log.h"
#include "error.h"
#include "gameinitexit.h"
#include "environment.h"

#define kMaxTrack 512		//size of track segment buffer
#define kTrackShiftSize 256 //how many track segmnents to delete when buffer is full

#define kTrackHeight 0.02	//how far tracks are drawn above ground (to avoid z-buffer problems)
#define kMaxIntensity 0.8
#define kTrackTexScale 0.18

typedef struct{
	tVector3 pos1l,pos1r,pos2l,pos2r,normal;
	int texture;
	float l1,l2;
	float intensity1,intensity2;
} tTrackSegment;

tTrackSegment gTrack[kMaxTrack];//track segment buffer
int gNumTracks=0;
int gTrackIndexShift=0;

//Add a new segment of tire tracks, going from pos1 to pos2
//attach specifies a track segment which links to this one
int TracksAdd(tVector3 pos1,tVector3 pos2,tVector3 normal,float width,int texture,float intensity,int attach)
{
	//is there any space left in the track segment buffer?
	if(gNumTracks>=kMaxTrack)
	{
		//if not, delete kTrackShiftSize elements, by shifting the track segment buffer
		gTrackIndexShift+=kTrackShiftSize;
		gNumTracks-=kTrackShiftSize;
		MemoryMove(gTrack,gTrack+kTrackShiftSize,(kMaxTrack-kTrackShiftSize)*sizeof(tTrackSegment));
	}
	
	float adjustedIntensity=intensity*kMaxIntensity;
	pos1.y+=kTrackHeight;//to avoid Z-Buffer Problems
	pos2.y+=kTrackHeight;
	
	tVector3 crossNormal=!((pos1-pos2)%normal);
	
	gTrack[gNumTracks].pos1l=pos1+crossNormal*width*0.5;
	gTrack[gNumTracks].pos1r=pos1-crossNormal*width*0.5;
	gTrack[gNumTracks].pos2l=pos2+crossNormal*width*0.5;
	gTrack[gNumTracks].pos2r=pos2-crossNormal*width*0.5;

	gTrack[gNumTracks].normal=normal;

	gTrack[gNumTracks].texture=texture;

	gTrack[gNumTracks].intensity1=adjustedIntensity;
	gTrack[gNumTracks].intensity2=adjustedIntensity;
	gTrack[gNumTracks].l1=0;
	gTrack[gNumTracks].l2=~(pos2-pos1);
	
	
	//does attach correspods to a given Track Segment in the Buffer?
	if(attach-gTrackIndexShift>0)
	{
		//fix the Track Segments to properly fit together.
		gTrack[attach-gTrackIndexShift].pos2l=gTrack[gNumTracks].pos1l;
		gTrack[attach-gTrackIndexShift].pos2r=gTrack[gNumTracks].pos1r;
		gTrack[attach-gTrackIndexShift].l2=gTrack[attach-gTrackIndexShift].l1+~(gTrack[attach-gTrackIndexShift].pos2l-gTrack[attach-gTrackIndexShift].pos1l);
		gTrack[attach-gTrackIndexShift].intensity2=adjustedIntensity;
		float lOffs=gTrack[attach-gTrackIndexShift].l2;
		gTrack[gNumTracks].l1+=lOffs;
		gTrack[gNumTracks].l2+=lOffs;	
	}
	return (gNumTracks++)+gTrackIndexShift;
}

//clear the Track Segment Buffer
void TracksClear()
{
	gNumTracks=0;
}

//Render the Tracks
void TracksRender(tVector3 *clipPlanes)
{
	SetupWorldTranslation();
	
	glPushAttrib(GL_COLOR_BUFFER_BIT+GL_CURRENT_BIT+GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT);
	glDisable(GL_LIGHTING);
	glEnable(GL_BLEND);	
	glDepthMask(false);								
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	int tex=-1;
	for(int i=0;i<gNumTracks;i++)
		//is the segment visible?
		if(!ClipPointDistanced(clipPlanes,&gTrack[i].pos1r,gTrack[i].l2-gTrack[i].l1))
		{
			if(gTrack[i].texture!=tex)
			{
				tex=gTrack[i].texture;
				int texLoaded=gFileTable[tex].parsed;
				TexturesSelectTex(tex);
				//if the texture has just been loaded, fade the alpha values of the mipmap level textures
				//this way we avoid moire effects for tire tracks further in the background.
				if(!texLoaded)
					TexturesAlphaFadeMipMaps();
			}
			
			//draw track segment.
			//glNormal3fv(&(gTrack[i].normal).x);
			float light=(gEnvironment->ambient.x+gEnvironment->ambient.y+gEnvironment->ambient.z)*0.33;
			glBegin(GL_TRIANGLE_STRIP);								
			glTexCoord2d(0,gTrack[i].l1*kTrackTexScale); 
			glColor4f(light,light,light,gTrack[i].intensity1);
			glVertex3fv(&(gTrack[i].pos1r).x); 	
			glTexCoord2d(0,gTrack[i].l2*kTrackTexScale); 
			glColor4f(light,light,light,gTrack[i].intensity2);
			glVertex3fv(&(gTrack[i].pos2r).x); 	
			glTexCoord2d(1,gTrack[i].l1*kTrackTexScale); 
			glColor4f(light,light,light,gTrack[i].intensity1);
			glVertex3fv(&(gTrack[i].pos1l).x);		
			glTexCoord2d(1,gTrack[i].l2*kTrackTexScale); 
			glColor4f(light,light,light,gTrack[i].intensity2);
			glVertex3fv(&(gTrack[i].pos2l).x); 	
			glEnd();
			#ifdef __POLYCOUNT
			gPolyCount+=2;
			#endif
		}	
	glPopAttrib();
}