#include "MLRHeaders.hpp"
#include "MLR\MLRFootstep.hpp"

DWORD	gShowClippedPolys=0;
DWORD	gShowBirdView=0;
DWORD	gEnableDetailTexture=1;
DWORD	gEnableTextureSort=1;
DWORD	gEnableAlphaSort=1;
DWORD	gEnableMultiTexture=1;
DWORD	gEnableLightMaps=1;
DWORD	gEnableVertexLighting=1;
DWORD	gEnableCulturals=1;
DWORD	gEnableFootSteps=1;
DWORD	gEnableBumpMap=0;
DWORD	gShowBucketColors=0;
DWORD	gEnableFancyWater=1;
DWORD	gEnableMovieTextures=1;
DWORD	gEnableSimpleLight=0;

static bool __stdcall CheckDetailTexture()
{
	return gEnableDetailTexture!=0;
}
static bool __stdcall CheckTextureSort()
{
	return gEnableTextureSort!=0;
}
static bool __stdcall CheckAlphaSort()
{
	return gEnableAlphaSort!=0;
}
static bool __stdcall CheckMultiTexture()
{
	return gEnableMultiTexture!=0;
}
static bool __stdcall CheckLightMaps()
{
	return gEnableLightMaps!=0;
}
static bool __stdcall CheckVertexLighting()
{
	return gEnableVertexLighting!=0;
}
static bool __stdcall CheckCulturals()
{
	return gEnableCulturals!=0;
}
static bool __stdcall CheckFootSteps()
{
	return gEnableFootSteps!=0;
}
static bool __stdcall CheckBumpMap()
{
	return gEnableBumpMap!=0;
}
static bool __stdcall CheckShowBucketColors()
{
	return gShowBucketColors!=0;
}
static bool __stdcall CheckFancyWater()
{
	return gEnableFancyWater!=0;
}
static bool __stdcall CheckMovieTextures()
{
	return gEnableMovieTextures!=0;
}
static bool __stdcall CheckSimpleLight()
{
	return gEnableSimpleLight!=0;
}

static void __stdcall EnableDetailTexture()
{
	gEnableDetailTexture=!gEnableDetailTexture;
}
static void __stdcall EnableTextureSort()
{
	gEnableTextureSort=!gEnableTextureSort;
}
static void __stdcall EnableAlphaSort()
{
	gEnableAlphaSort=!gEnableAlphaSort;
}
static void __stdcall EnableMultiTexture()
{
	gEnableMultiTexture=!gEnableMultiTexture;
}
static void __stdcall EnableLightMaps()
{
	gEnableLightMaps=!gEnableLightMaps;
}
static void __stdcall EnableVertexLighting()
{
	gEnableVertexLighting=!gEnableVertexLighting;
}
static void __stdcall EnableCulturals()
{
	gEnableCulturals=!gEnableCulturals;
}
static void __stdcall EnableFootSteps()
{
	gEnableFootSteps=!gEnableFootSteps;
}
static void __stdcall EnableBumpMap()
{
	gEnableBumpMap=!gEnableBumpMap;
}
static void __stdcall EnableShowBucketColors()
{
	gShowBucketColors=!gShowBucketColors;
}
static void __stdcall EnableFancyWater()
{
	gEnableFancyWater=!gEnableFancyWater;
}
static void __stdcall EnableMovieTextures()
{
	gEnableMovieTextures=!gEnableMovieTextures;
}
static void __stdcall EnableSimpleLight()
{
	gEnableSimpleLight=!gEnableSimpleLight;
}

extern DWORD gShowClippedPolys;
static bool __stdcall Check_ShowClippedPolys() {return gShowClippedPolys!=0;}
static void __stdcall Toggle_ShowClippedPolys() {gShowClippedPolys=!gShowClippedPolys;}

extern DWORD gShowBirdView;
static bool __stdcall Check_ShowBirdView() {return gShowBirdView!=0;}
static void __stdcall Toggle_ShowBirdView() {gShowBirdView=!gShowBirdView;}

unsigned
	Limits::Max_Number_Vertices_Per_Frame,
	Limits::Max_Number_Primitives_Per_Frame,
	Limits::Max_Number_ScreenQuads_Per_Frame,
	Limits::Max_Size_Of_LightMap_MemoryStream;

Scalar
	Limits::LightThreshold;

HGOSHEAP
	MidLevelRenderer::Heap = NULL,
	MidLevelRenderer::StaticHeap = NULL,
	MidLevelRenderer::StatesHeap = NULL,
	MidLevelRenderer::LightsHeap = NULL,
	MidLevelRenderer::MiscellaneousHeap = NULL,
	MidLevelRenderer::PrimitiveHeap = NULL,
	MidLevelRenderer::ShapeHeap = NULL,
	MidLevelRenderer::VertexPoolHeap = NULL,
	MidLevelRenderer::EffectHeap = NULL,
	MidLevelRenderer::ClipperHeap = NULL,
	MidLevelRenderer::SorterHeap = NULL,
	MidLevelRenderer::TexturePoolHeap = NULL;

DEFINE_TIMER(MidLevelRenderer, Scene_Draw_Time);

DEFINE_TIMER(MidLevelRenderer, Transform_Time);
DEFINE_TIMER(MidLevelRenderer, Clipping_Time);
DEFINE_TIMER(MidLevelRenderer, GOS_Draw_Time);
DEFINE_TIMER(MidLevelRenderer, Vertex_Light_Time);
DEFINE_TIMER(MidLevelRenderer, LightMap_Light_Time);
DEFINE_TIMER(MidLevelRenderer, Texture_Sorting_Time);
DEFINE_TIMER(MidLevelRenderer, Alpha_Sorting_Time);
DEFINE_TIMER(MidLevelRenderer, Unlock_Texture_Time);
DEFINE_TIMER(MidLevelRenderer, Shape_Setup_Time);
DEFINE_TIMER(MidLevelRenderer, Find_Backface_Time);
DEFINE_TIMER(MidLevelRenderer, Fog_Time);
DEFINE_TIMER(MidLevelRenderer, Shadow_Time);

DWORD MidLevelRenderer::Number_Of_Primitives;
DWORD MidLevelRenderer::NumAllIndices;
DWORD MidLevelRenderer::NumAllVertices;
float MidLevelRenderer::Index_Over_Vertex_Ratio;
DWORD MidLevelRenderer::TransformedVertices;
DWORD MidLevelRenderer::NumberOfAlphaSortedTriangles;
DWORD MidLevelRenderer::LitVertices;
DWORD MidLevelRenderer::NonClippedVertices;
DWORD MidLevelRenderer::ClippedVertices;
DWORD MidLevelRenderer::PolysClippedButOutside;
DWORD MidLevelRenderer::PolysClippedButInside;
DWORD MidLevelRenderer::PolysClippedButOnePlane;
DWORD MidLevelRenderer::PolysClippedButGOnePlane;
DWORD MidLevelRenderer::UsedGOSVertices;
DWORD MidLevelRenderer::UsedGOSVertices2UV;
DWORD MidLevelRenderer::UsedGOSVertices3UV;
DWORD MidLevelRenderer::UsedGOSIndicies;


bool MidLevelRenderer::ConvertToTriangleMeshes = false;

int MidLevelRenderer::terrainTextureResolution = 3;

DWORD MidLevelRenderer::bucketColors[] = {
	0xff800000,
	0xffc00000,
	0xff00ff00,
	0xff0000ff,

	0xff808000,
	0xffa0a000,
	0xffc0c000,
	0xffe0e000,

	0xff800080,
	0xffa000a0,
	0xffc000c0,
	0xffe000e0,

	0xff008080,
	0xff00a0a0,
	0xff00c0c0,
	0xff00e0e0
};

DWORD MidLevelRenderer::paintMeColorDW;
RGBAColor MidLevelRenderer::paintMeColorF;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MidLevelRenderer::InitializeClasses(
		Stuff::NotationFile *startup_ini,
		unsigned Max_Number_Vertices_Per_Frame,
		unsigned Max_Number_Primitives_Per_Frame,
		unsigned Max_Number_ScreenQuads_Per_Frame,
		unsigned Max_Size_Of_LightMap_MemoryStream,
		bool Convert_To_Triangle_Meshes
	)
{
	Verify(FirstFreeMLRClassID <= LastMLRClassID);

#if !(defined(NO_STATS) && defined(NO_TIMERS))
	StatisticFormat( "" );
	StatisticFormat( "Mid Level Renderer" );
	StatisticFormat( "==================" );
	StatisticFormat( "" );
#endif

	Verify(!Heap);
	Heap = gos_CreateMemoryHeap("MLR");
	Check_Pointer(Heap);

	Verify(!TexturePoolHeap);
	TexturePoolHeap = gos_CreateMemoryHeap("MLR Texture Pool", 0, Heap);
	Check_Pointer(TexturePoolHeap);

	Verify(!StatesHeap);
	StatesHeap = gos_CreateMemoryHeap("MLR States", 0, Heap);
	Check_Pointer(StatesHeap);

	Verify(!LightsHeap);
	LightsHeap = gos_CreateMemoryHeap("MLR Lights", 0, Heap);
	Check_Pointer(LightsHeap);

	Verify(!MiscellaneousHeap);
	MiscellaneousHeap = gos_CreateMemoryHeap("MLR Miscellaneous", 0, Heap);
	Check_Pointer(MiscellaneousHeap);

	Verify(!ShapeHeap);
	ShapeHeap = gos_CreateMemoryHeap("MLR Shapes", 0, Heap);
	Check_Pointer(ShapeHeap);

	Verify(!PrimitiveHeap);
	PrimitiveHeap = gos_CreateMemoryHeap("MLR Primitives", 0, Heap);
	Check_Pointer(PrimitiveHeap);

	Verify(!EffectHeap);
	EffectHeap = gos_CreateMemoryHeap("MLR Effect", 0, Heap);
	Check_Pointer(EffectHeap);

	Verify(!ClipperHeap);
	ClipperHeap = gos_CreateMemoryHeap("MLR Clipper", 0, Heap);
	Check_Pointer(ClipperHeap);

	Verify(!SorterHeap);
	SorterHeap = gos_CreateMemoryHeap("MLR Sorter", 0, Heap);
	Check_Pointer(SorterHeap);

	Verify(!VertexPoolHeap);
	VertexPoolHeap = gos_CreateMemoryHeap("MLR Vertex Pool", 0, Heap);
	Check_Pointer(VertexPoolHeap);

	Verify(!StaticHeap);
	StaticHeap = gos_CreateMemoryHeap("MLR Static", 0, Heap);
	Check_Pointer(StaticHeap);
	gos_PushCurrentHeap(StaticHeap);


	Limits::Max_Number_Vertices_Per_Frame = Max_Number_Vertices_Per_Frame;
	Limits::Max_Number_Primitives_Per_Frame = Max_Number_Primitives_Per_Frame;
	Limits::Max_Number_ScreenQuads_Per_Frame = Max_Number_ScreenQuads_Per_Frame;
	Limits::Max_Size_Of_LightMap_MemoryStream = Max_Size_Of_LightMap_MemoryStream;

	Limits::LightThreshold = 0.05f;

	ConvertToTriangleMeshes = Convert_To_Triangle_Meshes;

	MLRLight::InitializeClass();
	MLRTexturePool::InitializeClass();
	MLRClipper::InitializeClass();
	MLRSorter::InitializeClass();
	MLRSortByOrder::InitializeClass();
	MLRShape::InitializeClass();
	MLREffect::InitializeClass();
	MLRPointCloud::InitializeClass();
	MLRTriangleCloud::InitializeClass();
	MLRNGonCloud::InitializeClass();
	MLRCardCloud::InitializeClass();
	MLRAmbientLight::InitializeClass();
	MLRInfiniteLight::InitializeClass();
	MLRInfiniteLightWithFalloff::InitializeClass();
	MLRPointLight::InitializeClass();
	MLRSpotLight::InitializeClass();

	MLRPrimitiveBase::InitializeClass();
	MLRIndexedPrimitiveBase::InitializeClass();
	MLR_I_PMesh::InitializeClass();
	MLR_I_C_PMesh::InitializeClass();
	MLR_I_L_PMesh::InitializeClass();
	MLR_I_DT_PMesh::InitializeClass();
	MLR_I_C_DT_PMesh::InitializeClass();
	MLR_I_L_DT_PMesh::InitializeClass();

	MLR_I_DeT_PMesh::InitializeClass();
	MLR_I_C_DeT_PMesh::InitializeClass();
	MLR_I_L_DeT_PMesh::InitializeClass();

	MLR_I_TMesh::InitializeClass();
	MLR_I_DeT_TMesh::InitializeClass();
	MLR_I_C_TMesh::InitializeClass();
	MLR_I_L_TMesh::InitializeClass();

	MLR_Terrain2::InitializeClass();

	MLRLineCloud::InitializeClass();
	MLRIndexedTriangleCloud::InitializeClass();

	MLR_I_DT_TMesh::InitializeClass();
	MLR_I_C_DT_TMesh::InitializeClass();
	MLR_I_L_DT_TMesh::InitializeClass();

	MLR_I_C_DeT_TMesh::InitializeClass();
	MLR_I_L_DeT_TMesh::InitializeClass();

	MLRLookUpLight::InitializeClass();
	MLR_Water::InitializeClass();
	MLRProjectLight::InitializeClass();

	MLRSpriteCloud::InitializeClass();

	MLRShadowLight::InitializeClass();

	MLRCulturShape::InitializeClass();

	MLRCenterPointLight::InitializeClass();

	MLRFootStep::InitializeClass();

	MLR_BumpyWater::InitializeClass();

	MLRLightMap::InitializeClass();

	MLRTexture::InitializeClass();
	MLRMovieTexture::InitializeClass();

#if FOG_HACK
	for(int i=0;i<Limits::Max_Number_Of_FogStates;i++)
	{
		GOSVertex::SetFogTableEntry(i+1, 700.0f, 1000.0f, 0.0f);
	}
#endif

	gos_PopCurrentHeap();

	//
	//-------------------------
	// Setup the debugger menus
	//-------------------------
	//
	AddDebuggerMenuItem(
		"Libraries\\MLR\\Show Clipped Polygons",
		Check_ShowClippedPolys,
		Toggle_ShowClippedPolys,
		NULL
	);
	AddDebuggerMenuItem(
		"Libraries\\MLR\\Show Bird View",
		Check_ShowBirdView,
		Toggle_ShowBirdView,
		NULL
	);

	AddDebuggerMenuItem("Libraries\\MLR\\Texture Sort", CheckTextureSort, EnableTextureSort, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\Enable Detail Texture", CheckDetailTexture, EnableDetailTexture, NULL );
	AddDebuggerMenuItem("Libraries\\MLR\\Alpha Sort", CheckAlphaSort, EnableAlphaSort, NULL );
	AddDebuggerMenuItem("Libraries\\MLR\\Show Bucket Colors", CheckShowBucketColors, EnableShowBucketColors, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\MultiTexture Enabled", CheckMultiTexture, EnableMultiTexture, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\LightMaps Enabled", CheckLightMaps, EnableLightMaps, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\VertexLighting Enabled", CheckVertexLighting, EnableVertexLighting, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\Culturals Enabled", CheckCulturals, EnableCulturals, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\FootSteps Enabled", CheckFootSteps, EnableFootSteps, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\Fancy Water Enabled", CheckFancyWater, EnableFancyWater, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\Movie Textures Enabled", CheckMovieTextures, EnableMovieTextures, NULL );
	AddDebuggerMenuItem("Libraries\\Graphics Options\\Simple Lighting", CheckSimpleLight, EnableSimpleLight, NULL );

	if( (0<gos_GetMachineInformation(gos_Info_CanBumpEnvMap)) || (0<gos_GetMachineInformation(gos_Info_CanBumpDotMap)) )
	{
		AddDebuggerMenuItem("Libraries\\Graphics Options\\BumpMap Enabled", CheckBumpMap, EnableBumpMap, NULL );
	}

	//
	//--------------------------------------------
	// Now set the menu defaults from the ini file
	//--------------------------------------------
	//
	if (startup_ini)
	{
		Check_Object(startup_ini);
		Page *page = startup_ini->FindPage("Graphics Options");
		if (page)
		{
			Check_Object(page);

			bool status;
			if (page->GetEntry("DetailTexture", &status))
				gEnableDetailTexture = status;
			if (page->GetEntry("MultiTexture", &status))
				gEnableMultiTexture = status;
			if (page->GetEntry("LightMaps", &status))
				gEnableLightMaps = status;
			if (page->GetEntry("Culturals", &status))
				gEnableCulturals = status;
			if (page->GetEntry("Footsteps", &status))
				gEnableFootSteps = status;
			if (page->GetEntry("FancyWater", &status))
				gEnableFancyWater = status;
			if (page->GetEntry("MovieTextures", &status))
				gEnableMovieTextures = status;
			if (page->GetEntry("SimpleLighting", &status))
				gEnableSimpleLight = status;
		}
	}

	//
	//---------------------
	// Setup the statistics
	//---------------------
	//
	Initialize_Timer(Transform_Time, "Transform Time");
	Initialize_Timer(Clipping_Time, "Clipping Time");
	Initialize_Timer(GOS_Draw_Time, "GOS Draw Time");
	Initialize_Timer(Vertex_Light_Time, "Vertex Light Time");
	Initialize_Timer(LightMap_Light_Time, "LightMap Light Time");
	Initialize_Timer(Texture_Sorting_Time, "Texture Sorting Time");
	Initialize_Timer(Alpha_Sorting_Time, "Alpha Sorting Time");
	Initialize_Timer(Unlock_Texture_Time, "Unlock Texture Time");	
	Initialize_Timer(Shape_Setup_Time, "Shape Setup Time");	
	Initialize_Timer(Find_Backface_Time, "Find Backface Time");	
	Initialize_Timer(Fog_Time, "Fog Time");	
	Initialize_Timer(Shadow_Time, "Shadow Time");	

#if !defined(NO_STATS)
	AddStatistic( "MLR Primitives",			"prims",		gos_DWORD, &Number_Of_Primitives, Stat_AutoReset );
	AddStatistic( "Indices/Vertices",	"Ratio",	gos_float, &Index_Over_Vertex_Ratio, Stat_AutoReset+Stat_2DP );
	AddStatistic( "Transformed vertices",			"vertices",		gos_DWORD, &TransformedVertices, Stat_AutoReset );
	AddStatistic( "Number of alphasorted Tri",			"tri",		gos_DWORD, &NumberOfAlphaSortedTriangles, Stat_AutoReset );
	AddStatistic( "Lit vertices",			"vertices",		gos_DWORD, &LitVertices, Stat_AutoReset );
	AddStatistic( "Unclipped vertices",			"vertices",		gos_DWORD, &NonClippedVertices, Stat_AutoReset );
	AddStatistic( "Clipped vertices",			"vertices",		gos_DWORD, &ClippedVertices, Stat_AutoReset );

// Polygons in primitives which are clipped but polys are outside the viewing frustrum
	AddStatistic( "Clip: Offscreen",			"Poly",		gos_DWORD, &PolysClippedButOutside, Stat_AutoReset );
// Polygons in primitives which are clipped but polys are inside the viewing frustrum
	AddStatistic( "Clip: Onscreen",			"Poly",		gos_DWORD, &PolysClippedButInside, Stat_AutoReset );
// Polygons in primitives which are clipped, polys clipped against one plain
	AddStatistic( "Clip: One Plane",			"Poly",		gos_DWORD, &PolysClippedButOnePlane, Stat_AutoReset );
// Polygons in primitives which are clipped, polys clipped against more than one plain
	AddStatistic( "Clip: > One Plane",			"Poly",		gos_DWORD, &PolysClippedButGOnePlane, Stat_AutoReset );

	AddStatistic( "Used Vertices in GOSVertexPool",			"#",		gos_DWORD, &UsedGOSVertices, Stat_AutoReset );
	AddStatistic( "Used Vertices2UV in GOSVertexPool",			"#",		gos_DWORD, &UsedGOSVertices2UV, Stat_AutoReset );
	AddStatistic( "Used Vertices3UV in GOSVertexPool",			"#",		gos_DWORD, &UsedGOSVertices3UV, Stat_AutoReset );
	AddStatistic( "Used Indecies in GOSVertexPool",			"#",		gos_DWORD, &UsedGOSIndicies, Stat_AutoReset );
#endif

	paintMeColorDW = 0xffffffff;
	paintMeColorF = RGBAColor(1.0f, 1.0f, 1.0f, 1.0f);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MidLevelRenderer::TerminateClasses(Stuff::NotationFile *startup_ini)
{
	//
	//----------------------------------
	// Now set the ini file if it exists
	//----------------------------------
	//
	if (startup_ini)
	{
		Check_Object(startup_ini);
		Page *page = startup_ini->SetPage("Graphics Options");
		Check_Object(page);

		page->SetEntry("DetailTexture", gEnableDetailTexture!=0);
		page->SetEntry("MultiTexture", gEnableMultiTexture!=0);
		page->SetEntry("LightMaps", gEnableLightMaps!=0);
		page->SetEntry("Culturals", gEnableCulturals!=0);
		page->SetEntry("Footsteps", gEnableFootSteps!=0);
		page->SetEntry("FancyWater", gEnableFancyWater!=0);
		page->SetEntry("MovieTextures", gEnableMovieTextures!=0);
		page->SetEntry("SimpleLighting", gEnableSimpleLight!=0);
	}

	gos_PushCurrentHeap(Heap);

	MLRMovieTexture::TerminateClass();
	MLRTexture::TerminateClass();

	MLRLightMap::TerminateClass();

	MLR_BumpyWater::TerminateClass();

	MLRFootStep::TerminateClass();

	MLRCenterPointLight::TerminateClass();

	MLRCulturShape::TerminateClass();

	MLRShadowLight::TerminateClass();

	MLRSpriteCloud::TerminateClass();

	MLRProjectLight::TerminateClass();

	MLR_Water::TerminateClass();
	MLRLookUpLight::TerminateClass();

	MLR_I_L_DeT_TMesh::TerminateClass();
	MLR_I_C_DeT_TMesh::TerminateClass();

	MLR_I_L_DT_TMesh::TerminateClass();
	MLR_I_C_DT_TMesh::TerminateClass();
	MLR_I_DT_TMesh::TerminateClass();

	MLRIndexedTriangleCloud::TerminateClass();
	MLRLineCloud::TerminateClass();

	MLR_Terrain2::TerminateClass();

	MLR_I_L_TMesh::TerminateClass();
	MLR_I_C_TMesh::TerminateClass();
	MLR_I_DeT_TMesh::TerminateClass();
	MLR_I_TMesh::TerminateClass();

	MLR_I_L_DeT_PMesh::TerminateClass();
	MLR_I_C_DeT_PMesh::TerminateClass();
	MLR_I_DeT_PMesh::TerminateClass();

	MLR_I_L_DT_PMesh::TerminateClass();
	MLR_I_C_DT_PMesh::TerminateClass();
	MLR_I_DT_PMesh::TerminateClass();
	MLR_I_L_PMesh::TerminateClass();
	MLR_I_C_PMesh::TerminateClass();
	MLR_I_PMesh::TerminateClass();
	MLRIndexedPrimitiveBase::TerminateClass();
	MLRPrimitiveBase::TerminateClass();

	MLRSpotLight::TerminateClass();
	MLRPointLight::TerminateClass();
	MLRInfiniteLightWithFalloff::TerminateClass();
	MLRInfiniteLight::TerminateClass();
	MLRAmbientLight::TerminateClass();
	MLRCardCloud::TerminateClass();
	MLRNGonCloud::TerminateClass();
	MLRTriangleCloud::TerminateClass();
	MLRPointCloud::TerminateClass();
	MLREffect::TerminateClass();
	MLRShape::TerminateClass();
	MLRSortByOrder::TerminateClass();
	MLRSorter::TerminateClass();
	MLRClipper::TerminateClass();
	MLRTexturePool::TerminateClass();
	MLRLight::TerminateClass();
	gos_PopCurrentHeap();

	Check_Pointer(StaticHeap);
	gos_DestroyMemoryHeap(StaticHeap);
	StaticHeap = NULL;

	Check_Pointer(TexturePoolHeap);
	gos_DestroyMemoryHeap(TexturePoolHeap);
	TexturePoolHeap = NULL;

	Check_Pointer(StatesHeap);
	gos_DestroyMemoryHeap(StatesHeap);
	StatesHeap = NULL;

	Check_Pointer(LightsHeap);
	gos_DestroyMemoryHeap(LightsHeap);
	LightsHeap = NULL;

	Check_Pointer(MiscellaneousHeap);
	gos_DestroyMemoryHeap(MiscellaneousHeap);
	MiscellaneousHeap = NULL;

	Check_Pointer(ShapeHeap);
	gos_DestroyMemoryHeap(ShapeHeap);
	ShapeHeap = NULL;

	Check_Pointer(PrimitiveHeap);
	gos_DestroyMemoryHeap(PrimitiveHeap);
	PrimitiveHeap = NULL;

	Check_Pointer(VertexPoolHeap);
	gos_DestroyMemoryHeap(VertexPoolHeap);
	VertexPoolHeap = NULL;

	Check_Pointer(EffectHeap);
	gos_DestroyMemoryHeap(EffectHeap);
	EffectHeap = NULL;

	Check_Pointer(ClipperHeap);
	gos_DestroyMemoryHeap(ClipperHeap);
	ClipperHeap = NULL;

	Check_Pointer(SorterHeap);
	gos_DestroyMemoryHeap(SorterHeap);
	SorterHeap = NULL;

	Check_Pointer(Heap);
	gos_DestroyMemoryHeap(Heap);
	Heap = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	MidLevelRenderer::ReadMLRVersion(MemoryStream *erf_stream)
{
	Check_Object(erf_stream);

	//
	//------------------------------------------------------------------------
	// See if this file has an erf signature.  If so, the next int will be the
	// version number.  If not, assume it is version 1 and rewind the file
	//------------------------------------------------------------------------
	//
	int version = -1;
	int erf_signature;
	*erf_stream >> erf_signature;
	if (erf_signature == 'MLR#')
		*erf_stream >> version;
	else
		erf_stream->RewindPointer(sizeof(erf_signature));
	if (version > Current_MLR_Version)
		STOP(("Application must be rebuilt to use this version of MLR data"));
	return version;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MidLevelRenderer::WriteMLRVersion(MemoryStream *erf_stream)
{
	Check_Object(erf_stream);
	*erf_stream << 'MLR#' << static_cast<int>(Current_MLR_Version);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BYTE
	FogData::FogVertex(const Stuff::Point3D *p)
{
	Stuff::Vector3D v;

	v.Subtract(*p, cameraPos);
	Scalar d = v.GetApproximateLength();

	BYTE df = (BYTE)( (d<near_fog+SMALL) ? 0xff : (d+SMALL>far_fog) ? 0 : Truncate_Float_To_Byte(255.0f*(1.0f - (d-near_fog)*one_over)) );

	BYTE hhf;
	if(height_fog_density < 0xff)
	{
		v.Subtract(*p, orgInShape);
		Scalar h = v*upInShape;
		hhf = (BYTE)( (h<height_low_fog+SMALL) ? height_fog_density : (h+SMALL>height_top_fog) ? 0xff : Truncate_Float_To_Byte(height_fog_density + height_fog_density0*(h-height_low_fog)) );
		return (df < hhf ? df : hhf);
	}

	return df;
}