Backend: - Add /api/v1/ue/* endpoints (compute-points, cables, landing-points, satellites, status) returning flat JSON optimised for UE5 C++ parsing UE5 client (ue_client/): - PlanetDataManager: HTTP fetch + local mock JSON loader, spawns ComputePointActors - ComputePointActor / InteractiveObjectBase: hover/select state, material switching - GlobeInteractionComponent: drag-to-rotate via CesiumGeoreference origin shift, inertia, zoom - StereoRenderingManager: runtime SbS/TbB stereo toggle, IPD control (format TBD) - MotionCaptureInterface: protocol-agnostic gesture/rotate/zoom delegate interface (impl TBD) - PlanetPlayerController: unified mouse + motion-capture input routing - PlanetGameMode, Build.cs, Config, mock data Docs: - ue5_mvp_fused_plan.md updated to v3.0 for LED display context - ue_client_setup_guide.md: step-by-step editor setup guide - ue_todo.md: pending items blocked on vendor answers (stereo format + mocap protocol) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
123 lines
4.0 KiB
C++
123 lines
4.0 KiB
C++
#include "GlobeInteractionComponent.h"
|
||
#include "CesiumGeoreference.h"
|
||
#include "Engine/World.h"
|
||
#include "GameFramework/Pawn.h"
|
||
#include "GameFramework/PlayerController.h"
|
||
#include "Kismet/GameplayStatics.h"
|
||
|
||
UGlobeInteractionComponent::UGlobeInteractionComponent()
|
||
{
|
||
PrimaryComponentTick.bCanEverTick = true;
|
||
}
|
||
|
||
void UGlobeInteractionComponent::BeginPlay()
|
||
{
|
||
Super::BeginPlay();
|
||
FindGeoreference();
|
||
}
|
||
|
||
void UGlobeInteractionComponent::FindGeoreference()
|
||
{
|
||
Georeference = ACesiumGeoreference::GetDefaultGeoreference(GetWorld());
|
||
if (!Georeference)
|
||
{
|
||
UE_LOG(LogTemp, Error,
|
||
TEXT("GlobeInteractionComponent: 场景中没有 CesiumGeoreference,请添加一个"));
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 旋转
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void UGlobeInteractionComponent::RotateGlobe(float DeltaYaw, float DeltaPitch)
|
||
{
|
||
if (!Georeference) return;
|
||
|
||
// 累积惯性速度(本帧的输入叠加到惯性上)
|
||
InertiaYaw += DeltaYaw * RotateSensitivity;
|
||
InertiaPitch += DeltaPitch * RotateSensitivity;
|
||
|
||
// 立即应用(Tick 里再处理惯性衰减)
|
||
double NewLon = Georeference->GetOriginLongitude() - InertiaYaw;
|
||
double NewLat = FMath::Clamp(
|
||
Georeference->GetOriginLatitude() + InertiaPitch,
|
||
-85.0, 85.0
|
||
);
|
||
|
||
Georeference->SetOriginLongitude(NewLon);
|
||
Georeference->SetOriginLatitude(NewLat);
|
||
|
||
// 保持经度在 [-180, 180]
|
||
if (NewLon > 180.0) Georeference->SetOriginLongitude(NewLon - 360.0);
|
||
if (NewLon < -180.0) Georeference->SetOriginLongitude(NewLon + 360.0);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 缩放
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void UGlobeInteractionComponent::ZoomGlobe(float Value)
|
||
{
|
||
if (FMath::IsNearlyZero(Value)) return;
|
||
|
||
// Value > 0 = 拉近(高度减小),Value < 0 = 推远(高度增大)
|
||
CurrentAltitudeMeters -= Value * ZoomSensitivity;
|
||
CurrentAltitudeMeters = FMath::Clamp(CurrentAltitudeMeters,
|
||
MinAltitudeMeters,
|
||
MaxAltitudeMeters);
|
||
ApplyAltitudeToCamera();
|
||
}
|
||
|
||
void UGlobeInteractionComponent::ApplyAltitudeToCamera()
|
||
{
|
||
if (!Georeference) return;
|
||
|
||
// 把当前 Origin 经纬度 + 新高度转换为 Unreal 世界坐标,然后移动拥有者 Pawn
|
||
AController* Controller = Cast<AController>(GetOwner());
|
||
APawn* Pawn = Controller ? Controller->GetPawn() : Cast<APawn>(GetOwner());
|
||
if (!Pawn) return;
|
||
|
||
double Lon = Georeference->GetOriginLongitude();
|
||
double Lat = Georeference->GetOriginLatitude();
|
||
|
||
FVector NewPos = Georeference->TransformLongitudeLatitudeHeightPositionToUnreal(
|
||
FVector(Lon, Lat, CurrentAltitudeMeters)
|
||
);
|
||
Pawn->SetActorLocation(NewPos);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// 惯性 Tick
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void UGlobeInteractionComponent::TickComponent(float DeltaTime, ELevelTick TickType,
|
||
FActorComponentTickFunction* ThisTickFunction)
|
||
{
|
||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||
|
||
// 只有惯性速度足够大时才继续转动
|
||
if (FMath::IsNearlyZero(InertiaYaw, 0.001f) &&
|
||
FMath::IsNearlyZero(InertiaPitch, 0.001f)) return;
|
||
|
||
if (!Georeference) return;
|
||
|
||
double NewLon = Georeference->GetOriginLongitude() - InertiaYaw;
|
||
double NewLat = FMath::Clamp(
|
||
Georeference->GetOriginLatitude() + InertiaPitch,
|
||
-85.0, 85.0
|
||
);
|
||
Georeference->SetOriginLongitude(NewLon);
|
||
Georeference->SetOriginLatitude(NewLat);
|
||
|
||
// 惯性衰减
|
||
InertiaYaw *= InertiaDamping;
|
||
InertiaPitch *= InertiaDamping;
|
||
}
|
||
|
||
void UGlobeInteractionComponent::StopInertia()
|
||
{
|
||
InertiaYaw = 0.f;
|
||
InertiaPitch = 0.f;
|
||
}
|