//*******************************************************************
//
// File: Asura_Chunk_ResourceFile_PC_Botanical.cpp
//
// Created: 19 Apr 2006
//
// Description: 
//
//*******************************************************************

// system libraries
#include "Core/Asura.h"

#if defined( ASURA_USE_BOTANICALS)

// main header
#include "ChunkSystem/Asura_Chunk_ResourceFile_PC_Botanical.h"
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render.h"

// other libraries
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render.h"

// internal dependencies
#include "ChunkSystem/Asura_SaveBlock.h"
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "ChunkSystem/Asura_Chunk_Loaders.h"

#include "ChunkSystem/Asura_Chunk_ResourceFile_PC.h"
#include "ChunkSystem/Asura_Chunk_Stream_WindowsFile.h"

#include "Botanical/Asura_Direct3D_Botanicals_Game_Render_Manager.h"

#include "Core/Asura_Hash.h"
#include "Core/Asura_Texturemanagement.h"


//*******************************************************************
// Constants
//*******************************************************************


//*******************************************************************
// Local Classes
//*******************************************************************


//*******************************************************************
// Function Definitions
//*******************************************************************

#if defined( ASURA_TOOLS)

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
bool Asura_Direct3D_BGR_Type_VertexGeometry3DStorage::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << this->m_xPosition;
	xStream << this->m_xNormal;
	xStream << static_cast< uint32>( this->m_uColour);
	xStream << static_cast< float>( this->m_afTextcoord0[ 0]);
	xStream << static_cast< float>( this->m_afTextcoord0[ 1]);
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_SM30) && 1 == ASURA_DIRECT3D_BGR_SUPPORT_SM30
	xStream << m_afTextcoord1[ 0];
	xStream << m_afTextcoord1[ 1];
	xStream << m_xBinormal;
	xStream << m_xTangent;
	xStream << m_fBoneWeight0;
#endif

	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
bool Asura_Direct3D_BGR_Type_VertexGeometryLeafStorage::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << this->m_xPosition;
	xStream << static_cast< float>( this->m_afCorner[ 0]);
	xStream << static_cast< float>( this->m_afCorner[ 1]);
	xStream << static_cast< uint32>( this->m_uColour);
	xStream << static_cast< float>( this->m_afTextcoord0[ 0]);
	xStream << static_cast< float>( this->m_afTextcoord0[ 1]);
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_SM30) && 1 == ASURA_DIRECT3D_BGR_SUPPORT_SM30
	xStream << m_afTextcoord1[ 0];	// DLH - Texture coord of the corner
	xStream << m_afTextcoord1[ 1];	// DLH - Texture coord of the corner
	xStream << m_xNormal;
	xStream << m_xBinormal;
	xStream << m_xTangent;
	xStream << m_fBoneWeight0;		// DLH - How strong the is the bone influance
#endif

	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
bool Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << this->m_xDirection;
	xStream << static_cast< float>( this->m_fFieldOfViewDotOutter);
	xStream << static_cast< float>( this->m_fFieldOfViewAngleOutter);
	xStream << static_cast< float>( this->m_fFieldOfViewAngleInner);
	
	xStream << static_cast< float>( this->m_fWidth);
	xStream << static_cast< float>( this->m_fHeight);
	
	xStream << static_cast< float>( this->m_afTextcoord0[ 0]);
	xStream << static_cast< float>( this->m_afTextcoord0[ 1]);
	
	xStream << static_cast< float>( this->m_afTextcoord1[ 0]);
	xStream << static_cast< float>( this->m_afTextcoord1[ 1]);
	
#if defined( ASURA_USE_MATERIAL_RESPONSE_SYSTEM )
	xStream << static_cast< uint32>( this->m_uMaterialResponseHashID);
#else
	Asura_Hash_ID xDiffuseTextureHash = Asura_Texture_Management::GetHashIDFromIndex( this->m_iTextureDiffuse);
	Asura_Hash_ID xBumpTextureHash = Asura_Texture_Management::GetHashIDFromIndex( this->m_iTextureBump);

	xStream << xDiffuseTextureHash;
	xStream << xBumpTextureHash;
#endif
	
	return( true);
}
#endif

bool Asura_Direct3D_BGR_Type_GeometryLODRange::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << static_cast< float>( this->m_afDelta[ LOW_0]);
	xStream << static_cast< float>( this->m_afDelta[ LOW_1]);
	xStream << static_cast< float>( this->m_afDelta[ LOW_SCALE]);
	xStream << static_cast< float>( this->m_afDelta[ HIGH_1]);
	xStream << static_cast< float>( this->m_afDelta[ HIGH_0]);
	xStream << static_cast< float>( this->m_afDelta[ HIGH_SCALE]);
	return( true);
}

bool Asura_Direct3D_BGR_Type_Geometry::ExportIndices( Asura_Chunk_Stream& xStream, const Asura_Botanical_Array< uint32>& xArrayIndices) const
{
	const uint32 uArraySize = xArrayIndices.Size();
	xStream << static_cast< uint32>( uArraySize);
	for( uint32 uArrayIndex = 0; uArrayIndex < uArraySize; uArrayIndex += 1)
	{
		const uint32 uIndex = xArrayIndices[ uArrayIndex];
		
		xStream << uIndex;
	}
	
	return( true);
}

Asura_Chunk_Stream& operator << ( Asura_Chunk_Stream& xStream, const Asura_Direct3D_BGR_Material& xMaterial)
{
#if defined( ASURA_USE_MATERIAL_RESPONSE_SYSTEM )
	xStream << static_cast< uint32>( xMaterial.m_xMaterialResponseHashID);
#else
	xStream << Asura_Texture_Management::GetHashIDFromIndex( xMaterial.m_iDiffuseTexture0);
	xStream << Asura_Texture_Management::GetHashIDFromIndex( xMaterial.m_iDiffuseTexture1);
	xStream << xMaterial.m_bDiffuseDualPassTexture;
	
	xStream << Asura_Texture_Management::GetHashIDFromIndex( xMaterial.m_iSpecularTexture0);
	xStream << Asura_Texture_Management::GetHashIDFromIndex( xMaterial.m_iSpecularTexture1);
	xStream << xMaterial.m_bSpecularDualPassTexture;
	
	xStream << xMaterial.m_bHasNormalMaps;
	xStream << Asura_Texture_Management::GetHashIDFromIndex( xMaterial.m_iNormalTexture0);
	xStream << Asura_Texture_Management::GetHashIDFromIndex( xMaterial.m_iNormalTexture1);
	xStream << xMaterial.m_bNormalDualPassTexture;
	
	xStream << xMaterial.m_bParallaxMap;
	xStream << xMaterial.m_bSelfIlluminating;
	xStream << xMaterial.m_bSpecular;
	xStream << xMaterial.m_bOutputAlphaOfTexture;
#endif
	
	return( xStream);
}

bool Asura_Direct3D_BGR_Type_Geometry::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->m_xLodRange.Export( xStream))
	{
		return( false);
	}
	
	xStream << static_cast< float>( this->m_fAlphaCutValue);
	
	xStream << this->xMaterial;
	
	return( true);
}

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
bool Asura_Direct3D_BGR_Type_Geometry3D::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->Asura_Direct3D_BGR_Type_Geometry::Export( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayVertices.Export( xStream))
	{
		return( false);
	}
	
	if( false == this->ExportIndices( xStream, this->m_xArrayIndices))
	{
		return( false);
	}
	
	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
bool Asura_Direct3D_BGR_Type_GeometryLeaves::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->Asura_Direct3D_BGR_Type_Geometry::Export( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayVertices.Export( xStream))
	{
		return( false);
	}
	
	if( false == this->ExportIndices( xStream, this->m_xArrayIndices))
	{
		return( false);
	}
	
	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
bool Asura_Direct3D_BGR_Type_GeometryBillboard::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->Asura_Direct3D_BGR_Type_Geometry::Export( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayBillboards.Export( xStream))
	{
		return( false);
	}
	
	return( true);
}
#endif

bool Asura_Direct3D_BGR_Geometry::Export( Asura_Chunk_Stream& xStream) const
{
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
	if( false == this->m_xArrayBranchs.Export( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayFronds.Export( xStream))
	{
		return( false);
	}
#endif
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
	if( false == this->m_xArrayLeaves.Export( xStream))
	{
		return( false);
	}
#endif
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
	if( false == this->m_xArrayBillboards.Export( xStream))
	{
		return( false);
	}
#endif

	return( true);
}

bool Asura_Direct3D_BGR_Section_Version::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->m_xGeometry.Export( xStream))
	{
		return( false);
	}
	return( true);
}

bool Asura_Direct3D_BGR_Section::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << this->m_xArray_uVersionIDToVersionIndex;
	xStream << this->m_xArray_uVersionIndexToVersionID;
	
	if( false == this->m_xArray_xVersions.Export( xStream))
	{
		return( false);
	}
	
	return( true);
}

template< class Tclass>
Asura_Chunk_Stream& operator<< ( Asura_Chunk_Stream& xStream, const Asura_TemplateHashTree< Tclass>& tHashTree)
{
	const uint32 uNodeCount = tHashTree.GetNumberOfNodes();
	
	xStream << uNodeCount;
	
	for( uint32 uNodeIndex = 0; uNodeIndex < uNodeCount; uNodeIndex += 1)
	{
		const Asura_Hash_ID xHashID = tHashTree.GetHashByIndex( uNodeIndex);
		
		xStream << xHashID;

		const Tclass* pxData = tHashTree.GetDataByIndex( uNodeIndex);
		Asura_Assert( NULL != pxData, "NULL data pointer");
		
		xStream << (*pxData);
	}
	
	return( xStream);
}

bool Asura_Direct3D_BGR_Type::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->m_xTypeID.Export( xStream))
	{
		return( false);
	}
	
	if( false == this->Asura_BGR_Type::Export( xStream))
	{
		return( false);
	}
	
	xStream << static_cast< bool> ( this->m_bHasImposters);
	
	xStream << static_cast< float> ( this->m_fLodLimitNear);
	xStream << static_cast< float> ( this->m_fLodLimitFar);
	xStream << static_cast< float> ( this->m_fLodLimitDelta);
	xStream << static_cast< float> ( this->m_fLodLimitDeltaImposterNear);
	xStream << static_cast< float> ( this->m_fLodAuthoredFOVWidth);
	xStream << static_cast< float> ( this->m_fLodAuthoredRes);

	xStream << static_cast< uint32> ( this->m_uInstanceMaxCount);
	
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
	xStream << this->m_xHashTree_xSectionID;
	xStream << this->m_xHashTree_xVersionID;
#endif
	
	if( false == this->m_xArray_xSections.Export( xStream))
	{
		return( false);
	}
	
	return( true);
}

bool Asura_BGR_TypeID::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << static_cast< uint32> ( this->m_uID);
	return( true);
}

bool Asura_BGR_Instance::Export( Asura_Chunk_Stream& xStream) const
{
	#if !defined( ASURA_DIRECT3D_BGR_INSTANCE_ENABLE_COMPRESSED_DATA)
		#error Asura_Direct3D_BGR_Instance::Export
		return( false);
	#else
	
		xStream << this->m_afPosition[0];
		xStream << this->m_afPosition[1];
		xStream << this->m_afPosition[2];
		
		xStream << this->m_aiTransformMatrix3x3[0][0];
		xStream << this->m_aiTransformMatrix3x3[0][1];
		xStream << this->m_aiTransformMatrix3x3[0][2];
		
		xStream << this->m_aiTransformMatrix3x3[1][0];
		xStream << this->m_aiTransformMatrix3x3[1][1];
		xStream << this->m_aiTransformMatrix3x3[1][2];
		
		xStream << this->m_aiTransformMatrix3x3[2][0];
		xStream << this->m_aiTransformMatrix3x3[2][1];
		xStream << this->m_aiTransformMatrix3x3[2][2];
			
		xStream << this->m_auSphericalR[0];
		xStream << this->m_auSphericalR[1];
		xStream << this->m_auSphericalR[2];
		xStream << this->m_auSphericalR[3];
		
		xStream << this->m_auSphericalG[0];
		xStream << this->m_auSphericalG[1];
		xStream << this->m_auSphericalG[2];
		xStream << this->m_auSphericalG[3];
		
		xStream << this->m_auSphericalB[0];
		xStream << this->m_auSphericalB[1];
		xStream << this->m_auSphericalB[2];
		xStream << this->m_auSphericalB[3];

		xStream << this->m_fDecompSHScale;
		xStream << this->m_fDecompSHBias;
		
	#endif

	return( true);
}

bool Asura_Direct3D_BGR_Instances_Header::Export( Asura_Chunk_Stream& xStream) const
{
	if( false == this->m_xTypeID.Export( xStream))
	{
		return( false);
	}
	xStream << this->m_xBoundingBox;
	
	const uint32 uInstanceCount = this->GetInstanceCount();
	xStream << static_cast< uint32>( uInstanceCount);
	
	for( uint32 uInstanceIndex = 0; uInstanceIndex < uInstanceCount; uInstanceIndex += 1)
	{
		const Asura_Direct3D_BGR_Instance& xInstance = this->m_xArrayInstances[ uInstanceIndex];
		
		if( false == xInstance.Export( xStream))
		{
			return( false);
		}
	}
	
	return( true);
}

bool Asura_Direct3D_BGR_Module::Export( Asura_Chunk_Stream& xStream) const
{
	xStream << this->m_uInstanceHeaderStartIndex;
	xStream << this->m_uInstanceHeadeCount;
	return( true);
}

bool Asura_Direct3D_BGR_Manager::Export( Asura_Chunk_Stream& xStream) const
{
	
	if( false == this->m_xArray_xModule.Export( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArray_xTypes.Export( xStream))
	{
		return( false);
	}
	
	{
		// DLH - 19 April 2006 16:17:17 - Export Instances
		const uint32 uInstanceHeaderCount = this->m_xArray_pxInstanceHeaders.Size();
		
		xStream << uInstanceHeaderCount;
		
		for( uint32 uInstanceHeaderIndex = 0; uInstanceHeaderIndex < uInstanceHeaderCount; uInstanceHeaderIndex += 1)
		{
			Asura_Direct3D_BGR_Instances_Header* pxInstanceHeader = this->m_xArray_pxInstanceHeaders[ uInstanceHeaderIndex];
			
			if( false == pxInstanceHeader->Export( xStream))
			{
				return( false);
			}
		}
	}

	return( true);
}

bool Asura_Direct3D_Botanicals_Game_Render::Export( HANDLE xFileHandle)
{
	Asura_Chunk_Stream_WindowsFile xStream( xFileHandle);
	
	xStream.WriteResourceChunk_Start( ASURA_RESOURCEFILE_TYPE_PLATFORMSPECIFIC, ASURA_RESOURCEFILE_TYPE_PC_BOTANICAL, 4, 0, "Bot");

	{	
		Asura_Direct3D_BGR_Manager& xBGRManager = GetDirect3DBGRManager();
		
		xStream << static_cast< uint32>( Asura_BGR_Manager::s_uChunkVersion);
	
		uint32 uBGRTypeFlags = Asura_Direct3D_BGR_Manager::GetTypeFlags();
		xStream << uBGRTypeFlags;
		
		uint32 uBGRManagerCount = 1;
		xStream << uBGRManagerCount;
		
		if( false == xBGRManager.Export( xStream))
		{
			return( false);
		}
	}
	
	xStream.WriteResourceChunk_End();

	return( true);
}

#endif //defined( ASURA_TOOLS)

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
bool Asura_Direct3D_BGR_Type_VertexGeometry3DStorage::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> this->m_xPosition;
	xStream >> this->m_xNormal;
	xStream >> static_cast< uint32>( this->m_uColour);
	xStream >> static_cast< float>( this->m_afTextcoord0[ 0]);
	xStream >> static_cast< float>( this->m_afTextcoord0[ 1]);
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_SM30) && 1 == ASURA_DIRECT3D_BGR_SUPPORT_SM30
	xStream >> m_afTextcoord1[ 0];
	xStream >> m_afTextcoord1[ 1];
	xStream >> m_xBinormal;
	xStream >> m_xTangent;
	xStream >> m_fBoneWeight0;
#endif

	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
bool Asura_Direct3D_BGR_Type_VertexGeometryLeafStorage::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> this->m_xPosition;
	xStream >> static_cast< float>( this->m_afCorner[ 0]);
	xStream >> static_cast< float>( this->m_afCorner[ 1]);
	xStream >> static_cast< uint32>( this->m_uColour);
	xStream >> static_cast< float>( this->m_afTextcoord0[ 0]);
	xStream >> static_cast< float>( this->m_afTextcoord0[ 1]);
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_SM30) && 1 == ASURA_DIRECT3D_BGR_SUPPORT_SM30
	xStream >> m_afTextcoord1[ 0];	// DLH - Texture coord of the corner
	xStream >> m_afTextcoord1[ 1];	// DLH - Texture coord of the corner
	xStream >> m_xNormal;
	xStream >> m_xBinormal;
	xStream >> m_xTangent;
	xStream >> m_fBoneWeight0;		// DLH - How strong the is the bone influance
#endif

	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
bool Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> this->m_xDirection;
	xStream >> static_cast< float>( this->m_fFieldOfViewDotOutter);
	xStream >> static_cast< float>( this->m_fFieldOfViewAngleOutter);
	xStream >> static_cast< float>( this->m_fFieldOfViewAngleInner);
	
	xStream >> static_cast< float>( this->m_fWidth);
	xStream >> static_cast< float>( this->m_fHeight);
	
	xStream >> static_cast< float>( this->m_afTextcoord0[ 0]);
	xStream >> static_cast< float>( this->m_afTextcoord0[ 1]);
	
	xStream >> static_cast< float>( this->m_afTextcoord1[ 0]);
	xStream >> static_cast< float>( this->m_afTextcoord1[ 1]);
	
#if defined( ASURA_USE_MATERIAL_RESPONSE_SYSTEM )
	Asura_Hash_ID xMaterialResponseHashID;
	
	xStream >> xMaterialResponseHashID;
	
	this->m_uMaterialResponseHashID = xMaterialResponseHashID;
#else
	Asura_Hash_ID xDiffuseTextureHash;
	Asura_Hash_ID xBumpTextureHash;

	xStream >> xDiffuseTextureHash;
	xStream >> xBumpTextureHash;
	
	this->m_iTextureDiffuse = Asura_Texture_Management::GetIndexFromHashID( xDiffuseTextureHash);
	this->m_iTextureBump = Asura_Texture_Management::GetIndexFromHashID( xBumpTextureHash);
#endif

	return( true);
}
#endif

bool Asura_Direct3D_BGR_Type_GeometryLODRange::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> static_cast< float>( this->m_afDelta[ LOW_0]);
	xStream >> static_cast< float>( this->m_afDelta[ LOW_1]);
	xStream >> static_cast< float>( this->m_afDelta[ LOW_SCALE]);
	xStream >> static_cast< float>( this->m_afDelta[ HIGH_1]);
	xStream >> static_cast< float>( this->m_afDelta[ HIGH_0]);
	xStream >> static_cast< float>( this->m_afDelta[ HIGH_SCALE]);
	return( true);
}

bool Asura_Direct3D_BGR_Type_Geometry::ProcessIndices( Asura_Chunk_Stream& xStream, Asura_Botanical_Array< uint32>& xArrayIndices)
{
	uint32 uArraySize;
	xStream >> static_cast< uint32>( uArraySize);
	
	xArrayIndices.SetSize( uArraySize);
	
	for( uint32 uArrayIndex = 0; uArrayIndex < uArraySize; uArrayIndex += 1)
	{
		uint32 uIndex;
		
		xStream >> uIndex;
		
		xArrayIndices[ uArrayIndex] = uIndex;
	}
	
	return( true);
}

#if !defined( ASURA_USE_MATERIAL_RESPONSE_SYSTEM )
static int StreamInTextureHashConvertToIndex( Asura_Chunk_Stream& xStream)
{
	Asura_Hash_ID xTextureHash;

	xStream >> xTextureHash;

	return( Asura_Texture_Management::GetIndexFromHashID( xTextureHash));
}
#endif

Asura_Chunk_Stream& operator >> ( Asura_Chunk_Stream& xStream, Asura_Direct3D_BGR_Material& xMaterial)
{
#if defined( ASURA_USE_MATERIAL_RESPONSE_SYSTEM )
	uint32 uMaterialResponseHashID;
	xStream >> uMaterialResponseHashID;
	xMaterial.m_xMaterialResponseHashID = uMaterialResponseHashID;
#else
	xMaterial.m_iDiffuseTexture0 = StreamInTextureHashConvertToIndex( xStream);
	xMaterial.m_iDiffuseTexture1 = StreamInTextureHashConvertToIndex( xStream);
	xStream >> xMaterial.m_bDiffuseDualPassTexture;
	
	xMaterial.m_iSpecularTexture0 = StreamInTextureHashConvertToIndex( xStream);
	xMaterial.m_iSpecularTexture1 = StreamInTextureHashConvertToIndex( xStream);
	xStream >> xMaterial.m_bSpecularDualPassTexture;
	
	xStream >> xMaterial.m_bHasNormalMaps;
	xMaterial.m_iNormalTexture0 = StreamInTextureHashConvertToIndex( xStream);
	xMaterial.m_iNormalTexture1 = StreamInTextureHashConvertToIndex( xStream);
	xStream >> xMaterial.m_bNormalDualPassTexture;
	
	xStream >> xMaterial.m_bParallaxMap;
	xStream >> xMaterial.m_bSelfIlluminating;
	xStream >> xMaterial.m_bSpecular;
	xStream >> xMaterial.m_bOutputAlphaOfTexture;
#endif
	
	
	return( xStream);
}

bool Asura_Direct3D_BGR_Type_Geometry::Process( Asura_Chunk_Stream& xStream)
{
	if( false == this->m_xLodRange.Process( xStream))
	{
		return( false);
	}
	
	xStream >> static_cast< float>( this->m_fAlphaCutValue);
	
	xStream >> this->xMaterial;
	
	return( true);
}

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
bool Asura_Direct3D_BGR_Type_Geometry3D::Process( Asura_Chunk_Stream& xStream)
{
	if( false == this->Asura_Direct3D_BGR_Type_Geometry::Process( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayVertices.Process( xStream))
	{
		return( false);
	}
	
	if( false == this->ProcessIndices( xStream, this->m_xArrayIndices))
	{
		return( false);
	}
	
	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
bool Asura_Direct3D_BGR_Type_GeometryLeaves::Process( Asura_Chunk_Stream& xStream)
{
	if( false == this->Asura_Direct3D_BGR_Type_Geometry::Process( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayVertices.Process( xStream))
	{
		return( false);
	}
	
	if( false == this->ProcessIndices( xStream, this->m_xArrayIndices))
	{
		return( false);
	}
	
	return( true);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
bool Asura_Direct3D_BGR_Type_GeometryBillboard::Process( Asura_Chunk_Stream& xStream)
{
	if( false == this->Asura_Direct3D_BGR_Type_Geometry::Process( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayBillboards.Process( xStream))
	{
		return( false);
	}
	
	return( true);
}
#endif

bool Asura_Direct3D_BGR_Geometry::Process( Asura_Chunk_Stream& xStream)
{
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
	if( false == this->m_xArrayBranchs.Process( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArrayFronds.Process( xStream))
	{
		return( false);
	}
#endif
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
	if( false == this->m_xArrayLeaves.Process( xStream))
	{
		return( false);
	}
#endif
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
	if( false == this->m_xArrayBillboards.Process( xStream))
	{
		return( false);
	}
#endif

	return( true);
}

bool Asura_Direct3D_BGR_Section_Version::Process( Asura_Chunk_Stream& xStream)
{
	if( false == this->m_xGeometry.Process( xStream))
	{
		return( false);
	}
	return( true);
}

bool Asura_Direct3D_BGR_Section::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> this->m_xArray_uVersionIDToVersionIndex;
	xStream >> this->m_xArray_uVersionIndexToVersionID;
	
	if( false == this->m_xArray_xVersions.Process( xStream))
	{
		return( false);
	}
	
	return( true);
}

template< class Tclass>
Asura_Chunk_Stream& operator>> ( Asura_Chunk_Stream& xStream, Asura_TemplateHashTree< Tclass>& tHashTree)
{
	u_int uNodeCount;
	xStream >> uNodeCount;
	
	for( u_int uNodeIndex = 0; uNodeIndex < uNodeCount; uNodeIndex += 1)
	{
		Asura_Hash_ID xHashID;
		
		xStream >> xHashID;
		
		Tclass* pxData = tHashTree.AddNode( xHashID);
		Asura_Assert( NULL != pxData, "NULL data pointer");
		
		xStream >> (*pxData);
	}
	
	return( xStream);
}

bool Asura_Direct3D_BGR_Type::Process( Asura_Chunk_Stream& xStream)
{
	if( false == this->m_xTypeID.Process( xStream))
	{
		return( false);
	}

	if( false == this->Asura_BGR_Type::Process( xStream))
	{
		return( false);
	}
	
	xStream >> static_cast< bool> ( this->m_bHasImposters);
	
	xStream >> static_cast< float> ( this->m_fLodLimitNear);
	xStream >> static_cast< float> ( this->m_fLodLimitFar);
	xStream >> static_cast< float> ( this->m_fLodLimitDelta);
	xStream >> static_cast< float> ( this->m_fLodLimitDeltaImposterNear);
	xStream >> static_cast< float> ( this->m_fLodAuthoredFOVWidth);
	xStream >> static_cast< float> ( this->m_fLodAuthoredRes);
	
	xStream >> static_cast< uint32> ( this->m_uInstanceMaxCount);
	
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
	xStream >> this->m_xHashTree_xSectionID;
	xStream >> this->m_xHashTree_xVersionID;
#endif
	
	if( false == this->m_xArray_xSections.Process( xStream))
	{
		return( false);
	}
	
	return( true);
}

bool Asura_BGR_TypeID::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> static_cast< uint32> ( this->m_uID);
	return( true);
}

bool Asura_BGR_Instance::Process( Asura_Chunk_Stream& xStream)
{
	#if !defined( ASURA_DIRECT3D_BGR_INSTANCE_ENABLE_COMPRESSED_DATA)
		#error Asura_Direct3D_BGR_Instance::Export
		return( false);
	#else
	
		xStream >> this->m_afPosition[0];
		xStream >> this->m_afPosition[1];
		xStream >> this->m_afPosition[2];
		
		xStream >> this->m_aiTransformMatrix3x3[0][0];
		xStream >> this->m_aiTransformMatrix3x3[0][1];
		xStream >> this->m_aiTransformMatrix3x3[0][2];
		
		xStream >> this->m_aiTransformMatrix3x3[1][0];
		xStream >> this->m_aiTransformMatrix3x3[1][1];
		xStream >> this->m_aiTransformMatrix3x3[1][2];
		
		xStream >> this->m_aiTransformMatrix3x3[2][0];
		xStream >> this->m_aiTransformMatrix3x3[2][1];
		xStream >> this->m_aiTransformMatrix3x3[2][2];
			
		xStream >> this->m_auSphericalR[0];
		xStream >> this->m_auSphericalR[1];
		xStream >> this->m_auSphericalR[2];
		xStream >> this->m_auSphericalR[3];
		
		xStream >> this->m_auSphericalG[0];
		xStream >> this->m_auSphericalG[1];
		xStream >> this->m_auSphericalG[2];
		xStream >> this->m_auSphericalG[3];
		
		xStream >> this->m_auSphericalB[0];
		xStream >> this->m_auSphericalB[1];
		xStream >> this->m_auSphericalB[2];
		xStream >> this->m_auSphericalB[3];

		xStream >> this->m_fDecompSHScale;
		xStream >> this->m_fDecompSHBias;
		
	#endif

	return( true);
}

bool Asura_Direct3D_BGR_Module::Process( Asura_Chunk_Stream& xStream)
{
	xStream >> this->m_uInstanceHeaderStartIndex;
	xStream >> this->m_uInstanceHeadeCount;
	return( true);
}

bool Asura_Direct3D_BGR_Manager::Process( Asura_Chunk_Stream& xStream)
{
	// MGH 29/1/2008: Acquire a mutex to prevent Alt-Tabbing whilst loading this chunk.
	// Activating the application causes the Direct3D device to be reset, which we
	// mustn't do whilst loading the botanical data; otherwise we would get Direct3D
	// resource leaks and even occasional crashes.
	Asura_ScopedMutex xLockMutex(m_xLoadingMutex);

	this->Clear();
	
	if( false == this->m_xArray_xModule.Process( xStream))
	{
		return( false);
	}
	
	if( false == this->m_xArray_xTypes.Process( xStream))
	{
		return( false);
	}
	
	{
		uint32 uInstanceHeaderCount;
		
		xStream >> uInstanceHeaderCount;
		
		this->m_xArray_pxInstanceHeaders.SetSize( uInstanceHeaderCount);
		
		for( uint32 uInstanceHeaderIndex = 0; uInstanceHeaderIndex < uInstanceHeaderCount; uInstanceHeaderIndex += 1)
		{
			Asura_BGR_TypeID xTypeID;
			
			if( false == xTypeID.Process( xStream))
			{
				return( false);
			}
			
			Asura_Direct3D_BGR_Type* pxType = this->GetDirect3DType( xTypeID);
			Asura_Assert( NULL != pxType, "BGR Type Seems to be missing");
			if( NULL == pxType)
			{
				return( false);
			}
			
			Asura_Bounding_Box xBoundingBox;
			
			xStream >> xBoundingBox;
			
			uint32 uInstanceCount;
			xStream >> uInstanceCount;

			Asura_Direct3D_BGR_Instances_Header*& pxInstanceHeader = this->m_xArray_pxInstanceHeaders[ uInstanceHeaderIndex];
			
			pxInstanceHeader = this->CreateInstanceHeader( uInstanceCount);
			
			pxInstanceHeader->SetType( xTypeID);
			pxInstanceHeader->SetBoundingBox( xBoundingBox);
			
			for( uint32 uInstanceIndex = 0; uInstanceIndex < uInstanceCount; uInstanceIndex += 1)
			{
				Asura_Direct3D_BGR_Instance& xInstance = pxInstanceHeader->m_xArrayInstances[ uInstanceIndex];
				
				if( false == xInstance.Process( xStream))
				{
					return( false);
				}
			}

#if defined( ASURA_BOTANICAL_SUPPORT_DYNAMIC_DATA) && 1 == ASURA_BOTANICAL_SUPPORT_DYNAMIC_DATA
			pxInstanceHeader->SetupDynamicData( *pxType);
			pxInstanceHeader->AllocateDynamicData( uInstanceCount);
#endif
		}
	}
	
#if defined( ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS) && 1 == ASURA_BOTANICAL_SUPPORT_SECTION_VERSIONS
	this->SetupSectionCache();
#endif
	this->SetupTypeCache();
	this->CreateDirect3DData();
	
	return( true);
}

bool Asura_Chunk_ResourceFile_PC_Botanical::Process( Asura_Handle hFile )
{
	const u_int uChunkVersion = 4;
	Asura_Assert( uChunkVersion == this->Version, "Incorrent Botanical Chunk Version.\nRe-export.\n");
	if( uChunkVersion != this->Version)
	{
		return false;
	}
	
	Asura_Chunk_File_Stream	xStream( hFile);
	
	uint32 uBGRPlatformIndependentDataVersionAndFlags;
	
	xStream >> uBGRPlatformIndependentDataVersionAndFlags;
	if( Asura_BGR_Manager::s_uChunkVersion != uBGRPlatformIndependentDataVersionAndFlags)
	{
		return false;
	}
	
	uint32 uBGRTypeFlags;
	xStream >> uBGRTypeFlags;
	Asura_Assertf( Asura_Direct3D_BGR_Manager::GetTypeFlags() == uBGRTypeFlags, ("The version bit flag for the Botanical Data does not match the compiled EXE bit flags. File 0x%08X. EXE 0x%08X." , uBGRTypeFlags, Asura_Direct3D_BGR_Manager::GetTypeFlags()));
	if( Asura_Direct3D_BGR_Manager::GetTypeFlags() != uBGRTypeFlags)
	{
		return false;
	}
		
	uint32 uBGRManagerCount;
	xStream >> uBGRManagerCount;
	
	Asura_Assert( 1 == uBGRManagerCount, "Only one BGR is supported at present");
	
	{	
		Asura_Direct3D_BGR_Manager& xBGRManager = Asura_Direct3D_Botanicals_Game_Render::GetDirect3DBGRManager();
		
		if( false == xBGRManager.Process( xStream))
		{
			Asura_Assert( false, "Failed to load BGR Chunk");
			return false;
		}
	}

	return true;
}


//*******************************************************************
//
// (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.
//
//*******************************************************************

#endif //defined( ASURA_USE_BOTANICALS)
