diff --git a/Content/Blueprints/OptiXGameModeBP.uasset b/Content/Blueprints/OptiXGameModeBP.uasset index 9d3bff61140f07f2c52f9e2c50c8369c0a35960a..4a771f118266fbe3f06f2c8ea12ad939e428ccb9 100644 Binary files a/Content/Blueprints/OptiXGameModeBP.uasset and b/Content/Blueprints/OptiXGameModeBP.uasset differ diff --git a/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset b/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset index 28b42d429448e4fdb1b05068f2922209080a6860..7f898a4ba1f46f175d2df1fb2ddd575165f8938b 100644 Binary files a/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset and b/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset differ diff --git a/Content/UI/LoadingScreen.uasset b/Content/UI/LoadingScreen.uasset index efaa7303315fe2fb61e28fb0c26925232b4b5ed6..3f7ece913c843db4f3ea80e4448d50a44daa892a 100644 Binary files a/Content/UI/LoadingScreen.uasset and b/Content/UI/LoadingScreen.uasset differ diff --git a/Content/UI/Screen.uasset b/Content/UI/Screen.uasset new file mode 100644 index 0000000000000000000000000000000000000000..8c271b5a86d3d21ef73a37c2de2c7ea288d89f58 Binary files /dev/null and b/Content/UI/Screen.uasset differ diff --git a/Source/OptiX/Private/SelectableActorBase.cpp b/Source/OptiX/Private/SelectableActorBase.cpp index 53ef56dbc8fbc441d6f3e7c80dc6c9c0f6afcf01..ad331cddddcf0a42930d2bdd8f12b801cba27a07 100644 --- a/Source/OptiX/Private/SelectableActorBase.cpp +++ b/Source/OptiX/Private/SelectableActorBase.cpp @@ -1,547 +1,549 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -#include "SelectableActorBase.h" -#include "UObject/ConstructorHelpers.h" -#include "Runtime/Engine/Classes/Engine/StaticMesh.h" -#include "Kismet/GameplayStatics.h" -#include "Blueprint/UserWidget.h" -#include "Runtime/Engine/Classes/Materials/MaterialInstanceDynamic.h" - -#include "OptiXVRPawn.h" - -ASelectableActorBase::ASelectableActorBase(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) -{ - - UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor Start")); - - SetMobility(EComponentMobility::Movable); - - GetStaticMeshComponent()->SetGenerateOverlapEvents(true); - GetStaticMeshComponent()->CastShadow = 0; - - UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor Component Setup Start")); - - - Gizmo = CreateDefaultSubobject<USceneComponent>(TEXT("Gizmo")); - Gizmo->SetupAttachment(GetStaticMeshComponent()); - Gizmo->SetHiddenInGame(true); - //Gizmo->SetAbsolute(false, true, true); - - SupportWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("SupportWidget")); - SupportWidget->SetAbsolute(false, true, true); - - SupportWidget->SetupAttachment(Gizmo); - static ConstructorHelpers::FClassFinder<UUserWidget> SupportWidgetClass(TEXT("/OptiX/UI/SupportSwapWidget2")); - SupportWidget->SetWidgetClass(SupportWidgetClass.Class); - SupportWidget->SetWorldScale3D(FVector(0.05, 0.05, 0.05)); - SupportWidget->SetDrawSize(FVector2D(800, 2300)); - SupportWidget->SetGenerateOverlapEvents(false); - SupportWidget->SetHiddenInGame(true); - SupportWidget->SetTwoSided(true); - - UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 1/4")); - - - TranslationSupport = CreateDefaultSubobject<USceneComponent>(TEXT("TranslationSupport")); - TranslationSupport->SetupAttachment(Gizmo); - - TranslateX = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateX")); - TranslateX->SetAbsolute(false, true, true); - TranslateX->SetupAttachment(TranslationSupport); - static ConstructorHelpers::FObjectFinder<UStaticMesh> TranslateXMesh(TEXT("StaticMesh'/OptiX/UI/Translator/Arrowbody.Arrowbody'")); - TranslateX->SetStaticMesh(TranslateXMesh.Object); - TranslateX->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); - TranslateX->SetGenerateOverlapEvents(false); - TranslateX->SetHiddenInGame(true); - - TranslateX->CastShadow = 0; - TranslateX->bVisibleInReflectionCaptures = false; - TranslateX->SetCanEverAffectNavigation(false); - - ArrowX = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowX")); - ArrowX->SetAbsolute(false, false, true); - ArrowX->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); - ArrowX->SetupAttachment(TranslateX); - static ConstructorHelpers::FObjectFinder<UStaticMesh> TranslateArrow(TEXT("StaticMesh'/OptiX/UI/Translator/Arrowhead.Arrowhead'")); - ArrowX->SetStaticMesh(TranslateArrow.Object); - //ArrowX->SetAbsolute(false, true, false); - ArrowX->SetRelativeLocation(FVector(39, 0, 0)); - ArrowX->SetGenerateOverlapEvents(false); - ArrowX->SetHiddenInGame(true); - - ArrowX->CastShadow = 0; - ArrowX->bVisibleInReflectionCaptures = false; - ArrowX->SetCanEverAffectNavigation(false); - - TranslateWidgetX = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetX")); - TranslateWidgetX->SetAbsolute(false, true, true); - TranslateWidgetX->SetupAttachment(ArrowX); - static ConstructorHelpers::FClassFinder<UUserWidget> PosWidgetClass(TEXT("/OptiX/UI/Translator/PositionCounter")); - TranslateWidgetX->SetWidgetClass(PosWidgetClass.Class); - //TranslateWidgetX->SetRelativeLocationAndRotation(FVector(0, 0, 0), FRotator(0, 90, 0)); - //TranslateWidgetX->SetWorldRotation(FRotator()); - TranslateWidgetX->SetRelativeScale3D(FVector(0.05, 0.05, 0.05)); - TranslateWidgetX->SetDrawSize(FVector2D(300, 300)); - TranslateWidgetX->SetHiddenInGame(true); - TranslateWidgetX->SetGenerateOverlapEvents(false); - //TranslateWidgetX->SetTwoSided(true); - // todo - - TranslateY = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateY")); - TranslateY->SetAbsolute(false, true, true); - - TranslateY->SetupAttachment(TranslationSupport); - TranslateY->SetStaticMesh(TranslateXMesh.Object); - TranslateY->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); - TranslateY->SetGenerateOverlapEvents(false); - TranslateY->SetHiddenInGame(true); - TranslateY->SetWorldRotation(FRotator(0.f, 90.0f, 0.0f)); - - TranslateY->CastShadow = 0; - TranslateY->bVisibleInReflectionCaptures = false; - TranslateY->SetCanEverAffectNavigation(false); - - ArrowY = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowY")); - ArrowY->SetAbsolute(false, false, true); - - ArrowY->SetupAttachment(TranslateY); - ArrowY->SetStaticMesh(TranslateArrow.Object); - //ArrowY->SetAbsolute(false, true, false); - ArrowY->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); - ArrowY->SetRelativeLocation(FVector(39, 0, 0)); - ArrowY->SetGenerateOverlapEvents(false); - ArrowY->SetHiddenInGame(true); - - ArrowY->CastShadow = 0; - ArrowY->bVisibleInReflectionCaptures = false; - ArrowY->SetCanEverAffectNavigation(false); - - TranslateWidgetY = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetY")); - TranslateWidgetY->SetAbsolute(false, true, true); - TranslateWidgetY->SetupAttachment(ArrowY); - TranslateWidgetY->SetWidgetClass(PosWidgetClass.Class); - //TranslateWidgetY->SetWorldRotation(FRotator()); - TranslateWidgetY->SetRelativeScale3D(FVector(0.05, 0.05, 0.05)); - TranslateWidgetY->SetDrawSize(FVector2D(300, 300)); - TranslateWidgetY->SetHiddenInGame(true); - TranslateWidgetY->SetGenerateOverlapEvents(false); - //TranslateWidgetY->SetTwoSided(true); - - TranslateZ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateZ")); - TranslateZ->SetAbsolute(false, true, true); - TranslateZ->SetupAttachment(TranslationSupport); - TranslateZ->SetStaticMesh(TranslateXMesh.Object); - TranslateZ->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); - TranslateZ->SetGenerateOverlapEvents(false); - TranslateZ->SetHiddenInGame(true); - TranslateZ->SetWorldRotation(FRotator(90.f, 0.0f, 0.0f)); - TranslateZ->SetCanEverAffectNavigation(false); - TranslateZ->CastShadow = 0; - TranslateZ->bVisibleInReflectionCaptures = false; - - - ArrowZ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowZ")); - ArrowZ->SetAbsolute(false, false, true); - ArrowZ->SetupAttachment(TranslateZ); - ArrowZ->SetStaticMesh(TranslateArrow.Object); - //ArrowZ->SetAbsolute(false, true, false); - ArrowZ->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); - ArrowZ->SetRelativeLocation(FVector(39, 0, 0)); - ArrowZ->SetGenerateOverlapEvents(false); - ArrowZ->SetHiddenInGame(true); - ArrowZ->SetCanEverAffectNavigation(false); - ArrowZ->CastShadow = 0; - ArrowZ->bVisibleInReflectionCaptures = false; - - TranslateWidgetZ = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetZ")); - TranslateWidgetZ->SetAbsolute(false, true, true); - //TranslateWidgetZ->SetTwoSided(true); - - TranslateWidgetZ->SetupAttachment(ArrowZ); - TranslateWidgetZ->SetWidgetClass(PosWidgetClass.Class); - //TranslateWidgetZ->SetWorldRotation(FRotator()); - TranslateWidgetZ->SetRelativeScale3D(FVector(0.05, 0.05, 0.05)); - TranslateWidgetZ->SetDrawSize(FVector2D(300, 300)); - TranslateWidgetZ->SetRelativeLocation(FVector(8, 0, 0)); - - TranslateWidgetZ->SetHiddenInGame(true); - TranslateWidgetZ->SetGenerateOverlapEvents(false); - - UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 2/4")); - - - RotationSupport = CreateDefaultSubobject<USceneComponent>(TEXT("RotationSupport")); - RotationSupport->SetupAttachment(Gizmo); - - ScaleH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ScaleH")); - ScaleH->SetupAttachment(RotationSupport); - static ConstructorHelpers::FObjectFinder<UStaticMesh> ScaleMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/scale1.scale1'")); - ScaleH->SetStaticMesh(ScaleMesh.Object); - ScaleH->SetAbsolute(false, true, false); - ScaleH->SetGenerateOverlapEvents(false); - ScaleH->SetCollisionEnabled(ECollisionEnabled::NoCollision); - ScaleH->SetHiddenInGame(true); - ScaleH->SetCanEverAffectNavigation(false); - ScaleH->CastShadow = 0; - ScaleH->bVisibleInReflectionCaptures = false; - - ScaleV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ScaleV")); - ScaleV->SetupAttachment(RotationSupport); - ScaleV->SetStaticMesh(ScaleMesh.Object); - ScaleV->SetWorldRotation(FRotator(90, 0, 0)); - ScaleV->SetAbsolute(false, true, false); - ScaleV->SetGenerateOverlapEvents(false); - ScaleV->SetCollisionEnabled(ECollisionEnabled::NoCollision); - ScaleV->SetHiddenInGame(true); - ScaleV->SetCanEverAffectNavigation(false); - ScaleV->CastShadow = 0; - ScaleV->bVisibleInReflectionCaptures = false; - - SupportH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportH")); - SupportH->SetupAttachment(RotationSupport); - static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/Cylinder_2.Cylinder_2'")); - SupportH->SetStaticMesh(SupportMesh.Object); - SupportH->SetWorldRotation(FRotator(-90, 0, 0)); - SupportH->SetWorldScale3D(FVector(0.6, 0.6, 0.3)); - SupportH->SetGenerateOverlapEvents(false); - SupportH->SetHiddenInGame(true); - //SupportH->SetWorldLocation(FVector(25, 0, 0)); - SupportH->SetCanEverAffectNavigation(false); - SupportH->CastShadow = 0; - SupportH->bVisibleInReflectionCaptures = false; - - SupportSphereH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportSphereH")); - SupportSphereH->SetupAttachment(SupportH); - static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportSphereMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/SelectorSphere.SelectorSphere'")); - SupportSphereH->SetStaticMesh(SupportSphereMesh.Object); - SupportSphereH->SetAbsolute(false, false, true); - SupportSphereH->SetWorldScale3D(FVector(0.03, 0.03, 0.03)); - SupportSphereH->SetGenerateOverlapEvents(false); - SupportSphereH->SetHiddenInGame(true); - SupportSphereH->SetRelativeLocation(FVector(0, 0, 100)); - SupportSphereH->SetCanEverAffectNavigation(false); - SupportSphereH->CastShadow = 0; - SupportSphereH->bVisibleInReflectionCaptures = false; - - DegreeWidgetH = CreateDefaultSubobject<UWidgetComponent>(TEXT("DegreeWidgetH")); - DegreeWidgetH->SetupAttachment(SupportSphereH); - static ConstructorHelpers::FClassFinder<UUserWidget> DegreeWidgetClass(TEXT("/OptiX/UI/Rotator/DegreeCounter")); - DegreeWidgetH->SetWidgetClass(DegreeWidgetClass.Class); - DegreeWidgetH->SetRelativeLocationAndRotation(FVector(0, 0, -40), FRotator(0, 90, -90)); - //DegreeWidgetH->SetRelativeScale3D(FVector(2.0, 2.0, 0.08)); - DegreeWidgetH->SetDrawSize(FVector2D(200, 300)); - DegreeWidgetH->SetHiddenInGame(true); - DegreeWidgetH->SetGenerateOverlapEvents(false); - //DegreeWidgetH->SetTwoSided(true); - - SupportV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportV")); - SupportV->SetupAttachment(RotationSupport); - SupportV->SetStaticMesh(SupportMesh.Object); - SupportV->SetWorldRotation(FRotator(0.0f, 0.0f, 90.0f)); - SupportV->SetWorldScale3D(FVector(0.6, 0.6, 0.3)); - SupportV->SetGenerateOverlapEvents(false); - SupportV->SetHiddenInGame(true); - //SupportV->SetWorldLocation(FVector(0, 25, 0)); - SupportV->SetCanEverAffectNavigation(false); - SupportV->CastShadow = 0; - SupportV->bVisibleInReflectionCaptures = false; - - SupportSphereV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportSphereV")); - SupportSphereV->SetupAttachment(SupportV); - //static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportSphereMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/Sphere_2.Sphere_2'")); - SupportSphereV->SetStaticMesh(SupportSphereMesh.Object); - SupportSphereV->SetAbsolute(false, false, true); - SupportSphereV->SetWorldScale3D(FVector(0.03, 0.03, 0.03)); - SupportSphereV->SetGenerateOverlapEvents(false); - SupportSphereV->SetHiddenInGame(true); - SupportSphereV->SetRelativeLocation(FVector(0, 0, 100)); - SupportSphereV->SetCanEverAffectNavigation(false); - SupportSphereV->CastShadow = 0; - SupportSphereV->bVisibleInReflectionCaptures = false; - - DegreeWidgetV = CreateDefaultSubobject<UWidgetComponent>(TEXT("DegreeWidgetV")); - DegreeWidgetV->SetupAttachment(SupportSphereV); - DegreeWidgetV->SetWidgetClass(DegreeWidgetClass.Class); - DegreeWidgetV->SetRelativeLocationAndRotation(FVector(0, 0, 40), FRotator(0, 0, -90)); - //DegreeWidgetV->SetRelativeScale3D(FVector(2.0, 2.0, 0.08)); - DegreeWidgetV->SetDrawSize(FVector2D(200, 300)); - DegreeWidgetV->SetHiddenInGame(true); - DegreeWidgetV->SetGenerateOverlapEvents(false); - //DegreeWidgetV->SetTwoSided(true); - - UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 3/4")); - - - // Rods - - static ConstructorHelpers::FObjectFinder<UMaterial> MetalMaterial(TEXT("Material'/OptiX/Laser/MetalSilver.MetalSilver'")); - static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMesh(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'")); - static ConstructorHelpers::FObjectFinder<UStaticMesh> Cylinder2(TEXT("StaticMesh'/OptiX/UI/Rotator/Cylinder_2.Cylinder_2'")); - - Socket = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SocketNew")); - Socket->SetAbsolute(false, false, true); - - Socket->SetupAttachment(GetStaticMeshComponent()); - Socket->SetStaticMesh(SphereMesh.Object); - Socket->SetGenerateOverlapEvents(false); - Socket->SetMaterial(0, MetalMaterial.Object); - Socket->SetCollisionEnabled(ECollisionEnabled::NoCollision); - Socket->SetWorldScale3D(FVector(0.02, 0.02, 0.02)); - //Socket->SetRelativeLocation(FVector(0, 0, 0)); - Socket->SetCanEverAffectNavigation(false); - Socket->CastShadow = 0; - Socket->bVisibleInReflectionCaptures = false; - - ConnectorV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ConnectorVNew")); - ConnectorV->SetAbsolute(false, true, true); - - ConnectorV->SetupAttachment(Socket); - ConnectorV->SetStaticMesh(Cylinder2.Object); - ConnectorV->SetWorldScale3D(FVector(0.4, 0.4, -1)); - ConnectorV->SetGenerateOverlapEvents(false); - ConnectorV->SetCollisionEnabled(ECollisionEnabled::NoCollision); - ConnectorV->SetMaterial(0, MetalMaterial.Object); - ConnectorV->SetMaterial(1, MetalMaterial.Object); - ConnectorV->SetCanEverAffectNavigation(false); - ConnectorV->CastShadow = 0; - ConnectorV->bVisibleInReflectionCaptures = false; - - Sphere = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SphereNew")); - Sphere->SetAbsolute(false, false, true); - - Sphere->SetupAttachment(ConnectorV); - Sphere->SetStaticMesh(SphereMesh.Object); - Sphere->SetGenerateOverlapEvents(false); - Sphere->SetMaterial(0, MetalMaterial.Object); - Sphere->SetCollisionEnabled(ECollisionEnabled::NoCollision); - Sphere->SetWorldScale3D(FVector(0.02, 0.02, 0.02)); - Sphere->SetRelativeLocation(FVector(0, 0, 100)); - Sphere->SetCanEverAffectNavigation(false); - Sphere->CastShadow = 0; - Sphere->bVisibleInReflectionCaptures = false; - - ConnectorH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ConnectorHNew")); - ConnectorH->SetAbsolute(false, true, true); - ConnectorH->SetupAttachment(ConnectorV); - ConnectorH->SetStaticMesh(Cylinder2.Object); - ConnectorH->SetGenerateOverlapEvents(false); - ConnectorH->SetRelativeLocation(FVector(0, 0, 100)); - ConnectorH->SetWorldScale3D(FVector(0.4, 0.4, 1.0)); - ConnectorH->SetMaterial(0, MetalMaterial.Object); - ConnectorH->SetMaterial(1, MetalMaterial.Object); - ConnectorH->SetGenerateOverlapEvents(false); - ConnectorH->SetCollisionEnabled(ECollisionEnabled::NoCollision); - ConnectorH->SetCanEverAffectNavigation(false); - ConnectorH->CastShadow = 0; - ConnectorH->bVisibleInReflectionCaptures = false; - - UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor End 4/4")); - - -} - -void ASelectableActorBase::BeginPlay() -{ - Super::BeginPlay(); - - ArrowX->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowX->GetMaterial(0)); - ArrowX->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowX->GetMaterial(1)); - ArrowY->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowY->GetMaterial(0)); - ArrowY->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowY->GetMaterial(1)); - ArrowZ->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowZ->GetMaterial(0)); - ArrowZ->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowZ->GetMaterial(1)); - - SupportSphereH->CreateAndSetMaterialInstanceDynamicFromMaterial(0, SupportSphereH->GetMaterial(0)); - SupportSphereV->CreateAndSetMaterialInstanceDynamicFromMaterial(0, SupportSphereV->GetMaterial(0)); - - - SupportSphereH->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); - SupportSphereH->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); - - SupportSphereV->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); - SupportSphereV->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); - - ArrowX->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); - ArrowX->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); - - ArrowY->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); - ArrowY->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); - - ArrowZ->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); - ArrowZ->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); -} - -void ASelectableActorBase::Tick(float DeltaTime) -{ - Super::Tick(DeltaTime); - - - FVector PlayerLocation = UGameplayStatics::GetPlayerPawn(GetWorld(), 0)->GetActorLocation(); - { - FVector Diff = PlayerLocation - DegreeWidgetV->GetComponentTransform().GetLocation(); - FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); - DegreeWidgetV->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); - } - { - FVector Diff = PlayerLocation - DegreeWidgetH->GetComponentTransform().GetLocation(); - FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); - DegreeWidgetH->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); - } - { - FVector Diff = PlayerLocation - SupportWidget->GetComponentTransform().GetLocation(); - FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); - SupportWidget->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); - } - { - FVector Diff = PlayerLocation - TranslateWidgetX->GetComponentTransform().GetLocation(); - FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); - TranslateWidgetX->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); - } - { - FVector Diff = PlayerLocation - TranslateWidgetY->GetComponentTransform().GetLocation(); - FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); - TranslateWidgetY->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); - } - { - FVector Diff = PlayerLocation - TranslateWidgetZ->GetComponentTransform().GetLocation(); - FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); - TranslateWidgetZ->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); - } - -} - -void ASelectableActorBase::SetScaleV(FRotator Rot) -{ - ScaleV->SetWorldRotation(Rot); -} - -void ASelectableActorBase::SetScaleH(FRotator Rot) -{ - ScaleH->SetWorldRotation(Rot); -} - -void ASelectableActorBase::EnableTranslation() -{ - TranslationSupport->SetHiddenInGame(false, true); - RotationSupport->SetHiddenInGame(true, true); - - SupportSphereV->SetGenerateOverlapEvents(false); - SupportSphereH->SetGenerateOverlapEvents(false); - ArrowX->SetGenerateOverlapEvents(true); - ArrowY->SetGenerateOverlapEvents(true); - ArrowZ->SetGenerateOverlapEvents(true); - - AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); - if (OptiXVRPawn) - { - OptiXVRPawn->UIEventTranslation(); - } - -} - -void ASelectableActorBase::EnableRotation() -{ - TranslationSupport->SetHiddenInGame(true, true); - RotationSupport->SetHiddenInGame(false, true); - - SupportSphereV->SetGenerateOverlapEvents(true); - SupportSphereH->SetGenerateOverlapEvents(true); - ArrowX->SetGenerateOverlapEvents(false); - ArrowY->SetGenerateOverlapEvents(false); - ArrowZ->SetGenerateOverlapEvents(false); - - AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); - if (OptiXVRPawn) - { - OptiXVRPawn->UIEventRotation(); - } -} - -void ASelectableActorBase::DeselectActor() -{ - AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); - if (OptiXVRPawn) - { - OptiXVRPawn->UIEventDeselect(); - } - Deselect(); -} - -void ASelectableActorBase::DeleteActor() -{ - AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); - if (OptiXVRPawn) - { - OptiXVRPawn->UIEventDelete(); - } - Destroy(); -} - - -void ASelectableActorBase::SetRodPosition(FVector TablePosition) -{ - - // Flip socket? - if (Socket->GetComponentLocation().Z > GetActorLocation().Z) - { - Socket->SetRelativeLocation(-1 * Socket->RelativeLocation); - } - - - FVector TableZero = TablePosition + FVector(0, 0, 95); // Table Height - - // Far away from the table or below table, make it go straight down - if ( (Socket->GetComponentLocation().Z <= TableZero.Z) || (Socket->GetComponentLocation() - TableZero).Size() > 200) - { - ConnectorH->SetWorldScale3D(FVector(0, 0, 0)); - ConnectorV->SetWorldScale3D(FVector(0.4, 0.4, -10)); - return; - } - - - float ScaleFactorV = FMath::Abs(ConnectorV->GetComponentLocation().Z - TableZero.Z) / 100.0f; - ConnectorV->SetWorldScale3D(FVector(0.4, 0.4, -ScaleFactorV)); - - FVector DistanceToSphere = TableZero - Sphere->GetComponentLocation(); - float ScaleFactorH = DistanceToSphere.Size() / 100.0f; - ConnectorH->SetWorldScale3D(FVector(0.4, 0.4, ScaleFactorH)); - - ConnectorH->SetWorldRotation(FRotationMatrix::MakeFromZ(DistanceToSphere).Rotator()); - -} - -// TODO Material highlighting - swap material slots? -void ASelectableActorBase::OnOverlapBegin_Implementation(UPrimitiveComponent * OverlapComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) -{ - - AOptiXVRPawn* OverlappingPawn = Cast<AOptiXVRPawn>(OtherActor); - - if (OverlappingPawn != nullptr) - { - OverlappingPawn->OnOverlapBeginWithLever(OverlapComponent); - } - - //int32 N = OverlapComponent->GetNumMaterials(); - //for (int32 i = 0; i < N; i++) - //{ - // Cast<UMaterialInstanceDynamic>(OverlapComponent->GetMaterial(i))->SetVectorParameterValue("Color", FLinearColor(0.5, 0.5, 0.8)); - //} -} - -void ASelectableActorBase::OnOverlapEnd_Implementation(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) -{ - - AOptiXVRPawn* OverlappingPawn = Cast<AOptiXVRPawn>(OtherActor); - - if (OverlappingPawn != nullptr) - { - OverlappingPawn->OnOverlapEndWithLever(OverlappedComp); - } - - //int32 N = OverlappedComp->GetNumMaterials(); - //for (int32 i = 0; i < N; i++) - //{ - // Cast<UMaterialInstanceDynamic>(OverlappedComp->GetMaterial(i))->SetVectorParameterValue("Color", FLinearColor(0.4, 0.4, 0.4)); - //} -} +// Fill out your copyright notice in the Description page of Project Settings. + +#include "SelectableActorBase.h" +#include "UObject/ConstructorHelpers.h" +#include "Runtime/Engine/Classes/Engine/StaticMesh.h" +#include "Kismet/GameplayStatics.h" +#include "Blueprint/UserWidget.h" +#include "Runtime/Engine/Classes/Materials/MaterialInstanceDynamic.h" + +#include "OptiXVRPawn.h" + +ASelectableActorBase::ASelectableActorBase(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + + UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor Start")); + + SetMobility(EComponentMobility::Movable); + + GetStaticMeshComponent()->SetGenerateOverlapEvents(true); + GetStaticMeshComponent()->CastShadow = 0; + + UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor Component Setup Start")); + + + Gizmo = CreateDefaultSubobject<USceneComponent>(TEXT("Gizmo")); + Gizmo->SetupAttachment(GetStaticMeshComponent()); + Gizmo->SetHiddenInGame(true); + //Gizmo->SetAbsolute(false, true, true); + + SupportWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("SupportWidget")); + SupportWidget->SetAbsolute(false, true, true); + + SupportWidget->SetupAttachment(Gizmo); + static ConstructorHelpers::FClassFinder<UUserWidget> SupportWidgetClass(TEXT("/OptiX/UI/SupportSwapWidget2")); + SupportWidget->SetWidgetClass(SupportWidgetClass.Class); + SupportWidget->SetWorldScale3D(FVector(0.05, 0.05, 0.05)); + SupportWidget->SetDrawSize(FVector2D(800, 2300)); + SupportWidget->SetGenerateOverlapEvents(false); + SupportWidget->SetHiddenInGame(true); + SupportWidget->SetTwoSided(true); + + UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 1/4")); + + + TranslationSupport = CreateDefaultSubobject<USceneComponent>(TEXT("TranslationSupport")); + TranslationSupport->SetupAttachment(Gizmo); + + TranslateX = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateX")); + TranslateX->SetAbsolute(false, true, true); + TranslateX->SetupAttachment(TranslationSupport); + static ConstructorHelpers::FObjectFinder<UStaticMesh> TranslateXMesh(TEXT("StaticMesh'/OptiX/UI/Translator/Arrowbody.Arrowbody'")); + TranslateX->SetStaticMesh(TranslateXMesh.Object); + TranslateX->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); + TranslateX->SetGenerateOverlapEvents(false); + TranslateX->SetHiddenInGame(true); + + TranslateX->CastShadow = 0; + TranslateX->bVisibleInReflectionCaptures = false; + TranslateX->SetCanEverAffectNavigation(false); + + ArrowX = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowX")); + ArrowX->SetAbsolute(false, false, true); + ArrowX->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); + ArrowX->SetupAttachment(TranslateX); + static ConstructorHelpers::FObjectFinder<UStaticMesh> TranslateArrow(TEXT("StaticMesh'/OptiX/UI/Translator/Arrowhead.Arrowhead'")); + ArrowX->SetStaticMesh(TranslateArrow.Object); + //ArrowX->SetAbsolute(false, true, false); + ArrowX->SetRelativeLocation(FVector(39, 0, 0)); + ArrowX->SetGenerateOverlapEvents(false); + ArrowX->SetHiddenInGame(true); + + ArrowX->CastShadow = 0; + ArrowX->bVisibleInReflectionCaptures = false; + ArrowX->SetCanEverAffectNavigation(false); + + TranslateY = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateY")); + TranslateY->SetAbsolute(false, true, true); + + TranslateY->SetupAttachment(TranslationSupport); + TranslateY->SetStaticMesh(TranslateXMesh.Object); + TranslateY->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); + TranslateY->SetGenerateOverlapEvents(false); + TranslateY->SetHiddenInGame(true); + TranslateY->SetWorldRotation(FRotator(0.f, 90.0f, 0.0f)); + + TranslateY->CastShadow = 0; + TranslateY->bVisibleInReflectionCaptures = false; + TranslateY->SetCanEverAffectNavigation(false); + + ArrowY = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowY")); + ArrowY->SetAbsolute(false, false, true); + + ArrowY->SetupAttachment(TranslateY); + ArrowY->SetStaticMesh(TranslateArrow.Object); + //ArrowY->SetAbsolute(false, true, false); + ArrowY->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); + ArrowY->SetRelativeLocation(FVector(39, 0, 0)); + ArrowY->SetGenerateOverlapEvents(false); + ArrowY->SetHiddenInGame(true); + + ArrowY->CastShadow = 0; + ArrowY->bVisibleInReflectionCaptures = false; + ArrowY->SetCanEverAffectNavigation(false); + + TranslateZ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TranslateZ")); + TranslateZ->SetAbsolute(false, true, true); + TranslateZ->SetupAttachment(TranslationSupport); + TranslateZ->SetStaticMesh(TranslateXMesh.Object); + TranslateZ->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); + TranslateZ->SetGenerateOverlapEvents(false); + TranslateZ->SetHiddenInGame(true); + TranslateZ->SetWorldRotation(FRotator(90.f, 0.0f, 0.0f)); + TranslateZ->SetCanEverAffectNavigation(false); + TranslateZ->CastShadow = 0; + TranslateZ->bVisibleInReflectionCaptures = false; + + + ArrowZ = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ArrowZ")); + ArrowZ->SetAbsolute(false, false, true); + ArrowZ->SetupAttachment(TranslateZ); + ArrowZ->SetStaticMesh(TranslateArrow.Object); + //ArrowZ->SetAbsolute(false, true, false); + ArrowZ->SetWorldScale3D(FVector(0.6f, 0.6f, 0.6f)); + ArrowZ->SetRelativeLocation(FVector(39, 0, 0)); + ArrowZ->SetGenerateOverlapEvents(false); + ArrowZ->SetHiddenInGame(true); + ArrowZ->SetCanEverAffectNavigation(false); + ArrowZ->CastShadow = 0; + ArrowZ->bVisibleInReflectionCaptures = false; + + UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 2/4")); + + + RotationSupport = CreateDefaultSubobject<USceneComponent>(TEXT("RotationSupport")); + RotationSupport->SetupAttachment(Gizmo); + + ScaleH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ScaleH")); + ScaleH->SetupAttachment(RotationSupport); + static ConstructorHelpers::FObjectFinder<UStaticMesh> ScaleMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/scale1.scale1'")); + ScaleH->SetStaticMesh(ScaleMesh.Object); + ScaleH->SetAbsolute(false, true, false); + ScaleH->SetGenerateOverlapEvents(false); + ScaleH->SetCollisionEnabled(ECollisionEnabled::NoCollision); + ScaleH->SetHiddenInGame(true); + ScaleH->SetCanEverAffectNavigation(false); + ScaleH->CastShadow = 0; + ScaleH->bVisibleInReflectionCaptures = false; + + ScaleV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ScaleV")); + ScaleV->SetupAttachment(RotationSupport); + ScaleV->SetStaticMesh(ScaleMesh.Object); + ScaleV->SetWorldRotation(FRotator(90, 0, 0)); + ScaleV->SetAbsolute(false, true, false); + ScaleV->SetGenerateOverlapEvents(false); + ScaleV->SetCollisionEnabled(ECollisionEnabled::NoCollision); + ScaleV->SetHiddenInGame(true); + ScaleV->SetCanEverAffectNavigation(false); + ScaleV->CastShadow = 0; + ScaleV->bVisibleInReflectionCaptures = false; + + SupportH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportH")); + SupportH->SetupAttachment(RotationSupport); + static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/Cylinder_2.Cylinder_2'")); + SupportH->SetStaticMesh(SupportMesh.Object); + SupportH->SetWorldRotation(FRotator(-90, 0, 0)); + SupportH->SetWorldScale3D(FVector(0.6, 0.6, 0.3)); + SupportH->SetGenerateOverlapEvents(false); + SupportH->SetHiddenInGame(true); + //SupportH->SetWorldLocation(FVector(25, 0, 0)); + SupportH->SetCanEverAffectNavigation(false); + SupportH->CastShadow = 0; + SupportH->bVisibleInReflectionCaptures = false; + + SupportSphereH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportSphereH")); + SupportSphereH->SetupAttachment(SupportH); + static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportSphereMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/SelectorSphere.SelectorSphere'")); + SupportSphereH->SetStaticMesh(SupportSphereMesh.Object); + SupportSphereH->SetAbsolute(false, false, true); + SupportSphereH->SetWorldScale3D(FVector(0.03, 0.03, 0.03)); + SupportSphereH->SetGenerateOverlapEvents(false); + SupportSphereH->SetHiddenInGame(true); + SupportSphereH->SetRelativeLocation(FVector(0, 0, 100)); + SupportSphereH->SetCanEverAffectNavigation(false); + SupportSphereH->CastShadow = 0; + SupportSphereH->bVisibleInReflectionCaptures = false; + + DegreeWidgetH = CreateDefaultSubobject<UWidgetComponent>(TEXT("DegreeWidgetH")); + DegreeWidgetH->SetupAttachment(SupportSphereH); + static ConstructorHelpers::FClassFinder<UUserWidget> DegreeWidgetClass(TEXT("/OptiX/UI/Rotator/DegreeCounter")); + DegreeWidgetH->SetWidgetClass(DegreeWidgetClass.Class); + DegreeWidgetH->SetRelativeLocationAndRotation(FVector(0, 0, -40), FRotator(0, 90, -90)); + //DegreeWidgetH->SetRelativeScale3D(FVector(2.0, 2.0, 0.08)); + DegreeWidgetH->SetDrawSize(FVector2D(200, 300)); + DegreeWidgetH->SetHiddenInGame(true); + DegreeWidgetH->SetGenerateOverlapEvents(false); + //DegreeWidgetH->SetTwoSided(true); + + SupportV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportV")); + SupportV->SetupAttachment(RotationSupport); + SupportV->SetStaticMesh(SupportMesh.Object); + SupportV->SetWorldRotation(FRotator(0.0f, 0.0f, 90.0f)); + SupportV->SetWorldScale3D(FVector(0.6, 0.6, 0.3)); + SupportV->SetGenerateOverlapEvents(false); + SupportV->SetHiddenInGame(true); + //SupportV->SetWorldLocation(FVector(0, 25, 0)); + SupportV->SetCanEverAffectNavigation(false); + SupportV->CastShadow = 0; + SupportV->bVisibleInReflectionCaptures = false; + + SupportSphereV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SupportSphereV")); + SupportSphereV->SetupAttachment(SupportV); + //static ConstructorHelpers::FObjectFinder<UStaticMesh> SupportSphereMesh(TEXT("StaticMesh'/OptiX/UI/Rotator/Sphere_2.Sphere_2'")); + SupportSphereV->SetStaticMesh(SupportSphereMesh.Object); + SupportSphereV->SetAbsolute(false, false, true); + SupportSphereV->SetWorldScale3D(FVector(0.03, 0.03, 0.03)); + SupportSphereV->SetGenerateOverlapEvents(false); + SupportSphereV->SetHiddenInGame(true); + SupportSphereV->SetRelativeLocation(FVector(0, 0, 100)); + SupportSphereV->SetCanEverAffectNavigation(false); + SupportSphereV->CastShadow = 0; + SupportSphereV->bVisibleInReflectionCaptures = false; + + DegreeWidgetV = CreateDefaultSubobject<UWidgetComponent>(TEXT("DegreeWidgetV")); + DegreeWidgetV->SetupAttachment(SupportSphereV); + DegreeWidgetV->SetWidgetClass(DegreeWidgetClass.Class); + DegreeWidgetV->SetRelativeLocationAndRotation(FVector(0, 0, 40), FRotator(0, 0, -90)); + //DegreeWidgetV->SetRelativeScale3D(FVector(2.0, 2.0, 0.08)); + DegreeWidgetV->SetDrawSize(FVector2D(200, 300)); + DegreeWidgetV->SetHiddenInGame(true); + DegreeWidgetV->SetGenerateOverlapEvents(false); + //DegreeWidgetV->SetTwoSided(true); + + UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor 3/4")); + + + // Rods + + static ConstructorHelpers::FObjectFinder<UMaterial> MetalMaterial(TEXT("Material'/OptiX/Laser/MetalSilver.MetalSilver'")); + static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMesh(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'")); + static ConstructorHelpers::FObjectFinder<UStaticMesh> Cylinder2(TEXT("StaticMesh'/OptiX/UI/Rotator/Cylinder_2.Cylinder_2'")); + + Socket = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SocketNew")); + Socket->SetAbsolute(false, false, true); + + Socket->SetupAttachment(GetStaticMeshComponent()); + Socket->SetStaticMesh(SphereMesh.Object); + Socket->SetGenerateOverlapEvents(false); + Socket->SetMaterial(0, MetalMaterial.Object); + Socket->SetCollisionEnabled(ECollisionEnabled::NoCollision); + Socket->SetWorldScale3D(FVector(0.02, 0.02, 0.02)); + //Socket->SetRelativeLocation(FVector(0, 0, 0)); + Socket->SetCanEverAffectNavigation(false); + Socket->CastShadow = 0; + Socket->bVisibleInReflectionCaptures = false; + + ConnectorV = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ConnectorVNew")); + ConnectorV->SetAbsolute(false, true, true); + + ConnectorV->SetupAttachment(Socket); + ConnectorV->SetStaticMesh(Cylinder2.Object); + ConnectorV->SetWorldScale3D(FVector(0.4, 0.4, -1)); + ConnectorV->SetGenerateOverlapEvents(false); + ConnectorV->SetCollisionEnabled(ECollisionEnabled::NoCollision); + ConnectorV->SetMaterial(0, MetalMaterial.Object); + ConnectorV->SetMaterial(1, MetalMaterial.Object); + ConnectorV->SetCanEverAffectNavigation(false); + ConnectorV->CastShadow = 0; + ConnectorV->bVisibleInReflectionCaptures = false; + + Sphere = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SphereNew")); + Sphere->SetAbsolute(false, false, true); + + Sphere->SetupAttachment(ConnectorV); + Sphere->SetStaticMesh(SphereMesh.Object); + Sphere->SetGenerateOverlapEvents(false); + Sphere->SetMaterial(0, MetalMaterial.Object); + Sphere->SetCollisionEnabled(ECollisionEnabled::NoCollision); + Sphere->SetWorldScale3D(FVector(0.02, 0.02, 0.02)); + Sphere->SetRelativeLocation(FVector(0, 0, 100)); + Sphere->SetCanEverAffectNavigation(false); + Sphere->CastShadow = 0; + Sphere->bVisibleInReflectionCaptures = false; + + ConnectorH = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ConnectorHNew")); + ConnectorH->SetAbsolute(false, true, true); + ConnectorH->SetupAttachment(ConnectorV); + ConnectorH->SetStaticMesh(Cylinder2.Object); + ConnectorH->SetGenerateOverlapEvents(false); + ConnectorH->SetRelativeLocation(FVector(0, 0, 100)); + ConnectorH->SetWorldScale3D(FVector(0.4, 0.4, 1.0)); + ConnectorH->SetMaterial(0, MetalMaterial.Object); + ConnectorH->SetMaterial(1, MetalMaterial.Object); + ConnectorH->SetGenerateOverlapEvents(false); + ConnectorH->SetCollisionEnabled(ECollisionEnabled::NoCollision); + ConnectorH->SetCanEverAffectNavigation(false); + ConnectorH->CastShadow = 0; + ConnectorH->bVisibleInReflectionCaptures = false; + + + static ConstructorHelpers::FClassFinder<UUserWidget> PosWidgetClass(TEXT("/OptiX/UI/Translator/PositionCounter")); + + TranslateWidgetX = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetX")); + TranslateWidgetX->SetAbsolute(false, true, true); + TranslateWidgetX->SetupAttachment(ArrowX); + TranslateWidgetX->SetWidgetClass(PosWidgetClass.Class); + //TranslateWidgetX->SetRelativeLocationAndRotation(FVector(0, 0, 0), FRotator(0, 90, 0)); + //TranslateWidgetX->SetWorldRotation(FRotator()); + TranslateWidgetX->SetRelativeScale3D(FVector(0.05, 0.05, 0.05)); + TranslateWidgetX->SetDrawSize(FVector2D(300, 300)); + TranslateWidgetX->SetHiddenInGame(true); + TranslateWidgetX->SetGenerateOverlapEvents(false); + //TranslateWidgetX->SetTwoSided(true); + // todo + + TranslateWidgetY = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetY")); + TranslateWidgetY->SetAbsolute(false, true, true); + TranslateWidgetY->SetupAttachment(ArrowY); + TranslateWidgetY->SetWidgetClass(PosWidgetClass.Class); + //TranslateWidgetY->SetWorldRotation(FRotator()); + TranslateWidgetY->SetRelativeScale3D(FVector(0.05, 0.05, 0.05)); + TranslateWidgetY->SetDrawSize(FVector2D(300, 300)); + TranslateWidgetY->SetHiddenInGame(true); + TranslateWidgetY->SetGenerateOverlapEvents(false); + //TranslateWidgetY->SetTwoSided(true); + + TranslateWidgetZ = CreateDefaultSubobject<UWidgetComponent>(TEXT("TranslateWidgetZ")); + TranslateWidgetZ->SetAbsolute(false, true, true); + //TranslateWidgetZ->SetTwoSided(true); + + TranslateWidgetZ->SetupAttachment(ArrowZ); + TranslateWidgetZ->SetWidgetClass(PosWidgetClass.Class); + //TranslateWidgetZ->SetWorldRotation(FRotator()); + TranslateWidgetZ->SetRelativeScale3D(FVector(0.05, 0.05, 0.05)); + TranslateWidgetZ->SetDrawSize(FVector2D(300, 300)); + TranslateWidgetZ->SetRelativeLocation(FVector(8, 0, 0)); + + TranslateWidgetZ->SetHiddenInGame(true); + TranslateWidgetZ->SetGenerateOverlapEvents(false); + + UE_LOG(LogTemp, Display, TEXT("OptiX ASelectableActorBase Constructor End 4/4")); + + +} + +void ASelectableActorBase::BeginPlay() +{ + Super::BeginPlay(); + + ArrowX->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowX->GetMaterial(0)); + ArrowX->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowX->GetMaterial(1)); + ArrowY->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowY->GetMaterial(0)); + ArrowY->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowY->GetMaterial(1)); + ArrowZ->CreateAndSetMaterialInstanceDynamicFromMaterial(0, ArrowZ->GetMaterial(0)); + ArrowZ->CreateAndSetMaterialInstanceDynamicFromMaterial(1, ArrowZ->GetMaterial(1)); + + SupportSphereH->CreateAndSetMaterialInstanceDynamicFromMaterial(0, SupportSphereH->GetMaterial(0)); + SupportSphereV->CreateAndSetMaterialInstanceDynamicFromMaterial(0, SupportSphereV->GetMaterial(0)); + + + SupportSphereH->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); + SupportSphereH->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); + + SupportSphereV->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); + SupportSphereV->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); + + ArrowX->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); + ArrowX->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); + + ArrowY->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); + ArrowY->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); + + ArrowZ->OnComponentBeginOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapBegin); + ArrowZ->OnComponentEndOverlap.AddDynamic(this, &ASelectableActorBase::OnOverlapEnd); +} + +void ASelectableActorBase::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + + + FVector PlayerLocation = UGameplayStatics::GetPlayerPawn(GetWorld(), 0)->GetActorLocation(); + { + FVector Diff = PlayerLocation - DegreeWidgetV->GetComponentTransform().GetLocation(); + FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); + DegreeWidgetV->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); + } + { + FVector Diff = PlayerLocation - DegreeWidgetH->GetComponentTransform().GetLocation(); + FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); + DegreeWidgetH->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); + } + { + FVector Diff = PlayerLocation - SupportWidget->GetComponentTransform().GetLocation(); + FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); + SupportWidget->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); + } + { + FVector Diff = PlayerLocation - TranslateWidgetX->GetComponentTransform().GetLocation(); + FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); + TranslateWidgetX->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); + } + { + FVector Diff = PlayerLocation - TranslateWidgetY->GetComponentTransform().GetLocation(); + FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); + TranslateWidgetY->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); + } + { + FVector Diff = PlayerLocation - TranslateWidgetZ->GetComponentTransform().GetLocation(); + FVector Projected = FVector::VectorPlaneProject(Diff, FVector(0, 0, 1)); + TranslateWidgetZ->SetWorldRotation(FRotationMatrix::MakeFromXZ(Projected, FVector(0, 0, 1)).Rotator()); + } + +} + +void ASelectableActorBase::SetScaleV(FRotator Rot) +{ + ScaleV->SetWorldRotation(Rot); +} + +void ASelectableActorBase::SetScaleH(FRotator Rot) +{ + ScaleH->SetWorldRotation(Rot); +} + +void ASelectableActorBase::EnableTranslation() +{ + TranslationSupport->SetHiddenInGame(false, true); + RotationSupport->SetHiddenInGame(true, true); + + SupportSphereV->SetGenerateOverlapEvents(false); + SupportSphereH->SetGenerateOverlapEvents(false); + ArrowX->SetGenerateOverlapEvents(true); + ArrowY->SetGenerateOverlapEvents(true); + ArrowZ->SetGenerateOverlapEvents(true); + + AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); + if (OptiXVRPawn) + { + OptiXVRPawn->UIEventTranslation(); + } + +} + +void ASelectableActorBase::EnableRotation() +{ + TranslationSupport->SetHiddenInGame(true, true); + RotationSupport->SetHiddenInGame(false, true); + + SupportSphereV->SetGenerateOverlapEvents(true); + SupportSphereH->SetGenerateOverlapEvents(true); + ArrowX->SetGenerateOverlapEvents(false); + ArrowY->SetGenerateOverlapEvents(false); + ArrowZ->SetGenerateOverlapEvents(false); + + AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); + if (OptiXVRPawn) + { + OptiXVRPawn->UIEventRotation(); + } +} + +void ASelectableActorBase::DeselectActor() +{ + AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); + if (OptiXVRPawn) + { + OptiXVRPawn->UIEventDeselect(); + } + Deselect(); +} + +void ASelectableActorBase::DeleteActor() +{ + AOptiXVRPawn* OptiXVRPawn = Cast<AOptiXVRPawn>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0)); + if (OptiXVRPawn) + { + OptiXVRPawn->UIEventDelete(); + } + Destroy(); +} + + +void ASelectableActorBase::SetRodPosition(FVector TablePosition) +{ + + // Flip socket? + if (Socket->GetComponentLocation().Z > GetActorLocation().Z) + { + Socket->SetRelativeLocation(-1 * Socket->RelativeLocation); + } + + + FVector TableZero = TablePosition + FVector(0, 0, 95); // Table Height + + // Far away from the table or below table, make it go straight down + if ( (Socket->GetComponentLocation().Z <= TableZero.Z) || (Socket->GetComponentLocation() - TableZero).Size() > 200) + { + ConnectorH->SetWorldScale3D(FVector(0, 0, 0)); + ConnectorV->SetWorldScale3D(FVector(0.4, 0.4, -10)); + return; + } + + + float ScaleFactorV = FMath::Abs(ConnectorV->GetComponentLocation().Z - TableZero.Z) / 100.0f; + ConnectorV->SetWorldScale3D(FVector(0.4, 0.4, -ScaleFactorV)); + + FVector DistanceToSphere = TableZero - Sphere->GetComponentLocation(); + float ScaleFactorH = DistanceToSphere.Size() / 100.0f; + ConnectorH->SetWorldScale3D(FVector(0.4, 0.4, ScaleFactorH)); + + ConnectorH->SetWorldRotation(FRotationMatrix::MakeFromZ(DistanceToSphere).Rotator()); + +} + +// TODO Material highlighting - swap material slots? +void ASelectableActorBase::OnOverlapBegin_Implementation(UPrimitiveComponent * OverlapComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) +{ + + AOptiXVRPawn* OverlappingPawn = Cast<AOptiXVRPawn>(OtherActor); + + if (OverlappingPawn != nullptr) + { + OverlappingPawn->OnOverlapBeginWithLever(OverlapComponent); + } + + //int32 N = OverlapComponent->GetNumMaterials(); + //for (int32 i = 0; i < N; i++) + //{ + // Cast<UMaterialInstanceDynamic>(OverlapComponent->GetMaterial(i))->SetVectorParameterValue("Color", FLinearColor(0.5, 0.5, 0.8)); + //} +} + +void ASelectableActorBase::OnOverlapEnd_Implementation(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) +{ + + AOptiXVRPawn* OverlappingPawn = Cast<AOptiXVRPawn>(OtherActor); + + if (OverlappingPawn != nullptr) + { + OverlappingPawn->OnOverlapEndWithLever(OverlappedComp); + } + + //int32 N = OverlappedComp->GetNumMaterials(); + //for (int32 i = 0; i < N; i++) + //{ + // Cast<UMaterialInstanceDynamic>(OverlappedComp->GetMaterial(i))->SetVectorParameterValue("Color", FLinearColor(0.4, 0.4, 0.4)); + //} +} diff --git a/Source/OptiX/Public/OptiXContextManager.h b/Source/OptiX/Public/OptiXContextManager.h index 822beaa36cd843d78f68a91a659a42adf83ba91a..2634494b20ae6565db5bf26fb0aa8ecd1231a31f 100644 --- a/Source/OptiX/Public/OptiXContextManager.h +++ b/Source/OptiX/Public/OptiXContextManager.h @@ -1,797 +1,799 @@ -#pragma once - -#include "CoreMinimal.h" -#include "EngineUtils.h" - -#include "Runtime/Engine/Public/SceneViewExtension.h" - -#include "Runtime/Engine/Classes/Engine/Texture2D.h" - -#include "MaterialShared.h" -#include "Materials/MaterialInstance.h" -#include "Delegates/Delegate.h" - -#include "OptiXContext.h" -#include "OptiXObjectComponent.h" -#include "OptiXLaserComponent.h" -#include "OptiXLaserActor.h" -#include "OptiXCameraActor.h" - - - -// Let's try some events! - -DECLARE_EVENT(FOptiXContextManager, FLaserTraceFinishedEvent) -DECLARE_EVENT_OneParam(FOptiXContextManager, FWavelengthChangedEvent, const float) -DECLARE_MULTICAST_DELEGATE(FOnSceneChangedDelegate); - -// DX - -#if PLATFORM_WINDOWS -#include "AllowWindowsPlatformTypes.h" -#endif -#include <d3d11.h> -#if PLATFORM_WINDOWS -#include "HideWindowsPlatformTypes.h" -#endif - -// print cuda error helper: - -inline void PrintLastCudaError(FString Msg) -{ - cudaError_t Err = cudaGetLastError(); - if (cudaSuccess != Err) { - UE_LOG(LogTemp, Fatal, TEXT("Cuda Error: %s. "), *Msg, static_cast<int>(Err), cudaGetErrorString(Err)); - } -} - - -class OPTIX_API FOptiXContextManager : public FSceneViewExtensionBase -{ - -public: - - // The auto register thing is used to make sure this constructor is only called via the NewExtension function - FOptiXContextManager(const FAutoRegister& AutoRegister); - - ~FOptiXContextManager() - { - if (bIsInitialized) - { - cudaGraphicsUnregisterResource(CudaResourceDepthLeft); - cudaGraphicsUnregisterResource(CudaResourceDepthRight); - cudaGraphicsUnregisterResource(CudaResourceColorLeft); - cudaGraphicsUnregisterResource(CudaResourceColorRight); - cudaGraphicsUnregisterResource(CudaResourceIntersections); - cudaGraphicsUnregisterResource(CudaResourceColorOrtho); - cudaGraphicsUnregisterResource(CudaResourceDepthOrtho); - - PrintLastCudaError("cudaGraphicsUnregisterResource"); - cudaFree(CudaLinearMemoryDepth); - cudaFree(CudaLinearMemoryColor); - cudaFree(CudaLinearMemoryIntersections); - PrintLastCudaError("cudaFree"); - } - - AccelerationsToDeleteQueue.Empty(); - BuffersToDeleteQueue.Empty(); - GeometriesToDeleteQueue.Empty(); - GeometryGroupToDeleteQueue.Empty(); - GeometryInstancesToDeleteQueue.Empty(); - GroupsToDeleteQueue.Empty(); - MaterialsToDeleteQueue.Empty(); - ProgramToDeleteQueue.Empty(); - TextureSamplersToDeleteQueue.Empty(); - TransformsToDeleteQueue.Empty(); - - GroupChildrenToRemoveQueue.Empty(); - GeometryGroupChildrenToRemoveQueue.Empty(); - - ComponentsToInitializeQueue.Empty(); - ComponentsToUpdateQueue.Empty(); - CubemapComponentsToUpdateQueue.Empty(); - - LaserActor.Reset(); - CameraActor.Reset(); - } - - // ISceneViewExtension interface start, called by the render thread: -public: - virtual void SetupViewFamily(FSceneViewFamily& InViewFamily) override; - virtual void SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView) override; - virtual void BeginRenderViewFamily(FSceneViewFamily& InViewFamily) override; - virtual void PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& InView) override; - virtual void PreRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& InViewFamily) override; - virtual void PostRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& InViewFamily) override; - virtual bool IsActiveThisFrame(class FViewport* InViewport) const override; - virtual void PostRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& InView) override; - // ISceneViewExtension interface end - - - void RenderOrthoPass(); - - // Initialization methods, called by the GAME thread - void Init(); - - void EndPlay() - { - //CleanupOptiXOnEnd(); - //bCleanup.AtomicSet(true); - //bStartTracing.AtomicSet(false); - //bCleanup.AtomicSet(false); - //bEndPlay.AtomicSet(true); - } - - UOptiXContext* GetOptiXContext() - { - return OptiXContext.Get(); - } - - UMaterialInstanceDynamic* GetOptiXMID() // Used to set up the post process - { - return DynamicMaterial.Get(); - } - - UMaterialInstanceDynamic* GetOptiXMIDOrtho() // Used to set up the post process - { - return DynamicMaterialOrtho.Get(); - } - - void SceneChangedCallback(); - - // The OptiX context is not thread-safe, so any changes to variables/properties on the game thread - // while a trace is running will lead to errors. Game thread objects push their requested updates into several queues, - // which then get updated just before the trace runs on the render thread. - // TQueue is guaranteed to be thread-safe. - // There is probably a better and faster way of doing this. - - void RegisterOptiXComponent(IOptiXComponentInterface* Component) - { - ComponentsToInitializeQueue.Enqueue(Component); - } - - void QueueComponentUpdate(IOptiXComponentInterface* Component) - { - ComponentsToUpdateQueue.Enqueue(Component); - } - - void RequestCubemapUpdate(UOptiXCubemapComponent* Component) - { - CubemapComponentsToUpdateQueue.Enqueue(Component); - } - - void SetActiveLaserActor(AOptiXLaserActor* Laser) - { - LaserActor = Laser; - if (LaserMaterialDynamic.IsValid()) - { - LaserActor->SetLaserMaterial(LaserMaterialDynamic.Get()); - } - else - { - UE_LOG(LogTemp, Error, TEXT("LaserMaterialDynamic is invalid!")); - } - } - - void SetActiveCameraActor(AOptiXPlayerCameraManager* Cam) - { - CameraActor = Cam; - } - - FIntRect GetViewRectanglePerEye() - { - return FIntRect(0, 0, Width, Height); - } - - int32 RequestCubemapId(); - - void DeleteCubemapId(int32 Id); - - void AddCubemapToBuffer(int32 CubemapId, int32 SamplerId); - - void BroadcastWavelengthChange(float WL) - { - WavelengthChangedEvent.Broadcast(WL); - } - - -public: - - FThreadSafeBool bStartTracing = false; - //FThreadSafeBool bEndPlay = false; - FThreadSafeBool bIsInitialized = false; - FThreadSafeBool bLaserIsInitialized = false; - FThreadSafeBool bSceneChanged = true; - FThreadSafeBool bIsTracing = false; - FThreadSafeBool bClearToLaunch = true; - FThreadSafeBool bCleanup = false; - FThreadSafeBool bValidCubemap = false; - FThreadSafeBool bRequestOrthoPass = false; - - FLaserTraceFinishedEvent LaserTraceFinishedEvent; - FWavelengthChangedEvent WavelengthChangedEvent; - FOnSceneChangedDelegate OnSceneChangedDelegate; - - -public: - - // This is so ugly but the optix api structure doesn't really allow anything more abstract. - TQueue<optix::Acceleration> AccelerationsToDeleteQueue; - TQueue<optix::Buffer> BuffersToDeleteQueue; - TQueue<optix::Geometry> GeometriesToDeleteQueue; - TQueue<optix::GeometryGroup> GeometryGroupToDeleteQueue; - TQueue<optix::GeometryInstance> GeometryInstancesToDeleteQueue; - TQueue<optix::Group> GroupsToDeleteQueue; - TQueue<optix::Material> MaterialsToDeleteQueue; - TQueue<optix::Program> ProgramToDeleteQueue; - TQueue<optix::TextureSampler> TextureSamplersToDeleteQueue; - TQueue<optix::Transform> TransformsToDeleteQueue; - - TQueue<TPair<optix::Group, uint32>> GroupChildrenToRemoveQueue; - TQueue<TPair<optix::GeometryGroup, uint32>> GeometryGroupChildrenToRemoveQueue; - - FMatrix OrthoMatrix; - -private: - void InitContext(); - void InitRendering(); - void InitBuffers(); - void InitPrograms(); - void InitLaser(); - - void LaunchLaser(); - - void InitCubemap(); - - void InitOptiXComponents(FRHICommandListImmediate & RHICmdList) - { - // Possibly dangerous? Use limited for instead of while in case something goes wrong and we deadlock - for (uint32 i = 0; i < 100 && !ComponentsToInitializeQueue.IsEmpty(); i++) - { - IOptiXComponentInterface* Component; - if (ComponentsToInitializeQueue.Dequeue(Component)) - { - Component->InitOptiXComponent(RHICmdList); - } - } - } - - void UpdateOptiXComponentVariables() - { - for (uint32 i = 0; i < 100 && !ComponentsToUpdateQueue.IsEmpty(); i++) - { - IOptiXComponentInterface* Component; - if (ComponentsToUpdateQueue.Dequeue(Component)) - { - if (Component != nullptr) - { - Component->UpdateOptiXComponentVariables(); - Component->SetUpdateQueued(false);// bUpdateQueued.AtomicSet(false); - } - } - } - } - - void RemovePendingChildrenFromGroups() - { - for (uint32 i = 0; i < 100 && !GroupChildrenToRemoveQueue.IsEmpty(); i++) - { - TPair<optix::Group, uint32> Pair; - if (GroupChildrenToRemoveQueue.Dequeue(Pair)) - { - if (Pair.Key != NULL) - { - Pair.Key->removeChild(Pair.Value); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to remove optix child in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !GeometryGroupChildrenToRemoveQueue.IsEmpty(); i++) - { - TPair<optix::GeometryGroup, uint32> Pair; - if (GeometryGroupChildrenToRemoveQueue.Dequeue(Pair)) - { - if (Pair.Key != NULL) - { - Pair.Key->removeChild(Pair.Value); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to remove optix child in queue: Object was NULL")); - } - } - } - } - - void DestroyOptiXObjects() - { - for (uint32 i = 0; i < 100 && !AccelerationsToDeleteQueue.IsEmpty(); i++) - { - optix::Acceleration NativeObj; - if (AccelerationsToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - if(NativeObj->getContext() != NULL) - NativeObj->destroy(); // TODO do we need to do anything else here? - else - { - UE_LOG(LogTemp, Warning, TEXT("Context already destroyed but somehow this buffer handle is still valid")); - } - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !BuffersToDeleteQueue.IsEmpty(); i++) - { - optix::Buffer NativeObj; - if (BuffersToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - try - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - catch (optix::Exception& E) - { - FString Message = FString(E.getErrorString().c_str()); - UE_LOG(LogTemp, Error, TEXT("Trying to remove buffer: OptiX Error: %s"), *Message); - GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("OptiX Error %s"), *Message)); - } - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !GeometriesToDeleteQueue.IsEmpty(); i++) - { - optix::Geometry NativeObj; - if (GeometriesToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !GeometryInstancesToDeleteQueue.IsEmpty(); i++) - { - optix::GeometryInstance NativeObj; - if (GeometryInstancesToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !GeometryGroupToDeleteQueue.IsEmpty(); i++) - { - optix::GeometryGroup NativeObj; - if (GeometryGroupToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !GroupsToDeleteQueue.IsEmpty(); i++) - { - optix::Group NativeObj; - if (GroupsToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !MaterialsToDeleteQueue.IsEmpty(); i++) - { - optix::Material NativeObj; - if (MaterialsToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !ProgramToDeleteQueue.IsEmpty(); i++) - { - optix::Program NativeObj; - if (ProgramToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !TextureSamplersToDeleteQueue.IsEmpty(); i++) - { - optix::TextureSampler NativeObj; - if (TextureSamplersToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - try - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - catch (optix::Exception& E) - { - FString Message = FString(E.getErrorString().c_str()); - UE_LOG(LogTemp, Error, TEXT("Trying to remove texture sampler: OptiX Error: %s"), *Message); - GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("OptiX Error %s"), *Message)); - } - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - for (uint32 i = 0; i < 100 && !TransformsToDeleteQueue.IsEmpty(); i++) - { - optix::Transform NativeObj; - if (TransformsToDeleteQueue.Dequeue(NativeObj)) - { - if (NativeObj != NULL) - { - NativeObj->destroy(); // TODO do we need to do anything else here? - } - else - { - UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); - } - } - } - } - - void UpdateRequestedCubemaps(FRHICommandListImmediate & RHICmdList) - { - // update only the first for now, shouldn't be more than 1 in queue anyway: - - if (!CubemapComponentsToUpdateQueue.IsEmpty()) - { - UOptiXCubemapComponent* Comp; - if (CubemapComponentsToUpdateQueue.Dequeue(Comp)) - { - Comp->UpdateCubemap(RHICmdList); - } - } - } - - void UpdateCubemapBuffer(FRHICommandListImmediate & RHICmdList); - - void CleanupOptiXOnEnd() - { - - UE_LOG(LogTemp, Display, TEXT("Starting Cleanup in Context Manager")); - - - if (bIsInitialized) - { - if(CudaResourceDepthLeft != NULL) - cudaGraphicsUnregisterResource(CudaResourceDepthLeft); - if (CudaResourceDepthRight != NULL) - cudaGraphicsUnregisterResource(CudaResourceDepthRight); - if (CudaResourceColorLeft != NULL) - cudaGraphicsUnregisterResource(CudaResourceColorLeft); - if(CudaResourceColorRight != NULL) - cudaGraphicsUnregisterResource(CudaResourceColorRight); - if(CudaResourceIntersections != NULL) - cudaGraphicsUnregisterResource(CudaResourceIntersections); - if (CudaResourceDepthOrtho != NULL) - cudaGraphicsUnregisterResource(CudaResourceDepthOrtho); - if (CudaResourceColorOrtho != NULL) - cudaGraphicsUnregisterResource(CudaResourceColorOrtho); - PrintLastCudaError("cudaGraphicsUnregisterResource"); - if(CudaLinearMemoryDepth != NULL) - cudaFree(CudaLinearMemoryDepth); - - if (CudaLinearMemoryColor != NULL) - cudaFree(CudaLinearMemoryColor); - - if (CudaLinearMemoryIntersections != NULL) - cudaFree(CudaLinearMemoryIntersections); - - PrintLastCudaError("cudaFree"); - } - - - - //check(IsInRenderingThread()); - bStartTracing.AtomicSet(false); - //bEndPlay.AtomicSet(false); - bIsInitialized.AtomicSet(false); - bLaserIsInitialized.AtomicSet(false); - bSceneChanged.AtomicSet(true); - bIsTracing.AtomicSet(false); - bClearToLaunch.AtomicSet(true); - bCleanup.AtomicSet(false); - bValidCubemap.AtomicSet(false); - - // Clear the queue - DestroyOptiXObjects(); - - if (OptiXContext.IsValid()) - { - OptiXContext->RemoveFromRoot(); - } - if (LaserOutputBuffer.IsValid()) - { - LaserOutputBuffer->RemoveFromRoot(); - } - if (OutputTexture.IsValid()) - { - OutputTexture->RemoveFromRoot(); - } - if (OutputTexture2.IsValid()) - { - OutputTexture2->RemoveFromRoot(); - } - if (DepthTexture.IsValid()) - { - DepthTexture->RemoveFromRoot(); - } - if (DepthTexture2.IsValid()) - { - DepthTexture2->RemoveFromRoot(); - } - if (CubemapSampler.IsValid()) - { - CubemapSampler->RemoveFromRoot(); - } - if (CubemapBuffer.IsValid()) - { - CubemapBuffer->RemoveFromRoot(); - } - - OutputBuffer.Reset(); - OutputDepthBuffer.Reset(); - - OutputTexture.Reset(); - DepthTexture.Reset(); - OutputTexture2.Reset(); - DepthTexture2.Reset(); - LaserIntersectionTexture.Reset(); - - DynamicMaterial.Reset(); - DynamicMaterialOrtho.Reset(); - RegularMaterial.Reset(); - VRMaterial.Reset(); - LaserMaterial.Reset(); - - LaserMaterialDynamic.Reset(); - - LaserActor.Reset(); - - TopObject.Reset(); - TopAcceleration.Reset(); - OptiXContext.Reset(); - - if (NativeContext != NULL) - { - NativeContext->destroy(); - NativeContext = NULL; - } - - /*{ - - OptiXContext->RemoveFromRoot(); - LaserOutputBuffer->RemoveFromRoot(); - OutputTexture->RemoveFromRoot(); - OutputTexture2->RemoveFromRoot(); - DepthTexture->RemoveFromRoot(); - DepthTexture2->RemoveFromRoot(); - - - - OutputBuffer.Reset(); - OutputDepthBuffer.Reset(); - - OutputTexture.Reset(); - DepthTexture.Reset(); - OutputTexture2.Reset(); - DepthTexture2.Reset(); - - DynamicMaterial.Reset(); - RegularMaterial.Reset(); - VRMaterial.Reset(); - - - TopObject.Reset(); - TopAcceleration.Reset(); - OptiXContext.Reset(); - - if (NativeContext != NULL) - { - NativeContext->destroy(); - } - }*/ - } - - -private: - // OptiX Part - - // Todo: refactor this to delegates maybe? - TQueue<IOptiXComponentInterface*> ComponentsToInitializeQueue; - TQueue<IOptiXComponentInterface*> ComponentsToUpdateQueue; - TQueue<UOptiXCubemapComponent*> CubemapComponentsToUpdateQueue; - - TWeakObjectPtr<AOptiXLaserActor> LaserActor; - - TWeakObjectPtr<AOptiXPlayerCameraManager> CameraActor; - - // OptiX Objects to be kept in the context manager, TODO triple check that the GC doesn't nab them. - // Those are always required, but some should also be changeable! TODO make custom setters for them later. - TWeakObjectPtr<UOptiXContext> OptiXContext; - TWeakObjectPtr<UOptiXProgram> RayGenerationProgram; - TWeakObjectPtr<UOptiXProgram> MissProgram; - TWeakObjectPtr<UOptiXProgram> ExceptionProgram; - - TWeakObjectPtr<UOptiXGroup> TopObject; - TWeakObjectPtr<UOptiXAcceleration> TopAcceleration; - - TWeakObjectPtr<UOptiXBuffer> OutputBuffer; - TWeakObjectPtr<UOptiXBuffer> OutputDepthBuffer; - - TWeakObjectPtr<UOptiXTextureSampler> CubemapSampler; - TWeakObjectPtr<UOptiXBuffer> CubemapBuffer; - TWeakObjectPtr<UOptiXBuffer> CubemapsInputBuffer; - - TQueue<int32> UnallocatedCubemapIds; - - TArray<TArray<FColor>> SurfaceDataCube; - - optix::Context NativeContext; - - - // Laser Part - TWeakObjectPtr<UOptiXBuffer> LaserOutputBuffer; - TWeakObjectPtr<UOptiXProgram> LaserRayGenerationProgram; - TWeakObjectPtr<UOptiXProgram> LaserMissProgram; - TWeakObjectPtr<UOptiXProgram> LaserExceptionProgram; - - - - // Rendering Part - - //FUpdateTextureRegion2D TextureRegion; - - //UTextureCube* TextureCube; - - int32 Width; - int32 Height; - - FTexture2DRHIRef OutputTextureColorRightRef; - FTexture2DRHIRef OutputTextureColorLeftRef; - FTexture2DRHIRef OutputTextureDepthRightRef; - FTexture2DRHIRef OutputTextureDepthLeftRef; - - FTexture2DRHIRef OutputTextureColorOrthoRef; - FTexture2DRHIRef OutputTextureDepthOrthoRef; - - TWeakObjectPtr<UTexture2D> OutputTexture; - TWeakObjectPtr<UTexture2D> DepthTexture; - TWeakObjectPtr<UTexture2D> OutputTexture2; - TWeakObjectPtr<UTexture2D> DepthTexture2; - - TWeakObjectPtr<UTexture2D> OutputTextureOrtho; - TWeakObjectPtr<UTexture2D> DepthTextureOrtho; - - TWeakObjectPtr<UMaterialInstanceDynamic> DynamicMaterial; - TWeakObjectPtr<UMaterialInstanceDynamic> DynamicMaterialOrtho; - TWeakObjectPtr<UMaterial> RegularMaterial; - TWeakObjectPtr<UMaterial> VRMaterial; - bool bWithHMD; - - - // --------------------------------------------------------------------------------------------------- - // Laser stuff - // --------------------------------------------------------------------------------------------------- - - FTexture2DRHIRef LaserIntersectionTextureRef; - - TWeakObjectPtr<UTexture2D> LaserIntersectionTexture; - TWeakObjectPtr<UMaterial> LaserMaterial; - TWeakObjectPtr<UMaterialInstanceDynamic> LaserMaterialDynamic; - - -public: - - TQueue<TPair<uint32, TArray<FVector>>> LaserIntersectionQueue; - - TArray<TArray<FVector>> PreviousLaserResults; - - -private: - - TArray<FVector4> IntersectionData; - TArray<FVector4> OldIntersectionData; - - FThreadSafeBool bTracingLaser; - - FCriticalSection CriticalSection; - - int32 LaserMaxDepth; - int32 LaserEntryPoint; - int32 LaserBufferSize; - - int32 LaserBufferWidth; - int32 LaserBufferHeight; - - - // --------------------------------------------------------------------------------------------------- - // DX <-> CUDA stuff - // --------------------------------------------------------------------------------------------------- - - -public: - // I'm not sure which ones I actually need - IDXGIAdapter *CudaCapableAdapter = NULL; // Adapter to use - ID3D11Device *D3DDevice = NULL; // Rendering device - ID3D11DeviceContext *D3DDeviceContext = NULL; - - // RTX mode - int RTXOn = 1; - - -private: - - void InitCUDADX(); - - - //ID3D11Texture2D* D3D11Texture; - cudaGraphicsResource* CudaResourceDepthLeft; - cudaGraphicsResource* CudaResourceDepthRight; - cudaGraphicsResource* CudaResourceColorLeft; - cudaGraphicsResource* CudaResourceColorRight; - cudaGraphicsResource* CudaResourceIntersections; - cudaGraphicsResource* CudaResourceColorOrtho; - cudaGraphicsResource* CudaResourceDepthOrtho; - void* CudaLinearMemoryDepth; - void* CudaLinearMemoryColor; - void* CudaLinearMemoryIntersections; - size_t Pitch; // fix me - size_t PitchLaser; - - cudaGraphicsResource *Resources[7]; +#pragma once + +#include "CoreMinimal.h" +#include "EngineUtils.h" + +#include "Runtime/Engine/Public/SceneViewExtension.h" + +#include "Runtime/Engine/Classes/Engine/Texture2D.h" + +#include "MaterialShared.h" +#include "Materials/MaterialInstance.h" +#include "Delegates/Delegate.h" + +#include "OptiXContext.h" +#include "OptiXObjectComponent.h" +#include "OptiXLaserComponent.h" +#include "OptiXLaserActor.h" +#include "OptiXCameraActor.h" + + + +// Let's try some events! + +DECLARE_EVENT(FOptiXContextManager, FLaserTraceFinishedEvent) +DECLARE_EVENT_OneParam(FOptiXContextManager, FWavelengthChangedEvent, const float) +DECLARE_MULTICAST_DELEGATE(FOnSceneChangedDelegate); + +// DX + +#if PLATFORM_WINDOWS +#include "AllowWindowsPlatformTypes.h" +#endif +#include <d3d11.h> +#if PLATFORM_WINDOWS +#include "HideWindowsPlatformTypes.h" +#endif + +// print cuda error helper: + +inline void PrintLastCudaError(FString Msg) +{ + cudaError_t Err = cudaGetLastError(); + if (cudaSuccess != Err) { + UE_LOG(LogTemp, Fatal, TEXT("Cuda Error: %s. "), *Msg, static_cast<int>(Err), cudaGetErrorString(Err)); + } +} + + +class OPTIX_API FOptiXContextManager : public FSceneViewExtensionBase +{ + +public: + + // The auto register thing is used to make sure this constructor is only called via the NewExtension function + FOptiXContextManager(const FAutoRegister& AutoRegister); + + ~FOptiXContextManager() + { + if (bIsInitialized) + { + cudaGraphicsUnregisterResource(CudaResourceDepthLeft); + cudaGraphicsUnregisterResource(CudaResourceDepthRight); + cudaGraphicsUnregisterResource(CudaResourceColorLeft); + cudaGraphicsUnregisterResource(CudaResourceColorRight); + cudaGraphicsUnregisterResource(CudaResourceIntersections); + cudaGraphicsUnregisterResource(CudaResourceColorOrtho); + cudaGraphicsUnregisterResource(CudaResourceDepthOrtho); + + PrintLastCudaError("cudaGraphicsUnregisterResource"); + cudaFree(CudaLinearMemoryDepth); + cudaFree(CudaLinearMemoryColor); + cudaFree(CudaLinearMemoryIntersections); + PrintLastCudaError("cudaFree"); + } + + AccelerationsToDeleteQueue.Empty(); + BuffersToDeleteQueue.Empty(); + GeometriesToDeleteQueue.Empty(); + GeometryGroupToDeleteQueue.Empty(); + GeometryInstancesToDeleteQueue.Empty(); + GroupsToDeleteQueue.Empty(); + MaterialsToDeleteQueue.Empty(); + ProgramToDeleteQueue.Empty(); + TextureSamplersToDeleteQueue.Empty(); + TransformsToDeleteQueue.Empty(); + + GroupChildrenToRemoveQueue.Empty(); + GeometryGroupChildrenToRemoveQueue.Empty(); + + ComponentsToInitializeQueue.Empty(); + ComponentsToUpdateQueue.Empty(); + CubemapComponentsToUpdateQueue.Empty(); + + LaserActor.Reset(); + CameraActor.Reset(); + } + + // ISceneViewExtension interface start, called by the render thread: +public: + virtual void SetupViewFamily(FSceneViewFamily& InViewFamily) override; + virtual void SetupView(FSceneViewFamily& InViewFamily, FSceneView& InView) override; + virtual void BeginRenderViewFamily(FSceneViewFamily& InViewFamily) override; + virtual void PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& InView) override; + virtual void PreRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& InViewFamily) override; + virtual void PostRenderViewFamily_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneViewFamily& InViewFamily) override; + virtual bool IsActiveThisFrame(class FViewport* InViewport) const override; + virtual void PostRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& InView) override; + // ISceneViewExtension interface end + + + void RenderOrthoPass(); + + // Initialization methods, called by the GAME thread + void Init(); + + void EndPlay() + { + //CleanupOptiXOnEnd(); + //bCleanup.AtomicSet(true); + //bStartTracing.AtomicSet(false); + //bCleanup.AtomicSet(false); + //bEndPlay.AtomicSet(true); + } + + UOptiXContext* GetOptiXContext() + { + return OptiXContext.Get(); + } + + UMaterialInstanceDynamic* GetOptiXMID() // Used to set up the post process + { + return DynamicMaterial.Get(); + } + + UMaterialInstanceDynamic* GetOptiXMIDOrtho() // Used to set up the post process + { + return DynamicMaterialOrtho.Get(); + } + + void SceneChangedCallback(); + + // The OptiX context is not thread-safe, so any changes to variables/properties on the game thread + // while a trace is running will lead to errors. Game thread objects push their requested updates into several queues, + // which then get updated just before the trace runs on the render thread. + // TQueue is guaranteed to be thread-safe. + // There is probably a better and faster way of doing this. + + void RegisterOptiXComponent(IOptiXComponentInterface* Component) + { + ComponentsToInitializeQueue.Enqueue(Component); + } + + void QueueComponentUpdate(IOptiXComponentInterface* Component) + { + ComponentsToUpdateQueue.Enqueue(Component); + } + + void RequestCubemapUpdate(UOptiXCubemapComponent* Component) + { + CubemapComponentsToUpdateQueue.Enqueue(Component); + } + + void SetActiveLaserActor(AOptiXLaserActor* Laser) + { + LaserActor = Laser; + if (LaserMaterialDynamic.IsValid()) + { + LaserActor->SetLaserMaterial(LaserMaterialDynamic.Get()); + } + else + { + UE_LOG(LogTemp, Error, TEXT("LaserMaterialDynamic is invalid!")); + } + } + + void SetActiveCameraActor(AOptiXPlayerCameraManager* Cam) + { + CameraActor = Cam; + } + + FIntRect GetViewRectanglePerEye() + { + return FIntRect(0, 0, Width, Height); + } + + int32 RequestCubemapId(); + + void DeleteCubemapId(int32 Id); + + void AddCubemapToBuffer(int32 CubemapId, int32 SamplerId); + + void BroadcastWavelengthChange(float WL) + { + WavelengthChangedEvent.Broadcast(WL); + //UE_LOG(LogTemp, Error, TEXT("LaserMaterialDynamic is invalid!")); + + } + + +public: + + FThreadSafeBool bStartTracing = false; + FThreadSafeBool bIsInitialized = false; + FThreadSafeBool bLaserIsInitialized = false; + FThreadSafeBool bSceneChanged = true; + FThreadSafeBool bIsTracing = false; + FThreadSafeBool bClearToLaunch = true; + FThreadSafeBool bCleanup = false; + FThreadSafeBool bValidCubemap = false; + FThreadSafeBool bRequestOrthoPass = false; + //FThreadSafeBool bEndPlay = false; + + FLaserTraceFinishedEvent LaserTraceFinishedEvent; + FWavelengthChangedEvent WavelengthChangedEvent; + FOnSceneChangedDelegate OnSceneChangedDelegate; + + +public: + + // This is so ugly but the optix api structure doesn't really allow anything more abstract. + TQueue<optix::Acceleration> AccelerationsToDeleteQueue; + TQueue<optix::Buffer> BuffersToDeleteQueue; + TQueue<optix::Geometry> GeometriesToDeleteQueue; + TQueue<optix::GeometryGroup> GeometryGroupToDeleteQueue; + TQueue<optix::GeometryInstance> GeometryInstancesToDeleteQueue; + TQueue<optix::Group> GroupsToDeleteQueue; + TQueue<optix::Material> MaterialsToDeleteQueue; + TQueue<optix::Program> ProgramToDeleteQueue; + TQueue<optix::TextureSampler> TextureSamplersToDeleteQueue; + TQueue<optix::Transform> TransformsToDeleteQueue; + + TQueue<TPair<optix::Group, uint32>> GroupChildrenToRemoveQueue; + TQueue<TPair<optix::GeometryGroup, uint32>> GeometryGroupChildrenToRemoveQueue; + + FMatrix OrthoMatrix; + +private: + void InitContext(); + void InitRendering(); + void InitBuffers(); + void InitPrograms(); + void InitLaser(); + + void LaunchLaser(); + + void InitCubemap(); + + void InitOptiXComponents(FRHICommandListImmediate & RHICmdList) + { + // Possibly dangerous? Use limited for instead of while in case something goes wrong and we deadlock + for (uint32 i = 0; i < 100 && !ComponentsToInitializeQueue.IsEmpty(); i++) + { + IOptiXComponentInterface* Component; + if (ComponentsToInitializeQueue.Dequeue(Component)) + { + Component->InitOptiXComponent(RHICmdList); + } + } + } + + void UpdateOptiXComponentVariables() + { + for (uint32 i = 0; i < 100 && !ComponentsToUpdateQueue.IsEmpty(); i++) + { + IOptiXComponentInterface* Component; + if (ComponentsToUpdateQueue.Dequeue(Component)) + { + if (Component != nullptr) + { + Component->UpdateOptiXComponentVariables(); + Component->SetUpdateQueued(false);// bUpdateQueued.AtomicSet(false); + } + } + } + } + + void RemovePendingChildrenFromGroups() + { + for (uint32 i = 0; i < 100 && !GroupChildrenToRemoveQueue.IsEmpty(); i++) + { + TPair<optix::Group, uint32> Pair; + if (GroupChildrenToRemoveQueue.Dequeue(Pair)) + { + if (Pair.Key != NULL) + { + Pair.Key->removeChild(Pair.Value); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to remove optix child in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !GeometryGroupChildrenToRemoveQueue.IsEmpty(); i++) + { + TPair<optix::GeometryGroup, uint32> Pair; + if (GeometryGroupChildrenToRemoveQueue.Dequeue(Pair)) + { + if (Pair.Key != NULL) + { + Pair.Key->removeChild(Pair.Value); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to remove optix child in queue: Object was NULL")); + } + } + } + } + + void DestroyOptiXObjects() + { + for (uint32 i = 0; i < 100 && !AccelerationsToDeleteQueue.IsEmpty(); i++) + { + optix::Acceleration NativeObj; + if (AccelerationsToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + if(NativeObj->getContext() != NULL) + NativeObj->destroy(); // TODO do we need to do anything else here? + else + { + UE_LOG(LogTemp, Warning, TEXT("Context already destroyed but somehow this buffer handle is still valid")); + } + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !BuffersToDeleteQueue.IsEmpty(); i++) + { + optix::Buffer NativeObj; + if (BuffersToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + try + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + catch (optix::Exception& E) + { + FString Message = FString(E.getErrorString().c_str()); + UE_LOG(LogTemp, Error, TEXT("Trying to remove buffer: OptiX Error: %s"), *Message); + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("OptiX Error %s"), *Message)); + } + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !GeometriesToDeleteQueue.IsEmpty(); i++) + { + optix::Geometry NativeObj; + if (GeometriesToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !GeometryInstancesToDeleteQueue.IsEmpty(); i++) + { + optix::GeometryInstance NativeObj; + if (GeometryInstancesToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !GeometryGroupToDeleteQueue.IsEmpty(); i++) + { + optix::GeometryGroup NativeObj; + if (GeometryGroupToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !GroupsToDeleteQueue.IsEmpty(); i++) + { + optix::Group NativeObj; + if (GroupsToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !MaterialsToDeleteQueue.IsEmpty(); i++) + { + optix::Material NativeObj; + if (MaterialsToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !ProgramToDeleteQueue.IsEmpty(); i++) + { + optix::Program NativeObj; + if (ProgramToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !TextureSamplersToDeleteQueue.IsEmpty(); i++) + { + optix::TextureSampler NativeObj; + if (TextureSamplersToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + try + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + catch (optix::Exception& E) + { + FString Message = FString(E.getErrorString().c_str()); + UE_LOG(LogTemp, Error, TEXT("Trying to remove texture sampler: OptiX Error: %s"), *Message); + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("OptiX Error %s"), *Message)); + } + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + for (uint32 i = 0; i < 100 && !TransformsToDeleteQueue.IsEmpty(); i++) + { + optix::Transform NativeObj; + if (TransformsToDeleteQueue.Dequeue(NativeObj)) + { + if (NativeObj != NULL) + { + NativeObj->destroy(); // TODO do we need to do anything else here? + } + else + { + UE_LOG(LogTemp, Error, TEXT("Error while trying to destroy optix object in queue: Object was NULL")); + } + } + } + } + + void UpdateRequestedCubemaps(FRHICommandListImmediate & RHICmdList) + { + // update only the first for now, shouldn't be more than 1 in queue anyway: + + if (!CubemapComponentsToUpdateQueue.IsEmpty()) + { + UOptiXCubemapComponent* Comp; + if (CubemapComponentsToUpdateQueue.Dequeue(Comp)) + { + Comp->UpdateCubemap(RHICmdList); + } + } + } + + void UpdateCubemapBuffer(FRHICommandListImmediate & RHICmdList); + + void CleanupOptiXOnEnd() + { + + UE_LOG(LogTemp, Display, TEXT("Starting Cleanup in Context Manager")); + + + if (bIsInitialized) + { + if(CudaResourceDepthLeft != NULL) + cudaGraphicsUnregisterResource(CudaResourceDepthLeft); + if (CudaResourceDepthRight != NULL) + cudaGraphicsUnregisterResource(CudaResourceDepthRight); + if (CudaResourceColorLeft != NULL) + cudaGraphicsUnregisterResource(CudaResourceColorLeft); + if(CudaResourceColorRight != NULL) + cudaGraphicsUnregisterResource(CudaResourceColorRight); + if(CudaResourceIntersections != NULL) + cudaGraphicsUnregisterResource(CudaResourceIntersections); + if (CudaResourceDepthOrtho != NULL) + cudaGraphicsUnregisterResource(CudaResourceDepthOrtho); + if (CudaResourceColorOrtho != NULL) + cudaGraphicsUnregisterResource(CudaResourceColorOrtho); + PrintLastCudaError("cudaGraphicsUnregisterResource"); + if(CudaLinearMemoryDepth != NULL) + cudaFree(CudaLinearMemoryDepth); + + if (CudaLinearMemoryColor != NULL) + cudaFree(CudaLinearMemoryColor); + + if (CudaLinearMemoryIntersections != NULL) + cudaFree(CudaLinearMemoryIntersections); + + PrintLastCudaError("cudaFree"); + } + + + + //check(IsInRenderingThread()); + bStartTracing.AtomicSet(false); + //bEndPlay.AtomicSet(false); + bIsInitialized.AtomicSet(false); + bLaserIsInitialized.AtomicSet(false); + bSceneChanged.AtomicSet(true); + bIsTracing.AtomicSet(false); + bClearToLaunch.AtomicSet(true); + bCleanup.AtomicSet(false); + bValidCubemap.AtomicSet(false); + + // Clear the queue + DestroyOptiXObjects(); + + if (OptiXContext.IsValid()) + { + OptiXContext->RemoveFromRoot(); + } + if (LaserOutputBuffer.IsValid()) + { + LaserOutputBuffer->RemoveFromRoot(); + } + if (OutputTexture.IsValid()) + { + OutputTexture->RemoveFromRoot(); + } + if (OutputTexture2.IsValid()) + { + OutputTexture2->RemoveFromRoot(); + } + if (DepthTexture.IsValid()) + { + DepthTexture->RemoveFromRoot(); + } + if (DepthTexture2.IsValid()) + { + DepthTexture2->RemoveFromRoot(); + } + if (CubemapSampler.IsValid()) + { + CubemapSampler->RemoveFromRoot(); + } + if (CubemapBuffer.IsValid()) + { + CubemapBuffer->RemoveFromRoot(); + } + + OutputBuffer.Reset(); + OutputDepthBuffer.Reset(); + + OutputTexture.Reset(); + DepthTexture.Reset(); + OutputTexture2.Reset(); + DepthTexture2.Reset(); + LaserIntersectionTexture.Reset(); + + DynamicMaterial.Reset(); + DynamicMaterialOrtho.Reset(); + RegularMaterial.Reset(); + VRMaterial.Reset(); + LaserMaterial.Reset(); + + LaserMaterialDynamic.Reset(); + + LaserActor.Reset(); + + TopObject.Reset(); + TopAcceleration.Reset(); + OptiXContext.Reset(); + + if (NativeContext != NULL) + { + NativeContext->destroy(); + NativeContext = NULL; + } + + /*{ + + OptiXContext->RemoveFromRoot(); + LaserOutputBuffer->RemoveFromRoot(); + OutputTexture->RemoveFromRoot(); + OutputTexture2->RemoveFromRoot(); + DepthTexture->RemoveFromRoot(); + DepthTexture2->RemoveFromRoot(); + + + + OutputBuffer.Reset(); + OutputDepthBuffer.Reset(); + + OutputTexture.Reset(); + DepthTexture.Reset(); + OutputTexture2.Reset(); + DepthTexture2.Reset(); + + DynamicMaterial.Reset(); + RegularMaterial.Reset(); + VRMaterial.Reset(); + + + TopObject.Reset(); + TopAcceleration.Reset(); + OptiXContext.Reset(); + + if (NativeContext != NULL) + { + NativeContext->destroy(); + } + }*/ + } + + +private: + // OptiX Part + + // Todo: refactor this to delegates maybe? + TQueue<IOptiXComponentInterface*> ComponentsToInitializeQueue; + TQueue<IOptiXComponentInterface*> ComponentsToUpdateQueue; + TQueue<UOptiXCubemapComponent*> CubemapComponentsToUpdateQueue; + + TWeakObjectPtr<AOptiXLaserActor> LaserActor; + + TWeakObjectPtr<AOptiXPlayerCameraManager> CameraActor; + + // OptiX Objects to be kept in the context manager, TODO triple check that the GC doesn't nab them. + // Those are always required, but some should also be changeable! TODO make custom setters for them later. + TWeakObjectPtr<UOptiXContext> OptiXContext; + TWeakObjectPtr<UOptiXProgram> RayGenerationProgram; + TWeakObjectPtr<UOptiXProgram> MissProgram; + TWeakObjectPtr<UOptiXProgram> ExceptionProgram; + + TWeakObjectPtr<UOptiXGroup> TopObject; + TWeakObjectPtr<UOptiXAcceleration> TopAcceleration; + + TWeakObjectPtr<UOptiXBuffer> OutputBuffer; + TWeakObjectPtr<UOptiXBuffer> OutputDepthBuffer; + + TWeakObjectPtr<UOptiXTextureSampler> CubemapSampler; + TWeakObjectPtr<UOptiXBuffer> CubemapBuffer; + TWeakObjectPtr<UOptiXBuffer> CubemapsInputBuffer; + + TQueue<int32> UnallocatedCubemapIds; + + TArray<TArray<FColor>> SurfaceDataCube; + + optix::Context NativeContext; + + + // Laser Part + TWeakObjectPtr<UOptiXBuffer> LaserOutputBuffer; + TWeakObjectPtr<UOptiXProgram> LaserRayGenerationProgram; + TWeakObjectPtr<UOptiXProgram> LaserMissProgram; + TWeakObjectPtr<UOptiXProgram> LaserExceptionProgram; + + + + // Rendering Part + + //FUpdateTextureRegion2D TextureRegion; + + //UTextureCube* TextureCube; + + int32 Width; + int32 Height; + + FTexture2DRHIRef OutputTextureColorRightRef; + FTexture2DRHIRef OutputTextureColorLeftRef; + FTexture2DRHIRef OutputTextureDepthRightRef; + FTexture2DRHIRef OutputTextureDepthLeftRef; + + FTexture2DRHIRef OutputTextureColorOrthoRef; + FTexture2DRHIRef OutputTextureDepthOrthoRef; + + TWeakObjectPtr<UTexture2D> OutputTexture; + TWeakObjectPtr<UTexture2D> DepthTexture; + TWeakObjectPtr<UTexture2D> OutputTexture2; + TWeakObjectPtr<UTexture2D> DepthTexture2; + + TWeakObjectPtr<UTexture2D> OutputTextureOrtho; + TWeakObjectPtr<UTexture2D> DepthTextureOrtho; + + TWeakObjectPtr<UMaterialInstanceDynamic> DynamicMaterial; + TWeakObjectPtr<UMaterialInstanceDynamic> DynamicMaterialOrtho; + TWeakObjectPtr<UMaterial> RegularMaterial; + TWeakObjectPtr<UMaterial> VRMaterial; + bool bWithHMD; + + + // --------------------------------------------------------------------------------------------------- + // Laser stuff + // --------------------------------------------------------------------------------------------------- + + FTexture2DRHIRef LaserIntersectionTextureRef; + + TWeakObjectPtr<UTexture2D> LaserIntersectionTexture; + TWeakObjectPtr<UMaterial> LaserMaterial; + TWeakObjectPtr<UMaterialInstanceDynamic> LaserMaterialDynamic; + + +public: + + TQueue<TPair<uint32, TArray<FVector>>> LaserIntersectionQueue; + + TArray<TArray<FVector>> PreviousLaserResults; + + +private: + + TArray<FVector4> IntersectionData; + TArray<FVector4> OldIntersectionData; + + FThreadSafeBool bTracingLaser; + + FCriticalSection CriticalSection; + + int32 LaserMaxDepth; + int32 LaserEntryPoint; + int32 LaserBufferSize; + + int32 LaserBufferWidth; + int32 LaserBufferHeight; + + + // --------------------------------------------------------------------------------------------------- + // DX <-> CUDA stuff + // --------------------------------------------------------------------------------------------------- + + +public: + // I'm not sure which ones I actually need + IDXGIAdapter *CudaCapableAdapter = NULL; // Adapter to use + ID3D11Device *D3DDevice = NULL; // Rendering device + ID3D11DeviceContext *D3DDeviceContext = NULL; + + // RTX mode + int RTXOn = 1; + + +private: + + void InitCUDADX(); + + + //ID3D11Texture2D* D3D11Texture; + cudaGraphicsResource* CudaResourceDepthLeft; + cudaGraphicsResource* CudaResourceDepthRight; + cudaGraphicsResource* CudaResourceColorLeft; + cudaGraphicsResource* CudaResourceColorRight; + cudaGraphicsResource* CudaResourceIntersections; + cudaGraphicsResource* CudaResourceColorOrtho; + cudaGraphicsResource* CudaResourceDepthOrtho; + void* CudaLinearMemoryDepth; + void* CudaLinearMemoryColor; + void* CudaLinearMemoryIntersections; + size_t Pitch; // fix me + size_t PitchLaser; + + cudaGraphicsResource *Resources[7]; }; \ No newline at end of file