UE4: screen offset indication

如需转载本文,请声明作者及出处。

// 屏幕外的3d位置,在屏幕上的指向
void screen_offset_indicate(WorldLocalX, WorldLocalY, WorldLocalZ)
{

    APlayerController* Player = ...;
    //指向图标的角度
    float RotationAngleDegrees = 0.f;
    //指向图标在屏幕上的位置
    FVector2D *ScreenPosition = new FVector2D();

    const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY()) / UWidgetLayoutLibrary::GetViewportScale(Player);
    const FVector2D ViewportCenter = FVector2D(ViewportSize.X / 2, ViewportSize.Y / 2);
    ACharacter *PlayerCharacter = static_cast<ACharacter*>(Player->GetPawn());
    if (!PlayerCharacter)
    {
        return;
    }

    FVector Worldlocal = FVector(WorldLocalX, WorldLocalY, WorldLocalZ);
    FVector Forward = PlayerCharacter->GetActorForwardVector();
    FVector Offset = (Worldlocal - PlayerCharacter->GetActorLocation()).GetSafeNormal();
    float EdgePercent = 0.8f;   // 可调可配,贴边的百分比

    float DotProduct = FVector::DotProduct(Forward, Offset);
    bool IsBehindCamera = (DotProduct < 0.0);

    if (IsBehindCamera)
    {
        //当要指向的点跟到相机后时
        //取巧的做法,将相机后的位置取反,得到屏幕位置后,再用屏幕宽度来减
        FVector DiffVector = Worldlocal - PlayerCharacter->GetActorLocation();
        FVector Inverted = DiffVector * -1.f;
        FVector NewLocal = PlayerCharacter->GetActorLocation() + Inverted;

        Player->ProjectWorldLocationToScreen(NewLocal, *ScreenPosition);
        ScreenPosition->Y = ViewportSize.Y - ScreenPosition->Y;
        ScreenPosition->X = ViewportSize.X - ScreenPosition->X;
    }

    Player->ProjectWorldLocationToScreen(Worldlocal, *ScreenPosition);

    if (ScreenPosition->X >= 0.f && ScreenPosition->X <= ViewportSize.X && ScreenPosition->Y >= 0.f && ScreenPosition->Y <= ViewportSize.Y)
    {
        //ScreenPosition在屏幕内了
        return;
    }

    *ScreenPosition -= ViewportCenter;
    float AngleRadians = FMath::Atan2(ScreenPosition->Y, ScreenPosition->X);
    AngleRadians -= FMath::DegreesToRadians(90.0f);
    RotationAngleDegrees = FMath::RadiansToDegrees(AngleRadians) + 180.0f;

    float Cos = cosf(AngleRadians);
    float Sin = -sinf(AngleRadians);

    ScreenPosition = new FVector2D(ViewportCenter.X + (Sin * 150.0f), ViewportCenter.Y + (Cos * 150.0f));
    float m = Cos / Sin;
    FVector2D ScreenBounds = ViewportCenter * EdgePercent;
    if (Cos > 0.0)
    {
        ScreenPosition = new FVector2D(ScreenBounds.Y / m, ScreenBounds.Y);
    }
    else
    {
        ScreenPosition = new FVector2D(-ScreenBounds.Y / m, -ScreenBounds.Y);
    }

    if (ScreenPosition->X > ScreenBounds.X)
    {
        ScreenPosition = new FVector2D(ScreenBounds.X, ScreenBounds.X*m);
    }
    else if (ScreenPosition->X < -ScreenBounds.X)
    {
        ScreenPosition = new FVector2D(-ScreenBounds.X, -ScreenBounds.X*m);
    }

    *ScreenPosition += ViewportCenter;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值