仅作为学习UE4的记录,请勿转载。
先看效果图
上关键源码。
1. 通过两个点和点的切线向量构建一个SplineMeshCompoent。
USplineMeshComponent* ASplineRoadActor::CreateSplineMeshComponent(const FVector& StartPos, const FVector& StartTangent, const FVector& EndPos, const FVector& EndTangent, const FVector& UpDir)
{
USplineMeshComponent* pSplineMesh = NewObject<USplineMeshComponent>(this, USplineMeshComponent::StaticClass());
pSplineMesh->CreationMethod = EComponentCreationMethod::UserConstructionScript;
pSplineMesh->SetStaticMesh(SplineStaticMesh);
// pSplineMesh->AttachTo(pSpline);
pSplineMesh->SetForwardAxis(ForwardAxis, false);
FTransform t = pSplineMesh->GetRelativeTransform();
t.SetScale3D(FVector(1.f, 1.f, 1.f));
pSplineMesh->SetRelativeTransform(t);
pSplineMesh->SetStartAndEnd(StartPos, StartTangent, EndPos, EndTangent);
pSplineMesh->SetSplineUpDir(UpDir);
return pSplineMesh;
}
2. 使用上面的函数绘制多条道路
void ASplineRoadActor::CreateSplineMesh(const TArray<TArray<FVector>>& pts)
{
// 将数据显示加载到窗口进行显示
for (const TArray<FVector> &line : pts)
{
USplineComponent* pSpline = NewObject<USplineComponent>(this, USplineComponent::StaticClass());
pSpline->SetupAttachment(Scene);
pSpline->RegisterComponent();
pSpline->SetSplineLocalPoints(line);
// 只有两个点,则直接绘制
if (pSpline->GetNumberOfSplinePoints() == 2)
{
// 先获取三个点
FVector FirstPos, LastPos;
FVector Tangent;
FirstPos = pSpline->GetLocationAtSplinePoint(0, ESplineCoordinateSpace::Local);
LastPos = pSpline->GetLocationAtSplinePoint(1, ESplineCoordinateSpace::Local);
Tangent = LastPos - FirstPos;
CreateSplineMeshComponent(FirstPos, Tangent, LastPos, Tangent, FVector(0, -1, 0));
return;
}
// 两个以上点,则需要计算朝向
for (int32 i = 0; i < pSpline->GetNumberOfSplinePoints() - 2; i++)
{
// 先获取三个点
FVector FirstPos, MiddlePos, LastPos;
FVector StartTangent, EndTangent;
FirstPos = pSpline->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::Local);
MiddlePos = pSpline->GetLocationAtSplinePoint(i + 1, ESplineCoordinateSpace::Local);
LastPos = pSpline->GetLocationAtSplinePoint(i + 2, ESplineCoordinateSpace::Local);
// 计算两个线段的方向
StartTangent = MiddlePos - FirstPos;
StartTangent.Normalize();
EndTangent = LastPos - MiddlePos;
EndTangent.Normalize();
// 计算mesh的朝向
FVector StartDir = StartTangent;
FVector EndDir = EndTangent;
float LineDir = atan2(StartDir.Y, StartDir.X) - atan2(EndDir.Y, EndDir.X);
if (LineDir > PI)
LineDir = 0 - LineDir;
else if (LineDir < -PI)
LineDir = 0 - LineDir;
FVector UpDir(0, 1, 0);
if (LineDir < 0.f)
{
UpDir = StartDir - EndDir;
}
else if (LineDir > 0.f)
{
UpDir = EndDir - StartDir;
}
// 创建mesh
CreateSplineMeshComponent(FirstPos, StartTangent, MiddlePos, EndTangent, UpDir);
// 给最后一个线段创建mesh
if (i == pSpline->GetNumberOfSplinePoints() - 3)
{
CreateSplineMeshComponent(MiddlePos, EndTangent, LastPos, EndTangent, UpDir);
}
}
}
//注册组件
RegisterAllComponents();
}
3. 使用模拟数据进行显示。
void ASplineRoadActor::BeginPlay()
{
Super::BeginPlay();
// 使用一些模拟数据创建道路
TArray<TArray<FVector>> pts;
// 第一条道路
TArray<FVector> road1;
road1.Add(FVector(0, 0, 10));
road1.Add(FVector(200, 200, 10));
road1.Add(FVector(200, 400, 10));
road1.Add(FVector(0, 200, 10));
road1.Add(FVector(-200, 0, 10));
pts.Add(road1);
TArray<FVector> road2;
road2.Add(FVector(-400, 0, 10));
road2.Add(FVector(-400, -200, 10));
road2.Add(FVector(-200, -200, 10));
road2.Add(FVector(-400, -400, 10));
road2.Add(FVector(-600, -100, 10));
pts.Add(road2);
CreateSplineMesh(pts);
}
最后附上源码下载链接:https://download.csdn.net/download/chenxipu123/15866603