FIndirectLightingCacheAllocation* FIndirectLightingCache::CreateAllocation(int32 BlockSize, const FBoxSphereBounds& Bounds, bool bPointSample, bool bUnbuiltPreview)
{	
	check(BlockSize > 1 || bPointSample);

	FIndirectLightingCacheAllocation* NewAllocation = new FIndirectLightingCacheAllocation();
	FIndirectLightingCacheBlock NewBlock;

	//@todo - don't allocate point samples from the layout, they don't go through the volume texture
	if (AllocateBlock(BlockSize, NewBlock.MinTexel))
	{
		NewBlock.TexelSize = BlockSize;
		CalculateBlockPositionAndSize(Bounds, BlockSize, NewBlock.Min, NewBlock.Size);

		FVector Scale;
		FVector Add;
		FVector MinUV;
		FVector MaxUV;
		CalculateBlockScaleAndAdd(NewBlock.MinTexel, NewBlock.TexelSize, NewBlock.Min, NewBlock.Size, Scale, Add, MinUV, MaxUV);

		VolumeBlocks.Add(NewBlock.MinTexel, NewBlock);
		NewAllocation->SetParameters(NewBlock.MinTexel, NewBlock.TexelSize, Scale, Add, MinUV, MaxUV, bPointSample, bUnbuiltPreview);
	}

	return NewAllocation;
}
void FIndirectLightingCache::UpdateCacheAllocation(
	const FBoxSphereBounds& Bounds, 
	int32 BlockSize,
	bool bOpaqueRelevance,
	FIndirectLightingCacheAllocation*& Allocation, 
	TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate,
	TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate)
{
	if (Allocation && Allocation->IsValid())
	{
		FIndirectLightingCacheBlock& Block = FindBlock(Allocation->MinTexel);

		// Calculate a potentially new min and size based on the current bounds
		FVector NewMin;
		FVector NewSize;
		CalculateBlockPositionAndSize(Bounds, Block.TexelSize, NewMin, NewSize);

		// If the primitive has moved enough to change its block min and size, we need to interpolate it again
		if (Allocation->bIsDirty || GCacheUpdateEveryFrame || !Block.Min.Equals(NewMin) || !Block.Size.Equals(NewSize))
		{
			// Update the block and primitive allocation with the new bounds
			Block.Min = NewMin;
			Block.Size = NewSize;

			FVector NewScale;
			FVector NewAdd;
			FVector MinUV;
			FVector MaxUV;
			CalculateBlockScaleAndAdd(Allocation->MinTexel, Allocation->AllocationTexelSize, NewMin, NewSize, NewScale, NewAdd, MinUV, MaxUV);

			Allocation->SetParameters(Allocation->MinTexel, Allocation->AllocationTexelSize, NewScale, NewAdd, MinUV, MaxUV, bOpaqueRelevance);
			BlocksToUpdate.Add(Block.MinTexel, FBlockUpdateInfo(Block, Allocation));
		}

		if ((Allocation->SingleSamplePosition - Allocation->TargetPosition).SizeSquared() > DELTA)
		{
			TransitionsOverTimeToUpdate.AddUnique(Allocation);
		}
	}
	else
	{
		delete Allocation;
		Allocation = CreateAllocation(BlockSize, Bounds, bOpaqueRelevance);

		if (Allocation->IsValid())
		{
			// Must interpolate lighting for this new block
			BlocksToUpdate.Add(Allocation->MinTexel, FBlockUpdateInfo(VolumeBlocks.FindChecked(Allocation->MinTexel), Allocation));
		}
	}
}
FIndirectLightingCacheAllocation* FIndirectLightingCache::CreateAllocation(int32 BlockSize, const FBoxSphereBounds& Bounds, bool bOpaqueRelevance)
{
	FIndirectLightingCacheAllocation* NewAllocation = new FIndirectLightingCacheAllocation();
	FIndirectLightingCacheBlock NewBlock;

	if (AllocateBlock(BlockSize, NewBlock.MinTexel))
	{
		NewBlock.TexelSize = BlockSize;
		CalculateBlockPositionAndSize(Bounds, BlockSize, NewBlock.Min, NewBlock.Size);

		FVector Scale;
		FVector Add;
		FVector MinUV;
		FVector MaxUV;
		CalculateBlockScaleAndAdd(NewBlock.MinTexel, NewBlock.TexelSize, NewBlock.Min, NewBlock.Size, Scale, Add, MinUV, MaxUV);

		VolumeBlocks.Add(NewBlock.MinTexel, NewBlock);
		NewAllocation->SetParameters(NewBlock.MinTexel, NewBlock.TexelSize, Scale, Add, MinUV, MaxUV, bOpaqueRelevance);
	}

	return NewAllocation;
}