www.pudn.com > notWow.rar > Map.cpp


#include "Map.h" 
 
#include "time.h" 
#include "ModelMgr.h" 
#include "TexMgr.h" 
#include "ResLoader.h" 
#include "Camera.h" 
#include "HeroCtrl.h" 
 
extern ResLoader				g_ResLdr; 
extern TexturesManager			g_TexMgr; 
extern ModelsManager			g_MdlMgr; 
extern Camera					g_Camera; 
extern HeroController			g_HeroCtrl; 
 
bool Map::Init(LPDIRECT3DDEVICE9 pd3dDevice,const char *Name,const char *SkyName,ScriptID ID) 
{ 
	Free(); 
	if(pd3dDevice != NULL) 
		m_pd3dDevice = pd3dDevice; 
	m_ScriptID = ID; 
 
	int types,i,j,m,n,l,k,t; 
	char* pFile,*pOrg; 
	int Size; 
	pOrg = pFile = (char*)g_ResLdr.GetFile(Name,Size,RES_MAP); 
 
	TextureID* pID; 
	memcpy(&types,pFile,sizeof(int)); 
	pFile += sizeof(int); 
	pID = new TextureID[types]; 
	char name[128]; 
	int len; 
	for(i = 0 ; i < types ; ++ i) 
	{ 
		memcpy(&len,pFile,sizeof(int)); 
		pFile += sizeof(int); 
		memcpy(name,pFile,sizeof(char)*(len+1)); 
		pFile += sizeof(char)*(len+1); 
		pID[i] = g_TexMgr.AddTexture(name); 
	} 
 
	memcpy(&m_TerriansWidth,pFile,sizeof(int)); 
	pFile += sizeof(int); 
	memcpy(&m_TerriansHeight,pFile,sizeof(int)); 
	pFile += sizeof(int); 
 
	m_TexturesHeight = m_TerriansHeight / 4; 
	m_TexturesWidth = m_TerriansWidth / 4 ; 
	m_fTextureSize = 4.0; 
	m_fTerrianSize = 1.0;	 
	m_nTerrianVertices = m_TexturesWidth * m_TexturesHeight * 25; 
 
	int TexTotal = m_TexturesWidth*m_TexturesHeight; 
	m_pTerrians = new TERRIAN[m_TerriansWidth*m_TerriansHeight]; 
	m_pHeights = new float[(m_TerriansWidth+1)*(m_TerriansHeight+1)]; 
	m_pMaxHeights = new float[m_TexturesWidth * m_TexturesHeight]; 
	m_pMinHeights = new float[m_TexturesWidth * m_TexturesHeight]; 
	m_pTerrianDraw = new bool[m_TexturesWidth * m_TexturesHeight]; 
	m_pTextureID = new TextureID[TexTotal]; 
	 
	memcpy(m_pTerrians,pFile,m_TerriansWidth*m_TerriansHeight*sizeof(TERRIAN)); 
	pFile += m_TerriansWidth*m_TerriansHeight*sizeof(TERRIAN); 
	memcpy(m_pHeights,pFile,(m_TerriansWidth+1)*(m_TerriansHeight+1)*sizeof(float)); 
	pFile += (m_TerriansWidth+1)*(m_TerriansHeight+1)*sizeof(float); 
	memcpy(m_pTextureID,pFile,TexTotal*sizeof(short)); 
	pFile += TexTotal*sizeof(short); 
 
	for(i = 0 ; i < TexTotal ; ++ i) 
		m_pTextureID[i] = pID[m_pTextureID[i]]; 
 
 
 
 
	int count; 
	memcpy(&count,pFile,sizeof(int)); 
	pFile += sizeof(int); 
	WorldObject Obj; 
	for(i = 0 ; i <  count ; ++ i) 
	{	 
		memcpy(&Obj.m_ObjectID,pFile,sizeof(short)); 
		pFile += sizeof(short); 
		memcpy(&Obj.m_SignID,pFile,sizeof(short)); 
		pFile += sizeof(short); 
		memcpy(Obj.m_Name,pFile,sizeof(char)*32); 
		pFile += sizeof(char)*32; 
		memcpy(&Obj.m_fPosX,pFile,sizeof(float)); 
		pFile += sizeof(float); 
		memcpy(&Obj.m_fPosY,pFile,sizeof(float)); 
		pFile += sizeof(float); 
		memcpy(&Obj.m_fPosZ,pFile,sizeof(float)); 
		pFile += sizeof(float); 
		memcpy(&Obj.m_Dir,pFile,sizeof(short)); 
		pFile += sizeof(short); 
		Obj.m_ModelID = g_MdlMgr.AddModel(Obj.m_ObjectID); 
		m_ObjectsList.push_back(Obj);		 
	} 
 
	delete [] pID; 
	delete [] pOrg; 
	 
	//int nObj = m_ObjectsList.size(); 
	m_NearPtrs.resize(m_ObjectsList.size() ); 
	m_FarPtrs.resize(m_ObjectsList.size()); 
	uint16* pIB; 
	// Create the Index buffer 
	// 32 * 3 + 2 * 3 
	if( FAILED( m_pd3dDevice->CreateIndexBuffer( 102 * sizeof(uint16), 
	                                             0, D3DFMT_INDEX16, 
		                                         D3DPOOL_MANAGED, &m_pIB, NULL ) ) ) 
	{ 
		Free(); 
		return false; 
	} 
	 
	 
    if( FAILED( m_pIB->Lock( 0, 0, (VOID**)&pIB, 0 ) ) ) 
	{ 
		Free(); 
		return false; 
	} 
 
	for( i = 0 ; i < 4 ; ++ i) 
	{ 
		for( j = 0 ; j < 4 ; ++ j) 
		{ 
			k = 6 * ( i * 4 + j); 
			uint16 v1 = i * 5  + j; 
			uint16 v2 = (i + 1) * 5 + j; 
			uint16 v3 = (i + 1) * 5 + j + 1; 
			uint16 v4 = i * 5 + j + 1; 
			pIB[k] =  v1; 
			pIB[k+1] = v2; 
			pIB[k+2] = v3; 
			pIB[k+3] = v1; 
			pIB[k+4] = v3; 
			pIB[k+5] = v4; 
		} 
	} 
	pIB[96] = 0; 
	pIB[97] = 20; 
	pIB[98] = 24; 
	pIB[99] = 0; 
	pIB[100] = 24; 
	pIB[101] = 4; 
	m_pIB->Unlock(); 
	 
 
	if( FAILED(m_pd3dDevice->CreateVertexBuffer( m_nTerrianVertices * sizeof(TERRIANVERTEX), 
													   0, TERRIANVERTEX::FVF , 
                                                       D3DPOOL_MANAGED, &m_pTerriansVB, NULL ) ) ) 
	{ 
		Free(); 
        return false; 
	} 
	TERRIANVERTEX* pVBVertices; 
    if( FAILED(m_pTerriansVB->Lock( 0, 0, (VOID**)&pVBVertices, 0 ) ) ) 
	{ 
		Free(); 
        return false; 
	} 
 
	float Min = 0,Max = 0;		 
	float basew ; 
	float baseh ; 
	int iw ; 
	int ih ; 
	for(i = 0 ; i < m_TexturesHeight ; ++ i) 
	{ 
		for(j = 0 ; j < m_TexturesWidth ; ++ j) 
		{ 
			k = 25 * (i * m_TexturesWidth + j); 
			t = i * m_TexturesWidth + j; 
			basew = j * m_fTextureSize; 
			baseh = i * m_fTextureSize; 
			iw = j * 4; 
			ih = i * 4; 
			Min = Max = 0; 
			for(m = 0 ; m < 5 ; ++ m) 
			{ 
				for(n = 0 ; n < 5 ; ++ n) 
				{ 
					l = k + 4 * m + m + n; 
					float Height = m_pHeights[(ih + m) * (m_TerriansWidth+1) + iw + n]; 
					if(Min > Height) 
						Min = Height; 
					if(Max < Height) 
						Max = Height; 
					pVBVertices[l].Pos = D3DXVECTOR3(basew + (float)n ,Height , baseh + (float)m); 				 
					pVBVertices[l].Texcoord = D3DXVECTOR2(1.0f - 0.25f * m,0.25f * n); 
				} 
			}		 
			m_pMaxHeights[t] = Max; 
			m_pMinHeights[t] = Min; 
		} 
	} 
    m_pTerriansVB->Unlock(); 
 
	if( FAILED(m_pd3dDevice->CreateVertexBuffer(	4 * sizeof(SKYVERTEX), 
													   0, SKYVERTEX::FVF , 
                                                       D3DPOOL_MANAGED, &m_pSkyVB, NULL ) ) ) 
	{ 
		Free(); 
        return false; 
	} 
	SKYVERTEX* pSkyVB; 
    if( FAILED(m_pSkyVB->Lock( 0, 0, (VOID**)&pSkyVB, 0 ) ) ) 
	{ 
		Free(); 
        return false; 
	} 
	pSkyVB[0].Pos.x = -g_Camera.GetSkyHalfWidth(); 
	pSkyVB[0].Pos.y = g_Camera.GetSkyY(); 
	pSkyVB[0].Pos.z = 0; 
	pSkyVB[0].Color = 0xFF0000E0; 
	pSkyVB[1].Pos.x = g_Camera.GetSkyHalfWidth(); 
	pSkyVB[1].Pos.y = g_Camera.GetSkyY(); 
	pSkyVB[1].Pos.z = 0; 
	pSkyVB[1].Color = 0xFF0000E0; 
	pSkyVB[2].Pos.x = -g_Camera.GetSkyHalfWidth(); 
	pSkyVB[2].Pos.y = g_Camera.GetSkyY() + g_Camera.GetSkyHeight(); 
	pSkyVB[2].Pos.z = 0; 
	pSkyVB[2].Color = 0xFF0000E0; 
	pSkyVB[3].Pos.x = g_Camera.GetSkyHalfWidth(); 
	pSkyVB[3].Pos.y = g_Camera.GetSkyY() + g_Camera.GetSkyHeight(); 
	pSkyVB[3].Pos.z = 0; 
	pSkyVB[3].Color = 0xFF0000E0; 
	m_pSkyVB->Unlock(); 
 
	if( FAILED(m_pd3dDevice->CreateVertexBuffer(	6 * sizeof(BACKVERTEX), 
													   0, BACKVERTEX::FVF , 
                                                       D3DPOOL_MANAGED, &m_pBackVB, NULL ) ) ) 
	{ 
		Free(); 
        return false; 
	} 
	BACKVERTEX* pBackVB; 
    if( FAILED(m_pBackVB->Lock( 0, 0, (VOID**)&pBackVB, 0 ) ) ) 
	{ 
		Free(); 
        return false; 
	} 
	pBackVB[0].Pos.x = 0; 
	pBackVB[0].Pos.y = -0.2; 
	pBackVB[0].Pos.z = g_Camera.GetBGHalfWidth(); 
	pBackVB[0].Color = 0xFF808080; 
	pBackVB[1].Pos.x = 0; 
	pBackVB[1].Pos.y = -0.2; 
	pBackVB[1].Pos.z = -g_Camera.GetBGHalfWidth(); 
	pBackVB[1].Color = 0xFF808080; 
	pBackVB[2].Pos.x = 0; 
	pBackVB[2].Pos.y = g_Camera.GetBGHeight(); 
	pBackVB[2].Pos.z = g_Camera.GetBGHalfWidth(); 
	pBackVB[2].Color = 0xFF808080; 
	pBackVB[3].Pos.x = 0; 
	pBackVB[3].Pos.y = g_Camera.GetBGHeight(); 
	pBackVB[3].Pos.z = -g_Camera.GetBGHalfWidth(); 
	pBackVB[3].Color = 0xFF808080; 
	pBackVB[4].Pos.x = 0; 
	pBackVB[4].Pos.y = g_Camera.GetBGHeight() * 1.2; 
	pBackVB[4].Pos.z = g_Camera.GetBGHalfWidth(); 
	pBackVB[4].Color = 0x00808080; 
	pBackVB[5].Pos.x = 0; 
	pBackVB[5].Pos.y = g_Camera.GetBGHeight() * 1.2; 
	pBackVB[5].Pos.z = -g_Camera.GetBGHalfWidth(); 
	pBackVB[5].Color = 0x00808080; 
	m_pBackVB->Unlock();	 
 
 
	m_Effect.Init(pd3dDevice); 
 
 
	m_SkyTexture = g_TexMgr.AddTexture(SkyName); 
 
	SAFE_DELETE(m_pRootNode); 
	CreateTree(NULL,&m_pRootNode,m_TerriansWidth * m_fTerrianSize / 2 , 0 , m_TerriansWidth * m_fTerrianSize / 2, 
								 m_TerriansWidth * m_fTerrianSize / 2); 
 
	 
 
	return true; 
} 
 
bool Map::Reset() 
{ 
	m_Effect.Reset(); 
	return true; 
} 
 
void Map::Lost() 
{ 
	m_Effect.Lost(); 
} 
 
void Map::Free() 
{	 
	m_LastID = -1;  
 
//	for(list::iterator Itr = m_ObjectsList.begin() ; Itr != m_ObjectsList.end(); Itr ++) 
//		g_MdlMgr.Delete(Itr->m_ModelID); 
 
	SAFE_DELETE(m_pRootNode); 
	SAFE_RELEASE(m_pTerriansVB); 
	SAFE_RELEASE(m_pIB); 
	SAFE_RELEASE(m_pSkyVB); 
	SAFE_RELEASE(m_pBackVB); 
	 
	m_Effect.Free(); 
	SAFE_DELETE_A(m_pTerrianDraw); 
	SAFE_DELETE_A(m_pMaxHeights); 
	SAFE_DELETE_A(m_pMinHeights); 
	SAFE_DELETE_A(m_pHeights); 
	SAFE_DELETE_A(m_pTerrians); 
	SAFE_DELETE_A(m_pTextureID); 
 
	m_ObjectsList.clear(); 
} 
 
void Map::Render() 
{	 
	float Start = g_Camera.GetFogStart(); 
	float End = g_Camera.GetFogEnd(); 
 
	m_pd3dDevice->SetTransform(D3DTS_VIEW,g_Camera.GetView()); 
	m_pd3dDevice->SetTransform(D3DTS_PROJECTION,g_Camera.GetProj()); 
	m_pd3dDevice->SetRenderState(D3DRS_FOGENABLE,TRUE); 
	m_pd3dDevice->SetRenderState(D3DRS_FOGCOLOR,0x00808080); 
	m_pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE,D3DFOG_LINEAR); 
	m_pd3dDevice->SetRenderState(D3DRS_FOGSTART,*(DWORD*)(&Start)); 
	m_pd3dDevice->SetRenderState(D3DRS_FOGEND,*(DWORD*)(&End)); 
 
 
	 
	int k; 
	UINT nPasses,iPass; 
	HRESULT hr; 
 
	m_pd3dDevice->SetFVF( TERRIANVERTEX::FVF  ); 
	m_pd3dDevice->SetStreamSource(	0, m_pTerriansVB,0 ,sizeof(TERRIANVERTEX) ); 
	m_pd3dDevice->SetIndices( m_pIB );	 
	m_Effect.SetTechnique(EFFECT_TERRIAN); 
    m_Effect.Begin(&nPasses, 0); 
	m_Effect.SetViewProjMatrix(g_Camera.GetViewProj()); 
    for (iPass = 0; iPass < nPasses; ++ iPass) 
    { 
        m_Effect.BeginPass(iPass); 
		m_pd3dDevice->SetIndices( m_pIB );	 
		while(!m_NearDrawList.empty()) 
		{ 
			k = m_NearDrawList.front(); 
			m_NearDrawList.pop_front(); 
			m_Effect.SetTexture(g_TexMgr.GetTexture(m_pTextureID[k])); 
			m_Effect.CommitChanges(); 
			 
			 
			hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,  
													k * 25, // index base 
													0,  
													25,		 
													0,  
													32);	 
		} 
		m_Effect.EndPass(); 
    } 
    m_Effect.End(); 
 
	m_Effect.SetTechnique(EFFECT_TERRIAN); 
    m_Effect.Begin(&nPasses, 0); 
    for (iPass = 0; iPass < nPasses; ++ iPass) 
    { 
        m_Effect.BeginPass(iPass);	 
		while(!m_FarDrawList.empty()) 
		{ 
			k = m_FarDrawList.front(); 
			m_FarDrawList.pop_front(); 
			m_Effect.SetTexture(g_TexMgr.GetTexture(m_pTextureID[k])); 
			m_Effect.CommitChanges(); 
			hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,  
													k * 25, // index base 
													0,  
													25,		 
													0,  
													32);	 
			//hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,  
			//										k * 25, // index base 
			//										0,  
			//										25,		 
			//										96,  
			//										2);	 
		} 
 
		m_Effect.EndPass(); 
    } 
    m_Effect.End(); 
 
	vector::iterator Itr; 
	for(Itr = m_NearPtrs.begin() ; Itr != m_NearCurItr ; ++ Itr) 
	{ 
		Itr->Ptr->Render(g_Camera.GetViewProj()); 
	} 
 
 
	for(Itr = m_FarPtrs.begin() ; Itr != m_FarCurItr ; ++ Itr) 
	{ 
		Itr->Ptr->Render(g_Camera.GetViewProj(),true); 
	} 
	if(g_Camera.IsFPView()) 
	{ 
		m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 
		 
		float sinDir = Math::Sin(g_Camera.GetBGDir()); 
		float cosDir = Math::Cos(g_Camera.GetBGDir()); 
		m_Effect.SetPosition(&D3DXVECTOR4(g_Camera.GetBGX(),0,g_Camera.GetBGZ(),0)); 
		m_Effect.SetDirection(&D3DXVECTOR4(sinDir,cosDir,0,0)); 
 
		m_Effect.SetViewProjMatrix(g_Camera.GetViewProj()); 
		m_Effect.SetTechnique(EFFECT_BG); 
		m_Effect.Begin(&nPasses, 0); 
		m_pd3dDevice->SetFVF( BACKVERTEX::FVF  ); 
		m_pd3dDevice->SetStreamSource(	0, m_pBackVB,0 ,sizeof(BACKVERTEX) );									 
		for (iPass = 0; iPass < nPasses; ++ iPass) 
		{ 
			m_Effect.BeginPass(iPass); 
 
			hr = m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0,4);  
 
		m_Effect.EndPass(); 
		} 
		m_Effect.End(); 
		m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 
	} 
 
	m_pd3dDevice->SetRenderState(D3DRS_FOGENABLE,FALSE); 
 
} 
 
void Map::Update() 
{	 
	// Map Trigger 
	int x = (int)g_HeroCtrl.GetHero()->m_fPosX; 
	int z = (int)g_HeroCtrl.GetHero()->m_fPosZ; 
 
	TERRIAN Trr = m_pTerrians[z * m_TerriansWidth + x]; 
	if((Trr & 0xFF00) == TRR_SPECIAL) 
	{ 
		int id = (int)(Trr & 0x00FF); 
		if(id != m_LastID) 
		{ 
//			MapScript* pScript = (MapScript*)g_ScriptSys.GetScript(m_ScriptID); 
//			pScript->OnSpecial(id); 
			m_LastID = id; 
		} 
	} 
	FILE* fp = fopen("F:\\NewTest.txt","w"); 
	int time = timeGetTime(); 
	m_NearDrawList.clear(); 
	m_FarDrawList.clear(); 
	m_FarCurItr = m_FarPtrs.begin(); 
	m_NearCurItr = m_NearPtrs.begin(); 
	m_FarCurPos = m_NearCurPos = 0; 
 
	memset(m_pTerrianDraw,0,sizeof(bool)*m_TexturesWidth*m_TexturesHeight); 
	fprintf(fp,"memset time : %d\n",timeGetTime()-time); 
	time = timeGetTime(); 
	if(g_Camera.IsFPView()) 
	{ 
		AddTreeNode(g_Camera.GetVisibityFrustum(),true,m_pRootNode); 
		AddTreeNode(g_Camera.GetBackgroundFrustum(),false,m_pRootNode); 
	} 
	else 
	{ 
		AddTreeNode(g_Camera.GetFrustum(),true,m_pRootNode); 
	} 
 
	fprintf(fp,"frustum time : %d\n",timeGetTime()-time); 
	time = timeGetTime(); 
 
	vector::iterator Itr; 
	for(Itr = m_NearPtrs.begin() ; Itr != m_NearCurItr ; ++ Itr) 
	{ 
		Itr->Ptr->m_fViewZ = Itr->Ptr->m_fPosX * g_Camera.GetView()->_13 + 
							 Itr->Ptr->m_fPosY * g_Camera.GetView()->_23 + 
							 Itr->Ptr->m_fPosZ * g_Camera.GetView()->_33 + g_Camera.GetView()->_43; 
	} 
	sort(m_NearPtrs.begin(),m_NearCurItr); 
 
	fprintf(fp,"sort time : %d\n",timeGetTime()-time); 
	time = timeGetTime(); 
	 
	fprintf(fp,"Terrian:%d\nObject:%d\n",m_NearDrawList.size(), 
										 m_NearCurPos); 
	fprintf(fp,"Far Terrian:%d\nFar Object:%d\n",m_FarDrawList.size(), 
										 m_FarCurPos); 
	fclose(fp); 
} 
 
 
void Map::AddTreeNode(Frustum* pFrustum,bool bNear,Node *Node) 
{ 
	if(Node == NULL) 
		return; 
	int Count = 0; 
 
	bool CompletelyContained = false; 
	// the node is out of the frustum 
    if(!pFrustum->CheckRectangle(Node->XPos,Node->YPos,Node->ZPos,  
								 Node->Size,Node->Size,Node->Size , 
								 &CompletelyContained)) 
		return; 
  
 
	if(!CompletelyContained)  
	{ 
		for(int i = 0 ; i < 8; ++ i)  
		{ 
			if(Node->Nodes[i] != NULL)  
			{ 
				AddTreeNode(pFrustum,bNear,Node->Nodes[i]); 
				Count ++;	 
			} 
		} 
		if(Count) 
			return; 
	} 
 
	list::iterator TrrItr; 
	for(TrrItr = Node->TerrianList.begin() ; TrrItr != Node->TerrianList.end(); ++ TrrItr) 
	{ 
		if(!m_pTerrianDraw[*TrrItr]) 
		{ 
			if(bNear) 
				m_NearDrawList.push_back(*TrrItr); 
			else 
				m_FarDrawList.push_back(*TrrItr); 
			m_pTerrianDraw[*TrrItr] = true; 
		} 
	} 
 
	list::iterator>::iterator ObjItr; 
 
	for(ObjItr = Node->ObjectsList.begin() ; ObjItr != Node->ObjectsList.end() ; ++ ObjItr) 
	{	 
		if((*ObjItr)->m_bRender) 
			continue; 
		(*ObjItr)->m_bRender = true; 
		if(bNear) 
		{ 
			m_NearCurItr->Ptr = &(*(*ObjItr)); 
			m_NearCurItr ++; 
			m_NearCurPos ++; 
		} 
		else 
		{ 
			m_FarCurItr->Ptr = &(*(*ObjItr)); 
			m_FarCurItr ++; 
			m_FarCurPos ++; 
		} 
	} 
} 
 
void Map::CreateTree(Node* pParent,Node** ppNode,float XPos,float YPos,float ZPos,float Size) 
{ 
	int		i,j; 
	float   XOff, YOff, ZOff; 
 
	*ppNode = new Node; 
 
	// Store node coordinates and size 
	(*ppNode)->XPos = XPos; 
	(*ppNode)->YPos = YPos; 
	(*ppNode)->ZPos = ZPos; 
	(*ppNode)->Size = Size; 
 
	// Add Object 
	if(pParent == NULL) 
	{ 
		list::iterator Itr; 
		for(Itr = m_ObjectsList.begin() ; Itr != m_ObjectsList.end() ; ++ Itr) 
		{ 
			if(Itr->m_ModelID < 0) 
				continue; 
			g_MdlMgr.GetModel(Itr->m_ModelID)->GetBoundBox(Itr->m_fPosX,Itr->m_fPosY,Itr->m_fPosZ,Itr->m_Dir, 
															&Itr->m_vMin,&Itr->m_vMax); 
			if((*ppNode)->CheckRectangle(Itr->m_vMin,Itr->m_vMax)) 
				(*ppNode)->ObjectsList.push_back(Itr); 
		} 
	} 
	else 
	{ 
		list::iterator>::iterator Itr; 
		for(Itr = pParent->ObjectsList.begin(); Itr != pParent->ObjectsList.end() ; ++ Itr) 
		{ 
			if((*ppNode)->CheckRectangle((*Itr)->m_vMin,(*Itr)->m_vMax)) 
				(*ppNode)->ObjectsList.push_back((*Itr)); 
		} 
	} 
 
 
	// Add Terrian 
	int xs = (XPos - Size) / 4; 
	int xe = (XPos + Size) / 4; 
	int zs = (ZPos - Size) / 4; 
	int ze = (ZPos + Size) / 4; 
	float txs,txe,tzs,tze; 
	for(i = zs ; i < ze ; ++ i) 
	{ 
		for(j = xs; j < xe ; ++ j) 
		{ 
			int k = i * m_TexturesWidth + j; 
			txs = j * m_fTextureSize; 
			tzs = i * m_fTextureSize; 
			txe = txs + m_fTextureSize; 
			tze = tzs + m_fTextureSize; 
 
			D3DXVECTOR3 vMin(txs,m_pMinHeights[k],tzs);  
			D3DXVECTOR3 vMax(txe,m_pMaxHeights[k],tze); 
			if((*ppNode)->CheckRectangle(vMin,vMax)) 
				(*ppNode)->TerrianList.push_back(k); 
		} 
	} 
 
 
	// delete emtpy node 
	if((*ppNode)->ObjectsList.empty() && (*ppNode)->TerrianList.empty()) 
	{ 
		delete (*ppNode); 
		(*ppNode) = NULL; 
		return; 
	} 
	 
	// Split node if size > maximum  
	if(Size > 4.0)  
	{ 
		for( i = 0;  i < 8 ; ++ i)  
		{ 
			XOff = (((i % 2) < 1) ? -1.0f : 1.0f) * (Size / 2.0f); 
			ZOff = (((i % 4) < 2) ? -1.0f : 1.0f) * (Size / 2.0f); 
			YOff = (((i % 8) < 4) ? -1.0f : 1.0f) * (Size / 2.0f); 
 
			// Sort the polygons with the new child node 
			CreateTree(*ppNode,&((*ppNode)->Nodes[i]),XPos+XOff,YPos+YOff,ZPos+ZOff,Size/2.0f); 
		} 
	}	 
} 
 
float Map::GetY(float fX,float fZ) 
{ 
	int iX = (int)fX; 
	int iZ = (int)fZ; 
	if(iX < 0 || iX > m_TerriansWidth || iZ < 0 || iZ > m_TerriansHeight) 
		return 0.0f; 
	float fFX = fX - (float)iX; 
	float fFZ = fZ - (float)iZ; 
	float fHeights[4]; 
	fHeights[0] = m_pHeights[(m_TerriansWidth + 1) * iZ + iX]; 
	fHeights[1] = m_pHeights[(m_TerriansWidth + 1) * (iZ + 1) + iX]; 
	fHeights[2] = m_pHeights[(m_TerriansWidth + 1) * (iZ + 1) + iX + 1]; 
	fHeights[3] = m_pHeights[(m_TerriansWidth + 1) * iZ + iX + 1]; 
	float t1,t2; 
	t1 = (fHeights[3] -  fHeights[0]) * fFZ + fHeights[0]; 
	t2 = (fHeights[2] -  fHeights[1]) * fFZ + fHeights[1]; 
	float fY = (t2 - t1) * fFZ + t1;	 
	return fY; 
}