直接展示效果图(通过4个点来绘制一个面)
在UE5中创建一个自己的绘制MeshC++脚本继承自Actor
.h文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "AMyProceduralMeshActor.h"
// Sets default values
AAMyProceduralMeshActor::AAMyProceduralMeshActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// 创建 Procedural Mesh 组件并附加到 RootComponent
ProceduralMesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("ProceduralMesh"));
RootComponent = ProceduralMesh;
}
// Called when the game starts or when spawned
void AAMyProceduralMeshActor::BeginPlay()
{
Super::BeginPlay();
// 生成网格
}
// Called every frame
void AAMyProceduralMeshActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AAMyProceduralMeshActor::GenerateMesh(int Index,TArray<FVector> WorldPoints)
{
// 清空之前的数据
Vertices.Empty();;;
Triangles.Empty();
Normals.Empty();;
UVs.Empty();
Colors.Empty();
// 将传入的世界坐标点添加到 Vertices 数组
for (const FVector& WorldPoint : WorldPoints)
{
// 将世界坐标点转换为相对于 Actor 的本地坐标
FVector LocalPoint = GetTransform().InverseTransformPosition(WorldPoint);
Vertices.Add(LocalPoint);
}
// 生成三角形索引
for (int32 i = 1; i < Vertices.Num() - 1; ++i)
{
Triangles.Add(0);
Triangles.Add(i);
Triangles.Add(i + 1);
}
// 计算法线
// 计算法线
FVector Normal = FVector::CrossProduct(Vertices[2] - Vertices[0], Vertices[1] - Vertices[0]).GetSafeNormal();
for (int32 i = 0; i < Vertices.Num(); i++)
{
Normals.Add(Normal);
}
// 添加 UV 坐标
for (int32 i = 0; i < Vertices.Num(); ++i)
{
// 这里简单地用顶点坐标作为 UV,你可以根据需要进行更复杂的映射
UVs.Add(FVector2D(Vertices[i].X, Vertices[i].Y));
}
// 设置网格数据
ProceduralMesh->CreateMeshSection(Index, Vertices, Triangles, Normals, UVs, Colors, TArray<FProcMeshTangent>(), false);
}
.cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include "AMyProceduralMeshActor.generated.h"
UCLASS()
class MYCPP_API AAMyProceduralMeshActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AAMyProceduralMeshActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable)
void GenerateMesh(int Index,TArray<FVector> WorldPoints);
// 存储面的顶点坐标
TArray<FVector> Vertices;
TArray<TArray<FVector>> Vertices1;
// 存储面的三角形索引
TArray<int32> Triangles;
// 存储面的法线
TArray<FVector> Normals;
// 存储面的 UV 坐标
TArray<FVector2D> UVs;
// 存储面的颜色
TArray<FColor> Colors;
// Procedural Mesh 组件
UProceduralMeshComponent* ProceduralMesh;
};
让我们来看看引擎里面是如何操作的
基于咱刚刚的c++类创建出他的蓝图类
创建一个结构体用来储存一个面的多个点位
打开蓝图创建我们需要的几个变量 一个是V3的数组,一个是我定义的一个面的数组。
先去遍历我们的面再去遍历我们的点的坐标储存起来传给我们的方法就行啦!
把我们的蓝图Actor丢到关卡里,在细节面板进行细节调整
这是一个面的空点位,如有多个面 在下面的索引自行添加
最后对应的结就是这样的