A downloadable game

void ARealtimeCaptureActor::ReadRenderTargetWithStagingBuffer()

{

    if (!RenderTarget)

    {

        UE_LOG(LogTemp, Warning, TEXT("RenderTarget is NULL!"));

        return;

    }

    FTextureRenderTargetResource* RTResource = RenderTarget->GameThread_GetRenderTargetResource();

    if (!RTResource)

    {

        UE_LOG(LogTemp, Warning, TEXT("RenderTargetResource is NULL!"));

        return;

    }

    ENQUEUE_RENDER_COMMAND(CaptureFrame)(

        [RTResource, this](FRHICommandListImmediate& RHICmdList)

        {

            // Create a Staging Texture (CPU Readback)

            FRHIResourceCreateInfo ci = FRHIResourceCreateInfo(TEXT("CreateInfo"));

            FTexture2DRHIRef StagingTexture = RHICreateTexture2D(

                512, 512, PF_B8G8R8A8, 1, 1, TexCreate_CPUReadback, ci);

            if (!StagingTexture)

            {

                UE_LOG(LogTemp, Error, TEXT("Failed to create Staging Texture!"));

                return;

            }

            // Copy RenderTarget → Staging Texture (GPU-GPU, fast)

            FRHICopyTextureInfo CopyInfo;

            RHICmdList.CopyTexture(RTResource->GetRenderTargetTexture(), StagingTexture, CopyInfo);

            // Map and Read Data from Staging Buffer (GPU-CPU, optimized)

            uint32 Stride = 0;  // Let LockTexture2D set the correct stride

            void* Data = RHICmdList.LockTexture2D(StagingTexture, 0, EResourceLockMode::RLM_ReadOnly, Stride, false);

            if (!Data)

            {

                UE_LOG(LogTemp, Error, TEXT("LockTexture2D FAILED! Stride = %u"), Stride);

                return;

            }

            // Debugging stride value

            //UE_LOG(LogTemp, Log, TEXT("Stride Value: %u (Expected: %d)"), Stride, 512 * sizeof(FColor));

            // Ensure stride is valid

            if (Stride < 512 * sizeof(FColor))

            {

                UE_LOG(LogTemp, Error, TEXT("Invalid Stride! Got: %u, Expected: >= %d"), Stride, 512 * sizeof(FColor));

                RHICmdList.UnlockTexture2D(StagingTexture, 0, false);

                return;

            }

            // Read pixel data

            TArray<FColor> LocalBMP;

            LocalBMP.SetNum(512 * 512);

            uint8* SrcPtr = static_cast<uint8*>(Data);

            for (int32 Row = 0; Row < 512; ++Row)

            {

                FMemory::Memcpy(&LocalBMP[Row * 512], SrcPtr + (Row * Stride), 512 * sizeof(FColor));

            }

            RHICmdList.UnlockTexture2D(StagingTexture, 0, false);

            AsyncTask(ENamedThreads::GameThread, [this, LocalBMP]()

                {

                    UpdateDynamicTexture(LocalBMP, 512, 512);

                });

        });

    FlushRenderingCommands(); // Ensure execution

}
//////////////
Model Loader
////////////
.cpp
////

// Fill out your copyright notice in the Description page of Project Settings.

#include "XMLModelLoader.h"

#include "CoreMinimal.h"

#include "Misc/FileHelper.h"

#include "Misc/Paths.h"

#include "XmlParser.h"

#include "Engine/StaticMeshActor.h"

#include "Engine/StaticMesh.h"

#include "UObject/ConstructorHelpers.h"

// Sets default values

AXMLModelLoader::AXMLModelLoader()

{

  // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned

void AXMLModelLoader::BeginPlay()

{

Super::BeginPlay();

}

// Called every frame

void AXMLModelLoader::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

}

void AXMLModelLoader::SwapStaticMeshFromXML(FString XMLFilePath)

{

    // Load XML File

    FXmlFile XMLFile(XMLFilePath);

    if (!XMLFile.IsValid())

    {

        UE_LOG(LogTemp, Error, TEXT("Failed to read XML file: %s"), *XMLFilePath);

        return;

    }

    // Get the Root Node

    FXmlNode* RootNode = XMLFile.GetRootNode();

    if (!RootNode)

    {

        UE_LOG(LogTemp, Error, TEXT("Invalid XML structure"));

        return;

    }

    // Find <MeshPath> Node

    FXmlNode* MeshNode = RootNode->FindChildNode("MeshPath");

    if (!MeshNode)

    {

        UE_LOG(LogTemp, Error, TEXT("MeshPath node not found in XML"));

        return;

    }

    FString MeshPath = MeshNode->GetContent(); // Read Mesh Path

    UE_LOG(LogTemp, Log, TEXT("Found MeshPath: %s"), *MeshPath);

    // Load Mesh

    UStaticMesh* NewMesh = LoadObject<UStaticMesh>(nullptr, *MeshPath);

    if (!NewMesh)

    {

        UE_LOG(LogTemp, Error, TEXT("Failed to load mesh: %s"), *MeshPath);

        return;

    }

    // Swap Mesh on Actor's StaticMeshComponent

    if (UStaticMeshComponent* MeshComp = FindComponentByClass<UStaticMeshComponent>())

    {

        MeshComp->SetStaticMesh(NewMesh);

        UE_LOG(LogTemp, Log, TEXT("Successfully swapped mesh!"));

    }

    else

    {

        UE_LOG(LogTemp, Error, TEXT("No StaticMeshComponent found on actor!"));

    }

}

////////////////
.h

///////////////

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "XMLModelLoader.generated.h"

UCLASS()

class AIRSIM_API AXMLModelLoader : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

AXMLModelLoader();

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

public:

// Called every frame

virtual void Tick(float DeltaTime) override;

public:

void AXMLModelLoader::SwapStaticMeshFromXML(FString XMLFilePath);

};
/////////

Dont forget to add XMLParser to build.cs, and perhaps uproject, check other projects source that use XMLReader...........

//////////

Published 10 days ago
StatusReleased
Authorthe_gamearchitect

Leave a comment

Log in with itch.io to leave a comment.