x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Dynamically Spawn SceneCapture Visible in HUD

I have a WheeledVehicle which I want to be able to attach ASceneCapture2D. When the vehicle is driven around during game play the output texture of the scene capture should be visible in the HUD. I planned to do this by creating a custom WrapBox widget which contains UImages of each SceneCapture. Bellow is the code

Vehicle Class

 UENUM()
 enum SensorType { RADAR = 0, LIDAR };
 
 UCLASS(config = Game)
 class USensorPlacementConfigData : public UObject
 {
     GENERATED_BODY()
 public:
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float rot_x;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float rot_y;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float rot_z;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float rot_w;
 
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float scale_x;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float scale_y;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float scale_z;
 
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float trans_x;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float trans_y;
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         float trans_z;
 
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         TEnumAsByte<SensorType> type;
 };
 
 UCLASS(Config = Game)
 class WATOSIM_API ASensorMountedVehicle : public AWheeledVehicle
 {
     GENERATED_BODY()
     
 
 public:
     UPROPERTY(Config, BlueprintReadWrite, EditAnywhere)
         TArray<TSubclassOf<class USensorPlacementConfigData >> sensors;
 
     //UPROPERTY(BlueprintReadWrite, EditAnywhere)
     TArray<class ASceneCapture2D *> mountedSensors;
 
     //UPROPERTY(BlueprintReadWrite, EditAnywhere)
     TArray<class UTextureRenderTarget2D *> sensorRenderTargets;
 
 public:
     virtual void BeginPlay() override;
     virtual void Tick(float DeltaTime) override;
 
 
     ~ASensorMountedVehicle();
 };
 
 void ASensorMountedVehicle::BeginPlay()
 {
     Super::BeginPlay();
     UE_LOG(LogTemp, Error, TEXT("NumSensor: %d"), sensors.Num());
     sensorRenderTargets.Reset();
     for (auto& sensor : sensors) {
         auto s = sensor.GetDefaultObject();
         UE_LOG(LogTemp, Error, TEXT("%f %f %f %f, %f %f %f, %f %f %f, %d"), 
             s->rot_x, s->rot_y, s->rot_z, s->rot_w, s->scale_x, s->scale_y, s->scale_z,
             s->trans_x, s->trans_y, s->trans_z, (int)s->type.GetValue()
         );
 
         //Make the render target for this sensor
         UTextureRenderTarget2D *renderTarget2D = NewObject<UTextureRenderTarget2D>();
         renderTarget2D->InitAutoFormat(512, 512);
 
         //Create the ScreenCaptureActure which needs to be spawned into the worl
         ASceneCapture2D *sceneCaptureActor = (class ASceneCapture2D *)GetWorld()->SpawnActor<ASceneCapture2D>(ASceneCapture2D::StaticClass());
         if (sceneCaptureActor) {
             //Make the transform for this sensor
             FTransform cameraTransform = FTransform(
                 FQuat(s->rot_x, s->rot_y, s->rot_z, s->rot_w),
                 FVector(s->scale_x, s->scale_y, s->scale_z),
                 FVector(s->trans_x, s->trans_y, s->trans_z)
             );
 
             // Getting the actual component, registering and putting it where the camera was
             USceneCaptureComponent2D *sceneCaptureComponent = sceneCaptureActor->GetCaptureComponent2D();
             //sceneCaptureComponent->RegisterComponent();
             sceneCaptureComponent->SetRelativeTransform(cameraTransform);
             sceneCaptureComponent->FOVAngle = 90.0;
             sceneCaptureComponent->ProjectionType = ECameraProjectionMode::Perspective;
             
             // Setting the target
             sensorRenderTargets.Add(sceneCaptureComponent->TextureTarget);
             sceneCaptureComponent->TextureTarget = renderTarget2D;
 
             sceneCaptureComponent->bAutoActivate = true;
             sceneCaptureComponent->DetailMode = EDetailMode::DM_High;
             switch (sensor.GetDefaultObject()->type) {
             case SensorType::RADAR:
                 UE_LOG(LogTemp, Error, TEXT("Found Radar"));
                 sceneCaptureComponent->CaptureSource = SCS_SceneColorHDR;
                 break;
             case SensorType::LIDAR:
                 UE_LOG(LogTemp, Error, TEXT("Found Lidar"));
                 sceneCaptureComponent->CaptureSource = SCS_SceneDepth;
                 break;
             default:
                 UE_LOG(LogTemp, Error, TEXT("Sensor config has unknown type"));
                 break;
             }
 
             //sceneCaptureActor->RegisterAllComponents();
             mountedSensors.Add(sceneCaptureActor);
         }
         else {
             UE_LOG(LogTemp, Error, TEXT("SceneCapture loaded is null"));
         }
     }
 }
 
 void ASensorMountedVehicle::Tick(float DeltaTime) {
     Super::Tick(DeltaTime);
 
     /*for (int sensNum = 0; sensNum < mountedSensors.Num(); sensNum++) {
         USceneCaptureComponent2D *sceneCaptureComponent = mountedSensors[sensNum]->GetCaptureComponent2D();
         sceneCaptureComponent->CaptureScene();
 
         // Telling the target to "refresh"
         UTextureRenderTarget2D *renderTarget2D = sensorRenderTargets[sensNum];
         renderTarget2D->UpdateResourceImmediate();
 
         // Creating the actual texture
         //UTexture2D *newTexture = renderTarget2D->ConstructTexture2D(this, FString("Snapshot"), EObjectFlags::RF_NoFlags);
     
         //use the texture for something fun...
     }*/
 }
 
 ASensorMountedVehicle::~ASensorMountedVehicle()
 {
 }
 

Custom Wrapper Class

 UCLASS()
 class WATOSIM_API USensorHUDWrapBox : public UWrapBox
 {
     GENERATED_BODY()
     
         TArray<class UImage *> sensorsViews;
 
     class ASensorMountedVehicle *vehicle;
 
 public:
     void InitSensorViews(class ASensorMountedVehicle *v);
 
     //UFUNCTION(BlueprintCallable)
 
     ~USensorHUDWrapBox();
 };
 
 void USensorHUDWrapBox::InitSensorViews(ASensorMountedVehicle *v)
 {
     UE_LOG(LogTemp, Error, TEXT("USensorHUDWrapBox"));
     vehicle = v;
     if (vehicle) {
         UE_LOG(LogTemp, Error, TEXT("Here 2"));
         for (int i = 0; i < vehicle->sensorRenderTargets.Num(); i++) {
             UE_LOG(LogTemp, Error, TEXT("Here 3"));
             class UImage *image = (class UImage *)NewObject<class UImage>(UImage::StaticClass());
             image->SetBrushFromTexture((class UTexture2D *)vehicle->sensorRenderTargets[i]);
             
             UCanvasPanelSlot* canvasSlot = Cast<UCanvasPanelSlot>(AddChild(image));
 
             sensorsViews.Add(image);
         }
     }
 }
 
 USensorHUDWrapBox::~USensorHUDWrapBox()
 {
     for (int i = 0; i < sensorsViews.Num(); i++) {
         delete sensorsViews[i];
     }
 }


Custom HUD Class

 void AChevyBoltHUD::BeginPlay()
 {
     Super::BeginPlay();
 
     //Establish the PC
     ThePC = GetOwningPlayerController();
 
     //How to get a ref to your custom PC
     //AYourPlayerController* YourChar = Cast<AYourPlayerController>(ThePC);
 
     //How to Get The Character
     vehicle = Cast<ASensorMountedVehicle>(GetOwningPawn());
 
     sensorView = (USensorHUDWrapBox *)NewObject<class USensorHUDWrapBox>();
     sensorView->InitSensorViews(vehicle);
     sensorView->AddToRoot();
 }


The code runs fine and outputs the logs messages in the correct order. However, nothing shows up on the HUD. Any ideas? I know the code is being run and the AddChild() function is being called.

Product Version: UE 4.18
Tags:
more ▼

asked Mar 12 '18 at 03:19 AM in C++ Programming

avatar image

lufthansa747
3 2 5

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

If your AChevyBoltHUD inherits from AHUD then you need using DrawHUD() instead BeginPlay().

 void AMyHUD::BeginPlay()
 {
     Super::BeginPlay();
 
     DrawText(TEXT("Welcome in BeginPlay"), FColor::White, 100, 90);
 }
 
 void AMyHUD::DrawHUD()
 {
     Super::DrawHUD();
 
     DrawText(TEXT("DrawHUD here"), FColor::White, 100, 90);
 }

Text in BeginPlay doesn't show, but the text in DrawHUD is visible.

more ▼

answered Mar 13 '18 at 02:42 AM

avatar image

Shaggy41
301 1 5 3

avatar image lufthansa747 Mar 13 '18 at 09:42 PM

I'm not trying to draw text in begin play. What I was trying to do in the BeginPlay() was put a bunch of images in the HUD wrap box. I was hoping that these images would be tied to the sensor texture so that when the next capture happens the texture and image displayed in the HUD gets updated.

avatar image Shaggy41 Mar 14 '18 at 01:20 AM

I understand that SceneCapture2D creates a texture and you want to display this texture on HUD as below alt text

scenecapture.gif (1.9 MB)
avatar image lufthansa747 Mar 14 '18 at 09:00 PM

Yes! that looks like the exact effect I am aiming for. Do I have to continuously add the images to the HUDS' Wrap box widget? I thought adding the image in the BeginPlay() would have it there during the Draw step automatically?

avatar image Shaggy41 Mar 14 '18 at 10:51 PM

First off this:

 sensorRenderTargets.Add(sceneCaptureComponent->TextureTarget);

do after (or better somewhere at the end)

 sceneCaptureComponent->TextureTarget = renderTarget2D;

because

 sensorRenderTargets.Add(UTextureRenderTarget2D * const & Item) 

which means Item is constant pointer such a pointer cannot be moved.

I'm not using WrapBox. Only AChevyBoltHUD class:

 void AChevyBoltHUD::BeginPlay()
 {
     Super::BeginPlay();
 
     //How to Get The Character
     vehicle = Cast<ASensorMountedVehicle>(GetOwningPawn());
     
 }

 void AChevyBoltHUD::DrawHUD()
 {
     Super::DrawHUD();
     
     if (vehicle)
     {
         //UTexture * HandleTexture = vehicle->sensorRenderTargets[0];
         // Declaration HandleTexture in ChevyBoltHUD.h:
         //    class UTexture * HandleTexture;
 
         if (HandleTexture)
         {
             DrawTexture(HandleTexture, 100.0f, 100.0f, 400.0f, 400.0f, 0.0f, 0.0f, 1.0f, 1.0f, FColor::White);
         }
     }
 }

Only once you can set HandleTexture. I tested it quickly in ASensorMountedVehicle::Tick()

 void ASensorMountedVehicle::Tick(float DeltaTime) 
 {
     Super::Tick(DeltaTime);
 
     // only for a second set HandleTexture
     if(GetGameTimeSinceCreation() < 1.0f)
     {
         APlayerController * PlayerController = Cast<APlayerController>(Controller);
         AChevyBoltHUD * HUD = Cast<AChevyBoltHUD>(PlayerController->GetHUD());
 
         HUD->HandleTexture = sensorRenderTargets[0];
     }
 }

Also make sure to select good sceneCaptureComponent->CaptureSource: click for Video

avatar image lufthansa747 Mar 18 '18 at 08:47 PM

I tried doing this

 void AChevyBoltHUD::DrawHUD()
 {
     Super::DrawHUD();
     for (int i = 0; i < vehicle->sensorRenderTargets.Num(); i++) {
         if (vehicle->sensorRenderTargets[i] != nullptr) {
             UE_LOG(LogTemp, Error, TEXT("Texture: %s"), vehicle->sensorRenderTargets[i]);
             DrawTexture(vehicle->sensorRenderTargets[i], 10.0f, 10.0f, 100.0f, 100.0f, 0.0f, 0.0f, 1.0f, 1.0f, FColor::White);
         }
     }
 }

But i dont see any texture drawn on the sreen, I am using capture source "SCS_SceneColorHDR"

avatar image lufthansa747 Mar 18 '18 at 08:50 PM

Also the log line looks like

LogTemp: Error: Texture: 꼠璯翻

avatar image Shaggy41 Mar 18 '18 at 11:19 PM

You should use UE_LOG like this:

 UE_LOG(LogTemp, Error, TEXT("Texture: %s"), *vehicle->sensorRenderTargets[i]->GetName());
avatar image Shaggy41 Mar 18 '18 at 11:24 PM

If you sure, that you properly using SceneCapture and save textures, then you can try to manipulate CaptureSource and BlendMode in DrawTexture(). One of the parameters in DrawTexture() is EBlendMode (after FColor):

 void AHUD::DrawTexture(
     UTexture* Texture, 
     float ScreenX, 
     float ScreenY, 
     float ScreenW, 
     float ScreenH, 
     float TextureU, 
     float TextureV, 
     float TextureUWidth, 
     float TextureVHeight, 
     FLinearColor Color, 
     EBlendMode BlendMode, //<--- HERE
     float Scale, 
     bool bScalePosition, 
     float Rotation, 
     FVector2D RotPivot
 );

Below I have created a table that shows in which combination I am getting a texture on HUD.

alt text

Also, you can change FColor to get another output.

If you want I can share my code (ChevyBoltHUD and SensorMountedVehicle class).

table.png (29.9 kB)
avatar image lufthansa747 Mar 19 '18 at 12:29 AM

Sharing your code would be much appreciated, Will report back once I've tried your above suggestions

avatar image lufthansa747 Mar 21 '18 at 10:50 PM

Work! thanks allot

avatar image lufthansa747 Mar 21 '18 at 11:16 PM

The only thing slightly off is the SceneCaptureComponent doesnt follow the vehicle around. It just stays in the same spot it was spawned. Any idea how to attach it to the vehicle?

avatar image lufthansa747 Mar 21 '18 at 11:23 PM

nvm fixed with sceneCaptureActor->AttachToActor(),thanks for the help!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question