ue4绘制线的三种方式

第一种方式,是用样条线,简明扼要,但是打包后就消失了。

	AActor* actor = world->SpawnActor< AActor>(ActorClass);
	actor->AttachToActor(this, FAttachmentTransformRules::KeepRelativeTransform);
	USplineComponent* splineComponent = this->GenerateSplineComponent(info, radius,actor);
	splineComponent->AttachToComponent(actor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
	TArray<FVector> posArray;
			USplineComponent* splineComponent = this->GenerateSplineComponent(posArray,actor);
	splineComponent->AttachToComponent(actor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);

USplineComponent* MyActor::GenerateSplineComponent(TArray< FVector> posArray, AActor* actor)
{

TArray<FVector> posXYZArray;
USplineComponent* splineTrack = NewObject<USplineComponent>(actor, TEXT("Spline"));
splineTrack->RegisterComponent();
//设置样本条的颜色
splineTrack->SetUnselectedSplineSegmentColor(FLinearColor(0.0f, 0.0f, 1.0f));
//设置样条线的粗细或者宽度
splineTrack->ScaleVisualizationWidth = 70.0f;
splineTrack->SetSplineLocalPoints(posArray);
splineTrack->SetDrawDebug(true);
splineTrack->UpdateSpline();
splineTrack->SetHiddenInGame(false);

return splineTrack;

}

第二种方式是用ULineBatchComponent画线,这个是世界坐标系的,也就是说,即使父子节点,也不能用相对位置。好处是,是实体,可以从样条线中获取位置。关键就在于FSplinePositionLinearApproximation::Build()这个方法。这个方法有三个参数,第三个参数,可以在保持曲线不变的情况下,控制点的数量,这就很好了,比如,如果近处需要100个点,那么远处10个点就Ok了。

ULineBatchComponent* MyActor::GetBatchLineComponentFromSplineComponent(
AActor* parentActor,
USplineComponent* splineComponent)
{
if (nullptr == splineComponent)
{
return nullptr;
}
TArray< FSplinePositionLinearApproximation> outputSpline;
outputSpline.Empty();
FSplinePositionLinearApproximation::Build(splineComponent->SplineCurves, outputSpline);
int pointNumber = outputSpline.Num();
if ( 0 == pointNumber)
{
return nullptr;
}

ULineBatchComponent* lineBatchComponent = NewObject<ULineBatchComponent>(parentActor, TEXT("Line"));
lineBatchComponent->RegisterComponent();
TArray<FBatchedLine> batchLineArray;
batchLineArray.Empty();
for (int ptID = 0; ptID < pointNumber - 1; ptID++)
{
	
	FVector line_startPos = outputSpline[ptID].Position + _worldLocation;
	FVector line_endPos = outputSpline[ptID+1].Position + _worldLocation;

	FBatchedLine line = FBatchedLine(line_startPos, line_endPos, FLinearColor::Red, 0, 10, 0);
	batchLineArray.Add(line);
}
lineBatchComponent->BatchedLines.Empty();
lineBatchComponent->DrawLines(batchLineArray);

return lineBatchComponent;

}

void FSplinePositionLinearApproximation::Build(const FSplineCurves& InCurves, TArray< FSplinePositionLinearApproximation>& OutPoints, float InDensity)
{
OutPoints.Reset();

const float SplineLength = InCurves.GetSplineLength();
int32 NumLinearPoints = FMath::Max((int32)(SplineLength * InDensity), 2);

for (int32 LinearPointIndex = 0; LinearPointIndex < NumLinearPoints; ++LinearPointIndex)
{
	const float DistanceAlpha = (float)LinearPointIndex / (float)NumLinearPoints;
	const float SplineDistance = SplineLength * DistanceAlpha;
	const float Param = InCurves.ReparamTable.Eval(SplineDistance, 0.0f);
	OutPoints.Emplace(InCurves.Position.Eval(Param, FVector::ZeroVector), Param);
}

OutPoints.Emplace(InCurves.Position.Points.Last().OutVal, InCurves.ReparamTable.Points.Last().OutVal);

}

第三个方式就是用USplineMeshComponent,按照样条线的各段生成mesh就可以了。

void MyActor::GenerateSplineMeshComponentFromSplineComponent(AActor* parentActor, USplineComponent* splineComponent)
{
if (nullptr == splineComponent)
{
return ;
}
for (int i = 0; i < splineComponent->GetNumberOfSplinePoints() - 1; i++)
{
USplineMeshComponent* splineMesh = NewObject< USplineMeshComponent>(parentActor, TEXT(“SplineMesh” + i));
splineMesh->RegisterComponent();
splineMesh->AttachToComponent(parentActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
splineMesh->SetStaticMesh(_splineStaticMesh);

	splineMesh->SetMobility(EComponentMobility::Type::Movable);
	FVector pointLocationStart, pointTangentStart, pointLocationEnd, pointTangentEnd;
	splineComponent->GetLocalLocationAndTangentAtSplinePoint(i, pointLocationStart, pointTangentStart);
	splineComponent->GetLocalLocationAndTangentAtSplinePoint(i + 1, pointLocationEnd, pointTangentEnd);

	splineMesh->SetStartAndEnd(pointLocationStart, pointTangentStart, pointLocationEnd, pointTangentEnd);
}

}

### UE4 中动态生成任意阶数的贝塞尔曲线 要在 Unreal Engine 4 (UE4) 中实现动态生成任意阶数的贝塞尔曲线,可以通过蓝图或 C++ 编写自定义逻辑来完成。以下是详细的实现方法: #### 使用蓝图实现 在蓝图中,可以利用数组存储控制点的位置,并通过循环计算每一段贝塞尔曲线上的点位置。 1. **初始化控制点** 创建一个 `Vector` 类型的数组用于保存所有的控制点坐标[^1]。 2. **计算贝塞尔曲线上的点** 利用 De Casteljau 算法递归地计算给定 t 参数下的点位置。对于 n 阶贝塞尔曲线,t 的取值范围为 [0, 1]。具体公式如下: \[ B(t) = \sum_{i=0}^{n}{\binom{n}{i}(1-t)^{n-i}t^i P_i} \] 其中 \(P_i\) 表示第 i 个控制点[^3]。 3. **绘制线** 将计算得到的一系列点连接起来形成平滑的曲线。可以在每一帧更新这些点并重新渲染线条。 #### 使用C++实现 如果需要更高的性能或者更复杂的操作,则可以选择使用 C++ 来编写插件或模块。 1. 定义数据结构 构建一个类用来表示贝塞尔曲线及其属性,比如阶数、控制点集合等。 ```cpp class UBezierCurve : public UObject { GENERATED_BODY() public: TArray<FVector> ControlPoints; // 控制点列表 int Degree; // 曲线阶数 FVector EvaluatePoint(float T); }; ``` 2. 计算单一点位 提供函数接口接受参数 t 返回对应的空间坐标值。 ```cpp FVector UBezierCurve::EvaluatePoint(float T){ if(ControlPoints.Num()<=0 || !Degree )return FVector(0.f); auto NumControls = ControlPoints.Num(); std::vector<std::vector<FVector>> tempVectors; for(int j=0;j<NumControls;++j){ std::vector<FVector> row; for(int k=j;k<NumControls;++k){ float coeff=(float)(Factorial(Degree)/( Factorial(k)*Factorial(Degree-k))); FVector point=ControlPoints[k]*coeff*pow((double)(T),k)*pow((double)(1-T),(Degree-k)); row.push_back(point); } tempVectors.emplace_back(row); } FVector result=FVector::ZeroVector; for(auto &vec:tempVectors.at(tempVectors.size()-1)){ result+=vec; } return result; } ``` 上述代码片段展示了如何基于输入的时间变量 t 和预设好的控制顶点组求解最终路径上某时刻的具体三维空间定位。 #### 结合后期处理效果优化显示质量 当成功构建好基础几何形态之后还可以进一步探索更多可能性例如加入渐变色过渡或是阴影投射等功能提升视觉表现力。此时可参考有关 ue4 后期处理的相关技术文档学习应用实例如景深模糊调整等等[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值