SawInteractable, InteractableScreenCapturer optimizations

This commit is contained in:
Oleg Petruny 2024-05-20 23:02:13 +02:00
parent 8f702409c7
commit 2a5677656c
15 changed files with 163 additions and 124 deletions

View File

@ -7,12 +7,13 @@
#include "InputMappingContext.h" #include "InputMappingContext.h"
#include "CustomGameUserSettings.h" #include "CustomGameUserSettings.h"
#include "Interactable/SawInteractable.h"
#include "Interactable/UsableInteractable.h" #include "Interactable/UsableInteractable.h"
void UCustomGameInstanceBase::Init() void UCustomGameInstanceBase::Init()
{ {
// IN FUTURE ASSIGN FROM CONTENT LOADER MEMBER // IN FUTURE ASSIGN FROM CONTENT LOADER MEMBER
interactionsCollection = { {UUsableInteractable::StaticClass()} }; interactionsActivators = { {UUsableInteractable::StaticClass()}, {USawInteractable::StaticClass()} };
UGameInstance::Init(); UGameInstance::Init();

View File

@ -19,7 +19,7 @@ public:
void ApplyMouseSettings(); void ApplyMouseSettings();
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TArray<TSubclassOf<class UInteractableComponent>> interactionsCollection; TArray<TSubclassOf<class UInteractableComponent>> interactionsActivators;
protected: protected:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)

View File

@ -3,3 +3,48 @@
#include "Interactable/InCameraInteractableActivator.h" #include "Interactable/InCameraInteractableActivator.h"
#include "Interactable.h"
#include "InteractableScreenCapturer.h"
UInCameraInteractableActivator::UInCameraInteractableActivator(const FObjectInitializer& ObjectInitializer)
: UInteractableActivator(ObjectInitializer)
{
if(!world || !player)
{
return;
}
_capturer = CreateDefaultSubobject<UInteractableScreenCapturer>(TEXT("UInCameraInteractableActivator_UInteractableScreenCapturer"));
_capturer->interactableInScreenDelegate.BindUObject(this, &UInCameraInteractableActivator::NewSeenInteractable_Implementation);
_capturer->SetupAttachment(this);
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = false;
}
void UInCameraInteractableActivator::OnRegister()
{
UInteractableActivator::OnRegister();
_capturer->RegisterComponent();
_capturer->Activate();
}
void UInCameraInteractableActivator::NewSeenInteractable_Implementation(AInteractable* interactable)
{
_interactablesToActivate.Enqueue(interactable);
SetComponentTickEnabled(true);
}
void UInCameraInteractableActivator::Scan_Implementation()
{
SetComponentTickEnabled(false);
while(!_interactablesToActivate.IsEmpty())
{
AInteractable* interactable;
_interactablesToActivate.Dequeue(interactable);
if(interactableActivatedDelegate.IsBound())
{
interactableActivatedDelegate.Execute(interactable);
}
}
}

View File

@ -3,13 +3,30 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "InteractableActivator.h" #include "InteractableActivator.h"
#include "InCameraInteractableActivator.generated.h" #include "InCameraInteractableActivator.generated.h"
UCLASS() UCLASS(Blueprintable, BlueprintType)
class UInCameraInteractableActivator : public UInteractableActivator class UInCameraInteractableActivator : public UInteractableActivator
{ {
GENERATED_BODY() GENERATED_BODY()
public:
UInCameraInteractableActivator(const FObjectInitializer& ObjectInitializer);
protected:
virtual void OnRegister() override;
void Scan();
virtual void Scan_Implementation() override;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void NewSeenInteractable(class AInteractable* interactable);
virtual void NewSeenInteractable_Implementation(class AInteractable* interactable);
private:
class UInteractableScreenCapturer* _capturer;
TQueue<class AInteractable*> _interactablesToActivate;
}; };

View File

@ -39,7 +39,6 @@ UInteractableActivator::UInteractableActivator(const FObjectInitializer& ObjectI
PrimaryComponentTick.TickInterval = 0.05f; PrimaryComponentTick.TickInterval = 0.05f;
PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = true; PrimaryComponentTick.bStartWithTickEnabled = true;
RegisterComponent();
} }
void UInteractableActivator::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) void UInteractableActivator::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)

View File

@ -32,6 +32,5 @@ protected:
class UWorld* world; class UWorld* world;
class APlayerBase* player; class APlayerBase* player;
bool isTrace = true;
enum ECollisionChannel collisionChannel; enum ECollisionChannel collisionChannel;
}; };

View File

@ -7,29 +7,9 @@
#include "UObject/Interface.h" #include "UObject/Interface.h"
#include "InteractableActivator.h" #include "InteractableActivator.h"
#include "InteractableCaller.h"
#include "InteractableComponent.generated.h" #include "InteractableComponent.generated.h"
USTRUCT(BlueprintType)
struct FActivatorCallerPair
{
GENERATED_BODY()
public:
FActivatorCallerPair() {}
FActivatorCallerPair(TSubclassOf<UInteractableActivator> a, TSubclassOf<UInteractableCaller> c)
: activator(a), caller(c)
{}
UPROPERTY(EditAnywhere)
TSubclassOf<UInteractableActivator> activator;
UPROPERTY(EditAnywhere)
TSubclassOf<UInteractableCaller> caller;
};
UCLASS(Abstract, Blueprintable, BlueprintType) UCLASS(Abstract, Blueprintable, BlueprintType)
class UInteractableComponent : public UActorComponent class UInteractableComponent : public UActorComponent
{ {
@ -42,8 +22,8 @@ public:
PURE_VIRTUAL(UInteractableComponent::GetInteractionName_Implementation, return "NONE";); PURE_VIRTUAL(UInteractableComponent::GetInteractionName_Implementation, return "NONE";);
UFUNCTION(BlueprintNativeEvent, BlueprintCallable) UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
const TArray<FActivatorCallerPair> GetActivatorsAndCallers(); const TArray<TSubclassOf<UInteractableActivator>> GetActivators();
virtual const TArray<FActivatorCallerPair> GetActivatorsAndCallers_Implementation() virtual const TArray<TSubclassOf<UInteractableActivator>> GetActivators_Implementation()
PURE_VIRTUAL(UInteractableComponent::GetActivatorsAndCallers_Implementation, PURE_VIRTUAL(UInteractableComponent::GetActivatorsZ_Implementation,
TArray<FActivatorCallerPair> _activatorsAndCallers{}; return _activatorsAndCallers;); TArray<TSubclassOf<UInteractableActivator>> _activators{}; return _activators;);
}; };

View File

@ -4,51 +4,39 @@
#include "InteractableScreenCapturer.h" #include "InteractableScreenCapturer.h"
#include "Engine/Texture.h" #include "Engine/Texture.h"
#include "Interactable.h" #include "Engine/TextureRenderTarget2D.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
#include "RHIResources.h" #include "RHIResources.h"
#include "SceneView.h" #include "SceneView.h"
#include "TextureCompressorModule.h" #include "TextureCompressorModule.h"
#include "Interactable.h"
constexpr float tickInterval = 1.0f / 5; constexpr float tickInterval = 1.0f / 5;
constexpr float textureWidth = 1280 / 2;
constexpr float textureHeight = 720 / 2;
constexpr float rayDistance = 7000;
UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer) UInteractableScreenCapturer::UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer)
: USceneCaptureComponent2D(ObjectInitializer) : USceneCaptureComponent2D(ObjectInitializer)
{ {
//TextureTarget = CreateDefaultSubobject<UTextureRenderTarget2D>(TEXT("TextureTarget"));
//TextureTarget->InitAutoFormat(textureWidth, textureHeight);
//TextureTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA16f;
PrimaryComponentTick.bCanEverTick = false; PrimaryComponentTick.bCanEverTick = false;
PrimaryComponentTick.bStartWithTickEnabled = false; PrimaryComponentTick.bStartWithTickEnabled = false;
auto input = LoadObject<UTexture>(nullptr, TEXT("/Game/tempStaff/Input")); TextureTarget = LoadObject<UTextureRenderTarget2D>(this, TEXT("/Game/tempStaff/Input"));
if(!input) //TextureTarget = ObjectInitializer.CreateDefaultSubobject<UTextureRenderTarget2D>(this, TEXT("UInteractableScreenCapturer_TextureRenderTarget"));
{ //TextureTarget->RenderTargetFormat = ETextureRenderTargetFormat::RTF_RGBA8;
return; //TextureTarget->ClearColor = FLinearColor::Black;
} //TextureTarget->bAutoGenerateMips = false;
//TextureTarget->bCanCreateUAV = false;
_capture = input->GetResource()->TextureRHI; //TextureTarget->InitAutoFormat(textureWidth, textureHeight);
if(!_capture) //TextureTarget->UpdateResourceImmediate(true);
{
return;
}
switch(_capture->GetFormat())
{
case EPixelFormat::PF_R8G8B8A8:
case EPixelFormat::PF_B8G8R8A8:
break;
default:
return;
}
_world = GetWorld();
PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_LegacySceneCapture; PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_LegacySceneCapture;
bCaptureEveryFrame = 0; bCaptureEveryFrame = 0;
bCaptureOnMovement = 0; bCaptureOnMovement = 0;
LODDistanceFactor = 100; LODDistanceFactor = 10000;
bUseRayTracingIfEnabled = false; bUseRayTracingIfEnabled = false;
CaptureSource = ESceneCaptureSource::SCS_BaseColor; CaptureSource = ESceneCaptureSource::SCS_BaseColor;
@ -102,10 +90,10 @@ void UInteractableScreenCapturer::Process()
running = true; running = true;
ENQUEUE_RENDER_COMMAND(GetInteractablesFromScreen)( ENQUEUE_RENDER_COMMAND(GetInteractablesFromScreen)(
[ [
capture = _capture, capture = TextureTarget->GetResource()->TextureRHI,
output = _output, world = GetWorld(),
world = _world, view = _view,
view = _view this
] ]
(FRHICommandListImmediate& RHICmdList) (FRHICommandListImmediate& RHICmdList)
{ {
@ -113,7 +101,6 @@ void UInteractableScreenCapturer::Process()
static FIntPoint _extent = capture->GetDesc().Extent; static FIntPoint _extent = capture->GetDesc().Extent;
static uint32 _size = _extent.X * _extent.Y; static uint32 _size = _extent.X * _extent.Y;
static TArray<FColor> _capturePixels;
static uint8* _bitMap = new uint8[_size]; // cv::Mat allocation is weird sometimes... static uint8* _bitMap = new uint8[_size]; // cv::Mat allocation is weird sometimes...
uint32 stride = 0; uint32 stride = 0;
@ -180,7 +167,7 @@ void UInteractableScreenCapturer::Process()
* (FInverseRotationMatrix(view.Rotation) * FMatrix(FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0), FPlane(0, 0, 0, 1))) * (FInverseRotationMatrix(view.Rotation) * FMatrix(FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0), FPlane(0, 0, 0, 1)))
* view.CalculateProjectionMatrix()) * view.CalculateProjectionMatrix())
.InverseFast(); .InverseFast();
GEngine->AddOnScreenDebugMessage(60, 0.5f, FColor::Yellow, FString::Printf(TEXT("x:%f, y:%f"), view.Rotation.Yaw, view.Rotation.Roll));
FVector worldLoc, worldDir; FVector worldLoc, worldDir;
for(int i = 1; i < components; ++i) for(int i = 1; i < components; ++i)
{ {
@ -190,38 +177,33 @@ void UInteractableScreenCapturer::Process()
FHitResult result{}; FHitResult result{};
FVector startLocation = view.Location; FVector startLocation = view.Location;
FVector endLocation = worldLoc + worldDir * 1000000; FVector endLocation = worldLoc + worldDir * rayDistance;
world->LineTraceSingleByChannel( world->LineTraceSingleByChannel(
result, result,
startLocation, startLocation,
endLocation, endLocation,
ECC_GameTraceChannel1 ECC_GameTraceChannel1
); );
static AInteractable* _last = nullptr;
static bool _activated = false;
if(result.bBlockingHit) if(result.bBlockingHit)
{ {
if(_last != result.GetActor()) if(auto interactable = Cast<AInteractable>(result.GetActor()))
{ {
_activated = true; if(!_sawInteractables.Contains(interactable))
if(auto interactable = Cast<AInteractable>(result.GetActor()))
{ {
_last = interactable; _sawInteractables.Add(interactable);
GEngine->AddOnScreenDebugMessage(10 + i, 0.5f, FColor::Yellow, interactable->GetName()); AsyncTask(ENamedThreads::GameThread, [=, this]()
{
interactableInScreenDelegate.Execute(interactable);
});
} }
//GEngine->AddOnScreenDebugMessage(10 + i, 0.5f, FColor::Yellow, interactable->GetName());
GEngine->AddOnScreenDebugMessage(20 + i, 0.5f, FColor::Yellow, FString::Printf(TEXT("dist:%f"), (view.Location - interactable->GetActorLocation()).Length()));
} }
DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.5f); DrawDebugLine(world, startLocation, endLocation, FColor::Green, false, tickInterval, 0, 0.5f);
} }
else else
{ {
if(_activated)
{
_activated = false;
_last = nullptr;
}
DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.5f); DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 10, 0.5f);
} }
//DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 0, 0.5f); //DrawDebugLine(world, startLocation, endLocation, FColor::Red, false, tickInterval, 0, 0.5f);

View File

@ -7,6 +7,8 @@
#include "InteractableScreenCapturer.generated.h" #include "InteractableScreenCapturer.generated.h"
DECLARE_DELEGATE_OneParam(FInteractableInScreen, class AInteractable*);
UCLASS(hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent), MinimalAPI) UCLASS(hidecategories = (Collision, Object, Physics, SceneComponent), ClassGroup = Rendering, editinlinenew, meta = (BlueprintSpawnableComponent), MinimalAPI)
class UInteractableScreenCapturer : public USceneCaptureComponent2D class UInteractableScreenCapturer : public USceneCaptureComponent2D
{ {
@ -16,12 +18,12 @@ public:
UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer); UInteractableScreenCapturer(const FObjectInitializer& ObjectInitializer);
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
FInteractableInScreen interactableInScreenDelegate;
protected: protected:
void Process(); void Process();
private: private:
FTextureRHIRef _capture;
FBufferRHIRef _output;
UWorld* _world;
FMinimalViewInfo _view; FMinimalViewInfo _view;
TSet<class AInteractable*> _sawInteractables;
}; };

View File

@ -0,0 +1,21 @@
// Oleg Petruny proprietary.
#include "SawInteractable.h"
#include "InCameraInteractableActivator.h"
#include "InteractableCaller.h"
const FString USawInteractable::GetName_Implementation()
{
static auto _name = TEXT("Saw");
return _name;
}
const TArray<TSubclassOf<UInteractableActivator>> USawInteractable::GetActivators_Implementation()
{
static TArray<TSubclassOf<UInteractableActivator>> _array = {
{UInCameraInteractableActivator::StaticClass()}
};
return _array;
}

View File

@ -0,0 +1,23 @@
// Oleg Petruny proprietary.
#pragma once
#include "CoreMinimal.h"
#include "InteractableComponent.h"
#include "SawInteractable.generated.h"
UCLASS(Blueprintable, BlueprintType)
class USawInteractable : public UInteractableComponent
{
GENERATED_BODY()
public:
const FString GetName();
virtual const FString GetName_Implementation() override;
const TArray<TSubclassOf<UInteractableActivator>> GetActivators();
virtual const TArray<TSubclassOf<UInteractableActivator>> GetActivators_Implementation() override;
};

View File

@ -3,7 +3,6 @@
#include "UsableInteractable.h" #include "UsableInteractable.h"
#include "InteractableCaller.h"
#include "RaycastInteractableActivator.h" #include "RaycastInteractableActivator.h"
const FString UUsableInteractable::GetName_Implementation() const FString UUsableInteractable::GetName_Implementation()
@ -12,10 +11,10 @@ const FString UUsableInteractable::GetName_Implementation()
return _name; return _name;
} }
const TArray<FActivatorCallerPair> UUsableInteractable::GetActivatorsAndCallers_Implementation() const TArray<TSubclassOf<UInteractableActivator>> UUsableInteractable::GetActivators_Implementation()
{ {
static TArray<FActivatorCallerPair> _array = { static TArray<TSubclassOf<UInteractableActivator>> _array = {
{{URaycastInteractableActivator::StaticClass()}, {UInteractableCaller::StaticClass()}} {URaycastInteractableActivator::StaticClass()}
}; };
return _array; return _array;
} }

View File

@ -18,6 +18,6 @@ public:
const FString GetName(); const FString GetName();
virtual const FString GetName_Implementation() override; virtual const FString GetName_Implementation() override;
const TArray<FActivatorCallerPair> GetActivatorsAndCallers(); const TArray<TSubclassOf<UInteractableActivator>> GetActivators();
virtual const TArray<FActivatorCallerPair> GetActivatorsAndCallers_Implementation() override; virtual const TArray<TSubclassOf<UInteractableActivator>> GetActivators_Implementation() override;
}; };

View File

@ -145,31 +145,18 @@ void APlayerBase::LoadInteractable()
} }
TSet<TSubclassOf<UInteractableActivator>> activators; TSet<TSubclassOf<UInteractableActivator>> activators;
TMap<TSubclassOf<UInteractableCaller>, UInteractableCaller*> callers; for(auto& interaction : GI->interactionsActivators)
for(auto& interaction : GI->interactionsCollection)
{ {
auto actAndCallArray = interaction->GetDefaultObject<UInteractableComponent>()->GetActivatorsAndCallers_Implementation(); auto actArray = interaction->GetDefaultObject<UInteractableComponent>()->GetActivators_Implementation();
for(auto& actAndCall : actAndCallArray) for(auto& act : actArray)
{ {
if(!activators.Contains(actAndCall.activator)) if(!activators.Contains(act))
{ {
activators.Add(actAndCall.activator); activators.Add(act);
auto component = NewObject<UInteractableActivator>(this, actAndCall.activator); auto component = NewObject<UInteractableActivator>(this, act);
component->AttachToComponent(camera, FAttachmentTransformRules::SnapToTargetIncludingScale);
component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated); component->interactableActivatedDelegate.BindUObject(this, &APlayerBase::InteractableActivated);
} component->SetupAttachment(camera);
component->RegisterComponent();
if(!callers.Contains(actAndCall.caller))
{
auto component = NewObject<UInteractableCaller>(this, actAndCall.caller);
this->AddOwnedComponent(component);
component->Init();
callers.Add(actAndCall.caller, component);
AddInteractionCallersMapping(interaction, component);
}
else
{
AddInteractionCallersMapping(interaction, callers[actAndCall.caller]);
} }
} }
} }
@ -177,17 +164,5 @@ void APlayerBase::LoadInteractable()
void APlayerBase::InteractableActivated(AInteractable* interactable) void APlayerBase::InteractableActivated(AInteractable* interactable)
{ {
GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Yellow, interactable->GetName()); GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Cyan, TEXT("Player activate: ") + interactable->GetName());
}
void APlayerBase::AddInteractionCallersMapping(TSubclassOf<UInteractableComponent> interaction, UInteractableCaller* caller)
{
if(!_interactionsToCallers.Contains(interaction))
{
_interactionsToCallers.Add(interaction, { caller });
}
else
{
_interactionsToCallers[interaction].Add(caller);
}
} }

View File

@ -62,8 +62,4 @@ protected:
private: private:
void LoadInteractable(); void LoadInteractable();
void InteractableActivated(class AInteractable* interactable); void InteractableActivated(class AInteractable* interactable);
void AddInteractionCallersMapping(TSubclassOf<class UInteractableComponent> interaction, class UInteractableCaller* caller);
TMap<TSubclassOf<class UInteractableComponent>, TSet<class UInteractableCaller*>> _interactionsToCallers;
}; };