UE5.3 C++ Ceiusm中的POI 制作3DUI 结合坐标转化
一.核心思路WidgetComponent + CesiumGloberAnchor
二.先制作POI
创建C++ Actor来制作,APOI。直接上代码
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CesiumGlobeAnchorComponent.h"
#include "POI.generated.h"
UCLASS()
class HMS3DUI_API APOI : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
APOI();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable)
void MoveToLLA(double Longtitude,double Latitude,double Altidude);
UFUNCTION(BlueprintCallable)
FVector GetLLA();
// WidgetComponent
UPROPERTY(BlueprintReadWrite,EditAnywhere, Category = WidgetComponent)
class UWidgetComponent* WidgetComponent;
private:
UPROPERTY(BlueprintReadOnly, EditAnywhere, meta = (AllowPrivateAccess = "true"))
UCesiumGlobeAnchorComponent* globeAnchor;//地球组件
};
然后在CPP里,实现组件。并设置为3DUI,这里用的屏幕尺寸的。
// Sets default values
APOI::APOI()
{
// 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;
WidgetComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("WidgetComponent"));
WidgetComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
// 设置控件蓝图
//UClass* Widget = LoadClass<UUserWidget>(NULL, TEXT("/Script/UMGEditor.WidgetBlueprint'/HMS3DUI/POI.POI_C'"));
static ConstructorHelpers::FClassFinder<UUserWidget>WidgetClass(TEXT("/Script/UMGEditor.WidgetBlueprint'/HMS3DUI/POI.POI_C'"));
WidgetComponent->SetWidgetClass(WidgetClass.Class);
//设置渲染方式,是渲染到屏幕还是世界中
WidgetComponent->SetWidgetSpace(EWidgetSpace::Screen);
//设置绘制大小
WidgetComponent->SetDrawSize(FVector2D(1280, 720));
globeAnchor = CreateDefaultSubobject<UCesiumGlobeAnchorComponent>(TEXT("CesiumGlobe"));
}
两个函数,无论时显示UI现在的地方,还是UI输入去其它地方都能实现,坐标的转换。
void APOI::MoveToLLA(double Longtitude, double Latitude, double Altidude)
{
globeAnchor->MoveToLongitudeLatitudeHeight(FVector(Longtitude, Latitude, Altidude));
}
FVector APOI::GetLLA()
{
FVector tmp = globeAnchor->GetLongitudeLatitudeHeight();
if (globeAnchor)
{
return tmp;
}
return FVector(0,0,0);
}
简单做个UI,这个UI把锚点放到屏幕中心。就能实现3DUI刚好在那个点上。
通过UIManager, Spawn和管理3DUI.
void AHMSUIManager::Spawn3DUI(double Longtitude, double Latitude, double Altidude)
{
/*UClass* MyTmpClass = LoadClass<AActor>(this, TEXT("/Script/Engine.Blueprint'/HMS3DUI/BP_POI.BP_POI_C'"));
if (MyTmpClass)
{
AActor* SpawnActor = GetWorld()->SpawnActor<AActor>(MyTmpClass, FVector::ZeroVector, FRotator::ZeroRotator);
}*/
UClass* MyTmpClass = LoadClass<APOI>(this, TEXT("/Script/Engine.Blueprint'/HMS3DUI/BP_POI.BP_POI_C'"));
APOI* poi = GetWorld()->SpawnActor<APOI>(MyTmpClass);
poi->MoveToLLA(Longtitude, Latitude, Altidude);
}
简单的通过UI,传值调用。
这里当时卡住了,我继承了C++类来进一步写POI的写如UI的TEXT。获得WidgetComponet并GetWidget 转换为 POI这个Widget。这样就可以实现Actor拿到它想显示的UI,并赋值修改这个UI。
而且涉及经纬度,ToText需要设置小数点后的位数 7。
自动在对应经纬产出物体,显示经纬高
三. 延申功能,在鼠标射线中,点击的地方生成3DUI。
之所以用蓝图,因为快。C++也能写只是,要多加一些库。
核心