/// Update shader params loaders for the entity.
/// Shader params loaders are shared by entities, and need to be updated every time an entity is rendered.
void UpdateEntityForRendering( CCopyEntity& entity )
{
	BaseEntity& base_entity = *(entity.pBaseEntity);

	// light params writer
	if( entity.GetEntityFlags() & BETYPE_LIGHTING )
	{
		UpdateLightInfo( entity );

		if( base_entity.MeshProperty().m_pShaderLightParamsLoader )
		{
			// Set the entity to the light params loader, because a single light params loader
			// is shared by all the entities of this base entity.
			base_entity.MeshProperty().m_pShaderLightParamsLoader->SetEntity( entity.Self().lock() );
		}
	}

	const float offset_world_transform_threshold = 150000.0f;
	if( square(offset_world_transform_threshold) < Vec3LengthSq(entity.GetWorldPose().vPosition) )
	{
		Camera* pCam = entity.GetStage()->GetCurrentCamera();
		if( pCam )
		{
			sg_pWorldTransLoader->SetActive( true );
			sg_pWorldTransLoader->SetCameraPosition( pCam->GetPosition() );
		}
		else
			sg_pWorldTransLoader->SetActive( false );

	}
	else
		sg_pWorldTransLoader->SetActive( false );
}
Result::Name RegisterAsPlanarMirror( CCopyEntity& entity, BasicMesh& mesh, int subset_index )
{
	const AABB3& aabb = mesh.GetAABB(subset_index);

	EntityRenderManager& entity_render_mgr
		= *(entity.GetStage()->GetEntitySet()->GetRenderManager());

	// >>> TODO: support planes that are not axis-aligned or facing along the negative half-space
	SPlane plane;
	int plane_axis = 1;
	if(      aabb.vMax.x - aabb.vMin.x < 0.001f ) plane_axis = 0;
	else if( aabb.vMax.y - aabb.vMin.y < 0.001f ) plane_axis = 1;
	else if( aabb.vMax.z - aabb.vMin.z < 0.001f ) plane_axis = 2;
	else plane_axis = 1;

	plane.normal = Vector3(0,0,0);
	plane.normal[plane_axis] = 1;
	plane.dist = aabb.vMax[plane_axis];

	Result::Name res = entity_render_mgr.AddPlanarReflector( EntityHandle<>( entity.Self() ), plane );

	if( res != Result::SUCCESS )
		return Result::UNKNOWN_ERROR;

	entity.RaiseEntityFlags( BETYPE_PLANAR_REFLECTOR );

	// Create shader variable loader for mirror 

	if( !entity.m_pMeshRenderMethod )
	{
		if( entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod )
		{
			entity.m_pMeshRenderMethod
				= entity.pBaseEntity->MeshProperty().m_pMeshRenderMethod->CreateCopy();

			if( !entity.m_pMeshRenderMethod )
				return Result::UNKNOWN_ERROR;
		}
		else
			return Result::UNKNOWN_ERROR;
	}

	// create a planar reflection entity
//	shared_ptr<MeshContainerRenderMethod> pMeshRenderMethodCopy
//		= entity.m_pMeshRenderMethod->CreateCopy();

	shared_ptr<MirroredSceneTextureParam> pTexParam;
	pTexParam.reset( new MirroredSceneTextureParam( EntityHandle<>( entity.Self() ) ) );
	pTexParam->m_fReflection = mesh.GetMaterial(subset_index).m_Mat.fReflection;
//	pMeshRenderMethodCopy->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam );

	// test - we assume that the entity's mesh is composed of polygons that belong to a single plane.
	entity.m_pMeshRenderMethod->SetShaderParamsLoaderToAllMeshRenderMethods( pTexParam );

	// Move the indices of the planar reflection subset(s)
	// to the render method of the planar reflection entity

	return Result::SUCCESS;
}
void UpdateLightInfo( CCopyEntity& entity )
{
	if( entity.Lighting() )
	{
		if( entity.sState & CESTATE_LIGHT_INFORMATION_INVALID )
		{
			// need to update light information - find lights that reaches to this entity
			entity.ClearLights();
			entity.GetStage()->GetEntitySet()->UpdateLights( &entity );
			entity.sState &= ~CESTATE_LIGHT_INFORMATION_INVALID;
		}
	}
}