Select Git revision
VAReceiverActor.cpp
-
Philipp Schäfer authored
- now sends the reproduction input signal type (e.g. binaural / ambisonics) to the launcher
Philipp Schäfer authored- now sends the reproduction input signal type (e.g. binaural / ambisonics) to the launcher
VAReceiverActor.cpp 13.19 KiB
// Fill out your copyright notice in the Description page of Project Settings.
// what's up?
#include "VAReceiverActor.h"
#include "VAPlugin.h"
#include "VAUtils.h"
#include "VADefines.h"
#include "SoundSource/VAAbstractSourceComponent.h"
#include "ImageSourceModel/VAReflectionWall.h"
#include "Directivity/VADirectivityManager.h"
#include "HRIR/VAHRIRManager.h"
#include "Cluster/DisplayClusterClusterEvent.h"
#include "Engine/World.h" // World
#include "GameFramework/PlayerController.h" // Viewport
#include "IDisplayCluster.h" // For Events
#include "Pawn/VirtualRealityPawn.h" // VR Pawn
#include "Kismet/GameplayStatics.h" // Get Actors of class
#include "Utility/VirtualRealityUtilities.h"
// ****************************************************************** //
// ******* Initialization Functions ********************************* //
// ****************************************************************** //
AVAReceiverActor::AVAReceiverActor()
{
PrimaryActorTick.bCanEverTick = true;
DirManager = MakeShared<FVADirectivityManager>();
HRIRManager = MakeShared<FVAHRIRManager>();
AuralizationModeController = CreateDefaultSubobject<UVAAuralizationModeController>(TEXT("AuralizationModeController"));
}
void AVAReceiverActor::BeginPlay()
{
Super::BeginPlay();
FVAPlugin::SetReceiverActor(this);
// Cluster Stuff for Events //
RunOnAllNodesEvent.Attach(this);
// CurrentReceiverActor = this;
if(bReconnecToVAServer && UVirtualRealityUtilities::IsMaster() && FVAPlugin::IsConnected())
{
//this might be needed if different server version should be started between levels
FVAPlugin::DisconnectServer();
}
//try to start (remote) VAServer automatically
bool bStartedVAServer = false;
if (bAutomaticRemoteVAStart)
{
FVAPlugin::VAServerLauncher.StartVAServerLauncher(); //if possible
bStartedVAServer = FVAPlugin::VAServerLauncher.RemoteStartVAServer(GetIPAddress(), RemoteVAStarterPort, WhichVAServerVersionToStart, VARendererIniFile, ReproductionInputType);
if(bStartedVAServer){
FVAPlugin::SetUseVA(true);
}
}
// Ask if used or not
FVAPlugin::AskForSettings(GetIPAddress(), GetPort(), bAskForDebugMode, !bStartedVAServer);
if (UVirtualRealityUtilities::IsMaster())
{
if (FVAPlugin::GetUseVA())
{
RunOnAllNodes("useVA = true");
}
else
{
RunOnAllNodes("useVA = false");
return;
}
}
bWallsInitialized = false;
TimeSinceUpdate = 0.0f;
TotalTime = 0.0f;
if (!FVAPlugin::GetUseVA())
{
return;
}
if (UVirtualRealityUtilities::IsMaster())
{
FVAPlugin::SetScale(WorldScale);
if (!FVAPlugin::IsConnected())
{
FVAPlugin::ConnectServer(GetIPAddress(), GetPort());
}
else
{
FVAPlugin::ResetServer();
}
if (AuralizationModeController)
{
AuralizationModeController->Initialize();
}
// Initialize the dirManager
DirManager->ResetManager();
if (bReadInitialMappingFile)
{
DirManager->ReadConfigFile(DirMappingFileName);
}
// Initialize the HRIRManager
HRIRManager->ResetManager();
// Initialize Receiver Actor
ReceiverID = FVAPlugin::CreateNewSoundReceiver(this);
if (FVAHRIRManager::GetDefaultHRIR().IsValid() && VA::IsValidID( FVAHRIRManager::GetDefaultHRIR()->GetID() ))
{
CurrentHRIR = FVAHRIRManager::GetDefaultHRIR();
}
}
// Initialize Walls for Sound Reflection
if (!bWallsInitialized)
{
InitializeWalls();
}
// Handle all sound Sources
TArray<AActor*> ActorsA;
UGameplayStatics::GetAllActorsOfClass(this->GetWorld(), AActor::StaticClass(), ActorsA);
for (AActor* Actor : ActorsA)
{
TArray<UVAAbstractSourceComponent*> VASourceComponents;
Actor->GetComponents(VASourceComponents);
for (UVAAbstractSourceComponent* SourceComponent : VASourceComponents)
{
SourceComponent->Initialize();
}
}
if (UVirtualRealityUtilities::IsMaster())
{
if (FVAPlugin::GetDebugMode())
{
RunOnAllNodes("debugMode = true");
}
else
{
RunOnAllNodes("debugMode = false");
}
}
bInitialized = true;
}
void AVAReceiverActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
RunOnAllNodesEvent.Detach();
if(!FVAPlugin::GetWasStarted())
{
return;
}
DirManager->ResetManager();
HRIRManager->ResetManager();
Super::EndPlay(EndPlayReason);
}
void AVAReceiverActor::InitializeWalls()
{
TArray<AActor*> WallsA;
UGameplayStatics::GetAllActorsOfClass(this->GetWorld(), AVAReflectionWall::StaticClass(), WallsA);
for (AActor* EntryWalls : WallsA)
{
ReflectionWalls.Add(static_cast<AVAReflectionWall*>(EntryWalls));
}
bWallsInitialized = true;
}
void AVAReceiverActor::SetUpdateRate(const int Rate)
{
UpdateRate = Rate;
}
// ****************************************************************** //
// ******* Tick Function ******************************************** //
// ****************************************************************** //
void AVAReceiverActor::Tick(const float DeltaTime)
{
Super::Tick(DeltaTime);
if (!FVAPlugin::GetUseVA() || !UVirtualRealityUtilities::IsMaster())
{
return;
}
if (!bInitialized)
{
FVAUtils::OpenMessageBox("[AVAReceiverActor::Tick()]: Receiver Actor is not initialized", true);
}
TimeSinceUpdate += DeltaTime;
TotalTime += DeltaTime;
if (TimeSinceUpdate > (1.0f / float(UpdateRate)))
{
UpdateVirtualWorldPose();
UpdateRealWorldPose();
TimeSinceUpdate = 0.0f;
}
}
// ****************************************************************** //
// ******* Position updates ***************************************** //
// ****************************************************************** //
bool AVAReceiverActor::SetManualReceiverData(FVector VirtualPos, FRotator VirtualRot, FVector RealWorldPos /*= FVector(0, 0, 0)*/, FRotator RealWorldRot /*= FRotator(0, 0, 0)*/)
{
if (TrackingSource != ETrackingSource::ManualData)
{
FVAUtils::LogStuff("[AVAReceiverActor::SetManualReceiverData()]: SetManualReceiverData() called, but TrackingSource != ManualData", true);
return false;
}
const FVector HeadCenterPosition = VirtualPos + VirtualRot.RotateVector(ViewpointToHeadcenterOffset);
bool bResult = true;
//Update VirtualWorldPose
bResult &= FVAPlugin::SetSoundReceiverPosition(ReceiverID, HeadCenterPosition);
bResult &= FVAPlugin::SetSoundReceiverRotation(ReceiverID, VirtualRot);
//Update RealWorldPose
bResult &= FVAPlugin::SetSoundReceiverRealWorldPose(ReceiverID, RealWorldPos, RealWorldRot);
return bResult;
}
bool AVAReceiverActor::UpdateVirtualWorldPose()
{
if(TrackingSource == ETrackingSource::VirtualRealityPawn)
{
// Auralization Pose is coppled to the Virtual Reality Pawn, e.g, HMD, CAVE
FVector ViewPos;
FRotator ViewRot;
GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(ViewPos, ViewRot);
bool bResult = true;
bResult &= FVAPlugin::SetSoundReceiverPosition(ReceiverID, ViewPos + ViewRot.RotateVector(ViewpointToHeadcenterOffset)); //Offset from ViewPoint (between eyes) to head center, rotate according to view rotation
bResult &= FVAPlugin::SetSoundReceiverRotation(ReceiverID, ViewRot);
return bResult;
}
return false;
}
bool AVAReceiverActor::UpdateRealWorldPose()
{
if (TrackingSource==ETrackingSource::VirtualRealityPawn)
{
if (!UVirtualRealityUtilities::IsMaster() || !FVAPlugin::GetUseVA())
{
return false;
}
if (GetWorld() == nullptr)
{
return false;
}
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
if (PlayerController == nullptr)
{
return false;
}
AVirtualRealityPawn* VirtualRealityPawn = Cast<AVirtualRealityPawn>(PlayerController->AcknowledgedPawn);
if (VirtualRealityPawn == nullptr)
{
return false;
}
USceneComponent* Head = VirtualRealityPawn->Head;
if (!Head)
{
return false;
}
// calculate positions
const FQuat InverseOriginRot = VirtualRealityPawn->GetActorQuat().Inverse(); //Inverse Quaternion of Actor in Virtual World
const FVector HeadCenter = Head->GetComponentLocation() + Head->GetComponentRotation().RotateVector(ViewpointToHeadcenterOffset); //Location of Head Center in Virtual World
const FVector Pos = InverseOriginRot.RotateVector(
HeadCenter - VirtualRealityPawn->GetActorLocation()); //Get position by subtraction virtual origin
const FQuat Quat = InverseOriginRot * Head->GetComponentQuat();
return FVAPlugin::SetSoundReceiverRealWorldPose(ReceiverID, Pos, Quat.Rotator());
}
return false;
}
// ****************************************************************** //
// ******* Directivity / HRIR Handling ****************************** //
// ****************************************************************** //
TSharedPtr<FVADirectivity> AVAReceiverActor::GetDirectivityByMapping(const FString Phoneme) const
{
return DirManager->GetDirectivityByPhoneme(Phoneme);
}
TSharedPtr<FVADirectivity> AVAReceiverActor::GetDirectivityByFileName(const FString FileName)
{
return DirManager->GetDirectivityByFileName(FileName);
}
bool AVAReceiverActor::ReadDirMappingFile(const FString FileName)
{
if (DirManager->GetFileName() == FileName)
{
FVAUtils::LogStuff("[AVAReceiverActor::ReadDirMappingFile()]: file already loaded", false);
return false;
}
DirMappingFileName = FileName;
DirManager->ResetManager();
return DirManager->ReadConfigFile(DirMappingFileName);
}
bool AVAReceiverActor::SetHRIRByFileName(const FString FileName)
{
TSharedPtr<FVAHRIR> NewHRIR = HRIRManager->GetHRIRByFileName(FileName);
if (!NewHRIR.IsValid())
{
return false;
}
if(CurrentHRIR.IsValid() && NewHRIR->GetID() == CurrentHRIR->GetID())
{
return true;
}
if (FVAPlugin::SetSoundReceiverHRIR(ReceiverID, NewHRIR->GetID()))
{
CurrentHRIR = NewHRIR;
return true;
}
return false;
}
// ****************************************************************** //
// ******* Getter Functions ***************************************** //
// ****************************************************************** //
bool AVAReceiverActor::IsInitialized() const
{
return bInitialized;
}
float AVAReceiverActor::GetScale() const
{
return WorldScale;
}
FString AVAReceiverActor::GetIPAddress() const
{
switch (AddressSetting)
{
case EConnectionSetting::Automatic:
#if PLATFORM_WINDOWS
return FString("127.0.0.1");
#else
return FString("10.0.1.240");
#endif
break;
case EConnectionSetting::Cave:
return FString("10.0.1.240");
break;
case EConnectionSetting::Localhost:
return FString("127.0.0.1");
break;
case EConnectionSetting::Manual:
return ServerIPAddress;
break;
default:
break;
}
FVAUtils::LogStuff("[AVAReceiverActor::GetIPAddress()]: Unreachable Error", true);
return FString("127.0.0.1");
}
int AVAReceiverActor::GetPort() const
{
switch (AddressSetting)
{
case EConnectionSetting::Automatic:
case EConnectionSetting::Cave:
case EConnectionSetting::Localhost:
return 12340;
break;
case EConnectionSetting::Manual:
return ServerPort;
break;
default:
break;
}
FVAUtils::LogStuff("[AVAReceiverActor::GetPort()]: Unreachable Error", true);
return -1;
}
UVAAuralizationModeController* AVAReceiverActor::GetAuralizationModeController() const
{
return AuralizationModeController;
}
int AVAReceiverActor::GetReceiverID() const
{
return ReceiverID;
}
int AVAReceiverActor::GetUpdateRate() const
{
return UpdateRate;
}
TArray<AVAReflectionWall*> AVAReceiverActor::GetReflectionWalls()
{
if (!bWallsInitialized)
{
InitializeWalls();
}
return ReflectionWalls;
}
// ****************************************************************** //
// ******* Cluster Stuff ******************************************** //
// ****************************************************************** //
void AVAReceiverActor::SetDebugMode(const bool bDebugMode)
{
if (bDebugMode)
{
RunOnAllNodes("debugMode = true");
}
else
{
RunOnAllNodes("debugMode = false");
}
}
void AVAReceiverActor::RunOnAllNodes(FString Command)
{
FVAUtils::LogStuff("[AVAReceiverActor::RunOnAllNodes()]: Cluster Command " +
Command + " received", false);
if (Command == "useVA = true")
{
FVAPlugin::SetUseVA(true);
}
else if (Command == "useVA = false")
{
FVAPlugin::SetUseVA(false);
}
else if (Command == "debugMode = true")
{
FVAPlugin::SetDebugMode(true);
}
else if (Command == "debugMode = false")
{
FVAPlugin::SetDebugMode(false);
}
else
{
FVAUtils::LogStuff("[AVAReceiverActor::RunOnAllNodes()]: Cluster Command " +
Command + " could not be evaluated.", true);
}
}
// ****************************************************************** //
// ******* Blueprint Settings *************************************** //
// ****************************************************************** //
#if WITH_EDITOR
bool AVAReceiverActor::CanEditChange(const FProperty* InProperty) const
{
// Check manual Address
if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, ServerIPAddress) ||
InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, ServerPort))
{
return AddressSetting == EConnectionSetting::Manual;
}
if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, RemoteVAStarterPort) ||
InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, WhichVAServerVersionToStart) ||
InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, VARendererIniFile))
{
return bAutomaticRemoteVAStart;
}
if (InProperty->GetFName() == GET_MEMBER_NAME_CHECKED(AVAReceiverActor, DirMappingFileName))
{
return bReadInitialMappingFile;
}
return true;
}
#endif