// MFC GosDoc.cpp : implementation of the CMFCGosDoc class
//

#include "stdafx.h"
#include "MFC Gos.h"


#include <ElementRenderer\ElementRenderer.hpp>
#include <ElementRenderer\GroupElement.hpp>
#include <ElementRenderer\CameraElement.hpp>
#include <ElementRenderer\ShapeElement.hpp>
#include <ElementRenderer\StateChange.hpp>
#include <ElementRenderer\PointCloudElement.hpp>
#include <gosFX\gosFX.hpp>
#include <MLR\MLR.hpp>
#include <GameOS\GameOS.hpp>
#include <GameOS\ToolOS.hpp>
#include "MFC GosDoc.h"
#include "WaterDlg1.h"
#include "BumpMapDlg.h"
#include "SlideDlg.h"
#include <MLR\MLRHeaders.hpp>


extern CList<Stuff::MString*, Stuff::MString*> m_pErf_Name_List;
extern Stuff::MString *erf_texture_path;
extern ElementRenderer::GroupElement *Scene;
extern ElementRenderer::StateChange *LightState;
extern ElementRenderer::CameraElement *Camera;
extern Stuff::Point3D Camera_LookAt;
extern Stuff::YawPitchRange Camera_Direction;
//extern Stuff::Vector2DOf<Stuff::Scalar> Camera_Shift;
extern ElementRenderer::StateChange *Camera_State;
extern ElementRenderer::Element *ErfElement;
extern ElementRenderer::PointCloudElement *cloud;


void SIMPLEHEIRARCHY::DeleteHeirarchy(SIMPLEHEIRARCHY * pNode)
{
	if (!pNode)
		return;

	POSITION pos = pNode->listChildren.GetHeadPosition();
	while (pos)
	{
		SIMPLEHEIRARCHY * pChild = pNode->listChildren.GetNext(pos);
		DeleteHeirarchy(pChild);
	}
	delete pNode;
}

SIMPLEHEIRARCHY *  SIMPLEHEIRARCHY ::BuildHeirarchy(LPCSTR lpszChildToMake, Stuff::LinearMatrix4D lmParentLocalToWorld, Stuff::NotationFile * pNoteFile)
{
	Stuff::Page * page = pNoteFile->FindPage((LPCSTR)lpszChildToMake);
	//
	// If there was a page with this name, set it's translation and find it's children
	//

	if (!page)
		return NULL;
	
	Stuff::LinearMatrix4D ltwObjectArmaturePlacement = Stuff::LinearMatrix4D::Identity;
	SIMPLEHEIRARCHY * pTemp = new SIMPLEHEIRARCHY;
	
	pTemp->strPageName = lpszChildToMake;
	Stuff::Vector3D vValue;
	Stuff::Point3D pntValue;
	if (page->GetEntry("Translation", &vValue))
	{
		pntValue = vValue;
		ltwObjectArmaturePlacement.BuildTranslation(pntValue);
	}
	
	YawPitchRoll ypr;
	if (page->GetEntry("Rotation", &ypr))
	{
		ltwObjectArmaturePlacement.BuildRotation(ypr);
	}

	pTemp->lmLocalToWorld.Multiply(ltwObjectArmaturePlacement, lmParentLocalToWorld);
	
	//
	// Now iterate through the children of this page looking for Child...
	//

	Stuff::Page::NoteIterator *notes = page->MakeNoteIterator();
	Stuff::Note *note;
	const char * szCharPointer = NULL;
	while (note = notes->ReadAndNext())
	{
		if (!stricmp("Child", note->GetName()))
		{
			note->GetEntry(	&szCharPointer);
			SIMPLEHEIRARCHY * pTempChild = BuildHeirarchy(szCharPointer, pTemp->lmLocalToWorld, pNoteFile);
			if (pTempChild)
				pTemp->listChildren.AddTail(pTempChild);
		}
	}
	
	return pTemp;

}

SIMPLEHEIRARCHY *  SIMPLEHEIRARCHY::FindInHeirarchy(LPCSTR lpszChildToMake)
{
	if (!this)
		return NULL;
	if (!stricmp(lpszChildToMake, (LPCSTR) this->strPageName))
	{
		return this;
	}
	POSITION pos = this->listChildren.GetHeadPosition();
	while (pos)
	{
		SIMPLEHEIRARCHY * pTemp = NULL;
		SIMPLEHEIRARCHY * pHeirarchy = this->listChildren.GetNext(pos);
		if (pTemp = pHeirarchy->FindInHeirarchy(lpszChildToMake))
			return pTemp;
	}
	return NULL;
}

CMFCGosDoc * g_pActiveErfDocument = NULL;
CMFCGosDoc * GetActiveErfDocument() { return g_pActiveErfDocument;}

/////////////////////////////////////////////////////////////////////////////
// CMFCGosDoc

IMPLEMENT_DYNCREATE(CMFCGosDoc, CDocument)

BEGIN_MESSAGE_MAP(CMFCGosDoc, CDocument)
//{{AFX_MSG_MAP(CMFCGosDoc)
ON_COMMAND(ID_FILE_RELOAD, OnFileReload)
	ON_COMMAND(ID_EDIT_ADDLIGHT_AMBIENTLIGHT, OnEditAddlightAmbientlight)
	ON_COMMAND(ID_EDIT_ADDLIGHT_INFINITELIGHT, OnEditAddlightInfinitelight)
	ON_COMMAND(ID_EDIT_ADDLIGHT_POINTLIGHT, OnEditAddlightPointlight)
	ON_COMMAND(ID_EDIT_ADDLIGHT_SPOTLIGHT, OnEditAddlightSpotlight)
	ON_COMMAND(ID_EDIT_ADDLIGHT_PROJECTLIGHT, OnEditAddlightProjectlight)
	ON_COMMAND(ID_VIEW_BUMPMAPTEST, OnViewBumpmaptest)
	ON_COMMAND(ID_VIEW_WATERTEST, OnViewWatertest)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMFCGosDoc construction/destruction

CMFCGosDoc::CMFCGosDoc()
{
	cele=NULL;
	cmlr=NULL;
	UnStable=false;
  g_pActiveErfDocument = this;
	sphereCamera.radius = 0.0f;
	sphereCamera.center = Stuff::Point3D::Identity;
	m_sHeirarchy = NULL;
}

CMFCGosDoc::~CMFCGosDoc()
{
	SIMPLEHEIRARCHY::DeleteHeirarchy(m_sHeirarchy);
}

BOOL CMFCGosDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;
	
	return TRUE;
}

extern CMFCGosApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CMFCGosDoc serialization

void CMFCGosDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
	}
	else
	{
		//		theApp.GetTexturePath();
		if(theApp.TexturePath.GetLength()==0) 
		{
			MessageBox(NULL,"Texture Directory Not Set","Fatal Eror",MB_OK|MB_ICONERROR);
		}
		else
		{
			
		} //end else
	}
}

/////////////////////////////////////////////////////////////////////////////
// CMFCGosDoc diagnostics

#ifdef _DEBUG
void CMFCGosDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CMFCGosDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMFCGosDoc commands

void CMFCGosDoc::OnFileReload() 
{
	IsModified();

	//
	// Save off the current file names.
	//
	CList<Stuff::MString*, Stuff::MString*> tempFileNameList;
	
	Stuff::MString * pTemp = NULL;
	
	POSITION pos = m_pErf_Name_List.GetHeadPosition();
	while (pos) 
		{
		pTemp = m_pErf_Name_List.GetNext(pos);
		tempFileNameList.AddTail(new Stuff::MString((LPCSTR)*(pTemp)));
		}
	(*(theApp.m_phashErfNameMapping)).DeletePlugs();



	OnOpenMultipleDocumentsInit();
	pos = tempFileNameList.GetHeadPosition();
	while (pos) 
		{
		pTemp = tempFileNameList.GetNext(pos);
		OnOpenMultipleDocumentsAddFile(*(pTemp));
		}
	OnOpenMultipleDocumentsEnd();

	pos = tempFileNameList.GetHeadPosition();
	while (pos) 
		{
		pTemp = tempFileNameList.GetHead();
		delete pTemp;
		tempFileNameList.RemoveHead();
		pos = tempFileNameList.GetHeadPosition();
		}


//	OnOpenDocument(*erf_name);
}


BOOL CMFCGosDoc::OnSaveDocument(LPCTSTR lpszPathName) 
{
	//
	// This is only supported for single documents...where the filename matters
	//
	
	if (m_pErf_Name_List.GetCount() != 1)
		{
		return FALSE;
		}

	// TODO: Add your specialized code here and/or call the base class
	(*(theApp.m_phashErfNameMapping)).DeletePlugs();
	CString tstr=lpszPathName;
	delete m_pErf_Name_List.GetHead();
	m_pErf_Name_List.RemoveHead();
	m_pErf_Name_List.AddHead(new Stuff::MString((LPCSTR)tstr));
	Register_Object(m_pErf_Name_List.GetHead());
	
	ErfElement->SetRootMode();
	(*(theApp.m_phashErfNameMapping)).AddValue(new Stuff::PlugOf<MString *> (m_pErf_Name_List.GetHead()), (DWORD)(void *)ErfElement);

	Stuff::FileStream element_stream(*(m_pErf_Name_List.GetHead()), Stuff::FileStream::WriteOnly);
	ElementRenderer::WriteERFVersion(&element_stream);
	ErfElement->Save(&element_stream);
	
	SetModifiedFlag(FALSE);
//	ErfElement->SetVolumeCullMode();
//	ErfElement->Sync();
//	return CDocument::OnSaveDocument(lpszPathName);
	return TRUE;
}


BOOL CMFCGosDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
//	if (!CDocument::OnOpenDocument(lpszPathName))
//		return FALSE;
	SetModifiedFlag(FALSE);
	//
	// Loop throught lpszPathName looking for '/' as a filename divider
	//
	OnOpenMultipleDocumentsInit();

	char szTempStorage[64*1024+1];
	szTempStorage[64*1024-1] = 0;

	strcpy(szTempStorage, lpszPathName);
	char * tmpPtr = szTempStorage;

	while (tmpPtr && *tmpPtr) 
	{
		char * strEndOfCurrent = strchr(tmpPtr, '/');
		if (strEndOfCurrent)
		{
			*strEndOfCurrent = 0; // null terminate this one
		}
		OnOpenMultipleDocumentsAddFile(tmpPtr);
		if (strEndOfCurrent)
		{
			tmpPtr = strEndOfCurrent+1;
		}
		else
		{
			tmpPtr = NULL;
		}
	}
	OnOpenMultipleDocumentsEnd();
	return TRUE;

/*	UnStable=true;	
	cele=NULL;
	cmlr=NULL;
	
	CString tstr=lpszPathName;
	*erf_name=Stuff::MString((LPCSTR)tstr);
	
	Check_Object(Stuff::FileStreamManager::Instance);

	Check_Object(Scene);
	delete Scene;

	FileStream * pFile = NULL;
		
  while ((pFile = theApp.m_pFileSet_List.GetHead()) != NULL)
  {
		delete pFile;
		theApp.m_pFileSet_List.RemoveHead();
  }

  pFile =  new Stuff::FileStream(*erf_name);
	theApp.m_pFileSet_List.AddTail(pFile);

  Scene = new ElementRenderer::GroupElement;
	Check_Object(Scene);
	Scene->LockBounds();
	

	int version = ElementRenderer::ReadERFVersion(pFile);
	while((*(pFile)).GetBytesRemaining() > 0)
	{
		ErfElement =
			ElementRenderer::Element::Create(
				pFile,
				version
			);
		ErfElement->LockBounds();
		Scene->AttachChild(ErfElement);
#if 0
		ErfElement->ClearAlignX();
		ErfElement->SetNeverCullMode();
#endif
		ErfElement->SetLocalToParent(Stuff::LinearMatrix4D::Identity);
	}


	//---------------
	// Build a camera
	//---------------
	//
	Camera_State = new ElementRenderer::StateChange();
	Check_Object(Camera_State);
	Camera_State->EnableBackfaceCulling();
	Camera_State->EnableDithering();
	Camera_State->EnablePerspectiveCorrection();
	Camera_State->EnableZBufferWrite();
	Camera_State->EnableZBufferCompare();
	//			Camera_State->EnableFog();
//	Stuff::RGBAColor fogColor(0.1f, 0.1f, 0.1f, 1.0f);
//	Camera_State->SetFog(fogColor, 0.0f, 900.0f, 1000.0f);
	Camera = new ElementRenderer::CameraElement(Camera_State);
	Check_Object(Camera);
	Scene->AttachChild(Camera);
	Camera->SetPerspective(1.0f, 1000.0f, Stuff::Pi_Over_3);

//	Camera_LookAt = ErfElement->m_localOBB.localToParent;
	Camera_Direction.range = ErfElement->m_localOBB.sphereRadius * 2.0f;
	if(Camera_Direction.range<0.01f) Camera_Direction.range=1.0f;
	Camera->SetScene(Scene);

	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive;new_index++)
	{
	 LightState->m_lights[new_index]=NULL;
	}
	
	//
	//-----------------------------------------------------
	// Sync the matrices of the scene and load the textures
	//-----------------------------------------------------
	//
	
	Scene->Sync();
	MidLevelRenderer::MLRTexturePool::Instance->LoadImages();	
	
	UpdateAllViews(NULL,1);
	theApp.DrawScreen();
	UnStable=false;	
	
	return TRUE;
	*/
}

//---------------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------------
BOOL CMFCGosDoc::OnOpenMultipleDocumentsInit() 
{
	UnStable=true;	
	cele=NULL;
	cmlr=NULL;
	sphereCamera.radius = 0.0f;
	sphereCamera.center = Stuff::Point3D::Identity;
	SIMPLEHEIRARCHY::DeleteHeirarchy(m_sHeirarchy);
	m_sHeirarchy = NULL;

	FileStream * pFile = NULL;
	POSITION pos = NULL;
	while ((pos = theApp.m_pFileSet_List.GetHeadPosition()) != NULL)
	{
		pFile = theApp.m_pFileSet_List.GetHead();
		delete pFile;
		theApp.m_pFileSet_List.RemoveHead();
	}
	m_strPathName.Empty();
	//TODOTODO
	while (m_pErf_Name_List.GetCount() && m_pErf_Name_List.GetHead()) 
		{Unregister_Object(m_pErf_Name_List.GetHead()); delete m_pErf_Name_List.GetHead(); m_pErf_Name_List.RemoveHead();}
	(*(theApp.m_phashErfNameMapping)).DeletePlugs();

	
	Check_Object(Stuff::FileStreamManager::Instance);

	Check_Object(Scene);
	delete Scene;

  Scene = new ElementRenderer::GroupElement;
	Check_Object(Scene);
	Scene->LockBounds();
	


	//---------------
	// Build a camera
	//---------------
	//
	Camera_State = new ElementRenderer::StateChange();
	Check_Object(Camera_State);
	Camera_State->EnableBackfaceCulling();
	Camera_State->EnableDithering();
	Camera_State->EnablePerspectiveCorrection();
	Camera_State->EnableZBufferWrite();
	Camera_State->EnableZBufferCompare();
	//			Camera_State->EnableFog();
//	Stuff::RGBAColor fogColor(0.1f, 0.1f, 0.1f, 1.0f);
//	Camera_State->SetFog(fogColor, 0.0f, 900.0f, 1000.0f);
	Camera = new ElementRenderer::CameraElement(Camera_State);
	Check_Object(Camera);
	Scene->AttachChild(Camera);
	Camera->SetPerspective(1.0f, 1000.0f, Stuff::Pi_Over_3);

//	Camera_LookAt = ErfElement->m_localOBB.localToParent;
	Camera_Direction.range = 4.0f;
	if(Camera_Direction.range<0.01f) Camera_Direction.range=1.0f;
	Camera->SetScene(Scene);

	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive;new_index++)
	{
	 LightState->m_lights[new_index]=NULL;
	}
	
	//
	//-----------------------------------------------------
	// Sync the matrices of the scene and load the textures
	//-----------------------------------------------------
	//
	
	Scene->Sync();
	MidLevelRenderer::MLRTexturePool::Instance->LoadImages();	
	
	UpdateAllViews(NULL,1);
	theApp.DrawScreen();
	UnStable=false;	
	
	return TRUE;
}




BOOL CMFCGosDoc::OnOpenMultipleDocumentsAddFile(LPCTSTR lpszPathName) 
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;
	UnStable=true;	

	CString tstr=lpszPathName;
	if (!m_pErf_Name_List.GetCount())
	{
		m_strPathName = lpszPathName;
	}
	m_pErf_Name_List.AddTail(new Stuff::MString((LPCSTR)tstr));
	Register_Object(m_pErf_Name_List.GetTail());
	

	Stuff::FileStream * pFile =  new Stuff::FileStream(*(m_pErf_Name_List.GetTail()));
	theApp.m_pFileSet_List.AddTail	(pFile);

	int version = ElementRenderer::ReadERFVersion(pFile);
	while((*(pFile)).GetBytesRemaining() > 0)
	{
		ErfElement =
			ElementRenderer::Element::Create(
				pFile,
				version
			);
		(*(theApp.m_phashErfNameMapping)).AddValue(new Stuff::PlugOf<MString *> ( m_pErf_Name_List.GetTail()), (DWORD)(void *)ErfElement);


		ErfElement->LockBounds();
		Scene->AttachChild(ErfElement);
#if 0
		ErfElement->ClearAlignX();
		ErfElement->SetNeverCullMode();
#endif

	//
	// If there is an 
	//
		Stuff::LinearMatrix4D ltwObjectArmaturePlacement = LinearMatrix4D::Identity;
		AdjustMeshToArmatureIfAvailable(lpszPathName, &ltwObjectArmaturePlacement);

		ErfElement->SetLocalToParent(ltwObjectArmaturePlacement);
	}

	Stuff::Sphere sphereTemp;
	Stuff::Sphere sphereTempOBB;
	sphereTemp = sphereCamera;
	sphereTempOBB.center = ErfElement->m_localOBB.localToParent;
	sphereTempOBB.radius = ErfElement->m_localOBB.sphereRadius;
	sphereCamera.Union(sphereTemp, sphereTempOBB);
	Camera_Direction.range = sphereCamera.radius * 4.0f;
	if(Camera_Direction.range<0.01f) Camera_Direction.range=1.0f;

	UnStable=false;	
	
	return TRUE;
}





void CMFCGosDoc::AdjustMeshToArmatureIfAvailable(LPCSTR lpszPathName, Stuff::LinearMatrix4D *pltwObjectArmaturePlacement)
{
	//
	// Open the .contents file, and enumerate the pages
	// If the model= line matches the .erf name
	// Open the .armature file
	// search for the joint name and get the translation and rotation and make the matrix
	//

	//
	// Make the contents file name
	//
	char szFilename[1024];
	char szExtension[1024];
	char szDriveLetter[1024];
	char szDirectory[1024];
	_splitpath(lpszPathName, szDriveLetter, szDirectory, szFilename, szExtension);
	//
	// Find the .contents file // assume there is only one.
	//
	CString strDirectory;
	strDirectory.Format("%s%s", szDriveLetter, szDirectory);
	CString strFileToSearchFor;
	strFileToSearchFor.Format("%s*.contents", (LPCSTR) strDirectory);
	HANDLE hFindFileHandle = NULL;
	HANDLE hFindFileHandle2 = NULL;
	WIN32_FIND_DATA fdFindData;
	fdFindData.dwFileAttributes = 0;

	if ((hFindFileHandle = FindFirstFile((LPCSTR) strFileToSearchFor, &fdFindData)) == INVALID_HANDLE_VALUE)
		return;
	strFileToSearchFor.Format("%s*.armature", (LPCSTR) strDirectory);
	WIN32_FIND_DATA fdFindData2;
	fdFindData2.dwFileAttributes = 0;
	if ((hFindFileHandle2 = FindFirstFile((LPCSTR) strFileToSearchFor, &fdFindData2))==INVALID_HANDLE_VALUE)
	{
		FindClose(hFindFileHandle2);
		return;
	}
	//
	// We found the .contents file
	//
	CString strContentsFileName;
	CString strArmatureFileName;
	strContentsFileName.Format("%s%s", (LPCSTR)strDirectory, fdFindData.cFileName);
	strArmatureFileName.Format("%s%s", (LPCSTR)strDirectory, fdFindData2.cFileName);
	Stuff::NotationFile nfContentsFile((LPCSTR)strContentsFileName);
	Stuff::NotationFile nfArmatureFile((LPCSTR)strArmatureFileName);
	//
	// Enumerate the pages
	//
	Stuff::NotationFile::PageIterator *pages = nfContentsFile.MakePageIterator();
	Stuff::Page * page;
	char szErfMappingString[1024];
	const char * szCharPointer = NULL;
	while (page = pages->ReadAndNext())
	{
		if (page->GetEntry("Model", &szCharPointer , false))
		{
			strcpy(szErfMappingString, szCharPointer);
			//
			// Get just the file name, no extension of directory.
			//
			char * szCurrent = szErfMappingString, * szLastFind = szErfMappingString;
			char * szStart = szLastFind;
			while (szCurrent = strchr(szLastFind, '\\'))
			{
			  szLastFind = szCurrent + 1; // go to the first character after
			}
			// we are now, either at the begining of the string or after the last 
			szStart = szLastFind;
			szLastFind = NULL;
			if (szCurrent = strchr(szStart, '.'))
			{
				szLastFind = szCurrent + 1;
			}
			while (szCurrent = strchr(szLastFind, '.'))
			{
			  szLastFind = szCurrent+1; // go to after the period
			}
			if (szLastFind  && szLastFind > szStart)
			{
				*(szLastFind - 1)= 0;
			}

			//
			// HACK/HACK one last step. Strip _Dam off the end
			//
			szCurrent = szFilename;
			while (szCurrent = strchr(szCurrent+1, '_'))
			{
				if (!stricmp(szCurrent+1, "dam"))
				{
					*szCurrent = 0;
					break;
				}
			}
			// szStart is now the piece we are trying to compare against the one we are loading
			if (!stricmp(szStart, szFilename))
			{

				//
				// Build a heirarchy to get world translations from...
				//
				//
				// Note: For efficiency sake I only build the first tree we come across, which is not really correct
				//			 if the files are from different trees

				if (!m_sHeirarchy)
				{
					m_sHeirarchy = SIMPLEHEIRARCHY::BuildHeirarchy("joint_WORLD", Stuff::LinearMatrix4D::Identity, &nfArmatureFile);
				}
				if (!m_sHeirarchy)
				{
					//
					// If we didn't find the heiarchy based on joint_WORLD, let's just try the last
					// entry of the .contents file since usually that's where the root node is saved out to
					// HACKHACKHACKHACKHACK - just a quick fix to a feature request
					//
					Stuff::NotationFile::PageIterator *contentpages = nfContentsFile.MakePageIterator();
					Stuff::Page * currentpage = NULL, *lastpage = NULL;
					while (currentpage = contentpages->ReadAndNext())
					{
						lastpage = currentpage;
						//
						// If this has "attachedtoroot=true" then it's what we want
						//
						bool attachedToRoot = false;
						if (lastpage->GetEntry("AttachedToRoot", &attachedToRoot))
						{
							if (attachedToRoot)
								break;
						}
					}
					if (lastpage)
					{
						const char * rootjoint = lastpage->GetName();
						m_sHeirarchy = SIMPLEHEIRARCHY::BuildHeirarchy(rootjoint, Stuff::LinearMatrix4D::Identity, &nfArmatureFile);
					}
				}


				if (m_sHeirarchy)
				{
					SIMPLEHEIRARCHY * pChildHeirarchy = m_sHeirarchy->FindInHeirarchy(page->GetName());
					if (pChildHeirarchy)
					{
						 *pltwObjectArmaturePlacement = pChildHeirarchy->lmLocalToWorld;
							goto exit;
					}
				}
				else
				{
					//
					// We have a page to search for in the armature file
					//
					Stuff::Page * page2 = nfArmatureFile.FindPage(page->GetName());
					if (page2)
					{
						Stuff::Vector3D vValue;
						Stuff::Point3D pntValue;
						Stuff::YawPitchRoll ypr;
						if (page2->GetEntry("Translation", &vValue))
						{
							pntValue = vValue;
							pltwObjectArmaturePlacement->BuildTranslation(pntValue);
						}
						if (page2->GetEntry("Rotation", &ypr))
						{
							pltwObjectArmaturePlacement->BuildRotation(ypr);
						}
						goto exit;
					}
				}

			}	 // if we have a matching section in the contents file
		}	// if it has a model entry
	} // while enumerating pages in the .contents file


exit:
	if (hFindFileHandle)
		FindClose(hFindFileHandle);
	if (hFindFileHandle2)
		FindClose(hFindFileHandle2);


}

BOOL CMFCGosDoc::OnOpenMultipleDocumentsEnd() 
{
	
	//
	//-----------------------------------------------------
	// Sync the matrices of the scene and load the textures
	//-----------------------------------------------------
	//
	SIMPLEHEIRARCHY::DeleteHeirarchy(m_sHeirarchy);
	m_sHeirarchy = NULL;
	
	Scene->Sync();
	MidLevelRenderer::MLRTexturePool::Instance->LoadImages();	
	
	UpdateAllViews(NULL,1);
	theApp.DrawScreen();
	UnStable=false;	
	
	return TRUE;
}



void CMFCGosDoc::OnEditAddlightAmbientlight() 
{
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive && LightState->m_lights[new_index];new_index++)
	{
	}

	if (new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive)
	{
		MidLevelRenderer::MLRAmbientLight *Light=new MidLevelRenderer::MLRAmbientLight;
		LightState->m_lights[new_index]=Light;
	}
	gos_PopCurrentHeap();
	theApp.UpdateLightList();
}

void CMFCGosDoc::OnEditAddlightInfinitelight() 
{
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive && LightState->m_lights[new_index];new_index++)
	{
	}

	if (new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive)
	{
		MidLevelRenderer::MLRInfiniteLight *Light=new MidLevelRenderer::MLRInfiniteLight;
		LightState->m_lights[new_index]=Light;
	}
	gos_PopCurrentHeap();
	theApp.UpdateLightList();
}

void CMFCGosDoc::OnEditAddlightPointlight() 
{
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive && LightState->m_lights[new_index];new_index++)
	{
	}

	if (new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive)
	{
		MidLevelRenderer::MLRPointLight *Light=new MidLevelRenderer::MLRPointLight;
		LightState->m_lights[new_index]=Light;
	}
	gos_PopCurrentHeap();
	theApp.UpdateLightList();
}

void CMFCGosDoc::OnEditAddlightSpotlight() 
{
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	for (int new_index=0;new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive && LightState->m_lights[new_index];new_index++)
	{
	}

	if (new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive)
	{
		MidLevelRenderer::MLRSpotLight *Light=new MidLevelRenderer::MLRSpotLight;
		LightState->m_lights[new_index]=Light;
	}
	gos_PopCurrentHeap();
	theApp.UpdateLightList();		
}


void CMFCGosDoc::OnEditAddlightProjectlight() 
{
	gos_PushCurrentHeap(MidLevelRenderer::LightsHeap);
	for (
		int new_index=0;
		new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive &&
		LightState->m_lights[new_index];
		new_index++
	)
	{
	}

	if (new_index<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive)
	{
		MidLevelRenderer::MLRProjectLight *Light=new MidLevelRenderer::MLRProjectLight;

		MidLevelRenderer::MLRTexture *lightmap = MidLevelRenderer::MLRTexturePool::Instance->Add("lightspot");
		if(lightmap!=NULL)
		{
			MLRLightMap *firstLightMap = new MLRLightMap(lightmap);
			Register_Object(firstLightMap);
			Light->SetLightMap(firstLightMap);

			MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
		}
		LightState->m_lights[new_index]=Light;
	}
	gos_PopCurrentHeap();
	theApp.UpdateLightList();		
}

void CMFCGosDoc::OnViewBumpmaptest() 
{
	CBumpMapDlg dlg;

	if(dlg.DoModal()==IDOK)
	{
		OnOpenMultipleDocumentsInit();

		MidLevelRenderer::MLRTexture *terrrainmap = MidLevelRenderer::MLRTexturePool::Instance->Add(dlg.m_TerrainTxt);
		if( terrrainmap == NULL )
		{
			MessageBox(NULL, "Couldn't find Terrain Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::MLRTexture *terraindetail = MidLevelRenderer::MLRTexturePool::Instance->Add(dlg.m_DetailTxt);
		if( terraindetail == NULL )
		{
			MessageBox(NULL, "Couldn't find Terrain Detail Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::MLRTexture *water = MidLevelRenderer::MLRTexturePool::Instance->Add(dlg.m_WaterTxt);
		if( water == NULL )
		{
			MessageBox(NULL, "Couldn't find Water Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}
		if(dlg.m_WScrollU!=0.0f || dlg.m_WScrollV!=0.0f)
		{
			water->SetAnimateTexture(true);
			bumpAnime.water = water->GetTextureHandle();
			bumpAnime.wu = dlg.m_WScrollU;
			bumpAnime.wu = dlg.m_WScrollV;
		}

		Stuff::MString full_name, file_name = *erf_texture_path;

		file_name += dlg.m_BumpTxt;
		full_name =	file_name;
		full_name += ".png";

		if(!gos_DoesFileExist(full_name)) 
		{
			full_name=file_name;
			full_name += ".tga";
		}

		DWORD tex_handle = gos_NewTextureFromFile(gos_Texture_Bump, (const char *)full_name);
		if( tex_handle == 0 )
		{
			MessageBox(NULL, "Couldn't find Bump Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::GOSImage *image = new MidLevelRenderer::GOSImage(tex_handle);

		MidLevelRenderer::MLRTexture *bump = MidLevelRenderer::MLRTexturePool::Instance->Add(image);
		if( bump == NULL )
		{
			MessageBox(NULL, "Couldn't find Bump Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}
		if(dlg.m_BScrollU!=0.0f || dlg.m_BScrollV!=0.0f)
		{
			bump->SetAnimateTexture(true);
			bumpAnime.bump = bump->GetTextureHandle();
			bumpAnime.bu = dlg.m_BScrollU;
			bumpAnime.bu = dlg.m_BScrollV;
		}

		MidLevelRenderer::MLRTexture *envmap = MidLevelRenderer::MLRTexturePool::Instance->Add(dlg.m_EnvTxt);
		if( envmap == NULL )
		{
			MessageBox(NULL, "Couldn't find Env Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		file_name = *erf_texture_path;

		file_name += dlg.m_NormTxt;
		full_name =	file_name;
		full_name += ".png";

		if(!gos_DoesFileExist(full_name)) 
		{
			full_name = file_name;
			full_name += ".tga";
		}

		tex_handle = gos_NewTextureFromFile(gos_Texture_Normal, (const char *)full_name);
		if( tex_handle == 0 )
		{
			MessageBox(NULL, "Couldn't find Bump Normal Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		image = new MidLevelRenderer::GOSImage(tex_handle);

		MidLevelRenderer::MLRTexture *bumpnormal = MidLevelRenderer::MLRTexturePool::Instance->Add(image);
		if( bumpnormal == NULL )
		{
			MessageBox(NULL, "Couldn't find Bump Normal Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}
		if(dlg.m_NScrollU!=0.0f || dlg.m_NScrollV!=0.0f)
		{
			bumpnormal->SetAnimateTexture(true);
			bumpAnime.normal = bumpnormal->GetTextureHandle();
			bumpAnime.nu = dlg.m_NScrollU;
			bumpAnime.nu = dlg.m_NScrollV;
		}

		MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
	
		
		gos_PushCurrentHeap(MidLevelRenderer::MLR_Water::PrimitiveHeap);
		MidLevelRenderer::MLR_BumpyWater *water_mesh = new MidLevelRenderer::MLR_BumpyWater;
		Register_Object(water_mesh);
		gos_PopCurrentHeap();
		
		if(water_mesh->dataStore==NULL)
		{
			water_mesh->dataStore = new MidLevelRenderer::DataStorage;
		}

		water_mesh->dataStore->coords.SetLength(81);
		water_mesh->SetCoordData(water_mesh->dataStore->coords.GetData(), 81);

		water_mesh->dataStore->colors.SetLength(81);
		water_mesh->SetColorData(water_mesh->dataStore->colors.GetData(), 81);

		water_mesh->dataStore->texCoords.SetLength(81);
		water_mesh->SetTexCoordData(water_mesh->dataStore->texCoords.GetData(), 81);

		Scalar oneOver160 = 1.0f/160.f;
		int i, j;
		for(j=0;j<9;j++)
		{
			for(i=0;i<9;i++)
			{
				water_mesh->dataStore->coords[j*9+i] = Point3D(-160.0f+i*40.0f, 0.0f, -160.0f+j*40.0f);
				water_mesh->dataStore->texCoords[j*9+i][0] = water_mesh->dataStore->coords[j*9+i].x * dlg.m_WaterRep*oneOver160;
				water_mesh->dataStore->texCoords[j*9+i][1] = water_mesh->dataStore->coords[j*9+i].z * dlg.m_WaterRep*oneOver160;
			}
		}
		water_mesh->dataStore->index.SetLength(32*4*3);
		int index = 0;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				water_mesh->dataStore->index[index++] = j*9 + i;
				water_mesh->dataStore->index[index++] = j*9 + i + 1;
				water_mesh->dataStore->index[index++] = (j+1)*9 + i;

				water_mesh->dataStore->index[index++] = j*9 + i + 1;
				water_mesh->dataStore->index[index++] = (j+1)*9 + i + 1;
				water_mesh->dataStore->index[index++] = (j+1)*9 + i;
			}
		}
		water_mesh->SetIndexData(water_mesh->dataStore->index.GetData(), 32*4*3);

		water_mesh->SetSubprimitiveLengths(NULL, 128);
		water_mesh->FindFacePlanes();

		for(i=0;i<81;i++)
		{
			water_mesh->dataStore->colors[i] = 0xff808080;
		}

		MLRState state;

		state.SetTextureHandle(water->GetTextureHandle());

		state.SetBackFaceOn();
		state.SetDitherOn();
		state.SetTextureCorrectionOn();
		state.SetZBufferCompareOn();
		state.SetZBufferWriteOff();
		state.SetAlphaMode(MLRState::AlphaInvAlphaMode);
		state.SetPriority(MLRState::AlphaPriority);
		state.SetFilterMode(MLRState::TriLinearFilterMode);
		state.SetBumpMapOn();

		water_mesh->SetReferenceState(state);

		water_mesh->SetTextures(
			bump->GetTextureHandle(),
			envmap->GetTextureHandle(),
			bumpnormal->GetTextureHandle()
		);

		Vector3D sun(1.0f, -1.0f, 1.0f);
		sun.Normalize(sun);
		water_mesh->SetSunLight(UnitVector3D(sun));

		water_mesh->SetBumpWrapRatio(dlg.m_BumpRep);
		water_mesh->SetEnvWrapRatio(dlg.m_EvnRep);
		water_mesh->SetBumpNormWrapRatio(dlg.m_NormRep);

		gos_PushCurrentHeap(MidLevelRenderer::MLR_I_DeT_TMesh::PrimitiveHeap);
		MidLevelRenderer::MLR_I_DeT_TMesh *terrain_mesh = new MidLevelRenderer::MLR_I_DeT_TMesh;
		Register_Object(terrain_mesh);
		gos_PopCurrentHeap();
		
		if(terrain_mesh->dataStore==NULL)
		{
			terrain_mesh->dataStore = new MidLevelRenderer::DataStorage;
		}

		terrain_mesh->dataStore->coords.SetLength(81);
		terrain_mesh->SetCoordData(terrain_mesh->dataStore->coords.GetData(), 81);

		terrain_mesh->dataStore->texCoords.SetLength(81);
		terrain_mesh->SetTexCoordData(terrain_mesh->dataStore->texCoords.GetData(), 81);

		Scalar x, z;
		for(j=0;j<9;j++)
		{
			for(i=0;i<9;i++)
			{
				x = -160.0f+i*40.0f;
				z = -160.0f+j*40.0f;

				terrain_mesh->dataStore->coords[j*9+i] = Point3D(
					x, 
					16.0f*(float)cos(fabs(Pi_Over_2*x*oneOver160) + fabs(Pi_Over_2*z*oneOver160) - Pi),
					z
				);

				terrain_mesh->dataStore->texCoords[j*9+i][0] = x * dlg.m_TerrainRep * oneOver160 - 0.5f;
				terrain_mesh->dataStore->texCoords[j*9+i][1] = z * dlg.m_TerrainRep * oneOver160 - 0.5f;
			}
		}
		terrain_mesh->dataStore->index.SetLength(32*4*3);

		index = 0;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				terrain_mesh->dataStore->index[index++] = j*9 + i;
				terrain_mesh->dataStore->index[index++] = (j+1)*9 + i;
				terrain_mesh->dataStore->index[index++] = j*9 + i + 1;

				terrain_mesh->dataStore->index[index++] = j*9 + i + 1;
				terrain_mesh->dataStore->index[index++] = (j+1)*9 + i;
				terrain_mesh->dataStore->index[index++] = (j+1)*9 + i + 1;
			}
		}
		terrain_mesh->SetIndexData(terrain_mesh->dataStore->index.GetData(), 32*4*3);

		terrain_mesh->SetSubprimitiveLengths(NULL, 128);
		terrain_mesh->FindFacePlanes();

		MLRState terrain_state;

		terrain_state.SetTextureHandle(terrrainmap->GetTextureHandle());
		terrain_state.SetFilterMode(MLRState::TriLinearFilterMode);
		terrain_mesh->SetReferenceState(terrain_state);

		terrain_state.SetTextureHandle(terraindetail->GetTextureHandle());
		terrain_state.SetTextureWrapMode(MLRState::TextureWrap);
		terrain_state.SetAlphaMode(MLRState::AlphaInvAlphaMode);
		terrain_state.SetPriority(MLRState::DefaultPriority + 1);

		terrain_mesh->SetReferenceState(terrain_state, 1);

		terrain_mesh->SetDetailData(0.0f, 0.0f, dlg.m_DetailRep/dlg.m_TerrainRep,  dlg.m_DetailRep/dlg.m_TerrainRep, 80.0f, 250.0f);

		gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
		ElementRenderer::ShapeElement *Shape  = new ElementRenderer::ShapeElement;
		Register_Object(Shape);
		gos_PopCurrentHeap();
			
		gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
		MidLevelRenderer::MLRShape *shape = new MidLevelRenderer::MLRShape(2);
		Register_Object(shape);
		gos_PopCurrentHeap();
	
		shape->Add(terrain_mesh);
		terrain_mesh->DetachReference();

		shape->Add(water_mesh);
		water_mesh->DetachReference();

		Shape->SetMLRShape(shape);

		Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;

		Shape->m_localOBB.sphereRadius = 320.0f;
		Scene->AttachChild(Shape);
		Shape->SetVolumeCullMode();


		OnOpenMultipleDocumentsEnd();
	}
		
		
		
}

void CMFCGosDoc::OnViewWatertest() 
{
	// TODO: Add your command handler code here
	CWaterDlg1 dlg;
	
if(dlg.DoModal())
{
		OnOpenMultipleDocumentsInit();

		MidLevelRenderer::MLRTexture *terrrainmap = MidLevelRenderer::MLRTexturePool::Instance->Add("Maps\\alpine01\\AA\\alpine01_AA_0_0000");
		if( terrrainmap == NULL )
		{
			MessageBox(NULL, "Couldn't find Terrain Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::MLRTexture *terraindetail = MidLevelRenderer::MLRTexturePool::Instance->Add("Maps\\alpine01\\alpine01_detail_active");
		if( terraindetail == NULL )
		{
			MessageBox(NULL, "Couldn't find Terrain Detail Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::MLRTexture *water = MidLevelRenderer::MLRTexturePool::Instance->Add("Maps\\alpine01\\alpine01_water_active");
		if( water == NULL )
		{
			MessageBox(NULL, "Couldn't find Water Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::MLRTexture *water_detail = MidLevelRenderer::MLRTexturePool::Instance->Add("Maps\\alpine01\\alpine01_water_detail_active");
		if( water_detail == NULL )
		{
			MessageBox(NULL, "Couldn't find Water Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		/*
		if(dlg.m_WScrollU!=0.0f || dlg.m_WScrollV!=0.0f)
		{
			water->SetAnimateTexture(true);
			bumpAnime.water = water->GetTextureHandle();
			bumpAnime.wu = dlg.m_WScrollU;
			bumpAnime.wu = dlg.m_WScrollV;
		}

		Stuff::MString full_name, file_name = *erf_texture_path;

		file_name += dlg.m_BumpTxt;
		full_name =	file_name;
		full_name += ".png";

		if(!gos_DoesFileExist(full_name)) 
		{
			full_name=file_name;
			full_name += ".tga";
		}

		DWORD tex_handle = gos_NewTextureFromFile(gos_Texture_Bump, (const char *)full_name);
		if( tex_handle == 0 )
		{
			MessageBox(NULL, "Couldn't find Bump Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		MidLevelRenderer::GOSImage *image = new MidLevelRenderer::GOSImage(tex_handle);

		MidLevelRenderer::MLRTexture *bump = MidLevelRenderer::MLRTexturePool::Instance->Add(image);
		if( bump == NULL )
		{
			MessageBox(NULL, "Couldn't find Bump Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}
		if(dlg.m_BScrollU!=0.0f || dlg.m_BScrollV!=0.0f)
		{
			bump->SetAnimateTexture(true);
			bumpAnime.bump = bump->GetTextureHandle();
			bumpAnime.bu = dlg.m_BScrollU;
			bumpAnime.bu = dlg.m_BScrollV;
		}

		MidLevelRenderer::MLRTexture *envmap = MidLevelRenderer::MLRTexturePool::Instance->Add(dlg.m_EnvTxt);
		if( envmap == NULL )
		{
			MessageBox(NULL, "Couldn't find Env Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		file_name = *erf_texture_path;

		file_name += dlg.m_NormTxt;
		full_name =	file_name;
		full_name += ".png";

		if(!gos_DoesFileExist(full_name)) 
		{
			full_name = file_name;
			full_name += ".tga";
		}

		tex_handle = gos_NewTextureFromFile(gos_Texture_Normal, (const char *)full_name);
		if( tex_handle == 0 )
		{
			MessageBox(NULL, "Couldn't find Bump Normal Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}

		image = new MidLevelRenderer::GOSImage(tex_handle);

		MidLevelRenderer::MLRTexture *bumpnormal = MidLevelRenderer::MLRTexturePool::Instance->Add(image);
		if( bumpnormal == NULL )
		{
			MessageBox(NULL, "Couldn't find Bump Normal Texture","No bump mapping for you !", MB_OK|MB_ICONERROR);
		}
		if(dlg.m_NScrollU!=0.0f || dlg.m_NScrollV!=0.0f)
		{
			bumpnormal->SetAnimateTexture(true);
			bumpAnime.normal = bumpnormal->GetTextureHandle();
			bumpAnime.nu = dlg.m_NScrollU;
			bumpAnime.nu = dlg.m_NScrollV;
		}
		*/
		bumpAnime.water=NULL;
		bumpAnime.normal=NULL;
		bumpAnime.bump=NULL;

		MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
	
		
		gos_PushCurrentHeap(MidLevelRenderer::MLR_Water::PrimitiveHeap);
		MidLevelRenderer::MLR_Water *water_mesh = new MidLevelRenderer::MLR_Water;
		Register_Object(water_mesh);
		gos_PopCurrentHeap();
		
		if(water_mesh->dataStore==NULL)
		{
			water_mesh->dataStore = new MidLevelRenderer::DataStorage;
		}

		water_mesh->dataStore->coords.SetLength(81);
		water_mesh->SetCoordData(water_mesh->dataStore->coords.GetData(), 81);

		water_mesh->dataStore->colors.SetLength(81);
		water_mesh->SetColorData(water_mesh->dataStore->colors.GetData(), 81);

		water_mesh->dataStore->texCoords.SetLength(81);
		water_mesh->SetTexCoordData(water_mesh->dataStore->texCoords.GetData(), 81);


		Vector3D sun(1.0f, -1.0f, 1.0f);
		sun.Normalize(sun);
		water_mesh->SetSunLight(UnitVector3D(sun));


		Scalar oneOver160 = 1.0f/160.f;
		int i, j;
		for(j=0;j<9;j++)
		{
			for(i=0;i<9;i++)
			{
				water_mesh->dataStore->coords[j*9+i] = Point3D(-160.0f+i*40.0f, 0.0f, -160.0f+j*40.0f);
				water_mesh->dataStore->texCoords[j*9+i][0] = water_mesh->dataStore->coords[j*9+i].x * 1*oneOver160;
				water_mesh->dataStore->texCoords[j*9+i][1] = water_mesh->dataStore->coords[j*9+i].z * 1*oneOver160;
			}
		}
		water_mesh->dataStore->index.SetLength(32*4*3);
		int index = 0;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				water_mesh->dataStore->index[index++] = j*9 + i;
				water_mesh->dataStore->index[index++] = j*9 + i + 1;
				water_mesh->dataStore->index[index++] = (j+1)*9 + i;

				water_mesh->dataStore->index[index++] = j*9 + i + 1;
				water_mesh->dataStore->index[index++] = (j+1)*9 + i + 1;
				water_mesh->dataStore->index[index++] = (j+1)*9 + i;
			}
		}
		water_mesh->SetIndexData(water_mesh->dataStore->index.GetData(), 32*4*3);

		water_mesh->SetSubprimitiveLengths(NULL, 128);
		water_mesh->FindFacePlanes();

		for(i=0;i<81;i++)
		{
			water_mesh->dataStore->colors[i] = 0xff808080;
		}

		MLRState state;

		state.SetTextureHandle(water->GetTextureHandle());

		state.SetBackFaceOff();
		state.SetDitherOn();
		state.SetTextureCorrectionOn();
		state.SetZBufferCompareOn();
		state.SetZBufferWriteOff();
		state.SetFilterMode(MLRState::BiLinearFilterMode);
		state.SetAlphaMode(MLRState::AlphaInvAlphaMode);
		state.SetPriority(MLRState::AlphaPriority);

		state.SetSpecularOn();

		water_mesh->SetReferenceState(state);

		
		MLRState detState;
		detState = state;
		detState.SetSpecularOff();
		detState.SetPriority(state.GetPriority()+1);

		detState.SetTextureHandle(water_detail->GetTextureHandle());

		water_mesh->SetDetailData(
			0.0f,
			0.0f,
			4.0f,
			4.0f,
			200.0f,
			250.0f
			);

		water_mesh->SetReferenceState(detState, 1);

		gos_PushCurrentHeap(MidLevelRenderer::MLR_I_DeT_TMesh::PrimitiveHeap);
		MidLevelRenderer::MLR_I_DeT_TMesh *terrain_mesh = new MidLevelRenderer::MLR_I_DeT_TMesh;
		Register_Object(terrain_mesh);
		gos_PopCurrentHeap();
		
		if(terrain_mesh->dataStore==NULL)
		{
			terrain_mesh->dataStore = new MidLevelRenderer::DataStorage;
		}

		terrain_mesh->dataStore->coords.SetLength(81);
		terrain_mesh->SetCoordData(terrain_mesh->dataStore->coords.GetData(), 81);

		terrain_mesh->dataStore->texCoords.SetLength(81);
		terrain_mesh->SetTexCoordData(terrain_mesh->dataStore->texCoords.GetData(), 81);

		Scalar x, z;
		for(j=0;j<9;j++)
		{
			for(i=0;i<9;i++)
			{
				x = -160.0f+i*40.0f;
				z = -160.0f+j*40.0f;

				terrain_mesh->dataStore->coords[j*9+i] = Point3D(
					x, 
					16.0f*(float)cos(fabs(Pi_Over_2*x*oneOver160) + fabs(Pi_Over_2*z*oneOver160) - Pi),
					z
				);

				terrain_mesh->dataStore->texCoords[j*9+i][0] = x * 1 * oneOver160 - 0.5f;
				terrain_mesh->dataStore->texCoords[j*9+i][1] = z * 1 * oneOver160 - 0.5f;
			}
		}
		terrain_mesh->dataStore->index.SetLength(32*4*3);

		index = 0;
		for(j=0;j<8;j++)
		{
			for(i=0;i<8;i++)
			{
				terrain_mesh->dataStore->index[index++] = j*9 + i;
				terrain_mesh->dataStore->index[index++] = (j+1)*9 + i;
				terrain_mesh->dataStore->index[index++] = j*9 + i + 1;

				terrain_mesh->dataStore->index[index++] = j*9 + i + 1;
				terrain_mesh->dataStore->index[index++] = (j+1)*9 + i;
				terrain_mesh->dataStore->index[index++] = (j+1)*9 + i + 1;
			}
		}
		terrain_mesh->SetIndexData(terrain_mesh->dataStore->index.GetData(), 32*4*3);

		terrain_mesh->SetSubprimitiveLengths(NULL, 128);
		terrain_mesh->FindFacePlanes();

		MLRState terrain_state;

		terrain_state.SetTextureHandle(terrrainmap->GetTextureHandle());
		terrain_state.SetFilterMode(MLRState::TriLinearFilterMode);
		terrain_mesh->SetReferenceState(terrain_state);

		terrain_state.SetTextureHandle(terraindetail->GetTextureHandle());
		terrain_state.SetTextureWrapMode(MLRState::TextureWrap);
		terrain_state.SetAlphaMode(MLRState::AlphaInvAlphaMode);
		terrain_state.SetPriority(MLRState::DefaultPriority + 1);

		terrain_mesh->SetReferenceState(terrain_state, 1);

		terrain_mesh->SetDetailData(0.0f, 0.0f, 1,  1, 80.0f, 250.0f);

		gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
		ElementRenderer::ShapeElement *Shape  = new ElementRenderer::ShapeElement;
		Register_Object(Shape);
		gos_PopCurrentHeap();
			
		gos_PushCurrentHeap(MidLevelRenderer::ShapeHeap);
		MidLevelRenderer::MLRShape *shape = new MidLevelRenderer::MLRShape(2);
		Register_Object(shape);
		gos_PopCurrentHeap();
	
		shape->Add(terrain_mesh);
		terrain_mesh->DetachReference();

		shape->Add(water_mesh);
		water_mesh->DetachReference();

		Shape->SetMLRShape(shape);

		Shape->m_localOBB.localToParent = LinearMatrix4D::Identity;

		Shape->m_localOBB.sphereRadius = 320.0f;
		Scene->AttachChild(Shape);
		Shape->SetVolumeCullMode();


		OnOpenMultipleDocumentsEnd();
	CSlideDlg *dlg=new CSlideDlg;
	dlg->Create(IDD_SLIDEDLG,NULL);
	dlg->ShowWindow(SW_SHOW);

}



}