学习使用ProceduralMeshComponent在运行时构建Mesh数据

参考来源

主要参考的资源是https://nerivec.github.io/old-ue4-wiki/pages/procedural-mesh-component-in-cgetting-started.html,不过这并不是官方的链接,因为官方的网页似乎当前有些显示问题。。。

不过,代码上的改动比较大(变得复杂了一些)。主要是原版只生成了一个三角形,而我想要生成有体积的东西做测试。于是借用了上一篇中的数据,当然代码上构建了相同的接口。

步骤

步骤相比于上一篇使用BuildFromMeshDescriptions在运行时构建StaticMesh数据,简单很多,没有太多概念。主要就是使用UProceduralMeshComponent的接口:

/**
 *	Create/replace a section for this procedural mesh component.
 *	This function is deprecated for Blueprints because it uses the unsupported 'Color' type. Use new 'Create Mesh Section' function which uses LinearColor instead.
 *	@param	SectionIndex		Index of the section to create or replace.
 *	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
 *	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
 *	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
 *	@param	UV0					Optional array of texture co-ordinates for each vertex. If supplied, must be same length as Vertices array.
 *	@param	VertexColors		Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
 *	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
 *	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
 */
UFUNCTION(BlueprintCallable, Category = "Components|ProceduralMesh", meta = (DeprecatedFunction, DeprecationMessage = "This function is deprecated for Blueprints because it uses the unsupported 'Color' type. Use new 'Create Mesh Section' function which uses LinearColor instead.", DisplayName = "Create Mesh Section FColor", AutoCreateRefTerm = "Normals,UV0,VertexColors,Tangents"))
void CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0, const TArray<FColor>& VertexColors, const TArray<FProcMeshTangent>& Tangents, bool bCreateCollision)

另外要注意,UProceduralMeshComponent来自于 \Plugins\Runtime\ProceduralMeshComponent\Source\ProceduralMeshComponent模块。
要在.Build.cs文件中依赖这个模块:
在这里插入图片描述

代码

TestRTBuildPMActor.h

#pragma once

#include "GameFramework/Actor.h"
#include "TestRTBuildPMActor.generated.h"

UCLASS()
class ATestRTBuildPMActor : public AActor
{
public:
	GENERATED_UCLASS_BODY()

	UPROPERTY()
	class UProceduralMeshComponent *PMC;

	/** Overridable native event for when play begins for this actor. */
	virtual void BeginPlay() override;
};

TestRTBuildPMActor.cpp

#include "TestRTBuildPMActor.h"
#include "ProceduralMeshComponent.h"


ATestRTBuildPMActor::ATestRTBuildPMActor(const FObjectInitializer & ObjectInitializer)
	: Super(ObjectInitializer)
{
	//创建 ProceduralMeshComponent 对象:
	PMC = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("myPMC"), false);
	
	//设定其为根组件:
	SetRootComponent(PMC);
}

void ATestRTBuildPMActor::BeginPlay()
{
	//指定 5 个顶点各自的位置:
	TArray<FVector> VertexPositions;
	VertexPositions.Add(FVector(0.0, 0.0, 100.0));		// 顶尖
	VertexPositions.Add(FVector(-50.0, 50.0, 0.0));		// 角 1
	VertexPositions.Add(FVector(-50.0, -50.0, 0.0));	// 角 2
	VertexPositions.Add(FVector(50.0, -50.0, 0.0));		// 角 3
	VertexPositions.Add(FVector(50.0, 50.0, 0.0));		// 角 4
	
	//为了方便,定义一个结构体来封装三角形中一个顶点的信息
	struct VertexInfo
	{
		int ID;				//对应的顶点ID
		FVector Normal;		//法线
		FVector2D UV;		//UV
		VertexInfo(int InID, FVector InNormal, FVector2D InUV)
			:ID(InID), Normal(InNormal), UV(InUV)
		{
		}
	};

	//当前MeshSection的数目
	int MeshSectionCount = 0;

	//为了方便,创建一个局部函数用来快速根据给定的顶点信息创建三角形
	auto AppendTriangle = [this,&MeshSectionCount,&VertexPositions](TArray<VertexInfo> data)
	{
		TArray<FVector> Vertices;
		TArray<int32> Indices;
		TArray<FVector> Normals;
		TArray<FVector2D> UV0;
		TArray<FLinearColor> VertexColors;
		TArray<FProcMeshTangent> Tangents;

		for (int i = 0; i < 3; i++)
		{
			Vertices.Add(VertexPositions[data[i].ID]);			//位置
			Indices.Add(i);										//索引
			Normals.Add(data[i].Normal);						//法线
			UV0.Add(data[i].UV);								//UV
			Tangents.Add(FProcMeshTangent(0, 1, 0));			//切线暂时不需要,所以固定一个无用的值
			VertexColors.Add(FLinearColor(1.0, 1.0, 1.0, 1.0));	//顶点色暂时不需要,所以固定成白色
		}
		
		//调用 ProceduralMeshComponent 的接口创建三角形!
		PMC->CreateMeshSection_LinearColor(
			MeshSectionCount,	//SectionIndex
			Vertices, Indices, Normals, UV0, VertexColors, Tangents, //顶点数据列表
			true);				//bCreateCollision

		MeshSectionCount++;//递增MeshSection
	};

	//四个面的数据:

	// 面 1 (朝向 -X) 三角型的顶点数据:
	AppendTriangle({
		VertexInfo(0,FVector(-0.7071, 0, 0.7071),FVector2D(0, 1)),
		VertexInfo(2,FVector(-0.7071, 0, 0.7071),FVector2D(1, 0)),
		VertexInfo(1,FVector(-0.7071, 0, 0.7071),FVector2D(0, 0)) });
	// 面 2 (朝向 -Y) 三角型的顶点数据:
	AppendTriangle({
		VertexInfo(0,FVector(0, -0.7071, 0.7071),FVector2D(0, 1)),
		VertexInfo(3,FVector(0, -0.7071, 0.7071),FVector2D(1, 0)),
		VertexInfo(2,FVector(0, -0.7071, 0.7071),FVector2D(0, 0)) });
	// 面 3 (朝向 +X) 三角型的顶点数据:
	AppendTriangle({
		VertexInfo(0,FVector(0.7071, 0, 0.7071),FVector2D(0, 1)),
		VertexInfo(4,FVector(0.7071, 0, 0.7071),FVector2D(1, 0)),
		VertexInfo(3,FVector(0.7071, 0, 0.7071),FVector2D(0, 0)) });
	// 面 4 (朝向 +Y) 三角型的顶点数据:
	AppendTriangle({
		VertexInfo(0,FVector(0, 0.7071, 0.7071),FVector2D(0, 1)),
		VertexInfo(1,FVector(0, 0.7071, 0.7071),FVector2D(1, 0)),
		VertexInfo(4,FVector(0, 0.7071, 0.7071),FVector2D(0, 0)) });

	// Enable collision data
	PMC->ContainsPhysicsTriMeshData(true);
}

效果

ATestRTBuildPMActor拖入场景,点击Play后就可以看到金字塔了,看起来应和上一篇一样。

不过,值得注意的是。这次生成的模型碰撞更为精确(测试时将Actor缩放为(10,10,2)了):
在这里插入图片描述
不像上一篇使用的BuildFromMeshDescriptions在运行时构建StaticMesh数据,碰撞构建的是简单碰撞:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值