October3d55/M/UltraleapTracking/Source/ThirdParty/BodyState/Private/BodyStateHMDSnapshot.cpp

180 lines
5.8 KiB
C++

/*************************************************************************************************************************************
*The MIT License(MIT)
*
*Copyright(c) 2016 Jan Kaniewski(Getnamo)
*Modified work Copyright(C) 2019 - 2021 Ultraleap, Inc.
*
*Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
*files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
*merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
*furnished to do so, subject to the following conditions :
*
*The above copyright notice and this permission notice shall be included in all copies or
*substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
*FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
*CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*************************************************************************************************************************************/
#include "BodyStateHMDSnapshot.h"
#include "BodyStateUtility.h"
#include "Engine/Engine.h"
#include "IXRTrackingSystem.h"
void BSHMDSnapshotHandler::AddCurrentHMDSample(double CustomTimeStamp)
{
// Grab current sample
Samples[CurrentIndex] = CurrentHMDSample(CustomTimeStamp);
// Circular tracker - slot it in correctly
CurrentIndex++;
if (CurrentIndex >= MAX_HMD_SNAPSHOT_COUNT)
{
CurrentIndex = 0;
}
}
BodyStateHMDSnapshot::BodyStateHMDSnapshot(double InTimeStamp, const FVector& InPosition, const FQuat& InOrientation)
{
Timestamp = InTimeStamp;
Position = InPosition;
Orientation = InOrientation;
}
BodyStateHMDSnapshot BodyStateHMDSnapshot::Difference(BodyStateHMDSnapshot& Other)
{
BodyStateHMDSnapshot Result;
Result.Timestamp = Timestamp - Other.Timestamp;
FTransform DeltaTransform = Transform().GetRelativeTransform(Other.Transform());
Result.Orientation = DeltaTransform.GetRotation();
Result.Position = DeltaTransform.GetTranslation();
return Result;
}
FTransform BodyStateHMDSnapshot::Transform()
{
return FTransform(Orientation, Position, FVector(1.f));
}
BodyStateHMDSnapshot BodyStateHMDSnapshot::InterpolateWithOtherAtTimeStamp(BodyStateHMDSnapshot& Other, double DesiredTimeStamp)
{
// Is the timestamp between these two samples?
if ((Timestamp <= DesiredTimeStamp && DesiredTimeStamp <= Other.Timestamp) ||
(Other.Timestamp <= DesiredTimeStamp && DesiredTimeStamp <= Timestamp))
{
BodyStateHMDSnapshot result;
double range = FMath::Abs(Other.Timestamp - Timestamp);
float FactorThis = FMath::Abs(DesiredTimeStamp - Timestamp) / range;
float FactorOther = FMath::Abs(DesiredTimeStamp - Other.Timestamp) / range;
result.Position = Position * FactorThis + Other.Position * FactorOther;
result.Orientation = FQuat::Slerp(Orientation, Other.Orientation, FactorThis);
result.Timestamp = DesiredTimeStamp;
return result;
}
else
{
UE_LOG(BodyStateLog, Warning, TEXT("Invalid Lerp Timestamp, this: %1.0f other: %1.0f desired: %1.0f diff: %1.0f"),
Timestamp, Other.Timestamp, DesiredTimeStamp, Timestamp - Other.Timestamp);
// return self
return *this;
}
}
BodyStateHMDSnapshot BodyStateHMDSnapshot::operator*(float Mult)
{
// Orientation.Slerp(Orientation, )
return BodyStateHMDSnapshot(Timestamp, Position * Mult, Orientation * Mult);
}
void BodyStateHMDSnapshot::operator*=(float Mult)
{
this->Position *= Mult;
this->Orientation *= Mult;
}
BodyStateHMDSnapshot BSHMDSnapshotHandler::CurrentHMDSample(double CustomTimeStamp)
{
BodyStateHMDSnapshot Snapshot;
if (CustomTimeStamp >= 0)
{
Snapshot.Timestamp = CustomTimeStamp;
}
else
{
Snapshot.Timestamp = FPlatformTime::Seconds();
}
if (GEngine && GEngine->XRSystem.IsValid())
{
GEngine->XRSystem->GetCurrentPose(IXRTrackingSystem::HMDDeviceId, Snapshot.Orientation, Snapshot.Position);
}
return Snapshot;
}
BodyStateHMDSnapshot BSHMDSnapshotHandler::LastHMDSample()
{
return Samples[CurrentIndex];
}
BodyStateHMDSnapshot BSHMDSnapshotHandler::HMDSampleClosestToTimestamp(double PassedTimestamp)
{
double MinDifference = DBL_MAX;
int32 MinIndex = 0; // always have a valid index in case something goes wrong
// UE_LOG(LeapPluginLog, Log, TEXT("Time warp Debug - Now: %d"), Timestamp);
for (int32 i = 0; i < MAX_HMD_SNAPSHOT_COUNT; i++)
{
BodyStateHMDSnapshot& Snapshot = Samples[i];
int32 Difference = FMath::Abs(Snapshot.Timestamp - PassedTimestamp);
// UE_LOG(LeapPluginLog, Log, TEXT("Time warp Debug - Snapshot: %d, Difference: %d"), Snapshot.Timestamp, Difference);
if (Difference < MinDifference)
{
MinDifference = Difference;
MinIndex = i;
}
}
// Not a perfect match? lerp the sample
if (MinDifference > 0)
{
BodyStateHMDSnapshot& FoundSample = Samples[MinIndex];
int InterpIndex = MinIndex;
// Did we find an older timer stamp? use a future timestamp to interpolate
if (FoundSample.Timestamp < PassedTimestamp)
{
InterpIndex = MinIndex + 1;
}
else
{
InterpIndex = MinIndex - 1;
}
// Sanity check for the index
if (InterpIndex < 0)
{
InterpIndex = MAX_HMD_SNAPSHOT_COUNT - 1;
}
if (InterpIndex == MAX_HMD_SNAPSHOT_COUNT)
{
InterpIndex = 0;
}
BodyStateHMDSnapshot InterpSample = FoundSample.InterpolateWithOtherAtTimeStamp(Samples[InterpIndex], PassedTimestamp);
return InterpSample;
}
// UE_LOG(LogTemp, Log, TEXT("Time warp Debug - MinSnapshot: %d, MinDifference: %d"), Samples[MinIndex].Timestamp,
// MinDifference);
return Samples[MinIndex];
}