UE4 C++ 通过Spline绘制任意道路

仅作为学习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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值