//roads.cpp
//draws the road and detects collisions agains the road.

#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <math.h>
#include "entities.h"
#include "config.h"
#include "vectors.h"
#include "fileio.h"
#include "textures.h"
#include "gamemem.h"
#include "renderframe.h"
#include "roads.h"
#include "environment.h"
#include "gameinitexit.h"
#include "transparency.h"
#include "network.h"



#include <stdio.h>
#include "error.h"
#define kExtraLength 80

tRoadTypeList *gRoadTypes;
tSurfaceTypeList *gSurfaceTypes;
int gRoadRestrictedBorders=false;
int gQuickRoadCollision=false;

#define kMaxAILateralAcceleration 4.0
#define kMaxAITurboLateralAcceleration 12.0
#define kMaxAILongitunalAcceleration 4.8
#define kMaxAITurboLongitunalAcceleration 10.0
#define kMaxSpeedIndex 100

tVector2 GetFlatTrack(tConvertedRoad *convRoad,int i,int roadSize)
{
	if(i<0)i=0;
	if(i>roadSize-2)i=roadSize-2;
	tVector3 pos_3=convRoad->road[i].trackl+(convRoad->road[i].trackr-convRoad->road[i].trackl)*((convRoad->road[i].track+1)*0.5);
	return Vector(pos_3.x,pos_3.z);
}

#define kMinSignLateralAccel 2.5
#define kSignDistance 100.0

void CalcSpeedInfo(int ref)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(ref);
	tRoadSeg *road=roadData->road;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[ref].parsedData;
	
	
	for(int i=2;i<(roadData->roadSize)-2;i++)
	{	
		float traction=gRoadTypes->types[road[i].type].traction;
		if(traction==0)traction=1;
		tVector2 pos1=GetFlatTrack(convRoad,i-7,(roadData->roadSize));
		tVector2 pos2=GetFlatTrack(convRoad,i,(roadData->roadSize));
		tVector2 pos3=GetFlatTrack(convRoad,i+7,(roadData->roadSize));
		tVector2 v1=!(pos2-pos1);
		tVector2 v2=!(pos3-pos2);
		float veloDiff=~(v2-v1);
		float dist=~(pos1-pos2)+~(pos2-pos3);

		if(dist>0&&veloDiff>0)
		{
			float accel=dist/veloDiff;
			convRoad->road[i].speedIndex=sqrt(kMaxAILateralAcceleration*accel*traction);
			if(convRoad->road[i].speedIndex>kMaxSpeedIndex)
				convRoad->road[i].speedIndex=kMaxSpeedIndex;
			convRoad->road[i].turboSpeedIndex=sqrt(kMaxAITurboLateralAcceleration*accel*traction);
			if(convRoad->road[i].turboSpeedIndex>kMaxSpeedIndex)
				convRoad->road[i].turboSpeedIndex=kMaxSpeedIndex;
		}
		else
		{
			convRoad->road[i].speedIndex=kMaxSpeedIndex;
			convRoad->road[i].turboSpeedIndex=kMaxSpeedIndex;
		}
		
		convRoad->road[i].lateralAccel=(v1.y*v2.x-v2.y*v1.x)/dist*1000;
		if(road[i].speedModifier>=-1&&road[i].speedModifier<=1)
		{
			convRoad->road[i].speedIndex*=(1+road[i].speedModifier);
			convRoad->road[i].turboSpeedIndex*=(1+road[i].speedModifier);
		}
		convRoad->road[i].reverseSpeedIndex=convRoad->road[i].speedIndex;
		convRoad->road[i].reverseTurboSpeedIndex=convRoad->road[i].turboSpeedIndex;
	}
	convRoad->road[0].speedIndex=kMaxSpeedIndex;
	convRoad->road[1].speedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-1].speedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-2].speedIndex=kMaxSpeedIndex;
	convRoad->road[0].reverseSpeedIndex=kMaxSpeedIndex;
	convRoad->road[1].reverseSpeedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-1].reverseSpeedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-2].reverseSpeedIndex=kMaxSpeedIndex;

	convRoad->road[0].turboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[1].turboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-1].turboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-2].turboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[0].reverseTurboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[1].reverseTurboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-1].reverseTurboSpeedIndex=kMaxSpeedIndex;
	convRoad->road[(roadData->roadSize)-2].reverseTurboSpeedIndex=kMaxSpeedIndex;

	

	for(int i=(roadData->roadSize)-2;i>=0;i--)
	{
		float traction=gRoadTypes->types[road[i].type].traction;
		if(traction==0)traction=1;
		tVector2 pos1=Vector(road[i].pos.x,road[i].pos.z);
		tVector2 pos2=Vector(road[i+1].pos.x,road[i+1].pos.z);
		float dist=~(pos1-pos2);
		float speedIndex2=convRoad->road[i+1].speedIndex;
		float maxSpeedIndex1=sqrt(sqr(speedIndex2)+kMaxAILongitunalAcceleration*2*dist*traction);
		float maxTurboSpeedIndex1=sqrt(sqr(speedIndex2)+kMaxAITurboLongitunalAcceleration*2*dist*traction);
		if(convRoad->road[i].speedIndex>maxSpeedIndex1)
			convRoad->road[i].speedIndex=maxSpeedIndex1;
		if(convRoad->road[i].turboSpeedIndex>maxTurboSpeedIndex1)
			convRoad->road[i].turboSpeedIndex=maxTurboSpeedIndex1;
	}
	for(int i=1;i<(roadData->roadSize)-2;i++)
	{
		float traction=gRoadTypes->types[road[i].type].traction;
		if(traction==0)traction=1;
		tVector2 pos1=Vector(road[i].pos.x,road[i].pos.z);
		tVector2 pos2=Vector(road[i-1].pos.x,road[i-1].pos.z);
		float dist=~(pos1-pos2);
		float speedIndex2=convRoad->road[i-1].reverseSpeedIndex;
		float maxSpeedIndex1=sqrt(sqr(speedIndex2)+kMaxAILongitunalAcceleration*2*dist*traction);
		float maxTurboSpeedIndex1=sqrt(sqr(speedIndex2)+kMaxAITurboLongitunalAcceleration*2*dist*traction);
		if(convRoad->road[i].reverseSpeedIndex>maxSpeedIndex1)
			convRoad->road[i].reverseSpeedIndex=maxSpeedIndex1;
		if(convRoad->road[i].reverseTurboSpeedIndex>maxTurboSpeedIndex1)
			convRoad->road[i].reverseTurboSpeedIndex=maxTurboSpeedIndex1;
	}

	int cornerStart=-1;
	float corner=0;
	float iminus2=convRoad->road[0].lateralAccel;
	float iminus1=convRoad->road[1].lateralAccel;
	//smooth lateralAccel
	for(int i=2;i<(roadData->roadSize)-3;i++)
	{	
		float temp=convRoad->road[i].lateralAccel;
		convRoad->road[i].lateralAccel=
			(convRoad->road[i].lateralAccel+
			convRoad->road[i+1].lateralAccel+
			convRoad->road[i+2].lateralAccel+
			iminus1+iminus2)/5;
		iminus2=iminus1;
		iminus1=temp;
	}
	
	for(int i=1;i<(roadData->roadSize)-2;i++)
	{
		if((convRoad->road[i].lateralAccel>kMinSignLateralAccel&&corner>=0)||
			(convRoad->road[i].lateralAccel>1.5&&corner>0))
		{
			if(corner==0)
				cornerStart=i;
			if(convRoad->road[i].lateralAccel>corner)
				corner=convRoad->road[i].lateralAccel;
		}
		else if((convRoad->road[i].lateralAccel<-kMinSignLateralAccel&&corner<=0)||
			(convRoad->road[i].lateralAccel<-1.5&&corner<0))
		{
			if(corner==0)
				cornerStart=i;
			if(convRoad->road[i].lateralAccel<corner)
				corner=convRoad->road[i].lateralAccel;
		}
		else if(corner)
		{
			for(int j=cornerStart;j<i;j++)
				convRoad->road[j].lateralAccel=corner;
			convRoad->road[i].lateralAccel=0;
			corner=0;
			cornerStart=-1;
		}
		else
			convRoad->road[i].lateralAccel=0;
	}
	if(corner)
	{
		for(int j=cornerStart;j<(roadData->roadSize)-3;j++)
			convRoad->road[j].lateralAccel=corner;
	}
}

float Interpolation(float x)
{	
	return -x*x*x*x+2*x*x;
}

float InterpolateTrack(float l1, float l2, float l, float track1, float track2)
{
	return track1+(track2-track1)*Interpolation((l-l1)/(l2-l1));
}

void ConvertRoadEndianess(tRoadData *roadData)
{
	tRoadSeg *road=roadData->road;
	S32Swap(roadData->roadSize);
	
	for(int i=0;i<roadData->roadSize;i++)
	{
		F32Swap(road[i].pos.x);
		F32Swap(road[i].pos.y);
		F32Swap(road[i].pos.z);
		F32Swap(road[i].normal.x);
		F32Swap(road[i].normal.y);
		F32Swap(road[i].normal.z);
		S32Swap(road[i].type);
		F32Swap(road[i].track);
		F32Swap(road[i].typeSeg);
	}
}


void CompileRoadPoints(int id)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(id);
	tRoadSeg *road=roadData->road;
	
	ConvertRoadEndianess(roadData);
	
	tConvertedRoad *convRoad=(tConvertedRoad*)MemoryAllocateBlock(((roadData->roadSize)-1)*sizeof(tConvertedRoadSeg)+sizeof(tConvertedRoad));
	
	int vertexCount=0;
	for(int i=0;i<(roadData->roadSize)-1;i++)
		vertexCount+=gRoadTypes->types[(road[i].type)].numVertices+2;
		
	convRoad->vertexStorage=(tConvertedRoadVertex*)MemoryAllocateBlock(sizeof(tConvertedRoadVertex)*vertexCount);
	
	tVector3 prevSegDir,prevJunction2;
	tVector3 curSegDir,curJunction1,curJunction2;
	tVector3 nextSegDir,nextJunction1,nextJunction2;
	tVector3 junction1,junction2;	
	
	float totalLength=0;
	float startTypeSeg=0;
	vertexCount=0;

	curSegDir=road[1].pos-road[0].pos;
	curJunction1=!(curSegDir%road[0].normal);
	curJunction2=!(curSegDir%road[1].normal);
	prevSegDir=curSegDir;
	prevJunction2=curJunction1;
	junction1=!(curJunction1+prevJunction2);

	if(road[0].track>1)road[0].track=0;
	float lastTrackLength=0,lastTrack=road[0].track;	
	float nextTrackLength=0,nextTrack=road[0].track;
	int lastTrackIndex=0,nextTrackIndex=0;

	for(int i=0;i<(roadData->roadSize)-1;i++)
	{
		if(nextTrackIndex<=i)
		{
			float l=totalLength;
			for(int j=i+1;j<(roadData->roadSize)&&nextTrackIndex<=i;j++)
			{
				l+=~(road[j].pos-road[j-1].pos);
				if(road[j].track<=1||j==(roadData->roadSize)-1)
				{
					lastTrackLength=nextTrackLength;
					lastTrack=nextTrack;
					lastTrackIndex=nextTrackIndex;
					nextTrackIndex=j;
					nextTrackLength=l;			
					nextTrack=(j==(roadData->roadSize)-1?road[0].track:road[nextTrackIndex].track);
				}
			}
		}
		
		nextSegDir=i<(roadData->roadSize)-2?road[i+2].pos-road[i+1].pos:curSegDir;
		nextJunction1=!(nextSegDir%road[i+1].normal);
		nextJunction2=i<(roadData->roadSize)-2?!(nextSegDir%road[i+2].normal):nextJunction1;

		junction2=!(nextJunction1+curJunction1);
		
		convRoad->road[i].vertices=convRoad->vertexStorage+vertexCount+1;
		convRoad->road[i].maxExtends=0;
		
		int numVertices=gRoadTypes->types[(road[i].type)].numVertices;
		
		vertexCount+=numVertices+2;
		
		convRoad->road[i].track=InterpolateTrack(lastTrackLength,nextTrackLength,totalLength,lastTrack,nextTrack);
		convRoad->road[i].trackl=road[i].pos+junction1*gRoadTypes->types[(road[i].type)].minTrack;
		convRoad->road[i].trackr=road[i].pos+junction1*gRoadTypes->types[(road[i].type)].maxTrack;

		for(int v=-1;v<numVertices+1;v++)
		{
			tVector2 typePoint1,typePoint2;
			if(v==-1)
			{
				typePoint1=gRoadTypes->types[(road[i].type)].vertices[v+1].vertex1+(gRoadTypes->types[(road[i].type)].vertices[v+1].vertex2-gRoadTypes->types[(road[i].type)].vertices[v+1].vertex1)*startTypeSeg;
				typePoint2=gRoadTypes->types[(road[i].type)].vertices[v+1].vertex1+(gRoadTypes->types[(road[i].type)].vertices[v+1].vertex2-gRoadTypes->types[(road[i].type)].vertices[v+1].vertex1)*road[i].typeSeg;
				typePoint1.x-=3;
				typePoint2.x-=3;
			}
			else if(v==numVertices)
			{
				typePoint1=gRoadTypes->types[(road[i].type)].vertices[v-1].vertex1+(gRoadTypes->types[(road[i].type)].vertices[v-1].vertex2-gRoadTypes->types[(road[i].type)].vertices[v-1].vertex1)*startTypeSeg;
				typePoint2=gRoadTypes->types[(road[i].type)].vertices[v-1].vertex1+(gRoadTypes->types[(road[i].type)].vertices[v-1].vertex2-gRoadTypes->types[(road[i].type)].vertices[v-1].vertex1)*road[i].typeSeg;
				typePoint1.x+=3;
				typePoint2.x+=3;
			}
			else
			{
				typePoint1=gRoadTypes->types[(road[i].type)].vertices[v].vertex1+(gRoadTypes->types[(road[i].type)].vertices[v].vertex2-gRoadTypes->types[(road[i].type)].vertices[v].vertex1)*startTypeSeg;
				typePoint2=gRoadTypes->types[(road[i].type)].vertices[v].vertex1+(gRoadTypes->types[(road[i].type)].vertices[v].vertex2-gRoadTypes->types[(road[i].type)].vertices[v].vertex1)*road[i].typeSeg;
			}

			if(sqr(typePoint1)>convRoad->road[i].maxExtends)
				convRoad->road[i].maxExtends=sqr(typePoint1);
			if(sqr(typePoint2)>convRoad->road[i].maxExtends)
				convRoad->road[i].maxExtends=sqr(typePoint2);
			convRoad->road[i].vertices[v].v1=road[i].pos+road[i].normal*typePoint1.y+junction1*typePoint1.x;
			convRoad->road[i].vertices[v].v2=road[i+1].pos+road[i+1].normal*typePoint2.y+junction2*typePoint2.x;
			
			convRoad->road[i].vertices[v].d2=convRoad->road[i].vertices[v].v2.y-convRoad->road[i].vertices[v].v1.y;
			convRoad->road[i].vertices[v].d1=convRoad->road[i].vertices[v].v2.y-convRoad->road[i].vertices[v].v1.y;
			if(i>0)
				if((road[i-1].type)==(road[i].type))
				{
					tVector3 v1=convRoad->road[i].vertices[v].v2-convRoad->road[i].vertices[v].v1;
					tVector3 v2=convRoad->road[i].vertices[v].v1-convRoad->road[i-1].vertices[v].v1;
					float l1=~v1;
					float l2=~v2;
					tVector3 v12=!(!v1+!v2);
					float d=v12.y/sqrt(sqr(v12.x)+sqr(v12.z));
					if(fabs(convRoad->road[i].vertices[v].d1-d*l1)<2)
					{
						convRoad->road[i].vertices[v].d1=d*l1;
						convRoad->road[i-1].vertices[v].d2=d*l2;
					}
				}
		}
		
		startTypeSeg=road[i].typeSeg;
		if(startTypeSeg>=1)startTypeSeg=0;
		for(int v=-1;v<numVertices;v++)
		{
			if(v==-1)
			{
				convRoad->road[i].vertices[v].n1=!(junction1);
				convRoad->road[i].vertices[v].n2=!(junction2);
			}
			else if(v==numVertices-1)
			{
				convRoad->road[i].vertices[v].n1=!(-junction1);
				convRoad->road[i].vertices[v].n2=!(-junction2);
			}
			else
			{
				tVector2 typeNormal1=(gRoadTypes->types[(road[i].type)].vertices[v].vertex1-gRoadTypes->types[(road[i].type)].vertices[v+1].vertex1);
				tVector2 typeNormal2=(gRoadTypes->types[(road[i].type)].vertices[v].vertex2-gRoadTypes->types[(road[i].type)].vertices[v+1].vertex2);
				if(VectorEqual(typeNormal1,Vector(0,0)))
					typeNormal1=Vector(-1,0);
				if(VectorEqual(typeNormal2,Vector(0,0)))
					typeNormal2=Vector(-1,0);
				typeNormal1=!typeNormal1;
				typeNormal2=!typeNormal2;
		
				convRoad->road[i].vertices[v].n1=!(-road[i].normal*typeNormal1.x+junction1*typeNormal1.y);
				convRoad->road[i].vertices[v].n2=!(-road[i+1].normal*typeNormal2.x+junction2*typeNormal2.y);
			}
		}
		
		convRoad->road[i].length=totalLength;
		totalLength+=~curSegDir;
		
		convRoad->road[i].maxExtends=sqrt(convRoad->road[i].maxExtends);
		
		prevJunction2=curJunction2;
		curSegDir=nextSegDir;
		curJunction1=nextJunction1;
		curJunction2=nextJunction2;	
		junction1=junction2;	
	}
	gFileTable[id].parsedData=convRoad;
	gFileTable[id].parsed=true;
	CalcSpeedInfo(id);
}


//Renders the Road
void RoadRender(tVector3 *clipPlanes)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	if(!gFileTable[gMapInfo->road].parsed)
		CompileRoadPoints(gMapInfo->road);
	if(!gFileTable[gMapInfo->road].parsed)
		return;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;

	SetupWorldTranslation();

	glPushAttrib(GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_POLYGON_BIT);
	
/*	GLfloat specularReflectance[]={0.0,0.0,0.0,1};
	GLfloat ambientReflectance[]={0.6,0.6,0.6,1};
	GLfloat diffuseReflectance[]={0.4,0.4,0.4,1};
*/
	GLfloat specularReflectance[]={0.0,0.0,0.0,1};
	GLfloat ambientReflectance[]={0.4,0.4,0.4,1};
	GLfloat diffuseReflectance[]={0.6,0.6,0.6,1};

	glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuseReflectance);
	glMaterialfv(GL_FRONT,GL_AMBIENT,ambientReflectance);
	glMaterialfv(GL_FRONT,GL_SPECULAR,specularReflectance);
	glMaterialf(GL_FRONT,GL_SHININESS,20);

	int lastClipped=0;
	int texture=-1;
	
	tPolyMaterial mat;
	mat.flags=kMaterialBothSides+kMaterialUseAlphaChannel+kMaterialDisableWrapS;
	mat.shininess=0;
	mat.specular=Vector(0,0,0);
	mat.ambient=Vector(0.6,0.6,0.6);
	mat.diffuse=Vector(0.4,0.4,0.4);
		
	for(int i=0;i<(roadData->roadSize)-2;i++)
	{		
		float len1=convRoad->road[i].length;
		float len2=convRoad->road[i+1].length;
		int clipped=ClipPointDistanced(clipPlanes,&road[i+1].pos,convRoad->road[i].maxExtends);
		
		if(!(clipped&lastClipped))
		{
			int numVertices=gRoadTypes->types[(road[i].type)].numVertices;
			for(int v=0;v<numVertices-1;v++)
			{
				float texZoom=gRoadTypes->types[(road[i].type)].vertices[v].texZoom;
				if(texZoom>=0)
				{
					if(!(gRoadTypes->types[(road[i].type)].vertices[v].materialFlags&1))
					{
						if(gRoadTypes->types[(road[i].type)].vertices[v].materialFlags&2)
							glDisable(GL_CULL_FACE);
						else
							glEnable(GL_CULL_FACE);
							
						if(texture!=gRoadTypes->types[(road[i].type)].vertices[v].texture)
						{
							texture=gRoadTypes->types[(road[i].type)].vertices[v].texture;
							TexturesSelectTex(texture);
							if(!gConfig->carsOnSpeed)
								glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
						}
							
						glBegin(GL_TRIANGLE_STRIP);
						
						glNormal3fv(&convRoad->road[i].vertices[v].n2.x);
						glTexCoord2f(gRoadTypes->types[(road[i].type)].vertices[v+1].texCoord1,texZoom?convRoad->road[i+1].length*texZoom:1);
						glVertex3fv(&convRoad->road[i].vertices[v+1].v2.x);
						
						glNormal3fv(&convRoad->road[i].vertices[v].n1.x);
						glTexCoord2f(gRoadTypes->types[(road[i].type)].vertices[v].texCoord2,texZoom?convRoad->road[i+1].length*texZoom:1);
						glVertex3fv(&convRoad->road[i].vertices[v].v2.x);

						glNormal3fv(&convRoad->road[i].vertices[v].n2.x);
						glTexCoord2f(gRoadTypes->types[(road[i].type)].vertices[v+1].texCoord1,texZoom?convRoad->road[i].length*texZoom:0);
						glVertex3fv(&convRoad->road[i].vertices[v+1].v1.x);
						
						glNormal3fv(&convRoad->road[i].vertices[v].n1.x);				
						glTexCoord2f(gRoadTypes->types[(road[i].type)].vertices[v].texCoord2,texZoom?convRoad->road[i].length*texZoom:0);
						glVertex3fv(&convRoad->road[i].vertices[v].v1.x);
						
						glEnd();
						/*
						glBegin(GL_LINES);
						glVertex3fv(&convRoad->road[i].vertices[v+1].v2.x);
						glVertex3fv(&(convRoad->road[i].vertices[v+1].v2+convRoad->road[i].vertices[v].n2).x);
						glVertex3fv(&convRoad->road[i].vertices[v+1].v1.x);
						glVertex3fv(&(convRoad->road[i].vertices[v+1].v1+convRoad->road[i].vertices[v].n1*2).x);
						glVertex3fv(&convRoad->road[i].vertices[v].v2.x);
						glVertex3fv(&(convRoad->road[i].vertices[v].v2+convRoad->road[i].vertices[v].n2).x);
						glVertex3fv(&convRoad->road[i].vertices[v].v1.x);
						glVertex3fv(&(convRoad->road[i].vertices[v].v1+convRoad->road[i].vertices[v].n1*2).x);
						glEnd();*/
					}
					else if(tTransparentPoly *p=GetNextTransparentPoly(true))
					{
						mat.texRef=gRoadTypes->types[(road[i].type)].vertices[v].texture;

						*p->mat=mat;
						p->textureSet=0;
						p->v[0].vertex=convRoad->road[i].vertices[v+1].v2;
						p->v[1].vertex=convRoad->road[i].vertices[v].v2;
						p->v[2].vertex=convRoad->road[i].vertices[v+1].v1;
						p->v[0].normal=convRoad->road[i].vertices[v].n2;
						p->v[1].normal=convRoad->road[i].vertices[v].n1;
						p->v[2].normal=convRoad->road[i].vertices[v].n2;
						p->v[0].texel=Vector(gRoadTypes->types[(road[i].type)].vertices[v+1].texCoord1,texZoom?convRoad->road[i+1].length*texZoom:1);
						p->v[1].texel=Vector(gRoadTypes->types[(road[i].type)].vertices[v].texCoord2,texZoom?convRoad->road[i+1].length*texZoom:1);
						p->v[2].texel=Vector(gRoadTypes->types[(road[i].type)].vertices[v+1].texCoord1,texZoom?convRoad->road[i].length*texZoom:0);

						if(tTransparentPoly *p=GetNextTransparentPoly(true))
						{
							*p->mat=mat;
							p->textureSet=0;
							p->v[0].vertex=convRoad->road[i].vertices[v].v1;
							p->v[1].vertex=convRoad->road[i].vertices[v].v2;
							p->v[2].vertex=convRoad->road[i].vertices[v+1].v1;
							p->v[0].normal=convRoad->road[i].vertices[v].n1;
							p->v[1].normal=convRoad->road[i].vertices[v].n1;
							p->v[2].normal=convRoad->road[i].vertices[v].n2;
							p->v[0].texel=Vector(gRoadTypes->types[(road[i].type)].vertices[v].texCoord2,texZoom?convRoad->road[i].length*texZoom:0);
							p->v[1].texel=Vector(gRoadTypes->types[(road[i].type)].vertices[v].texCoord2,texZoom?convRoad->road[i+1].length*texZoom:1);
							p->v[2].texel=Vector(gRoadTypes->types[(road[i].type)].vertices[v+1].texCoord1,texZoom?convRoad->road[i].length*texZoom:0);
						}
					}
					#ifdef __POLYCOUNT
					gPolyCount+=2;
					#endif
				}
			}

		}
		lastClipped=clipped;
	}
	
	glPopAttrib();
}


tVector2 OrtoVec(tVector2 v)
{
	return Vector(v.y,-v.x);
}

float GetPlaneHeight(tVector3 pos,tVector3 planeNormal,tVector3 planePoint)
{
	return -(planeNormal.x*pos.x+planeNormal.z*pos.z-planeNormal*planePoint)/planeNormal.y;
}

int RoadGetRoadSegment(tVector3 pos,int lastSegment)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	if(!gFileTable[gMapInfo->road].parsed)
		CompileRoadPoints(gMapInfo->road);
	if(!gFileTable[gMapInfo->road].parsed)
		return 0;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;
	
	tVector2 flatPos=Vector(pos.x,pos.z);

	int max=(gRoadRestrictedBorders&&lastSegment)?15:(roadData->roadSize)*2;
	
	//a hack to always get a result for the camera, which jumps around a lot.
	//if((lastSegment==gCameraEntity->lastRoadIndex)||gReplay||lastSegment==0)
	//	max=(roadData->roadSize)*2;
		
	for(int ind=1;ind<max;ind++)
	{	
		int i=lastSegment+((ind&1)?(ind/2):-(ind/2));
		while(i<0)i+=(roadData->roadSize)-2;
		while(i>=(roadData->roadSize)-2)i-=(roadData->roadSize)-2;
		if(sqr(road[i].pos.x-flatPos.x)+sqr(road[i].pos.z-flatPos.y)<sqr(convRoad->road[i+1].length-convRoad->road[i].length+kExtraLength))
		{
			int numVertices=gRoadTypes->types[(road[i].type)].numVertices;
//			int endTopVertices=gRoadTypes->types[(road[i].type)].endTopVertices;
//			int startTopVertices=gRoadTypes->types[(road[i].type)].startTopVertices;
			int endTopVertices=gRoadTypes->types[(road[i].type)].numVertices+1;
			int startTopVertices=-1;
			tVector2 right1,left1,right2,left2;
			tVector2 rDir=Vector(road[i+1].pos.x-road[i].pos.x,road[i+1].pos.z-road[i].pos.z);
			do{
				right1=Vector(convRoad->road[i].vertices[startTopVertices].v1.x,	convRoad->road[i].vertices[startTopVertices].v1.z	);
				right2=Vector(convRoad->road[i].vertices[startTopVertices].v2.x,	convRoad->road[i].vertices[startTopVertices].v2.z	);
				startTopVertices++;
			}while((right2-right1)*rDir<0);
			do{
				left1=	Vector(convRoad->road[i].vertices[endTopVertices-1].v1.x,	convRoad->road[i].vertices[endTopVertices-1].v1.z	);
				left2=	Vector(convRoad->road[i].vertices[endTopVertices-1].v2.x,	convRoad->road[i].vertices[endTopVertices-1].v2.z	);
				endTopVertices--;
			}while((left2-left1)*rDir<0);
			if((right1-flatPos)	*!OrtoVec(left1-right1)<=0.5)
			if((left2-flatPos)	*OrtoVec(right2-left2)<=0)
			if((right1-flatPos)	*!OrtoVec(right1-right2)<=0.5)
			if((left2-flatPos)	*OrtoVec(left2-left1)<=0)
			return i;
		}
	}
	return -1;
}

float RoadGetPosition(tVector3 pos,int lastSegment)
{
	int i=RoadGetRoadSegment(pos,lastSegment);
	if(i==-1)return 0;

	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	
	tVector3 point1=road[i].pos;
	tVector3 point2=road[i+1].pos;
	float localPosition=((pos-point1)*(point2-point1))/sqr(point2-point1);
	return localPosition+i;
}

float RoadGetLength(tVector3 pos,int lastSegment)
{
	float f=RoadGetPosition(pos,lastSegment);
	int i=floor(f);
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;
	if(i<0)i=0;
	if(i<roadData->roadSize-1)
		return convRoad->road[i].length+(convRoad->road[i+1].length-convRoad->road[i].length)*(f-i);
	else
		return convRoad->road[i].length;
}

void RoadInitCheckPoints(tVector3 startPos)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	float pos=RoadGetPosition(startPos,0);
	float stepSize=((roadData->roadSize)-3)/kNumCheckPoints;
	for(int i=0;i<kNumCheckPoints;i++)
	{
		gCheckPoints[i].index=pos;
		pos+=gGameInfo->reverse?-stepSize:stepSize;
		if(pos>((roadData->roadSize)-3))
			pos-=((roadData->roadSize)-3);
		if(pos<0)
			pos+=(roadData->roadSize)-3;

		for(int j=0;j<kMaxLaps+1;j++)
		{
			gCheckPoints[i].passTimes[j].setBy=nil;
			gCheckPoints[i].passTimes[j].hit=false;
		}
	}
}

void RoadInitCheckPoints(tVector3 startPos,tVector3 endPos)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	float pos1=RoadGetPosition(startPos,0);
	float pos2=RoadGetPosition(endPos,0);
/*	if(gGameInfo->reverse)
	{
		float tmp=pos2;
		pos2=pos1;
		pos1=tmp;
	}*/
	float pos=pos1;
	float stepSize=(pos2-pos1)/kNumCheckPoints;
	
	for(int i=0;i<kNumCheckPoints;i++)
	{
		gCheckPoints[i].index=pos;
		pos+=stepSize;
		for(int j=0;j<kMaxLaps+1;j++)
		{
			gCheckPoints[i].passTimes[j].setBy=nil;
			gCheckPoints[i].passTimes[j].hit=false;
		}
	}
}

float RoadPosFromLength(int initPos,float length)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;

	float l=convRoad->road[initPos].length+length;
	int i=initPos;
	
	if(l<0)
		l+=convRoad->road[(roadData->roadSize)-2].length;
	if(l>convRoad->road[(roadData->roadSize)-2].length)
		l-=convRoad->road[(roadData->roadSize)-2].length;
	
	if(l<convRoad->road[initPos].length)
		while(i>0&&convRoad->road[i].length>l)
			i--;
	else
		while(i<(roadData->roadSize)-1&&convRoad->road[i].length<l)
			i++;
	return i;
	
}

#define kCornerSignDistance 120
void RoadInitCornerSigns()
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	if(!gFileTable[gMapInfo->road].parsed)
		CompileRoadPoints(gMapInfo->road);
	if(!gFileTable[gMapInfo->road].parsed)
		return;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;
	gNumCornerSigns=0;
	
	float accel=0;
	int lastCurvePos=0;
	
	if(gGameInfo->reverse)
		for(int i=(roadData->roadSize)-3;i>0;i--)
		{
			if(convRoad->road[i].lateralAccel!=accel)
			{
				if(convRoad->road[i].lateralAccel!=0&&gNumCornerSigns<kMaxCornerSigns)
				{
					gCornerSigns[gNumCornerSigns].pos=RoadPosFromLength(i,kCornerSignDistance);
					if(gCornerSigns[gNumCornerSigns].pos>lastCurvePos)
						gCornerSigns[gNumCornerSigns].pos=lastCurvePos;
					gCornerSigns[gNumCornerSigns].accel=convRoad->road[i].lateralAccel;
					gNumCornerSigns++;
				}
				accel=convRoad->road[i].lateralAccel;
				lastCurvePos=i;
			}
		}
	else for(int i=1;i<(roadData->roadSize)-2;i++)
		{
			if(convRoad->road[i].lateralAccel!=accel)
			{
				if(convRoad->road[i].lateralAccel!=0&&gNumCornerSigns<kMaxCornerSigns)
				{
					gCornerSigns[gNumCornerSigns].pos=RoadPosFromLength(i,-kCornerSignDistance);
					if(gCornerSigns[gNumCornerSigns].pos<lastCurvePos)
						gCornerSigns[gNumCornerSigns].pos=lastCurvePos;
					gCornerSigns[gNumCornerSigns].accel=convRoad->road[i].lateralAccel;
					gNumCornerSigns++;
				}
				accel=convRoad->road[i].lateralAccel;
				lastCurvePos=i;
			}
		}
	
}

tVector3 RoadGetDir(int segment)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	
	tVector3 point1=road[segment].pos;
	tVector3 point2=road[segment+1].pos;
	return !(gGameInfo->reverse?point1-point2:point2-point1);
}

void RoadCenterCar(tGameEntity *carEntity)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;

	int i=RoadGetRoadSegment(carEntity->pos,carEntity->lastRoadIndex);
	if(i==-1)return;

	
	tVector3 point=(convRoad->road[i].trackl+convRoad->road[i].trackr)*0.5;
	tVector3 dir=RoadGetDir(i);
	*MatrixGetZVector(carEntity->dir)=dir;
	*MatrixGetYVector(carEntity->dir)=Vector(0,1,0);
	MatrixReAdjust(carEntity->dir);
	carEntity->pos=point+((carEntity->pos-point)*dir)*dir;
	carEntity->pos.y+=2+gRoadTypes->types[(road[i].type)].reviveY;
	carEntity->pos=carEntity->pos-*MatrixGetXVector(carEntity->dir)*gRoadTypes->types[(road[i].type)].reviveX;
	carEntity->velo=Vector(0,0,0);
	MatrixIdentity(carEntity->rVelo);	
}

tVector3 RoadGetNextWaypoint(tVector3 pos,int *lastRoadIndex,float *overtaking,float *speedIndex,float aheadDistance)
{
	*lastRoadIndex=RoadGetRoadSegment(pos,*lastRoadIndex);
	float l=RoadGetLength(pos,*lastRoadIndex)+(gGameInfo->reverse?-aheadDistance:aheadDistance);
	int i=*lastRoadIndex;
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;
	
	if(l<0)
		l+=convRoad->road[(roadData->roadSize)-2].length;
	if(l>convRoad->road[(roadData->roadSize)-2].length)
		l-=convRoad->road[(roadData->roadSize)-2].length;
	
	if(l<RoadGetLength(pos,*lastRoadIndex))
		while(i>0&&convRoad->road[i].length>l)
			i--;
	else
		while(i<(roadData->roadSize)-1&&convRoad->road[i].length<l)
			i++;
	
	float f=RoadGetPosition(pos,*lastRoadIndex);
	if(gGameInfo->reverse)
		if(gGameInfo->arcade==2)
			*speedIndex=convRoad->road[(int)f].reverseTurboSpeedIndex+(convRoad->road[((int)f)+1].reverseTurboSpeedIndex-convRoad->road[(int)f].reverseTurboSpeedIndex)*(f-(int)f);
		else
			*speedIndex=convRoad->road[(int)f].reverseSpeedIndex+(convRoad->road[((int)f)+1].reverseSpeedIndex-convRoad->road[(int)f].reverseSpeedIndex)*(f-(int)f);
	else
		if(gGameInfo->arcade==2)
			*speedIndex=convRoad->road[(int)f].turboSpeedIndex+(convRoad->road[((int)f)+1].turboSpeedIndex-convRoad->road[(int)f].turboSpeedIndex)*(f-(int)f);
		else
			*speedIndex=convRoad->road[(int)f].speedIndex+(convRoad->road[((int)f)+1].speedIndex-convRoad->road[(int)f].speedIndex)*(f-(int)f);
	
	if(i<=0)i=1;
	f=(l-convRoad->road[i-1].length)/(convRoad->road[i].length-convRoad->road[i-1].length);
	if(f<0)f=0;
	if(f>1)f=1;
	
	float track1=convRoad->road[i-1].track+(*overtaking>0?(1-convRoad->road[i-1].track)**overtaking:(1+convRoad->road[i-1].track)**overtaking);
	tVector3 trackPos1=convRoad->road[i-1].trackl+((convRoad->road[i-1].trackr-convRoad->road[i-1].trackl)*((track1+1)/2));		
	float track2=convRoad->road[i].track+(*overtaking>0?(1-convRoad->road[i].track)**overtaking:(1+convRoad->road[i].track)**overtaking);
	tVector3 trackPos2=convRoad->road[i].trackl+((convRoad->road[i].trackr-convRoad->road[i].trackl)*((track2+1)/2));		
	*overtaking=convRoad->road[i].track;
	
	return trackPos1+f*(trackPos2-trackPos1)+Vector(0,gRoadTypes->types[(roadData->road[i].type)].reviveY,0);
}


float InterpolateSplineAt(float y0,float y1,float d0,float d1,float x)
{
	float a= 2*y0-2*y1+  d0+  d1;
	float b=-3*y0+3*y1-2*d0-  d1;
	float c=             d0     ;
	float d=   y0               ;
	return a*x*x*x+b*x*x+c*x+d;
}

float RoadGetYValue(tVector3 point,int *lastRoadIndex,tVector3 *groundNormal,int *surfaceType,float *bumpOut)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	if(!gFileTable[gMapInfo->road].parsed)
		CompileRoadPoints(gMapInfo->road);
	if(!gFileTable[gMapInfo->road].parsed)
		return -INFINITY;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;
	
	tVector2 flatPos=Vector(point.x,point.z);

	int i=RoadGetRoadSegment(point,*lastRoadIndex);
	if(i!=-1)
	{
		*lastRoadIndex=i;
		int numVertices=gRoadTypes->types[(road[i].type)].numVertices;
		int endTopVertices=gRoadTypes->types[(road[i].type)].endTopVertices;
		int startTopVertices=gRoadTypes->types[(road[i].type)].startTopVertices;
//		int endTopVertices=gRoadTypes->types[(road[i].type)].numVertices+1;
//		int startTopVertices=-1;

		unsigned int min=startTopVertices,max=endTopVertices-1;

		tVector2 min1v2=Vector(convRoad->road[i].vertices[min].v1.x,	convRoad->road[i].vertices[min].v1.z	);
		tVector2 min2v2=Vector(convRoad->road[i].vertices[min].v2.x,	convRoad->road[i].vertices[min].v2.z	);
		if((min1v2-flatPos)*OrtoVec(min1v2-min2v2)>=0)
		{
			if(surfaceType)
				*surfaceType=gMapInfo->baseSurfaceType;
			if(groundNormal)
				*groundNormal=convRoad->road[i].vertices[-1].n1;
			if(bumpOut)
				*bumpOut=0;
			return -(min1v2-flatPos)*!OrtoVec(min1v2-min2v2);
		}
		tVector2 max1v2=Vector(convRoad->road[i].vertices[max].v1.x,	convRoad->road[i].vertices[max].v1.z	);
		tVector2 max2v2=Vector(convRoad->road[i].vertices[max].v2.x,	convRoad->road[i].vertices[max].v2.z	);
		if((max1v2-flatPos)*OrtoVec(max1v2-max2v2)<=0)
		{
			if(surfaceType)
				*surfaceType=gMapInfo->baseSurfaceType;
			if(groundNormal)
				*groundNormal=convRoad->road[i].vertices[gRoadTypes->types[(road[i].type)].numVertices-1].n1;
//				*groundNormal=!(road[i].pos-point);
			if(bumpOut)
				*bumpOut=0;
			//printf("max %f\n",(max1v2-flatPos)*!OrtoVec(max1v2-max2v2));
			return (max1v2-flatPos)*!OrtoVec(max1v2-max2v2);
		}
		
		while(max>min+1)
		{
			unsigned int mid=(min+max)/2;
			tVector2 mid1=Vector(convRoad->road[i].vertices[mid].v1.x,	convRoad->road[i].vertices[mid].v1.z	);
			tVector2 mid2=Vector(convRoad->road[i].vertices[mid].v2.x,	convRoad->road[i].vertices[mid].v2.z	);
			if((mid1-flatPos)*OrtoVec(mid1-mid2)>=0)
				max=mid;
			else
				min=mid;
		}
		int surface;
		if(min!=-1&&max!=endTopVertices-1)
			surface=gRoadTypes->types[(road[i].type)].vertices[min].surfaceType;
		else
			surface=gMapInfo->baseSurfaceType;
		if(surfaceType)
			*surfaceType=surface;
		tVector3 min2=convRoad->road[i].vertices[min].v2;
		tVector3 max2=convRoad->road[i].vertices[max].v2;	
		tVector3 min1=convRoad->road[i].vertices[min].v1;
		tVector3 max1=convRoad->road[i].vertices[max].v1;	
		
		tVector2 flatMin1=Vector(min1.x,min1.z);
		tVector2 flatMin2=Vector(min2.x,min2.z);
		tVector2 flatMax1=Vector(max1.x,max1.z);
		tVector2 flatMax2=Vector(max2.x,max2.z);

		float u,v;
		tVector2 a,b,c;
		if(((flatMin1-flatPos)*OrtoVec(flatMin1-flatMax2)<=0||sqr(flatMax1-flatMin1)==0)&&!(sqr(flatMin2-flatMax2)==0))
		{
			a=flatMin2-flatMax2;
			b=flatMax1-flatMax2;
			c=flatPos-flatMax2;
		}
		else			
		{
			a=flatMax1-flatMin1;
			b=flatMin2-flatMin1;
			c=(flatMin1+a+b)-flatPos;
		}
		
		if(a.x!=0&&a.y!=0&&b.x!=0&&b.y!=0){
			if(a.x==0)
			{
				v=(c.x)/(b.x);
				u=(c.y-v*b.y)/(a.y);
			}
			else if(a.y==0)
			{
				v=(c.y)/(b.y);
				u=(c.x-v*b.x)/(a.x);
			}
			else
			{			
				u=(b.x*c.y-b.y*c.x)/(a.y*b.x-a.x*b.y);
				if(b.y==0)
				{
					v=(c*a)/sqr(a);				
				}
				else
					v=(c.y-u*a.y)/b.y;
			}
			
			

		//	float miny=InterpolateSplineAt(min1.y,min2.y,convRoad->road[i].vertices[min].d1,convRoad->road[i].vertices[min].d2,1-v);
		//	float maxy=InterpolateSplineAt(max1.y,max2.y,convRoad->road[i].vertices[max].d1,convRoad->road[i].vertices[max].d2,1-v);
			float miny=min2.y-v*(min2.y-min1.y);
			float maxy=max2.y-v*(max2.y-max1.y);
			float y=maxy-u*(maxy-miny);
			
			if(groundNormal)
			{
				tVector3 vmin=min2-v*(min2-min1);
				vmin.y=miny;
				tVector3 vmax=max2-v*(max2-max1);
				vmax.y=maxy;
				tVector3 v1=max1-u*(max1-min1);
				tVector3 v2=max2-u*(max2-min2);
				*groundNormal=!((vmin-vmax)%(v1-v2));
			}

			float bumpFreq=gSurfaceTypes->types[surface].bumpFreq;
			float bump=gSurfaceTypes->types[surface].bumpHeight*sin(flatPos.x*bumpFreq)*sin(flatPos.y*bumpFreq);
			if(bumpOut)*bumpOut=bump;
			return point.y-y-bump;
		}
		else
		{
			tVector3 normal=!((min1-max2)%(max1-min2));

			if(groundNormal)
				*groundNormal=normal;
			float bumpFreq=gSurfaceTypes->types[surface].bumpFreq;
			float bump=gSurfaceTypes->types[surface].bumpHeight*sin(flatPos.x*bumpFreq)*sin(flatPos.y*bumpFreq);
			if(bumpOut)*bumpOut=bump;
			return point.y-GetPlaneHeight(point,normal,min2)-bump;
		}
	}
	
	if(!gQuickRoadCollision)
	{
		int closestRoadSeg=-1;
		float closestRoadSegDist=INFINITY;
		tVector2 normal;
		for(int i=0;i<(roadData->roadSize)-2;i++)
		{	
			if(sqr(road[i].pos.x-point.x)+sqr(road[i].pos.z-point.z)<sqr(convRoad->road[i+1].length-convRoad->road[i].length+kExtraLength))
			{
				int numVertices=gRoadTypes->types[(road[i].type)].numVertices;
				int endTopVertices=gRoadTypes->types[(road[i].type)].endTopVertices;
				int startTopVertices=gRoadTypes->types[(road[i].type)].startTopVertices;
				tVector2 right1=Vector(convRoad->road[i].vertices[startTopVertices].v1.x,	convRoad->road[i].vertices[startTopVertices].v1.z	);
				tVector2 left1=	Vector(convRoad->road[i].vertices[endTopVertices-1].v1.x,	convRoad->road[i].vertices[endTopVertices-1].v1.z	);
				tVector2 right2=Vector(convRoad->road[i].vertices[startTopVertices].v2.x,	convRoad->road[i].vertices[startTopVertices].v2.z	);
				tVector2 left2=	Vector(convRoad->road[i].vertices[endTopVertices-1].v2.x,	convRoad->road[i].vertices[endTopVertices-1].v2.z	);
				float dist;
				tVector2 testNormal;
				if(((right1-flatPos)*!OrtoVec(right1-left1))>=0)
				if(((left2-flatPos)*!OrtoVec(right2-left2))<=0)
				{
					if((dist=(right1-flatPos)*(testNormal=!OrtoVec(right1-right2)))<=closestRoadSegDist)
						if(dist>=0)
						{
							closestRoadSeg=i;
							closestRoadSegDist=dist;
							normal=testNormal;
						}
					if((dist=(left2-flatPos)*(testNormal=!OrtoVec(left2-left1)))<=closestRoadSegDist)
						if(dist>=0)
						{
							closestRoadSeg=i;
							closestRoadSegDist=dist;
							normal=testNormal;
						}
				}
			}
		}	
		if(closestRoadSeg!=-1)
		{
			if(surfaceType)
				*surfaceType=gMapInfo->baseSurfaceType;
			if(groundNormal)
				*groundNormal=Vector(normal.x,0,normal.y);
			return -closestRoadSegDist;
		}
	}
	if(surfaceType)
		*surfaceType=gMapInfo->baseSurfaceType;
	if(groundNormal)
		*groundNormal=Vector(0,1,0);
	return -INFINITY;
}

void RoadGetWayPointData(int startRoadSeg,float dist,float *minTrack,float *maxTrack,float *minSpeed)
{
	tRoadData *roadData=(tRoadData*)FileGetDataPtr(gMapInfo->road);
	tRoadSeg *road=roadData->road;
	if(!gFileTable[gMapInfo->road].parsed)
		CompileRoadPoints(gMapInfo->road);
	if(!gFileTable[gMapInfo->road].parsed)
		return;
	tConvertedRoad *convRoad=(tConvertedRoad*)gFileTable[gMapInfo->road].parsedData;
	float l=0;
	*minTrack=1;
	*maxTrack=-1;
	*minSpeed=INFINITY;
	while(l<dist)
	{
		if(convRoad->road[startRoadSeg].track<*minTrack)
			*minTrack=convRoad->road[startRoadSeg].track;
		if(convRoad->road[startRoadSeg].track>*maxTrack)
			*maxTrack=convRoad->road[startRoadSeg].track;
		if(convRoad->road[startRoadSeg].speedIndex<*minSpeed)
			*minSpeed=convRoad->road[startRoadSeg].speedIndex;
		startRoadSeg++;	
		if(startRoadSeg>=(roadData->roadSize)-1)
			startRoadSeg=0;
		else
			l+=convRoad->road[startRoadSeg].length-convRoad->road[startRoadSeg-1].length;
	}
}
