MPLandmarkStruct.h:用与记录关键点XYZ
GetMPLandmarkComponent.h与GetMPLandmarkComponent.cpp:获取关键点数据与动作识别判断
MyUobjectClass.h与MyUobjectClass.cpp:创建委托负责消息中转,应为单例模式确保其他类中始终使用的是同一个实例
MyThreadClass.h与MyThreadClass.cpp:用于主线程之外的其他计算,避免阻塞主线程导致崩溃
MyActorClass.h与MyActorClass.cpp:动作识别后触发的响应类,触发某个事件
MPLandmarkStruct.h
cpp
#pragma once
#include "CoreMinimal.h"
#include "MPLandmarkStruct.generated.h"
USTRUCT(BlueprintType)
struct FLandMarkStruct
{
GENERATED_BODY()
// 使用 UPROPERTY 宏定义结构体的成员变量
UPROPERTY(BlueprintReadOnly, Category = "Landmark")
float X;
UPROPERTY(BlueprintReadOnly, Category = "Landmark")
float Y;
UPROPERTY(BlueprintReadOnly, Category = "Landmark")
float Z;
// 可以定义构造函数
FLandMarkStruct()
: X(0.0f), Y(0.0f), Z(0.0f) {}
};
GetMPLandmarkComponent.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MediaPipeHolisticComponent.h"
#include "Components/ActorComponent.h"
#include "MPLandmarkStruct.h"
#include "MyUobjectClass.h"
#include "GetMPLandmarkComponent.generated.h"
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class MEDIAPIPE4UDEMO_API UGetMPLandmarkComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UGetMPLandmarkComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
UPROPERTY(VisibleAnywhere)
UMediaPipeHolisticComponent* MediaPipeHolisticComponent;
void OnPoseLandmarkDetected(const TSharedPtr<TArray<FMediaPipeLandmark,FDefaultAllocator>,ESPMode::ThreadSafe>& Landmarks,const FMediaPipeSourceInfo& SourceInfo);
UPROPERTY(VisibleAnywhere)
FLandMarkStruct LandMarkStruct;
UMyUobjectClass* MyUobjectClass;
};
GetMPLandmarkComponent.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "GetMPLandmarkComponent.h"
#include "Engine/Engine.h"
#include "GameFramework/Actor.h"
UGetMPLandmarkComponent::UGetMPLandmarkComponent()
{
PrimaryComponentTick.bCanEverTick = true;
MyUobjectClass = nullptr;
}
void UGetMPLandmarkComponent::BeginPlay()
{
Super::BeginPlay();
MyUobjectClass = UMyUobjectClass::GetInstance();
// 获取父Actor上的MediaPipeHolisticComponent实例
AActor* Owner = GetOwner();
if (Owner)
{
MediaPipeHolisticComponent = Owner->FindComponentByClass<UMediaPipeHolisticComponent>();
if (MediaPipeHolisticComponent)
{
// 订阅PoseLandmarksEventTrigger事件
MediaPipeHolisticComponent->PoseLandmarksEventTrigger().AddUObject(this, &UGetMPLandmarkComponent::OnPoseLandmarkDetected);
}
}
else
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("Owner is not valid"));
}
}
void UGetMPLandmarkComponent::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
void UGetMPLandmarkComponent::OnPoseLandmarkDetected(
const TSharedPtr<TArray<FMediaPipeLandmark, FDefaultAllocator>, ESPMode::ThreadSafe>& Landmarks,
const FMediaPipeSourceInfo& SourceInfo)
{
if (Landmarks.IsValid())
{
// 解引用指针来访问 TArray
const TArray<FMediaPipeLandmark>& LandmarkArray = *Landmarks;
// 处理接收到的Landmarks数据
for (const FMediaPipeLandmark& Landmark : LandmarkArray)
{
float X = Landmark.Pos.X;
float Y = Landmark.Pos.Y;
float Z = Landmark.Pos.Z;
}
const FMediaPipeLandmark& land123 = LandmarkArray[12];
LandMarkStruct.X = land123.Pos.X;
LandMarkStruct.Y = land123.Pos.Y;
LandMarkStruct.Z = land123.Pos.Z;
const FMediaPipeLandmark& leftwrist = LandmarkArray[15];
const FMediaPipeLandmark& leftshoulder = LandmarkArray[11];
if (!MyUobjectClass->bConditionTriggered)
{
if(leftwrist.Pos.Y < leftshoulder.Pos.Y)
{
if (MyUobjectClass->LandMarkGet.IsBound())
{
MyUobjectClass->LandMarkGet.Broadcast();
MyUobjectClass->bConditionTriggered = true;
}
}
}
}
else
{
GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, TEXT("Landmarks pointer is not valid"));
}
}
MyUobjectClass.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "MyUobjectClass.generated.h"
DECLARE_MULTICAST_DELEGATE(FLandMarkGet);
DECLARE_DELEGATE(FThreadMessage);
UCLASS()
class MEDIAPIPE4UDEMO_API UMyUobjectClass : public UObject
{
GENERATED_BODY()
public:
static UMyUobjectClass* GetInstance();
FLandMarkGet LandMarkGet;
FThreadMessage ThreadMessage;
bool bConditionTriggered = false;
};
MyUobjectClass.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyUobjectClass.h"
UMyUobjectClass* UMyUobjectClass::GetInstance()
{
static UMyUobjectClass* SingInstance = nullptr;
if (!SingInstance)
{
SingInstance = NewObject<UMyUobjectClass>();
SingInstance->AddToRoot();
}
return SingInstance;
}
MyThreadClass.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "MyUobjectClass.h"
#include "HAL/Runnable.h"
class MEDIAPIPE4UDEMO_API UMyThreadClass : public FRunnable
{
public:
UMyThreadClass();
~UMyThreadClass();
virtual bool Init() override;
virtual uint32 Run() override;
virtual void Stop() override;
virtual void Exit() override;
UMyUobjectClass* MyUobjectClass;
};
MyThreadClass.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyThreadClass.h"
#include "Engine/Engine.h"
#include "Windows/WindowsPlatformProcess.h"
UMyThreadClass::UMyThreadClass()
{
MyUobjectClass = nullptr;
}
UMyThreadClass::~UMyThreadClass()
{
}
bool UMyThreadClass::Init()
{
MyUobjectClass = UMyUobjectClass::GetInstance();
if (MyUobjectClass)
{
return true;
}
return false;
}
uint32 UMyThreadClass::Run()
{
FPlatformProcess::Sleep(5.0f);
MyUobjectClass->bConditionTriggered = false;
GEngine->AddOnScreenDebugMessage(-1,1.0f,FColor::Red,TEXT("this sleep finished"));
return 0;
}
void UMyThreadClass::Stop()
{
FRunnable::Stop();
}
void UMyThreadClass::Exit()
{
if (MyUobjectClass->ThreadMessage.IsBound())
{
MyUobjectClass->ThreadMessage.Execute();
FRunnable::Exit();
}
}
MyActorClass.h
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyThreadClass.h"
#include "HAL/RunnableThread.h"
#include "MyActorClass.generated.h"
UCLASS()
class MEDIAPIPE4UDEMO_API AMyActorClass : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActorClass();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(VisibleAnywhere)
USceneComponent* SceneComponent;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* StaticMeshComponent;
UPROPERTY(BlueprintReadWrite)
UStaticMesh* StaticMesh;
TUniquePtr<UMyThreadClass> MyThreadClass;
TUniquePtr<FRunnableThread> ThreadRunnable;
void TiaoCallBack();
void deletthread();
};
MyActorClass.cpp
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyActorClass.h"
#include "Engine/StaticMesh.h"
#include "Components/StaticMeshComponent.h"
// Sets default values
AMyActorClass::AMyActorClass()
{
// 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;
SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
RootComponent = SceneComponent;
StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComponent"));
StaticMeshComponent->SetupAttachment(SceneComponent);
StaticMesh = LoadObject<UStaticMesh>(nullptr,TEXT("/Engine/BasicShapes/Sphere.Sphere"));
StaticMeshComponent->SetStaticMesh(StaticMesh);
}
// Called when the game starts or when spawned
void AMyActorClass::BeginPlay()
{
Super::BeginPlay();
StaticMeshComponent->SetSimulatePhysics(true);
StaticMeshComponent->SetMassOverrideInKg(EName::None,10.f);
UMyUobjectClass* MyUobjectClass = UMyUobjectClass::GetInstance();
if (MyUobjectClass)
{
MyUobjectClass->LandMarkGet.AddUObject(this,&AMyActorClass::TiaoCallBack);
MyUobjectClass->ThreadMessage.BindUObject(this,&AMyActorClass::deletthread);
}
}
// Called every frame
void AMyActorClass::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AMyActorClass::TiaoCallBack()
{
FVector force = FVector(0.0f,0.0f,5000.0f);
StaticMeshComponent->AddImpulse(force,NAME_None);
MyThreadClass = MakeUnique<UMyThreadClass>();
ThreadRunnable = TUniquePtr<FRunnableThread>(FRunnableThread::Create(MyThreadClass.Get(), TEXT("sleep 5.0f")));
}
void AMyActorClass::deletthread()
{
ThreadRunnable.Reset();
MyThreadClass.Reset();
}