场景编辑器Atmospheric Directional Light UI

场景编辑器Atmospheric Directional Light UI

前言

项目工具需要做个一个可视化调整角度的UI。

这里想参考一下:Atmospheric Directional Lights的UI。

于是,查阅了一下源码,在这做一下记录。

一、相关源码

首先,在编辑器操作中,发现当DirectionalLight勾选了以下开关才可以改变上述UI的方向。

  • Atmosphere Sun Light

根据bUsedAsAtmosphereSunLight去查找如何被调用:

在在LevelEditorViewport.cpp文件中,可以追溯到函数:

static UDirectionalLightComponent* GetAtmosphericLight(const uint8  DesiredLightIndex, UWorld* ViewportWorld)

再继续追踪这个函数的使用,有以下几个地方:

InputKey函数中,发现这个是判断是否开启UI。

MouseMove中可以看到计算如下:可以大概猜测出,下面计算的是UI的方向。

接着可以看到UI的绘制部分:通过搜索UserIsControllingAtmosphericLightTimer

  • FLevelEditorViewportClient::Draw中具体代码如下:
// void FLevelEditorViewportClient::Draw(const FSceneView*  View,FPrimitiveDrawInterface* PDI) 
if (UserIsControllingAtmosphericLightTimer > 0.0f)
{
    // Draw a gizmo helping to figure out where is the light when moving it using a shortcut.
    FQuat ViewRotation = FQuat(GetViewRotation());
    FVector ViewPosition = GetViewLocation();
    const float GizmoDistance = 50.0f;
    const float GizmoSideOffset = 15.0f;
    const float GizmoRadius = 10.0f;
    const float ThicknessLight = 0.05f;
    const float ThicknessBold = 0.2f;


    // Always draw the gizmo right in in front of the camera with a little side shift.
    const FVector X(1.0f, 0.0f, 0.0f);
    const FVector Y(0.0f, 1.0f, 0.0f);
    const FVector Z(0.0f, 0.0f, 1.0f);
    const FVector Base = ViewPosition + GizmoDistance * ViewRotation.GetForwardVector() + GizmoSideOffset * (-ViewRotation.GetUpVector() + ViewRotation.GetRightVector());


    // Draw world main axis
    FRotator IdentityX(0.0f, 0.0f, 0.0f);
    FRotator IdentityY(0.0f, 90.0f, 0.0f);
    FRotator IdentityZ(90.0f, 0.0f, 0.0f);
    DrawDirectionalArrow(PDI, FQuatRotationTranslationMatrix(FQuat(IdentityX), Base), FColor(255, 0, 0, 127), GizmoRadius, 0.3f, SDPG_World, ThicknessBold);
    DrawDirectionalArrow(PDI, FQuatRotationTranslationMatrix(FQuat(IdentityY), Base), FColor(0, 255, 0, 127), GizmoRadius, 0.3f, SDPG_World, ThicknessBold);
    DrawDirectionalArrow(PDI, FQuatRotationTranslationMatrix(FQuat(IdentityZ), Base), FColor(0, 0, 255, 127), GizmoRadius, 0.3f, SDPG_World, ThicknessBold);


    // Render polar coordinate circles
    DrawCircle(PDI, Base, X, Y, FLinearColor(0.2f, 0.2f, 1.0f), GizmoRadius, 32, SDPG_World, ThicknessBold);
    DrawCircle(PDI, Base, X, Y, FLinearColor(0.2f, 0.2f, 0.75f), GizmoRadius*0.75f, 32, SDPG_World, ThicknessLight);
    DrawCircle(PDI, Base, X, Y, FLinearColor(0.2f, 0.2f, 0.50f), GizmoRadius*0.50f, 32, SDPG_World, ThicknessLight);
    DrawCircle(PDI, Base, X, Y, FLinearColor(0.2f, 0.2f, 0.25f), GizmoRadius*0.25f, 32, SDPG_World, ThicknessLight);
    DrawArc(PDI, Base, Z, Y, -90.0f, 90.0f, GizmoRadius, 32, FLinearColor(1.0f, 0.2f, 0.2f), SDPG_World);
    DrawArc(PDI, Base, Z, X, -90.0f, 90.0f, GizmoRadius, 32, FLinearColor(0.2f, 1.0f, 0.2f), SDPG_World);


    // Draw the light incoming light direction. The arrow is offset outward to help depth perception when it intersects with other gizmo elements.
    const FLinearColor ArrowColor = -UserControlledAtmosphericLightMatrix.GetRotation().GetForwardVector() * 0.5f + 0.5f;
    const FVector ArrowOrigin = Base - UserControlledAtmosphericLightMatrix.GetRotation().GetForwardVector()*GizmoRadius*1.25;
    const FQuatRotationTranslationMatrix ArrowToWorld(UserControlledAtmosphericLightMatrix.GetRotation(), ArrowOrigin);
    DrawDirectionalArrow(PDI, ArrowToWorld, ArrowColor, GizmoRadius, 0.3f, SDPG_World, ThicknessBold);


    // Now draw x, y and z axis to help getting a sense of depth when look at the vectors on screen.
    FVector LightArrowTip = -UserControlledAtmosphericLightMatrix.GetRotation().GetForwardVector()*GizmoRadius;
    FVector P0 = Base + LightArrowTip * FVector(1.0f, 0.0f, 0.0f);
    FVector P1 = Base + LightArrowTip * FVector(1.0f, 1.0f, 0.0f);
    FVector P2 = Base + LightArrowTip * FVector(1.0f, 1.0f, 1.0f);
    PDI->DrawLine(Base, P0, FLinearColor(1.0f, 0.0f, 0.0f), SDPG_World, ThicknessLight);
    PDI->DrawLine(P0, P1, FLinearColor(0.0f, 1.0f, 0.0f), SDPG_World, ThicknessLight);
    PDI->DrawLine(P1, P2, FLinearColor(0.0f, 0.0f, 1.0f), SDPG_World, ThicknessLight);
}

小结

  • LevelEditorViewport::InputKey,通过热键判断是否开启UI显示。
  • LevelEditorViewport::MouseMove,计算鼠标移动,来求得Transform矩阵用于渲染。
  • LevelEditorViewport::Draw,渲染调整角度的UI。

通过以上的代码分析,很快可以在场景编辑器中模仿实现一个简单的角度控制的UI。

参考文献

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值