//
// Tools_RenderCollisionMesh.cpp
//
// Created by Richard Rice - 20/09/2004
// 
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"
#include "Rendering/Tools_RenderCollisionMesh.h"

#include "Core/Asura_TextureManagement.h"
#include "Core/Asura_HashTree.h"
#include "Interface/Asura_Overlay_System.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Dialog.h"
#include "Mesh/Asura_CollisionMesh.h"
#include "Mesh/Asura_Mesh.h"
#include "Rendering/Asura_Direct3D.h"
#include "Rendering/Asura_Module.h"
#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_Direct3D_Shaders.h"
#ifdef ASURA_USE_STREAMING
#include "Streaming/Tools_Streaming_System.h"
#endif

#include "Misc/Tools_Render_Options.h"

//////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////
/*---------------------------**
** Tools_RenderCollisionMesh **
**---------------------------*/

static const int g_iPOLYGON_FLAGS_USED = AsuraPolygonFlag_DontRender | AsuraPolygonFlag_NoCollisions | AsuraPolygonFlag_IgnoreLOS;


class Tools_RenderCollisionMesh
{
	public:
		Tools_RenderCollisionMesh()
		{
			m_pxVertexBuffer = 0;
			m_pxIndexBuffer = 0;
			m_iNumberOfVertices = 0;
			m_iNumberOfIndices = 0;
		}
		~Tools_RenderCollisionMesh()
		{
			if (m_pxVertexBuffer)
			{
				m_pxVertexBuffer->Release();
			}
			if(m_pxIndexBuffer)
			{
				m_pxIndexBuffer->Release();
			}
		}
		void Reset(void)
		{
			if (m_pxVertexBuffer)
			{
				m_pxVertexBuffer->Release();
				m_pxVertexBuffer = 0;
			}
			if(m_pxIndexBuffer)
			{
				m_pxIndexBuffer->Release();
				m_pxIndexBuffer = 0;
			}
			m_iNumberOfVertices = 0;
			m_iNumberOfIndices = 0;
		}

		void Initialise(int iModuleIndex,const Asura_CollisionMesh* pxColMesh,int iFlagsNotToShow);
		void RenderSolid();
		void RenderTrans(int iPass);

		bool IsValid() const {return m_pxVertexBuffer && m_pxIndexBuffer;}



private :
		static Asura_Hash_ID GetPolygonHash(const Asura_Mesh* pxMesh,int iPoly);
		static Asura_Hash_ID GetPolygonHash(const Asura_CollisionMesh* pxMesh,int iPoly);
		static Asura_Hash_ID GetPolygonHash(int iNumVerts,const Asura_Vector_3 **  ppxVerts);

		Direct3D_VertexBuffer*	m_pxVertexBuffer;
		Direct3D_IndexBuffer*	m_pxIndexBuffer;

		int m_iNumberOfVertices;
		int m_iNumberOfIndices;

		
};

#define CMESH_VERTEX_DESC (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

struct CMeshVertex
{
	Asura_Vector_3 xPos;
	u_int uDiffuse;
	float U;
	float V;
};


void Tools_RenderCollisionMesh::Initialise(int iModuleIndex,const Asura_CollisionMesh* pxColMesh,int iFlagsNotToShow)
{
	
	//get hash values of all polygons that are hidden as a result of the mode in the Asura_Mesh
	Asura_HashTree xHiddenPolyHashTree;
	const Asura_Mesh* pxMesh = Asura_Module_System::GetMeshForModule(iModuleIndex);
	int iJunkIndex;//generaly junk receptacle

	int iToolsHideFlags = Tools_Render_Options::GetHideFlags();
	if(iToolsHideFlags)
	{
		for(int i=0;i<pxMesh->NumberOfPolygons;i++)
		{
			if(Tools_Render_Options::GetRenderFlags(iModuleIndex,i) & iToolsHideFlags)
			{
				//this polygon should be hidden , so add to tree
				Asura_Hash_ID uHash = GetPolygonHash(pxMesh,i);
				xHiddenPolyHashTree.FindNodeIndexByHash(uHash,true,iJunkIndex);

			}
		}
	}
	


	m_iNumberOfVertices = 0;
	m_iNumberOfIndices = 0;

	bool bUseDoubleSidedFlag = (Tools_RenderCollisionMesh_System::GetRenderMode() == TOOLS_COLLRENDER_SOLID);
	
	u_int uNumPolys = pxColMesh->GetNumberOfPolys();
	for(u_int i=0;i<uNumPolys;i++)
	{
		if(pxColMesh->GetFlags(i) & iFlagsNotToShow)
		{
			continue;
		}

		if(xHiddenPolyHashTree.GetNumberOfNodes())
		{
			if(xHiddenPolyHashTree.FindNodeIndexByHash(GetPolygonHash(pxColMesh,i),false,iJunkIndex))
			{
				//polygon corresponds with a hidden polygon in the Asura_Mesh
				continue;
			}
		}

		m_iNumberOfVertices += pxColMesh->IsQuad(i) ? 4 : 3;
		if(bUseDoubleSidedFlag && (pxColMesh->GetFlags(i) & AsuraPolygonFlag_DoubleSided))
		{
			m_iNumberOfIndices += (pxColMesh->IsQuad(i) ? 6 : 3)*2;
		}
		else
		{
			m_iNumberOfIndices += pxColMesh->IsQuad(i) ? 6 : 3;
		}
	}

	if(!m_iNumberOfVertices) return;

	//allocate buffers
	Asura_Direct3D::D3DDevice->CreateVertexBuffer
	(
		m_iNumberOfVertices*sizeof(CMeshVertex),
		D3DUSAGE_WRITEONLY,
		CMESH_VERTEX_DESC,
		D3DPOOL_MANAGED,
		&m_pxVertexBuffer,
		0
	);
	Asura_Assert(m_pxVertexBuffer,"Failed to allocate vertex buffer");

	Asura_Direct3D::D3DDevice->CreateIndexBuffer
	(
		m_iNumberOfIndices*sizeof(unsigned int),  
		D3DUSAGE_WRITEONLY,
		D3DFMT_INDEX32,
		D3DPOOL_MANAGED,
		&m_pxIndexBuffer,
		0
	);
	Asura_Assert(m_pxIndexBuffer,"Failed to allocate index buffer");

	CMeshVertex* pxVertexData;
	m_pxVertexBuffer->Lock(0,sizeof(CMeshVertex)*m_iNumberOfVertices,(void**)&pxVertexData,0);
	Asura_Assert( pxVertexData, "Failed to lock vertex buffer" );

	unsigned int* puIndexData;
	m_pxIndexBuffer->Lock(0,sizeof(unsigned int)*m_iNumberOfIndices,(void**)&puIndexData,0);
	Asura_Assert( puIndexData, "Failed to lock index buffer" );

	unsigned int uIndex = 0;

	Asura_Vector_3 xModulePos = Asura_Module_System::GetPositionOfModule(iModuleIndex);


	for(u_int i=0;i<uNumPolys;i++)
	{
		if(pxColMesh->GetFlags(i) & iFlagsNotToShow) 
		{
			continue;
		}
		
		if(xHiddenPolyHashTree.GetNumberOfNodes())
		{
			if(xHiddenPolyHashTree.FindNodeIndexByHash(GetPolygonHash(pxColMesh,i),false,iJunkIndex))
			{
				//polygon corresponds with a hidden polygon in the Asura_Mesh
				continue;
			}
		}
		
		
		int iNumVerts = pxColMesh->IsQuad(i) ? 4 : 3;

		Asura_Vector_3 xNorm;
		pxColMesh->GetNormal(i,xNorm);
		int iBright = (int)((xNorm.x-xNorm.y+xNorm.z)/1.73f*50.0f + 150.0f);
		u_int uCol = 0xff000000 | (iBright<<16)|(iBright<<8)|iBright;

		
		for(int j=0;j<iNumVerts;j++)
		{
			pxVertexData->xPos = pxColMesh->GetVertex(pxColMesh->GetVertexIndex(i,j))+xModulePos;
			pxVertexData->uDiffuse = uCol;
			pxVertexData->U = (j==0 || j==3) ? 0.0f : 1.0f;
			pxVertexData->V = (j==2 || j==3) ? 0.0f : 1.0f;
			pxVertexData++;
		}

		if(iNumVerts == 3)
		{
			*puIndexData++ = uIndex;
			*puIndexData++ = (uIndex+1);
			*puIndexData++ = (uIndex+2);

			if(bUseDoubleSidedFlag && (pxColMesh->GetFlags(i) & AsuraPolygonFlag_DoubleSided))
			{
				*puIndexData++ = (uIndex+2);
				*puIndexData++ = (uIndex+1);
				*puIndexData++ = uIndex;
			}

			uIndex+=3;
		}
		else
		{
			*puIndexData++ = uIndex;
			*puIndexData++ = (uIndex+1);
			*puIndexData++ = (uIndex+2);

			*puIndexData++ = (uIndex+2);
			*puIndexData++ = (uIndex+3);
			*puIndexData++ = uIndex;

			if(bUseDoubleSidedFlag && (pxColMesh->GetFlags(i) & AsuraPolygonFlag_DoubleSided))
			{
				*puIndexData++ = (uIndex+2);
				*puIndexData++ = (uIndex+1);
				*puIndexData++ = uIndex;

				*puIndexData++ = uIndex;
				*puIndexData++ = (uIndex+3);
				*puIndexData++ = (uIndex+2);
			}


			uIndex+=4;
		}
	}
		
	m_pxVertexBuffer->Unlock();
	m_pxIndexBuffer->Unlock();

}

static int g_iTextureIndex = ASURA_TEXTURE_NONE;

void Tools_RenderCollisionMesh::RenderSolid()
{

	if (!m_iNumberOfIndices) return;

	Asura_Render::CurrentStates.RequestAlphaTest(false);
	// no BFC option
    if (Tools_Render_Options::NoBackFaceCull)
    {
		Asura_Render::CurrentStates.RequestCullMode(ASURA_CULLMODE_NONE);
    }
    else
    {
		Asura_Render::CurrentStates.RequestCullMode(ASURA_CULLMODE_CW);
    }
	Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
	
	HRESULT h;

	h=Asura_Direct3D::D3DDevice->SetStreamSource(0,m_pxVertexBuffer,0,sizeof(CMeshVertex));
	Asura_Direct3D_Shaders::RequestFixedFunctionVertexShader(CMESH_VERTEX_DESC);
	h=Asura_Direct3D::D3DDevice->SetIndices(m_pxIndexBuffer);
	
	Asura_Render::CurrentStates.RequestTextureIndex(0,g_iTextureIndex);
	Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_SINGLE_PASS);
	Asura_Render::CurrentStates.RequestAlphaTest(false);


	
	h=Asura_Direct3D::D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_iNumberOfVertices,0,m_iNumberOfIndices/3);
	

	Asura_Render::AddToTrianglesRendered(m_iNumberOfIndices/3);

}

void Tools_RenderCollisionMesh::RenderTrans(int iPass)
{

	if (!m_iNumberOfIndices) return;


	Asura_Render::CurrentStates.RequestCullMode(ASURA_CULLMODE_NONE);
	Asura_Render::CurrentStates.RequestAlphaTest(false);
	

	Asura_Direct3D::D3DDevice->SetStreamSource(0,m_pxVertexBuffer,0,sizeof(CMeshVertex));
	Asura_Direct3D::D3DDevice->SetIndices(m_pxIndexBuffer);
	Asura_Render::CurrentStates.RequestTextureIndex(0,ASURA_TEXTURE_NONE);
	Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_SINGLE_PASS);

	Asura_Direct3D::D3DDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	Asura_Direct3D::D3DDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TFACTOR );

	Asura_Direct3D::D3DDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,  D3DTOP_SELECTARG1 );
	Asura_Direct3D::D3DDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1, D3DTA_TFACTOR );

   	Asura_Direct3D::D3DDevice->SetTextureStageState(1,D3DTSS_COLOROP,   D3DTOP_DISABLE);


	if(iPass==0)
	{
		//First Pass
		//Render base colour for all modules , but with z value offset back however many metres

	    Asura_Direct3D_Shaders::RequestVertexShader(ASURA_D3D_VS_TOOLS_CMESH_ZOFFSET );

		Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
		Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0xff404040);

	    D3DXMATRIX xObjectToWorldMat;
	    D3DXMATRIX xWorldToViewMat;
	    D3DXMATRIX xViewToScreenMat;
	    D3DXMATRIX xTempMat;

	    // Setup obj->world matrix.
		D3DXMatrixTranslation( &xObjectToWorldMat, 0,0,0 );

	    // Fetch world->view and view->screen matrices from DirectX.
		Asura_Direct3D::D3DDevice->GetTransform( D3DTS_VIEW, &xWorldToViewMat );
		Asura_Direct3D::D3DDevice->GetTransform( D3DTS_PROJECTION, &xViewToScreenMat );

	    // Concatenate.
	    D3DXMatrixMultiply( &xTempMat, &xObjectToWorldMat, &xWorldToViewMat );
	    D3DXMatrixMultiplyTranspose( &xTempMat, &xTempMat, &xViewToScreenMat );

	    // Copy to vertex shader's constant registers.
	    Asura_Direct3D::D3DDevice->SetVertexShaderConstantF( 0, (float*)&xTempMat, 4 );

		float fZOffset = Tools_RenderCollisionMesh_System::GetZPenetration();
		const float afOffset[4] = { -fZOffset, -fZOffset, -fZOffset, 0.0f };

	    Asura_Direct3D::D3DDevice->SetVertexShaderConstantF( 4, afOffset, 1 );

		// Setup  camera position in constant register.
		{
		    const Asura_Vector_3* pxCamPos = Asura_Camera::GetPosition();

		    float afTransformedCamPos[4] =
		    {
		        pxCamPos->x, pxCamPos->y, pxCamPos->z, 1.0f
		    };
		    
		    Asura_Direct3D::D3DDevice->SetVertexShaderConstantF( 5, afTransformedCamPos, 1 );
		}

		Asura_Direct3D::D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_iNumberOfVertices,0,m_iNumberOfIndices/3);

	}
	else if(iPass==1)
	{
		//Second Pass
		//Render all polygons with additive alpha , but without writing z values

		Asura_Direct3D_Shaders::RequestFixedFunctionVertexShader(CMESH_VERTEX_DESC);

		Asura_Render::CurrentStates.RequestZBufferWriteEnabled(false);
		Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_GLOWING);
		Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0xff101010);

		Asura_Direct3D::D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_iNumberOfVertices,0,m_iNumberOfIndices/3);
	
	}
	else if(iPass==2)
	{
		//Third Pass
		//Just set Z for all polygons , so the z values are no longer offset
		Asura_Direct3D_Shaders::RequestFixedFunctionVertexShader(CMESH_VERTEX_DESC);

		Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_JUSTSETZ);
		Asura_Direct3D::D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_iNumberOfVertices,0,m_iNumberOfIndices/3);

	}
	else if(iPass==3)
	{
		//Forth Pass
		//Add a wireframe outline
		Asura_Direct3D_Shaders::RequestFixedFunctionVertexShader(CMESH_VERTEX_DESC);

		Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
		Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_TEXTUREFACTOR,0xff7f7f7f);

		Asura_Render::CurrentStates.RequestWireFrameMode(true);

		Asura_Direct3D::D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,m_iNumberOfVertices,0,m_iNumberOfIndices/3);
		
		Asura_Render::CurrentStates.RequestWireFrameMode(Asura_Render::GetWireframe());
	}



 	Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_SINGLE_PASS_2X);
 	Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_SINGLE_PASS);
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(true);


	if(iPass==0)
	{
		Asura_Render::AddToTrianglesRendered(m_iNumberOfIndices/3);
	}

}



Asura_Hash_ID Tools_RenderCollisionMesh::GetPolygonHash(const Asura_Mesh* pxMesh,int iPoly)
{
	const Asura_Mesh_Polygon* pxPoly = &pxMesh->PolygonDataPtr[iPoly];
	const Asura_Vector_3* apxVerts[4];
	int iNumVerts = pxPoly->NumberOfVertices();
	for(int i=0;i<iNumVerts;i++)
	{
		apxVerts[i] = &pxMesh->VertexDataPtr[pxPoly->VertexID[i]].Position;
	}
	return GetPolygonHash(iNumVerts,&apxVerts[0]);

}

Asura_Hash_ID Tools_RenderCollisionMesh::GetPolygonHash(const Asura_CollisionMesh* pxColMesh,int iPoly)
{
	const Asura_Vector_3* apxVerts[4];
	int iNumVerts = pxColMesh->IsQuad(iPoly) ? 4 : 3;

	for(int i=0;i<iNumVerts;i++)
	{
		apxVerts[i] = &pxColMesh->GetVertex(pxColMesh->GetVertexIndex(iPoly,i));
	}
	return GetPolygonHash(iNumVerts,&apxVerts[0]);
}

Asura_Hash_ID Tools_RenderCollisionMesh::GetPolygonHash(int iNumVerts,const Asura_Vector_3 ** ppxVerts)
{
	Asura_Hash_ID uHash = iNumVerts;

	u_int uScale = 2;
	for(int i=0;i<iNumVerts;i++)
	{
		uHash += (*(const u_int*)&(ppxVerts[i]->x))*(uScale++);
		uHash += (*(const u_int*)&(ppxVerts[i]->y))*(uScale++);
		uHash += (*(const u_int*)&(ppxVerts[i]->z))*(uScale++);
	}
	return uHash;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
/*----------------------------------**
** Tools_RenderCollisionMesh_System **
**----------------------------------*/

int Tools_RenderCollisionMesh_System::s_iNumModules = 0;
Tools_RenderCollisionMesh** Tools_RenderCollisionMesh_System::s_ppxRenderMeshes = 0;

int Tools_RenderCollisionMesh_System::s_iFlagsNotToShow = AsuraPolygonFlag_NoCollisions;
bool Tools_RenderCollisionMesh_System::s_bFlagsChanged = false;

int Tools_RenderCollisionMesh_System::s_iRenderMode = TOOLS_COLLRENDER_NONE;

float Tools_RenderCollisionMesh_System::s_fZPenetration = 20.0f;

void Tools_RenderCollisionMesh_System::Initialise()
{
	s_iNumModules = Asura_Module_System::GetNumberOfModules();
	s_ppxRenderMeshes = new Tools_RenderCollisionMesh*[s_iNumModules];

	for(int i=0;i<s_iNumModules;i++)
	{
		s_ppxRenderMeshes[i] = new Tools_RenderCollisionMesh;
	}

	//If the render mode was set to something else when previously in tools , then set it again
	if(s_iRenderMode != TOOLS_COLLRENDER_NONE)
	{
		SetRenderMode((Tools_CollRenderMode)s_iRenderMode);
	}


	//g_iTextureIndex = Asura_Texture_Management::AddTexture("\\environments\\default.bmp");
	g_iTextureIndex = Asura_Texture_Management::AddTexture("\\tools\\CollMesh.bmp");
	Asura_Texture_Management::LoadTextures();
}

void Tools_RenderCollisionMesh_System::Shutdown()
{
	for(int i=0;i<s_iNumModules;i++)
	{
		delete s_ppxRenderMeshes[i];
	}
	delete [] s_ppxRenderMeshes;
	s_ppxRenderMeshes = 0;
	s_iNumModules = 0;
}

void Tools_RenderCollisionMesh_System::RenderModule(int iPass,int iModule)
{
	Asura_Assert(iModule>=0 && iModule<s_iNumModules,"");

	//if the visibility flags have changed , will need to regenerate the meshes
	if(s_bFlagsChanged)
	{
		s_bFlagsChanged = false;
		for(int i=0;i<s_iNumModules;i++)
		{
			s_ppxRenderMeshes[i]->Reset();
		}
		Tools_Render_Options::SetMaskedPolygonFlagsToHide(s_iFlagsNotToShow,g_iPOLYGON_FLAGS_USED);
	}
	
	Asura_Vector_3 xPos = Asura_Module_System::GetPositionOfModule(iModule);
	
	if(!s_ppxRenderMeshes[iModule]->IsValid())
	{
		s_ppxRenderMeshes[iModule]->Initialise(iModule,Asura_Module_System::GetCollisionMeshForModule(iModule),s_iFlagsNotToShow);
	}


	switch(s_iRenderMode)
	{
		case TOOLS_COLLRENDER_SOLID :
			s_ppxRenderMeshes[iModule]->RenderSolid();
			break;
		case TOOLS_COLLRENDER_TRANS :
			s_ppxRenderMeshes[iModule]->RenderTrans(iPass);
			break;
		default :
			Asura_Assert(0,"Unexpected render mode");
	}
		
}

int Tools_RenderCollisionMesh_System::GetNumPasses()
{
	switch(s_iRenderMode)
	{
		case TOOLS_COLLRENDER_SOLID :
			return 1;
		case TOOLS_COLLRENDER_TRANS :
			return 4;
		default :
			Asura_Assert(0,"Unexpected render mode");
			return 1;
	}
}

void Tools_RenderCollisionMesh_System::InvalidateModule(int iModule)
{
	//Ignore if this is called before the system has been initialised
	if(s_iNumModules)
	{
		if(iModule>=0 && iModule<s_iNumModules)
		{
			s_ppxRenderMeshes[iModule]->Reset();
		}
		else
		{
			Asura_Assert(iModule>=0 && iModule<s_iNumModules,"");
		}
	}
}


void Tools_RenderCollisionMesh_System::AddRenderModeOverlayControls(class Asura_Overlay* pxOverlay,Asura_Vector_2& xOffset)
{

	static const char* s_apszRenderMode[] =
	{
		"None",
		"Coll Mesh (Solid)",
		"Coll Mesh (Trans)",
	};

	static const char* s_apszRenderModeHelp[] =
	{
		"Collision meshes not rendered",
		"Renders the module collision meshes as solid objects",
		"Renders the module collision meshes as translucent objects",
	};


	Asura_Dialog* pxDialog = new Asura_Dialog("Coll Mesh Rendering :",xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	Asura_DropDown_List_Dialog* pxListDialog;
	pxListDialog = new Asura_DropDown_List_Dialog(xOffset,s_apszRenderMode,&s_iRenderMode,3,3,NULL,&s_bFlagsChanged);
	pxListDialog->SetListHelpStrings(s_apszRenderModeHelp);
	pxOverlay->AddDialog(pxListDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog("Z Penetration",xOffset,&s_fZPenetration,0.0f,10000,1.0f,"%.1f");
	pxDialog->SetHelpText("Distance that should be rendered through polygons when using translucent rendering mode.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();


	pxDialog = new Asura_FlagTickbox_Dialog("Visible",xOffset,&s_iFlagsNotToShow,AsuraPolygonFlag_DontRender,&s_bFlagsChanged);
	pxDialog->SetHelpText("Only draw collision mesh polygons that are visible");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_FlagTickbox_Dialog("Collidable",xOffset,&s_iFlagsNotToShow,AsuraPolygonFlag_NoCollisions,&s_bFlagsChanged);
	pxDialog->SetHelpText("Only draw collision mesh polygons that are collidable");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_FlagTickbox_Dialog("Used by LOS",xOffset,&s_iFlagsNotToShow,AsuraPolygonFlag_IgnoreLOS,&s_bFlagsChanged);
	pxDialog->SetHelpText("Only draw collision mesh polygons that are used by LOS tests");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

}

void Tools_RenderCollisionMesh_System::SetRenderMode(Tools_CollRenderMode eMode)
{
	s_iRenderMode = eMode;
	if(eMode == TOOLS_COLLRENDER_NONE)
	{
		Tools_Render_Options::SetMaskedPolygonFlagsToHide(0,g_iPOLYGON_FLAGS_USED);
	}
	else
	{
		Tools_Render_Options::SetMaskedPolygonFlagsToHide(s_iFlagsNotToShow,g_iPOLYGON_FLAGS_USED);
	}

}

void Tools_RenderCollisionMesh_System::NextRenderMode()
{
	SetRenderMode((Tools_CollRenderMode)((s_iRenderMode+1)%3));
}

bool Tools_RenderCollisionMesh_System::IsRenderingCollMeshes()
{
	#ifdef ASURA_USE_STREAMING
	//collision mesh rendering only setup for main level. RAR 06/04/2006
	if(!Tools_Streaming_System::IsSetToMainZone()) return false;
	#endif

	return s_iRenderMode != TOOLS_COLLRENDER_NONE;
}
