// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. #include "GeometryCacheModulePrivatePCH.h" #include "GeometryCacheTrack.h" GEOMETRYCACHE_API UGeometryCacheTrack::UGeometryCacheTrack(const FObjectInitializer& ObjectInitializer /*= FObjectInitializer::Get()*/) : UObject(ObjectInitializer) { NumMaterials = 0; } const bool UGeometryCacheTrack::UpdateMeshData(const float Time, const bool bLooping, int32& InOutMeshSampleIndex, FGeometryCacheMeshData*& OutMeshData) { return false; } const bool UGeometryCacheTrack::UpdateMatrixData(const float Time, const bool bLooping, int32& InOutMatrixSampleIndex, FMatrix& OutWorldMatrix) { // Retrieve sample index from Time const uint32 MatrixSampleIndex = FindSampleIndexFromTime(MatrixSampleTimes, Time, bLooping); // Update the Matrix and Index if MatrixSampleIndex is different from the stored InOutMatrixSampleIndex if (MatrixSampleIndex != InOutMatrixSampleIndex) { InOutMatrixSampleIndex = MatrixSampleIndex; OutWorldMatrix = MatrixSamples[MatrixSampleIndex]; return true; } return false; } UGeometryCacheTrack::~UGeometryCacheTrack() { MatrixSamples.Empty(); MatrixSampleTimes.Empty(); } void UGeometryCacheTrack::Serialize(FArchive& Ar) { Ar << MatrixSamples; Ar << MatrixSampleTimes; Ar << NumMaterials; } void UGeometryCacheTrack::SetMatrixSamples(const TArray& Matrices, const TArray& SampleTimes) { // Copy Matrix samples and sample-times MatrixSamples.Append(Matrices); MatrixSampleTimes.Append(SampleTimes); } const float UGeometryCacheTrack::GetMaxSampleTime() const { // If there are sample-times available return the (maximal) time from the last sample if ( MatrixSampleTimes.Num() > 0 ) { return MatrixSampleTimes.Last(); } // Otherwise no data/times availabel return 0.0f; } const uint32 UGeometryCacheTrack::FindSampleIndexFromTime(const TArray& SampleTimes, const float Time, const bool bLooping) { // No index possible if (SampleTimes.Num() == 0) { return 0; } // Modulo the incoming Time if the animation is played on a loop float SampleTime = Time; if (bLooping) { SampleTime = fmod(Time, SampleTimes[SampleTimes.Num() - 1]); } // Binary searching for closest (floored) SampleIndex uint32 MinIndex = 0; uint32 MaxIndex = SampleTimes.Num() - 1; if (SampleTime > SampleTimes[MaxIndex]) { return MaxIndex; } else if (SampleTime < SampleTimes[MinIndex]) { return MinIndex; } while (MaxIndex > 0 && MaxIndex >= MinIndex) { uint32 Mid = (MinIndex + MaxIndex) / 2; if (SampleTime > SampleTimes[Mid]) { MinIndex = Mid + 1; } else { MaxIndex = Mid - 1; } } return MinIndex; } SIZE_T UGeometryCacheTrack::GetResourceSize(EResourceSizeMode::Type Mode) { SIZE_T ResourceSize = 0; // Determine resource size from data that is serialized ResourceSize += MatrixSamples.Num() * sizeof(FMatrix); ResourceSize += MatrixSampleTimes.Num() * sizeof(float); return ResourceSize; }