//*******************************************************************
//
// File: Asura_Direct3D_Botanicals_Game_Render_Manager_SM11.h
//
// Created: 20 Oct 2006
//
// Description: 
//
//*******************************************************************

template< class Tgeometry, class TgeometryCache, class TgeometryInstanceCache, class TptrDrawTreeInstances>
void Asura_Direct3D_BGR_Manager::DrawCacheSM30_DrawGeometryCache( const Asura_Direct3D_BGR_Type& xTreeDescription, const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, const u_int uIndexGeometry, TgeometryCache& xCacheGeometrys, ptrDrawTreeRenderStates pfnRenderStates, TptrDrawTreeInstances pfnDraw, const void* pxDataPointer)
{
	TgeometryInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexGeometry];
	uint32 uCountInstances = xCacheGeometryInstances.Size();
	
	if( 0 == uCountInstances)
	{
		return;
	}

	SCOPEDPIXEVENT((0xff00ff00, L"Botanical DrawGeometry Cache"));

	Asura_Direct3D_Effect* pxD3DEffect = NULL;
	const Tgeometry &tGeometry = xArrayGeometry[ uIndexGeometry];
	if( false == (this->*(pfnRenderStates))( xTreeDescription, tGeometry, pxDataPointer, pxD3DEffect))
	{
		return;
	}

	(this->*(pfnDraw))( xTreeDescription, tGeometry, xCacheGeometryInstances, pxDataPointer, pxD3DEffect);
}

template< class Tgeometry, class TptrDrawTreeInstances>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_DrawGeometryCache( const Asura_Direct3D_BGR_Type& xTreeDescription, const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, const u_int uIndexGeometry, Asura_Direct3D_BGR_GeometryVertexCache& xCacheGeometrys, ptrDrawTreeRenderStates pfnRenderStates, TptrDrawTreeInstances pfnDraw, const void* pxDataPointer)
{
	this->DrawCacheSM30_DrawGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryVertexCache, Asura_Direct3D_BGR_GeometryVertexInstanceCache, TptrDrawTreeInstances>( xTreeDescription, xArrayGeometry, uIndexGeometry, xCacheGeometrys, pfnRenderStates, pfnDraw, pxDataPointer);
}

template< class Tgeometry, class TptrDrawTreeInstances>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_DrawGeometryCache( const Asura_Direct3D_BGR_Type& xTreeDescription, const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, const u_int uIndexGeometry, Asura_Direct3D_BGR_GeometryIndexCache& xCacheGeometrys, ptrDrawTreeRenderStates pfnRenderStates, TptrDrawTreeInstances pfnDraw, const void* pxDataPointer)
{
	this->DrawCacheSM30_DrawGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryIndexCache, Asura_Direct3D_BGR_GeometryIndexInstanceCache, TptrDrawTreeInstances>( xTreeDescription, xArrayGeometry, uIndexGeometry, xCacheGeometrys, pfnRenderStates, pfnDraw, pxDataPointer);
}

template< const bool bUseSections>
void Asura_Direct3D_BGR_Manager::DrawCacheSM30_FillGeometryCache( const Asura_Botanical_Array< Asura_Direct3D_BGR_Type_GeometryBillboard>& xArrayGeometry, const Asura_BGR_Section_ID xGeometrySection, const Asura_BGR_Version_ID xGeometrySectionVersion, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryIndexCache& xCacheGeometrys)
{
	// DLH - Fill Each LOD with new constants
	const uint32 uCountInstances = xCacheInstances.Size();
//	const uint32 uCountGeometrys = xArrayGeometry.Size();
	for( uint32 uIndexInstance = 0; uIndexInstance < uCountInstances; uIndexInstance += 1)
	{
		const Asura_Direct3D_BGR_InstanceCache &xCacheInstance = xCacheInstances[ uIndexInstance];
				
		//const uint32 indexLOD = 0;
//		if( 1.0f < xCacheInstance.m_fDistance)
//		{
//			continue;
//		}
		
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
		if( true == bUseSections)
		{
			const Asura_BGR_Version_ID* pxInstanceSectionVersions0 = xCacheInstance.m_pxSectionVersions;
			const Asura_BGR_Version_ID xInstanceSectionVersion = pxInstanceSectionVersions0[ xGeometrySection];
			if( xInstanceSectionVersion != xGeometrySectionVersion)
			{
				continue;
			}
		}
#endif
		
		const uint32 uInstanceHeaderInstanceIndex = xCacheInstance.m_uInstanceHeaderInstanceIndex;
		const Asura_Direct3D_BGR_Instances_Header* pxInstanceHeader = xCacheInstance.m_pxInstanceHeader;
		
		uint32 uIndexLOD = 0;
		
		{
			const Asura_Direct3D_BGR_Type_GeometryBillboard &tGeometry = xArrayGeometry[ uIndexLOD];

			const float fDistance = xCacheInstance.m_fDistance;
			if( fDistance < 1.0f && false == tGeometry.m_xLodRange.IsInRange( fDistance))
			{
				continue;
			}

			Asura_Direct3D_BGR_GeometryIndexInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexLOD];
			
			if( false == xCacheGeometryInstances.IsLocked())
			{
				continue;
			}
			
			const uint32 uVertexIndex0 = pxInstanceHeader->m_uImposterVBStart + (4 * uInstanceHeaderInstanceIndex);
			
			const uint32 uIndexIndex0 = xCacheGeometryInstances.Size() + xCacheGeometryInstances.GetIndexBufferOffset();
			
			uint16& usVertexIndex0 = xCacheGeometryInstances.GetNext();
			uint16& usVertexIndex1 = xCacheGeometryInstances.GetNext();
			uint16& usVertexIndex2 = xCacheGeometryInstances.GetNext();
			uint16& usVertexIndex3 = xCacheGeometryInstances.GetNext();
			uint16& usVertexIndex4 = xCacheGeometryInstances.GetNext();
			uint16& usVertexIndex5 = xCacheGeometryInstances.GetNext();

			usVertexIndex0 = static_cast< uint16 >( uVertexIndex0 + 2);
			usVertexIndex1 = static_cast< uint16 >( uVertexIndex0 + 1);
			usVertexIndex2 = static_cast< uint16 >( uVertexIndex0 + 0);
			usVertexIndex3 = static_cast< uint16 >( uVertexIndex0 + 1);
			usVertexIndex4 = static_cast< uint16 >( uVertexIndex0 + 2);
			usVertexIndex5 = static_cast< uint16 >( uVertexIndex0 + 3);
			
			Asura_DIPCache_DIPData xDIPData;
			
			xDIPData.Set(
				uIndexIndex0, uIndexIndex0 + 6,
				pxInstanceHeader->m_uImposterVBStart, pxInstanceHeader->m_uImposterVBStart + pxInstanceHeader->m_uImposterVBSize,
				pxInstanceHeader->m_uImposterVBOffset
			);
			
			xCacheGeometryInstances.m_xDIPCache.AddDIP( xDIPData);
		}
	}
}

template< class Tgeometry, class TgeometryCache, class TgeometryInstanceCache, const bool bUseSections>
void Asura_Direct3D_BGR_Manager::DrawCacheSM30_FillGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, const Asura_BGR_Section_ID xGeometrySection, const Asura_BGR_Version_ID xGeometrySectionVersion, Asura_Direct3D_BGR_Cache& xCacheInstances, TgeometryCache& xCacheGeometrys)
{
	// DLH - Fill Each LOD with new constants
	const uint32 uCountInstances = xCacheInstances.Size();
	const uint32 uCountGeometrys = xArrayGeometry.Size();
	for( uint32 uIndexInstance = 0; uIndexInstance < uCountInstances; uIndexInstance += 1)
	{
		const Asura_Direct3D_BGR_InstanceCache &xCacheInstance = xCacheInstances[ uIndexInstance];
		//const uint32 indexLOD = 0;
		if( 1.0f < xCacheInstance.m_fDistance)
		{
			continue;
		}
		
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
		if( true == bUseSections)
		{
			const Asura_BGR_Version_ID* pxInstanceSectionVersions0 = xCacheInstance.m_pxSectionVersions;
			const Asura_BGR_Version_ID xInstanceSectionVersion = pxInstanceSectionVersions0[ xGeometrySection];
			if( xInstanceSectionVersion != xGeometrySectionVersion)
			{
				continue;
			}
		}
#endif
		
		for( uint32 uIndexLOD = 0; uIndexLOD < uCountGeometrys; uIndexLOD += 1)
		{
			const Tgeometry &tGeometry = xArrayGeometry[ uIndexLOD];

			if( 0 == tGeometry.m_uPrimitiveCount)
			{
				continue;
			}
			
			if( false == tGeometry.m_xLodRange.IsInRange( xCacheInstance.m_fDistance))
			{
				continue;
			}

			TgeometryInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexLOD];
			
			if( false == xCacheGeometryInstances.IsLocked())
			{
				continue;
			}
			Asura_Direct3D_BGR_Type_VertexInstanceSM30 &xCacheConstants = xCacheGeometryInstances.GetNext();
			
			xCacheConstants = xCacheInstance.m_xInstanceVertex;
			
			const float fAlphaCutValue = tGeometry.m_fAlphaCutValue;
			const float fAlphaCutScale = 1.0f - fAlphaCutValue;
			const float fAlpha = fAlphaCutValue + (fAlphaCutScale * (1 - tGeometry.m_xLodRange.CalcStrength( xCacheInstance.m_fDistance)));

			xCacheConstants.m_fAlphaCut = fAlpha;
		}
	}
}

template< class Tgeometry, const bool bUseSections>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_FillGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, const Asura_BGR_Section_ID xGeometrySection, const Asura_BGR_Version_ID xGeometrySectionVersion, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryVertexCache& xCacheGeometrys)
{
	this->DrawCacheSM30_FillGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryVertexCache, Asura_Direct3D_BGR_GeometryVertexInstanceCache, bUseSections>( xArrayGeometry, xGeometrySection, xGeometrySectionVersion, xCacheInstances, xCacheGeometrys);
}

template< class Tgeometry, const bool bUseSections>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_FillGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, const Asura_BGR_Section_ID xGeometrySection, const Asura_BGR_Version_ID xGeometrySectionVersion, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryIndexCache& xCacheGeometrys)
{
	this->DrawCacheSM30_FillGeometryCache< bUseSections>( xArrayGeometry, xGeometrySection, xGeometrySectionVersion, xCacheInstances, xCacheGeometrys);
}

template< class Tgeometry, class TgeometryCache, class TgeometryInstanceCache>
void Asura_Direct3D_BGR_Manager::DrawCacheSM30_ClearGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, TgeometryCache& xCacheGeometrys)
{
	if( xCacheGeometrys.Size() < xArrayGeometry.Size())
	{
		xCacheGeometrys.SetSize( xArrayGeometry.Size());
	}
	
	{
		const uint32 uCountInstances = xCacheInstances.Capacity();
		const uint32 uCountGeometrys = xCacheGeometrys.Capacity();
		
		for( uint32 uIndexGeometry = 0; uIndexGeometry < uCountGeometrys; uIndexGeometry += 1)
		{
			TgeometryInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexGeometry];
			
			if( xCacheGeometryInstances.Capacity() < uCountInstances)
			{
				xCacheGeometryInstances.SetCapacity( uCountInstances);
			}
			
			xCacheGeometryInstances.Clear();
		}
	}
}

template< class Tgeometry>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_ClearGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryVertexCache& xCacheGeometrys)
{
	this->DrawCacheSM30_ClearGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryVertexCache, Asura_Direct3D_BGR_GeometryVertexInstanceCache>( xArrayGeometry, xCacheInstances, xCacheGeometrys);
}

template< class Tgeometry>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_ClearGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryIndexCache& xCacheGeometrys)
{
	if( xCacheGeometrys.Size() < xArrayGeometry.Size())
	{
		xCacheGeometrys.SetSize( xArrayGeometry.Size());
	}
	
	{
		const uint32 uCountInstances = 6 * xCacheInstances.Capacity();
		const uint32 uCountGeometrys = xCacheGeometrys.Capacity();
		
		for( uint32 uIndexGeometry = 0; uIndexGeometry < uCountGeometrys; uIndexGeometry += 1)
		{
			Asura_Direct3D_BGR_GeometryIndexInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexGeometry];
			
			if( xCacheGeometryInstances.Capacity() < uCountInstances)
			{
				xCacheGeometryInstances.SetCapacity( uCountInstances);
			}
			
			xCacheGeometryInstances.Clear();
		}
	}
}

template< class Tgeometry, class TgeometryCache, class TgeometryInstanceCache>
bool Asura_Direct3D_BGR_Manager::DrawCacheSM30_LockGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, TgeometryCache& xCacheGeometrys)
{
	const uint32 uCountGeometrys = xArrayGeometry.Size();
	
	for( uint32 uIndexGeometry = 0; uIndexGeometry < uCountGeometrys; uIndexGeometry += 1)
	{
		TgeometryInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexGeometry];
		
		if( false == xCacheGeometryInstances.Lock())
		{
			return( false);
		}
	}
	
	return( true);
}

template< class Tgeometry>
inline bool Asura_Direct3D_BGR_Manager::DrawCacheSM30_LockGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryVertexCache& xCacheGeometrys)
{
	return( this->DrawCacheSM30_LockGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryVertexCache, Asura_Direct3D_BGR_GeometryVertexInstanceCache>( xArrayGeometry, xCacheInstances, xCacheGeometrys));
}

template< class Tgeometry>
inline bool Asura_Direct3D_BGR_Manager::DrawCacheSM30_LockGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryIndexCache& xCacheGeometrys)
{
	return( this->DrawCacheSM30_LockGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryIndexCache, Asura_Direct3D_BGR_GeometryIndexInstanceCache>( xArrayGeometry, xCacheInstances, xCacheGeometrys));
}

template< class Tgeometry, class TgeometryCache, class TgeometryInstanceCache>
void Asura_Direct3D_BGR_Manager::DrawCacheSM30_UnlockGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, TgeometryCache& xCacheGeometrys)
{
	const uint32 uCountGeometrys = xArrayGeometry.Size();
	
	for( uint32 uIndexGeometry = 0; uIndexGeometry < uCountGeometrys; uIndexGeometry += 1)
	{
		TgeometryInstanceCache &xCacheGeometryInstances = xCacheGeometrys[ uIndexGeometry];
		
		if( false == xCacheGeometryInstances.IsLocked())
		{
			continue;
		}
		
		xCacheGeometryInstances.Unlock();
	}
}

template< class Tgeometry>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_UnlockGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryVertexCache& xCacheGeometrys)
{
	this->DrawCacheSM30_UnlockGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryVertexCache, Asura_Direct3D_BGR_GeometryVertexInstanceCache>( xArrayGeometry, xCacheInstances, xCacheGeometrys);
}

template< class Tgeometry>
inline void Asura_Direct3D_BGR_Manager::DrawCacheSM30_UnlockGeometryCache( const Asura_Botanical_Array< Tgeometry>& xArrayGeometry, Asura_Direct3D_BGR_Cache& xCacheInstances, Asura_Direct3D_BGR_GeometryIndexCache& xCacheGeometrys)
{
	this->DrawCacheSM30_UnlockGeometryCache< Tgeometry, Asura_Direct3D_BGR_GeometryIndexCache, Asura_Direct3D_BGR_GeometryIndexInstanceCache>( xArrayGeometry, xCacheInstances, xCacheGeometrys);
}

template< class Tgeometry, class TgeometryCache, class TptrDrawTreeInstances, const bool bUsePhotonSources, const bool bUseSections>
void Asura_Direct3D_BGR_Manager::DrawCacheSM30( const Asura_Direct3D_BGR_Type& xTreeDescription, const Asura_Botanical_Array< Tgeometry> &xArrayGeometry, const Asura_BGR_Section_ID xGeometrySection, const Asura_BGR_Version_ID xGeometrySectionVersion, Asura_Direct3D_BGR_RenderCache& xRenderCache, ptrDrawTreeRenderStates pfnRenderStates, TptrDrawTreeInstances pfnDraw)
{
	if( xArrayGeometry.Size() == 0)
	{
		return;
	}

	SCOPEDPIXEVENT((0xff00ff00, L"Botanical DrawCache Instances Type"));
	
	{
		bool bDataLocked = false;

		// DLH - Cache all the different LOD levels that need to be drawn
		TgeometryCache* ptGeometryCache;
		xRenderCache.GetCacheGeometrys( ptGeometryCache);
		
		this->DrawCacheSM30_ClearGeometryCache( xArrayGeometry, xRenderCache.m_xCacheInstances, *ptGeometryCache);
		if( true == this->DrawCacheSM30_LockGeometryCache( xArrayGeometry, xRenderCache.m_xCacheInstances, *ptGeometryCache))
		{
			bDataLocked = true;
			this->DrawCacheSM30_FillGeometryCache< Tgeometry, bUseSections>( xArrayGeometry, xGeometrySection, xGeometrySectionVersion, xRenderCache.m_xCacheInstances, *ptGeometryCache);
		}
		this->DrawCacheSM30_UnlockGeometryCache( xArrayGeometry, xRenderCache.m_xCacheInstances, *ptGeometryCache);
		
		if( false == bDataLocked)
		{
			return;
		}
	}
	
	if( true == bUsePhotonSources)
	{
		Asura_Botanical_Array< Asura_Direct3D_BGR_DynamicLightCache>& xArray_xDynamicLightCache = xRenderCache.m_xArray_xDynamicLightCache;
		const u_int uDynamicLightCacheCount = xArray_xDynamicLightCache.Size();
		for( u_int uDynamicLightCacheIndex = 0; uDynamicLightCacheIndex < uDynamicLightCacheCount; uDynamicLightCacheIndex += 1)
		{
			Asura_Direct3D_BGR_DynamicLightCache& xDynamicLightCache = xArray_xDynamicLightCache[ uDynamicLightCacheIndex];
			const Asura_Photon* pxPhoton = xDynamicLightCache.m_pxPhoton;

			if( NULL == pxPhoton)
			{
				// DLH - 30 June 2006 14:39:56 - Photons should be stored in a linear maner, so there should not be any more
				break;
			}
			
			bool bDataLocked = false;

			TgeometryCache* ptDynamicGeometryCache;
			xDynamicLightCache.GetCacheGeometrys( ptDynamicGeometryCache);
			
			this->DrawCacheSM30_ClearGeometryCache( xArrayGeometry, xDynamicLightCache.m_xCacheInstances, *ptDynamicGeometryCache);
			if( true == this->DrawCacheSM30_LockGeometryCache( xArrayGeometry, xDynamicLightCache.m_xCacheInstances, *ptDynamicGeometryCache))
			{
				bDataLocked = true;
				this->DrawCacheSM30_FillGeometryCache< Tgeometry, bUseSections>( xArrayGeometry, xGeometrySection, xGeometrySectionVersion, xDynamicLightCache.m_xCacheInstances, *ptDynamicGeometryCache);
			}
			this->DrawCacheSM30_UnlockGeometryCache( xArrayGeometry, xDynamicLightCache.m_xCacheInstances, *ptDynamicGeometryCache);
		
			if( false == bDataLocked)
			{
				return;
			}
		}
	}
	
	{
		// DLH - Must use the xArrayGeometry as the static and dynamic arrays can have different sizes due to being setup as and when they are needed
		const uint32 uCountGeometrys = xArrayGeometry.Size();

		// DLH - Draw Each LOD level in turn. For each LOD: Opaque part first the add each Dynhamic Light, Then Next LOD Opaque parts
		for( uint32 uIndexGeometry = 0; uIndexGeometry < uCountGeometrys; uIndexGeometry += 1)
		{
			TgeometryCache* ptGeometryCache;
			xRenderCache.GetCacheGeometrys( ptGeometryCache);
			
			this->DrawCacheSM30_DrawGeometryCache( xTreeDescription, xArrayGeometry, uIndexGeometry, *ptGeometryCache, pfnRenderStates, pfnDraw, NULL);
			if( true == bUsePhotonSources)
			{
				Asura_Botanical_Array< Asura_Direct3D_BGR_DynamicLightCache>& xArray_xDynamicLightCache = xRenderCache.m_xArray_xDynamicLightCache;
				const u_int uDynamicLightCacheCount = xArray_xDynamicLightCache.Size();
				for( u_int uDynamicLightCacheIndex = 0; uDynamicLightCacheIndex < uDynamicLightCacheCount; uDynamicLightCacheIndex += 1)
				{
					Asura_Direct3D_BGR_DynamicLightCache& xDynamicLightCache = xArray_xDynamicLightCache[ uDynamicLightCacheIndex];
					const Asura_Photon* pxPhoton = xDynamicLightCache.m_pxPhoton;

					if( NULL == pxPhoton)
					{
						// DLH - 30 June 2006 14:39:56 - Photons should be stored in a linear maner, so there should not be any more
						break;
					}
		
					const void* pxDataPointer = reinterpret_cast< const void*>( pxPhoton);
					
					TgeometryCache* ptDynamicGeometryCache;
					xDynamicLightCache.GetCacheGeometrys( ptDynamicGeometryCache);
			
					Asura_Assert( ptGeometryCache->Size() == ptDynamicGeometryCache->Size(), "Static and Dynamic Geomerty LOD caching has a different size!");			
					this->DrawCacheSM30_DrawGeometryCache( xTreeDescription, xArrayGeometry, uIndexGeometry, *ptDynamicGeometryCache, pfnRenderStates, pfnDraw, pxDataPointer);
				}
			}
		}
	}
}

template< const bool bUsePhotonSources> void Asura_Direct3D_BGR_Manager::DrawCache( const Asura_Direct3D_BGR_Type* pxTreeDescription, Asura_Direct3D_BGR_RenderCache &xRenderCache)
{
	SCOPEDPIXEVENT((0xff00ff00, L"Botanical DrawCache Instances"));
	
	const u_int uSectionCount = pxTreeDescription->m_xArray_xSections.Size();
	for( u_int uSectionIndex = 0; uSectionIndex < uSectionCount; uSectionIndex += 1)
	{
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
		const Asura_Botanical_Array< bool>& xArrayVersion_bUsed = xRenderCache.m_xArraySection_xArrayVersion_bUsed[ uSectionIndex];
		Asura_BGR_Section_ID xSectionID = static_cast< Asura_BGR_Section_ID>( uSectionIndex);
#endif
		const Asura_Direct3D_BGR_Section& xSection = pxTreeDescription->m_xArray_xSections[ uSectionIndex];
		
		const u_int uSectionVersionCount = xSection.m_xArray_xVersions.Size();
		for( u_int uSectionVersionIndex = 0; uSectionVersionIndex < uSectionVersionCount; uSectionVersionIndex += 1)
		{
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
			bool bVersionUsed = xArrayVersion_bUsed[ uSectionVersionIndex];
			if( false == bVersionUsed)
			{
				continue;
			}
			
			Asura_BGR_Version_ID xSectionVersionID = xSection.m_xArray_uVersionIndexToVersionID[ uSectionVersionIndex];
#endif
			const Asura_Direct3D_BGR_Section_Version& xSectionVersion = xSection.m_xArray_xVersions[ uSectionVersionIndex];
			const Asura_Direct3D_BGR_Geometry& xGeometry = xSectionVersion.m_xGeometry;
	
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
			#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_Geometry3D, Asura_Direct3D_BGR_GeometryVertexCache, ptrDrawTreeVertexInstances, bUsePhotonSources, true>( *pxTreeDescription, xGeometry.m_xArrayBranchs, xSectionID, xSectionVersionID, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D1SidedRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D1SidedInstances);
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_Geometry3D, Asura_Direct3D_BGR_GeometryVertexCache, ptrDrawTreeVertexInstances, bUsePhotonSources, true>( *pxTreeDescription, xGeometry.m_xArrayFronds, xSectionID, xSectionVersionID, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D2SidedRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D2SidedInstances);
			#endif
			
			#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_GeometryLeaves, Asura_Direct3D_BGR_GeometryVertexCache, ptrDrawTreeVertexInstances, bUsePhotonSources, true>( *pxTreeDescription, xGeometry.m_xArrayLeaves, xSectionID, xSectionVersionID, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_LeafRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_LeafInstances);
			#endif
			
			#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS_SECTION_VERSIONS)
			if( true == pxTreeDescription->GetDynamicDataLayout().HasDynamicSectionVersionData())
			{
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_GeometryBillboard, Asura_Direct3D_BGR_GeometryIndexCache, ptrDrawTreeIndexInstances, bUsePhotonSources, true>( *pxTreeDescription, xGeometry.m_xArrayBillboards, xSectionID, xSectionVersionID, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_ImposterRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_ImposterInstances);
			}
			#endif
#else
			#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_Geometry3D, Asura_Direct3D_BGR_GeometryVertexCache, ptrDrawTreeVertexInstances, bUsePhotonSources, false>( *pxTreeDescription, xGeometry.m_xArrayBranchs, 0, 0, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D1SidedRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D1SidedInstances);
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_Geometry3D, Asura_Direct3D_BGR_GeometryVertexCache, ptrDrawTreeVertexInstances, bUsePhotonSources, false>( *pxTreeDescription, xGeometry.m_xArrayFronds, 0, 0, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D2SidedRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_3D2SidedInstances);
			#endif
			
			#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
				this->DrawCacheSM30< Asura_Direct3D_BGR_Type_GeometryLeaves, Asura_Direct3D_BGR_GeometryVertexCache, ptrDrawTreeVertexInstances, bUsePhotonSources, false>( *pxTreeDescription, xGeometry.m_xArrayLeaves, 0, 0, xRenderCache, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_LeafRenderStates, &Asura_Direct3D_BGR_Manager::DrawTree_SM30_LeafInstances);
			#endif
#endif
		}
	}
}


//*******************************************************************
//
// (c) 2006 Rebellion (Derby)
//
// Warning: This computer program is protected by copyright law and 
// international treaties. Unauthorized reproduction or distribution
// of this program, or any portion of it, may result in severe civil and
// criminal penalties, and will be prosecuted to the maximum extent 
// possible under the law.
//
//*******************************************************************
