hello unreal people, this time with a powerfull existential question… how is the best way of texture refresh?
i try to integrate kinect in the best way posible, but when i try from a single ActorComponent with a texture i got a poor 15 fps, so is very slow for my porposes, so i try all with FRunnable but is run even slower at 1 fps jajaja, obviosly i do something very bad
this is the full source if you want check i dont care share, maybe some unreal developer can point me in the right way.
Actor component h:
#pragma once
#include "KinectInterface.h"
#include "CameraCapture.h"
#include "Components/ActorComponent.h"
#include "UEKinect.generated.h"
using namespace std;
UCLASS(ClassGroup = (Hardware), meta = (BlueprintSpawnableComponent), meta = (FriendlyName = "Kinect"))
class VIRTUALDRESSER_API UUEKinect : public UActorComponent
{
GENERATED_BODY()
private:
UTexture2D* colorTexture;
KinectInterface kinectThread;
public:
// Sets default values for this component's properties
UUEKinect();
// Called when the game starts
virtual void InitializeComponent() override;
virtual void UninitializeComponent() override;
// Called every frame
virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override;
UFUNCTION(BlueprintCallable, Category = Kinect)
UTexture2D* open();
};
actor component cpp:
#include "VirtualDresser.h"
#include "UEKinect.h"
// Sets default values for this component's properties
UUEKinect::UUEKinect()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
bWantsInitializeComponent = true;
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UUEKinect::InitializeComponent()
{
Super::InitializeComponent();
// ...
}
void UUEKinect::UninitializeComponent()
{
Super::UninitializeComponent();
kinectThread.Detach();
}
// Called every frame
void UUEKinect::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
{
Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
// ...
}
UTexture2D* UUEKinect::open()
{
kinectThread = KinectInterface();
colorTexture = kinectThread.getTexture();
kinectThread.Attach();
return colorTexture;
}
my kinect interface for do thread h:
#pragma once
#include "Runtime/Core/Public/HAL/ThreadingBase.h"
#include "CameraCapture.h"
#include "AllowWindowsPlatformTypes.h"
#include "Kinect.h"
#include "HideWindowsPlatformTypes.h"
#include "Components/ActorComponent.h"
/**
*
*/
class KinectInterface : FRunnable
{
bool bStop;
FRunnableThread* Thread;
int width;
int height;
FUpdateTextureRegion2D *echoUpdateTextureRegion;
//kinect
IKinectSensor* pKinect;
IColorFrameSource* pColorFrameSource;
IColorFrameReader* pColorFrameReader;
ICoordinateMapper* pCoordinateMapper;
IBodyFrameSource* pBodyFrameSource;
IBodyFrameReader* pBodyFrameReader;
private:
void updateKinect(bool bFreeData);
public:
UTexture2D* texture;
KinectInterface();
~KinectInterface();
//Overrides
virtual void Exit() override;
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
//Callables
void Attach();
void Detach();
UTexture2D* getTexture();
};
template<class Interface>
inline void SafeRelease(Interface *& pInterfaceRelease)
{
if (pInterfaceRelease != NULL)
{
pInterfaceRelease->Release();
pInterfaceRelease = NULL;
}
}
and finally the interface cpp:
#include "VirtualDresser.h"
#include "KinectInterface.h"
#define print(text) if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 1.5, FColor::White,text)
KinectInterface::KinectInterface()
{
}
KinectInterface::~KinectInterface()
{
Exit();
}
void KinectInterface::Exit()
{
if (Thread != NULL)
{
Thread->Kill(false);
Thread->~FRunnableThread();
Thread = NULL;
}
}
bool KinectInterface::Init()
{
HRESULT hr = S_OK;
hr = GetDefaultKinectSensor(&pKinect);
if (SUCCEEDED(hr))
{
hr = pKinect->Open();
if (SUCCEEDED(hr))
{
hr = pKinect->get_ColorFrameSource(&pColorFrameSource);
}
if (SUCCEEDED(hr))
{
hr = pColorFrameSource->OpenReader(&pColorFrameReader);
}
if (SUCCEEDED(hr))
{
hr = pKinect->get_CoordinateMapper(&pCoordinateMapper);
}
if (SUCCEEDED(hr))
{
hr = pKinect->get_BodyFrameSource(&pBodyFrameSource);
}
if (SUCCEEDED(hr))
{
hr = pBodyFrameSource->OpenReader(&pBodyFrameReader);
}
if (SUCCEEDED(hr))
{
bStop = false;
}
}
SafeRelease(pBodyFrameSource);
SafeRelease(pColorFrameSource);
return true;
}
uint32 KinectInterface::Run()
{
FPlatformProcess::Sleep(0.03f);
while (!bStop && texture != NULL)
{
print("hell yeah");
updateKinect(false);
FPlatformProcess::Sleep(.033f);
}
return 0;
}
void KinectInterface::Stop()
{
bStop = true;
}
void KinectInterface::Attach()
{
Thread = FRunnableThread::Create(this, TEXT("KinectInterface"), true, true, 0, TPri_BelowNormal);
}
void KinectInterface::Detach()
{
Stop();
Exit();
}
UTexture2D* KinectInterface::getTexture()
{
width = 1920;
height = 1080;
texture = UTexture2D::CreateTransient(width, height, PF_B8G8R8A8);
echoUpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, width, height);
texture->UpdateResource();
return texture;
}
void KinectInterface::updateKinect(bool bFreeData)
{
if (!pColorFrameReader && !pBodyFrameReader)
{
return;
}
IColorFrame* pColorFrame = nullptr;
HRESULT hr = pColorFrameReader->AcquireLatestFrame(&pColorFrame);
if (SUCCEEDED(hr))
{
unsigned int bufferSize = width * height * 4 * sizeof(unsigned char);
unsigned char* rawData = new unsigned char[bufferSize];
hr = pColorFrame->CopyConvertedFrameDataToArray(bufferSize, rawData, ColorImageFormat::ColorImageFormat_Bgra);
if (SUCCEEDED(hr))
{
FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;
RegionData->Texture2DResource = (FTexture2DResource*)texture->Resource;
RegionData->MipIndex = 0;
RegionData->NumRegions = 1;
RegionData->Regions = echoUpdateTextureRegion;
RegionData->SrcPitch = (uint32)(4 * width);
RegionData->SrcBpp = 4;
RegionData->SrcData = (uint8*)rawData;
// call the RHIUpdateTexture2D to refresh the texture with new info
ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
UpdateTextureRegionsData,
FUpdateTextureRegionsData*, RegionData, RegionData,
bool, bFreeData, bFreeData,
{
for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
{
int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
if (RegionData->MipIndex >= CurrentFirstMip)
{
RHIUpdateTexture2D(
RegionData->Texture2DResource->GetTexture2DRHI(),
RegionData->MipIndex - CurrentFirstMip,
RegionData->Regions[RegionIndex],
RegionData->SrcPitch,
RegionData->SrcData
+ RegionData->Regions[RegionIndex].SrcY * RegionData->SrcPitch
+ RegionData->Regions[RegionIndex].SrcX * RegionData->SrcBpp
);
}
}
if (bFreeData)
{
FMemory::Free(RegionData->Regions);
FMemory::Free(RegionData->SrcData);
}
delete RegionData;
});
}
}
SafeRelease(pColorFrame);
}
All the code works perfectly but is slow, why? that the question
if someone can try is free to do