126 lines
5.0 KiB
C++
126 lines
5.0 KiB
C++
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
|
|
#include "OculusXRInputOVR.h"
|
|
|
|
#include "Haptics/HapticFeedbackEffect_Base.h"
|
|
|
|
namespace OculusXRInput
|
|
{
|
|
|
|
FOculusXRInput* GetOculusXRInput()
|
|
{
|
|
const TSharedPtr<FOculusXRInput> OculusXRInput = StaticCastSharedPtr<FOculusXRInput>(IOculusXRInputModule::Get().GetInputDevice());
|
|
if (!OculusXRInput)
|
|
{
|
|
UE_LOG(LogOcInput, Error, TEXT("Failed getting Oculus XR input."));
|
|
return nullptr;
|
|
}
|
|
return OculusXRInput.Get();
|
|
}
|
|
|
|
float FOculusXRInputOVR::GetControllerSampleRateHz(EControllerHand Hand) const
|
|
{
|
|
float SampleRateHz = 0.f;
|
|
const ovrpController OvrpController = (EControllerHand(Hand) == EControllerHand::Left) ? ovrpController_LTouch : ovrpController_RTouch;
|
|
if (OVRP_FAILURE(FOculusXRHMDModule::GetPluginWrapper().GetControllerSampleRateHz(OvrpController, &SampleRateHz)))
|
|
{
|
|
UE_LOG(LogOcInput, Error, TEXT("GetControllerSampleRateHz failed."));
|
|
}
|
|
return SampleRateHz;
|
|
}
|
|
|
|
int FOculusXRInputOVR::GetMaxHapticDuration(EControllerHand Hand) const
|
|
{
|
|
const ovrpController OvrpController = (EControllerHand(Hand) == EControllerHand::Left) ? ovrpController_LTouch : ovrpController_RTouch;
|
|
if (!GetOculusXRInput()->GetOvrpHapticsDesc((int32)Hand))
|
|
return 0;
|
|
|
|
return GetOculusXRInput()->OvrpHapticsDesc.MaximumBufferSamplesCount / GetOculusXRInput()->OvrpHapticsDesc.SampleRateHz;
|
|
}
|
|
|
|
void FOculusXRInputOVR::PlayHapticEffect(
|
|
UHapticFeedbackEffect_Base* HapticEffect, EControllerHand Hand,
|
|
EOculusXRHandHapticsLocation Location, bool bAppend, float Scale,
|
|
bool bLoop)
|
|
{
|
|
if (HapticEffect)
|
|
{
|
|
switch (Hand)
|
|
{
|
|
case EControllerHand::Left:
|
|
GetOculusXRInput()->ActiveHapticEffect_Left.Reset();
|
|
GetOculusXRInput()->HapticsDesc_Left.Reset();
|
|
GetOculusXRInput()->ActiveHapticEffect_Left = MakeShareable(new FActiveHapticFeedbackEffect(HapticEffect, Scale, bLoop));
|
|
GetOculusXRInput()->HapticsDesc_Left = MakeShareable(new FOculusXRHapticsDesc(Location, bAppend));
|
|
break;
|
|
case EControllerHand::Right:
|
|
GetOculusXRInput()->ActiveHapticEffect_Right.Reset();
|
|
GetOculusXRInput()->HapticsDesc_Right.Reset();
|
|
GetOculusXRInput()->ActiveHapticEffect_Right = MakeShareable(new FActiveHapticFeedbackEffect(HapticEffect, Scale, bLoop));
|
|
GetOculusXRInput()->HapticsDesc_Right = MakeShareable(new FOculusXRHapticsDesc(Location, bAppend));
|
|
break;
|
|
default:
|
|
UE_LOG(LogOcInput, Warning, TEXT("Invalid hand specified (%d) for haptic feedback effect %s"), (int32)Hand, *HapticEffect->GetName());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FOculusXRInputOVR::PlayAmplitudeEnvelopeHapticEffect(EControllerHand Hand,
|
|
int SamplesCount, void* Samples,
|
|
int InSampleRate)
|
|
{
|
|
int TimeToSend = GetMaxHapticDuration(Hand);
|
|
if (TimeToSend == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const ovrpController OvrpController = (EControllerHand(Hand) == EControllerHand::Left) ? ovrpController_LTouch : ovrpController_RTouch;
|
|
int SampleRate = (InSampleRate > 0 ? InSampleRate : GetOculusXRInput()->OvrpHapticsDesc.SampleRateHz);
|
|
int MaxSamplesCount = TimeToSend * SampleRate;
|
|
if (SamplesCount > MaxSamplesCount || SamplesCount < GetOculusXRInput()->OvrpHapticsDesc.MinimumBufferSamplesCount)
|
|
{
|
|
UE_LOG(LogOcInput, Error, TEXT("Sample count should be between %d and %d which last %d time."),
|
|
GetOculusXRInput()->OvrpHapticsDesc.MinimumBufferSamplesCount, MaxSamplesCount, TimeToSend);
|
|
}
|
|
int WantToSend = FMath::Min(SamplesCount, MaxSamplesCount);
|
|
WantToSend = FMath::Max(WantToSend, GetOculusXRInput()->OvrpHapticsDesc.MinimumBufferSamplesCount);
|
|
|
|
float* BufferToSend = (float*)FMemory::Malloc(WantToSend * sizeof(*BufferToSend));
|
|
for (int i = 0; i < WantToSend; i++)
|
|
{
|
|
float Amplitude = ((uint8_t*)Samples)[i] / 255.0f;
|
|
Amplitude = FMath::Min(1.0f, Amplitude);
|
|
Amplitude = FMath::Max(0.0f, Amplitude);
|
|
BufferToSend[i] = Amplitude;
|
|
UE_CLOG(OVR_HAP_LOGGING, LogOcInput, Log, TEXT("amplitude, %.3f"), Amplitude);
|
|
}
|
|
|
|
ovrpHapticsAmplitudeEnvelopeVibration HapticsVibration;
|
|
HapticsVibration.Duration = WantToSend / SampleRate;
|
|
HapticsVibration.AmplitudeCount = WantToSend;
|
|
HapticsVibration.Amplitudes = BufferToSend;
|
|
|
|
FOculusXRHMDModule::GetPluginWrapper().SetControllerHapticsAmplitudeEnvelope(
|
|
OvrpController,
|
|
HapticsVibration);
|
|
UE_CLOG(OVR_HAP_LOGGING, LogOcInput, Log, TEXT("HAEHaptics is finished: AmplitudeCount: %d, SampleRate: %d"),
|
|
HapticsVibration.AmplitudeCount,
|
|
SampleRate);
|
|
|
|
if (BufferToSend)
|
|
{
|
|
FMemory::Free(BufferToSend);
|
|
}
|
|
}
|
|
|
|
void FOculusXRInputOVR::SetHapticsByValue(float Frequency, float Amplitude, EControllerHand Hand, EOculusXRHandHapticsLocation Location)
|
|
{
|
|
const ovrpController OvrpController = (EControllerHand(Hand) == EControllerHand::Left) ? ovrpController_LTouch : ovrpController_RTouch;
|
|
FOculusXRHMDModule::GetPluginWrapper().SetControllerLocalizedVibration(OvrpController, GetOculusXRInput()->GetOVRPHapticsLocation(Location), Frequency, Amplitude);
|
|
UE_CLOG(OVR_HAP_LOGGING, LogOcInput, Log, TEXT("LocalizedVibration is finished: Location: %d, Frequency: %f, Amplitude: %f"), (int)(Location), Frequency, Amplitude);
|
|
}
|
|
|
|
} // namespace OculusXRInput
|