//*******************************************************************
//
// File: Asura_Platform_Botanicals_Game_Render_Manager_Update_Dynamic_Data.h
//
// Created: 1 Dec 2006
//
// Description: This is the Direct3D_Botanical class that allows imposter's Direct3D vertex buffers to be updated in the Update() 
//
//*******************************************************************

#ifndef _ASURA_PLATFORM_BOTANICALS_GAME_RENDER_MANAGER_UPDATE_DYNAMIC_DATA_H_
#define _ASURA_PLATFORM_BOTANICALS_GAME_RENDER_MANAGER_UPDATE_DYNAMIC_DATA_H_

#if defined( ASURA_BOTANICAL_SUPPORT_INTERACTIVE_PLATFORM_DATA_UPDATE)
// other libraries
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render_Manager.h"

// internal dependencies

// forward declarations

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


//*******************************************************************
// Class Definitions
//*******************************************************************

class Asura_Platform_BGR_Manager_Update_Dynamic_Data
{
public:
	static bool StartProcessing( Asura_BGR_Manager& xManager);
	static bool StopProcessing( Asura_BGR_Manager& xManager);
	
	Asura_Platform_BGR_Manager_Update_Dynamic_Data();
	
	bool StartInstanceHeader(  Asura_BGR_Manager& xManager, Asura_BGR_Type& xType, Asura_BGR_Instances_Header& xInstanceHeader);
	bool StopInstanceHeader( Asura_BGR_Instances_Header& xInstanceHeader);
	
	bool UpdateInstance( const Asura_BGR_Instance& xInstance, const Asura_AVector3& xNewInstanceBoneOffset, const Asura_AVector3& xNewInstanceBoneVelocity);
	bool NeedToUpdateInstances();
public:

	bool m_bHasImposters;
	Asura_Direct3D_BGR_Type_VertexGeometryImposterInteractive* m_pxD3DBoneVertex0;
	Asura_Direct3D_BGR_Type_VertexGeometryImposterInteractive* m_pxD3DBoneVertex;
};

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

inline Asura_Platform_BGR_Manager_Update_Dynamic_Data::Asura_Platform_BGR_Manager_Update_Dynamic_Data()
{
	this->m_bHasImposters = false;
}

inline bool Asura_Platform_BGR_Manager_Update_Dynamic_Data::StartProcessing( Asura_BGR_Manager& xManager)
{
	Asura_Direct3D_BGR_Manager& xDirect3DManager = static_cast< Asura_Direct3D_BGR_Manager&>( xManager);
	Asura_Direct3D_BGR_Type_VertexGeometryImposterInteractive* pxD3DBoneVertex0 = xDirect3DManager.m_xD3DBufferImposterInteractive.m_pxArrayVertex;
	
	if( NULL == pxD3DBoneVertex0)
	{		
		xDirect3DManager.m_xD3DBufferImposterInteractive.Lock( true);
			
		xDirect3DManager.m_xD3DBufferImposterInteractive.m_pxArrayVertex;
	}
		
	return( true);
}

inline bool Asura_Platform_BGR_Manager_Update_Dynamic_Data::StopProcessing( Asura_BGR_Manager& xManager)
{
	Asura_Direct3D_BGR_Manager& xDirect3DManager = static_cast< Asura_Direct3D_BGR_Manager&>( xManager);
	if( NULL != xDirect3DManager.m_xD3DBufferImposterInteractive.m_pxArrayVertex) 
	{
		xDirect3DManager.m_xD3DBufferImposterInteractive.Unlock();
		Asura_Assert( NULL == xDirect3DManager.m_xD3DBufferImposterInteractive.m_pxArrayVertex, "Vertex Buffer has bot unlocked.");
	}
	
	return( true);
}

inline bool Asura_Platform_BGR_Manager_Update_Dynamic_Data::StartInstanceHeader( Asura_BGR_Manager& xManager, Asura_BGR_Type& xType, Asura_BGR_Instances_Header& xInstanceHeader)
{
	Asura_Direct3D_BGR_Type& xDirect3DType = static_cast< Asura_Direct3D_BGR_Type&>( xType);
	
	this->m_bHasImposters = false;
	
	if (false == xDirect3DType.m_bHasImposters)
	{
		return( true);
	}

	Asura_Direct3D_BGR_Manager& xDirect3DManager = static_cast< Asura_Direct3D_BGR_Manager&>( xManager);
	
	this->m_pxD3DBoneVertex0 = xDirect3DManager.m_xD3DBufferImposterInteractive.m_pxArrayVertex;

#if 0	
	if( NULL == this->m_pxD3DBoneVertex0)
	{		
		const bool bInstanceHasImposters = xDirect3DType.m_bHasImposters;

		if( true == bInstanceHasImposters) 
		{
			xDirect3DManager.m_xD3DBufferImposterInteractive.Lock( true);
		
			this->m_pxD3DBoneVertex0 = xDirect3DManager.m_xD3DBufferImposterInteractive.m_pxArrayVertex;
		}
	}
#endif
		
	this->m_pxD3DBoneVertex = NULL;
	if( NULL == this->m_pxD3DBoneVertex0)
	{
		return( true);
	}
		
	Asura_Direct3D_BGR_Instances_Header& xDirect3DInstanceHeader = static_cast< Asura_Direct3D_BGR_Instances_Header&>( xInstanceHeader);
	
	this->m_pxD3DBoneVertex = this->m_pxD3DBoneVertex0 + (xDirect3DInstanceHeader.m_uImposterVBStart + xDirect3DInstanceHeader.m_uImposterVBOffset);
	this->m_bHasImposters = true;
	
	return( true);
}

inline bool Asura_Platform_BGR_Manager_Update_Dynamic_Data::StopInstanceHeader( Asura_BGR_Instances_Header& xInstanceHeader)
{
	return( true);
}

inline bool Asura_Platform_BGR_Manager_Update_Dynamic_Data::UpdateInstance( const Asura_BGR_Instance& xInstance, const Asura_AVector3& xNewInstanceBoneOffset, const Asura_AVector3& xNewInstanceBoneVelocity)
{
	Asura_AMatrix3x3 xInstanceOrientationLocalToWorld;
	
	xInstance.GetOrientation( xInstanceOrientationLocalToWorld);

	Asura_AVector3 xNewWorldInstanceBoneOffset = xNewInstanceBoneOffset * xInstanceOrientationLocalToWorld;

#if defined(ASURA_PC_SSE) && defined( ASURA_USE_PLATFORM_VECTORS) && 1 == ASURA_USE_PLATFORM_VECTORS 
	__m128 xPositionSSE = xNewWorldInstanceBoneOffset.GetM128();
	
	{
		Asura_Direct3D_BGR_Type_VertexGeometryImposterInteractive* pxD3DBoneVertex = m_pxD3DBoneVertex;
		
		_mm_storeu_ps( (pxD3DBoneVertex + 0)->m_afBonePosition, xPositionSSE);
		_mm_storeu_ps( (pxD3DBoneVertex + 1)->m_afBonePosition, xPositionSSE);
		_mm_storeu_ps( (pxD3DBoneVertex + 2)->m_afBonePosition, xPositionSSE);
		_mm_storeu_ps( (pxD3DBoneVertex + 3)->m_afBonePosition, xPositionSSE);
	}
#else
	const float fPositionX = xNewWorldInstanceBoneOffset.GetX();
	const float fPositionY = xNewWorldInstanceBoneOffset.GetY();
	const float fPositionZ = xNewWorldInstanceBoneOffset.GetZ();
	const float fPositionW = 0.0f;
	
	{
		Asura_Direct3D_BGR_Type_VertexGeometryImposterInteractive* pxD3DBoneVertex = m_pxD3DBoneVertex;
		
		(pxD3DBoneVertex + 0)->m_afBonePosition[0] = fPositionX;
		(pxD3DBoneVertex + 0)->m_afBonePosition[1] = fPositionY;
		(pxD3DBoneVertex + 0)->m_afBonePosition[2] = fPositionZ;
		(pxD3DBoneVertex + 0)->m_afBonePosition[3] = fPositionW;
		
		(pxD3DBoneVertex + 1)->m_afBonePosition[0] = fPositionX;
		(pxD3DBoneVertex + 1)->m_afBonePosition[1] = fPositionY;
		(pxD3DBoneVertex + 1)->m_afBonePosition[2] = fPositionZ;
		(pxD3DBoneVertex + 1)->m_afBonePosition[3] = fPositionW;
		
		(pxD3DBoneVertex + 2)->m_afBonePosition[0] = fPositionX;
		(pxD3DBoneVertex + 2)->m_afBonePosition[1] = fPositionY;
		(pxD3DBoneVertex + 2)->m_afBonePosition[2] = fPositionZ;
		(pxD3DBoneVertex + 2)->m_afBonePosition[3] = fPositionW;
		
		(pxD3DBoneVertex + 3)->m_afBonePosition[0] = fPositionX;
		(pxD3DBoneVertex + 3)->m_afBonePosition[1] = fPositionY;
		(pxD3DBoneVertex + 3)->m_afBonePosition[2] = fPositionZ;
		(pxD3DBoneVertex + 3)->m_afBonePosition[3] = fPositionW;
	}
#endif
	
	this->m_pxD3DBoneVertex += 4;

	return( true);
}

inline bool Asura_Platform_BGR_Manager_Update_Dynamic_Data::NeedToUpdateInstances()
{
	return( this->m_bHasImposters);
}


//*******************************************************************
//
// (c) 2006 Rebellion
//
// 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_BOTANICAL_SUPPORT_INTERACTIVE_PLATFORM_DATA_UPDATE)
#endif // _ASURA_PLATFORM_BOTANICALS_GAME_RENDER_MANAGER_UPDATE_DYNAMIC_DATA_H_
