当前位置: 首页 > news >正文

【UE5 C++】“ProceduralMeshComponent”的使用记录

效果

        如下所示,通过“ProceduralMeshComponent”创建了一个自定义形状的Mesh,并且该Mesh包含碰撞信息,然后2s后更新Mesh形状。

步骤

1. 在“xxx.Build.cs”中引入“ProceduralMeshComponent”模块

2. 新建一个Actor类,这里命名为“DrawMeshActor”

在“DrawMeshActor.h”中引入“ProceduralMeshComponent.h”

定义“程序化网格组件”和创建自定义Mesh的方法“GenerateMesh”。其中函数“GenerateMesh”需要传入材质、三角形网格数组“Triangles”和一个布尔值“bCreateCollision”,“bCreateCollision”表示是否要生成碰撞。

三角形网格数组“Triangles”中的元素是结构体“FTriangleData”,该结构体定义如下,主要由三个点的位置构成

3. 在“DrawMeshActor.cpp”中,先引入"Materials/MaterialInterface.h",然后在“DrawMeshActor”构造时添加“ProceduralMeshComponent”组件

最后实现函数“GenerateMesh”如下

void ADrawMeshActor::GenerateMesh(UMaterialInterface* InMaterial, const TArray<FTriangleData>& Triangles, bool bCreateCollision)
{if (!ProceduralMesh){UE_LOG(LogTemp, Error, TEXT("GenerateMeshFromTriangles: ProceduralMesh component is null."));return;}if (Triangles.Num() == 0){UE_LOG(LogTemp, Warning, TEXT("GenerateMeshFromTriangles: Input Triangles array is empty. Clearing mesh."));ProceduralMesh->ClearMeshSection(0);return;}//清除之前的网格ProceduralMesh->ClearMeshSection(0);//根据三角形数量计算顶点个数int32 NumTriangles = Triangles.Num();int32 NumVertices = NumTriangles * 3;TArray<FVector> Vertices;TArray<int32> TriangleIndices;TArray<FVector> Normals;TArray<FVector2D> UV0;TArray<FProcMeshTangent> Tangents;TArray<FLinearColor> VertexColors;//预留空间Vertices.Reserve(NumVertices);TriangleIndices.Reserve(NumVertices);Normals.Reserve(NumVertices);UV0.Reserve(NumVertices);//循环添加每一个三角形网格数据for (int32 TriIndex = 0; TriIndex < NumTriangles; ++TriIndex){const FTriangleData& CurrentTriangle = Triangles[TriIndex];int32 BaseVertexIndex = TriIndex * 3;//为三角形添加顶点Vertices.Add(CurrentTriangle.Point1);Vertices.Add(CurrentTriangle.Point2);Vertices.Add(CurrentTriangle.Point3);//添加三角形索引TriangleIndices.Add(BaseVertexIndex + 0);TriangleIndices.Add(BaseVertexIndex + 1);TriangleIndices.Add(BaseVertexIndex + 2);// 计算三角形法线FVector Normal = FVector::CrossProduct(CurrentTriangle.Point3 - CurrentTriangle.Point1, CurrentTriangle.Point2 - CurrentTriangle.Point1);Normal.Normalize();//为三角形的所有3个顶点添加相同的法线Normals.Add(Normal);Normals.Add(Normal);Normals.Add(Normal);//添加UVUV0.Add(FVector2D(0.0f, 1.0f)); // UV for Point1UV0.Add(FVector2D(1.0f, 1.0f)); // UV for Point2UV0.Add(FVector2D(0.0f, 0.0f)); // UV for Point3}//创建网格ProceduralMesh->CreateMeshSection_LinearColor(0,Vertices,TriangleIndices,Normals,UV0,VertexColors,Tangents,bCreateCollision);//设置材质if (InMaterial){ProceduralMesh->SetMaterial(0, InMaterial);}else{UE_LOG(LogTemp, Warning, TEXT("GenerateMeshFromTriangles: Input Material (InMaterial) is null. Mesh section 0 might have default material."));// if (DefaultMaterial) ProceduralMesh->SetMaterial(0, DefaultMaterial);}
}

源码:

// 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 "DrawMeshActor.generated.h"USTRUCT(BlueprintType)
struct FTriangleData
{GENERATED_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Triangle Data")FVector Point1 = FVector::ZeroVector;UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Triangle Data")FVector Point2 = FVector::ZeroVector;UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Triangle Data")FVector Point3 = FVector::ZeroVector;FTriangleData() {}FTriangleData(const FVector& InP1, const FVector& InP2, const FVector& InP3): Point1(InP1), Point2(InP2), Point3(InP3) {}
};UCLASS()
class TESTPROJECT2_API ADrawMeshActor : public AActor
{GENERATED_BODY()public:	ADrawMeshActor();protected:virtual void BeginPlay() override;public:	virtual void Tick(float DeltaTime) override;public:// 程序化网格组件UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")UProceduralMeshComponent* ProceduralMesh;UFUNCTION(BlueprintCallable)void GenerateMesh(UMaterialInterface* InMaterial, const TArray<FTriangleData>& Triangles, bool bCreateCollision);
};
// Fill out your copyright notice in the Description page of Project Settings.#include "DrawMeshActor.h"
#include "Materials/MaterialInterface.h"ADrawMeshActor::ADrawMeshActor()
{PrimaryActorTick.bCanEverTick = false;// 创建程序化网格组件并设为根组件ProceduralMesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("ProceduralMesh"));SetRootComponent(ProceduralMesh);ProceduralMesh->bUseAsyncCooking = true; // 可选:在单独线程准备物理数据}// Called when the game starts or when spawned
void ADrawMeshActor::BeginPlay()
{Super::BeginPlay();}// Called every frame
void ADrawMeshActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}void ADrawMeshActor::GenerateMesh(UMaterialInterface* InMaterial, const TArray<FTriangleData>& Triangles, bool bCreateCollision)
{if (!ProceduralMesh){UE_LOG(LogTemp, Error, TEXT("GenerateMeshFromTriangles: ProceduralMesh component is null."));return;}if (Triangles.Num() == 0){UE_LOG(LogTemp, Warning, TEXT("GenerateMeshFromTriangles: Input Triangles array is empty. Clearing mesh."));ProceduralMesh->ClearMeshSection(0);return;}//清除之前的网格ProceduralMesh->ClearMeshSection(0);//根据三角形数量计算顶点个数int32 NumTriangles = Triangles.Num();int32 NumVertices = NumTriangles * 3;TArray<FVector> Vertices;TArray<int32> TriangleIndices;TArray<FVector> Normals;TArray<FVector2D> UV0;TArray<FProcMeshTangent> Tangents;TArray<FLinearColor> VertexColors;//预留空间Vertices.Reserve(NumVertices);TriangleIndices.Reserve(NumVertices);Normals.Reserve(NumVertices);UV0.Reserve(NumVertices);//循环添加每一个三角形网格数据for (int32 TriIndex = 0; TriIndex < NumTriangles; ++TriIndex){const FTriangleData& CurrentTriangle = Triangles[TriIndex];int32 BaseVertexIndex = TriIndex * 3;//为三角形添加顶点Vertices.Add(CurrentTriangle.Point1);Vertices.Add(CurrentTriangle.Point2);Vertices.Add(CurrentTriangle.Point3);//添加三角形索引TriangleIndices.Add(BaseVertexIndex + 0);TriangleIndices.Add(BaseVertexIndex + 1);TriangleIndices.Add(BaseVertexIndex + 2);// 计算三角形法线FVector Normal = FVector::CrossProduct(CurrentTriangle.Point3 - CurrentTriangle.Point1, CurrentTriangle.Point2 - CurrentTriangle.Point1);Normal.Normalize();//为三角形的所有3个顶点添加相同的法线Normals.Add(Normal);Normals.Add(Normal);Normals.Add(Normal);//添加UVUV0.Add(FVector2D(0.0f, 1.0f)); // UV for Point1UV0.Add(FVector2D(1.0f, 1.0f)); // UV for Point2UV0.Add(FVector2D(0.0f, 0.0f)); // UV for Point3}//创建网格ProceduralMesh->CreateMeshSection_LinearColor(0,Vertices,TriangleIndices,Normals,UV0,VertexColors,Tangents,bCreateCollision);//设置材质if (InMaterial){ProceduralMesh->SetMaterial(0, InMaterial);}else{UE_LOG(LogTemp, Warning, TEXT("GenerateMeshFromTriangles: Input Material (InMaterial) is null. Mesh section 0 might have default material."));// if (DefaultMaterial) ProceduralMesh->SetMaterial(0, DefaultMaterial);}
}

4. 在UE编辑器中创建基于“DrawMeshActor”的蓝图派生类“BP_DrawMeshActor”,再创建一个材质

在“BP_DrawMeshActor”事件图表中调用函数“GenerateMesh”来生成自定义网格体

最终效果如文章开头所示。

相关文章:

  • Jmeter创建使用变量——能够递增递减的计数器
  • 《extern:如何在编译时“暗通款曲“》
  • 解析大尺寸液晶屏视觉检测,装配错位如何避免?
  • vue文件预览docx-preview
  • TypeScript 快速入门
  • ebpf: CO-RE, BTF, and Libbpf(二)
  • 西瓜书机器学习——第八章EM算法
  • 【密码学——基础理论与应用】李子臣编著 第五章 序列密码 课后习题
  • spring.factories文件作用详解,@SpringBootApplication启动过程与其关联
  • SpringCloud-快速通关(二)
  • Scrapy结合Selenium实现搜索点击爬虫的最佳实践
  • 一站式Windows下Docker开启MySQL并链接本地Navicat(附乱码解决方案)
  • Docker学习笔记-docker安装、删除
  • 单片机任意普通IO引脚使用定时器扩展外部中断的巧妙方法
  • 如何撤回刚提交的 commit
  • 在交换机上划分VLAN并配置IP地址的完整指南
  • C数据结构--顺序表
  • 【Linux】41.网络基础(2.3)
  • SQL 查询中 ORDER BY 的执行顺序
  • 30学Java第十天——类加载的过程
  • 气象干旱黄色预警继续:陕西西南部、河南西南部等地特旱
  • “一节课、两小时”,体育正在回归“C位”
  • 印称一名高级官员在巴基斯坦发动的袭击中死亡
  • 《尤物公园》连演8场:观众上台,每一场演出都独一无二
  • 巴基斯坦称对印度发起军事行动
  • 华泰柏瑞基金总经理韩勇因工作调整卸任,董事长贾波代为履职