UStaticMesh几何数据相关(UE5.2)

UStaticMesh相关类图

8f663eb4989e48579fd3d47252243c43.png

 

UStaticMesh的数据构成

 

UStaticMesh的FStaticMeshSourceModel

UStaticMesh的Mesh几何元数据来自于FStaticMeshSourceModel, 一级Lod就存在一个FStaticMeshSourceModel. FStaticMeshSourceModel几何数据大致包含以下几类:

Vertex(点), VertexInstance(顶点), Edge(边),   Triangle(三角形),   Polygon(多边形)

总体上概念和Houdini的一些几何概念相似,每种几何元素都可以附带属性,比如点的“Position”, 顶点的“Normal,UV”等等。

下面介绍下如何获取Mesh元数据和相关属性

void AMyActor::TestMeshInfo() const
{
	if(!Mesh)
		return;

	// SourceModel
	const TArray<FStaticMeshSourceModel>& SourceModels = Mesh->GetSourceModels();
	for(int32 Index = 0; Index < SourceModels.Num(); Index++)
	{
		FMeshDescription* MeshDesc = Mesh->GetMeshDescription(Index);
		if(MeshDesc)
		{
			const FVertexArray& VertexArray =  MeshDesc->Vertices();

			// TVertexAttributesRef<FVector3f> VertexPositions = MeshDesc->VertexAttributes().GetAttributesRef<FVector3f>(MeshAttribute::Vertex::Position);
			TVertexAttributesRef<FVector3f> VertexPositions = MeshDesc->GetVertexPositions();

			//loop vertex postion
			for(const FVertexID VertexID : VertexArray.GetElementIDs())
			{
				FVector3f& Pos = VertexPositions[VertexID];
			}

			UE_LOG(LogTemp, Warning, TEXT("Vertex num = %d"), VertexArray.Num());


			//loop vertex instance attribute
			const FVertexInstanceArray& VertexInstanceArray = MeshDesc->VertexInstances();
			TVertexInstanceAttributesRef<FVector4f> VertexInstanceColors = MeshDesc->VertexInstanceAttributes().GetAttributesRef<FVector4f>(MeshAttribute::VertexInstance::Color);
			for(const FVertexInstanceID VertxInstanceId : VertexInstanceArray.GetElementIDs())
			{
				
			}

			UE_LOG(LogTemp, Warning, TEXT("VertexInstanceArray num = %d"), VertexInstanceArray.Num());

			//loop vertex edge attribute
			const FEdgeArray& EdgeArray = MeshDesc->Edges();
			TEdgeAttributesRef<bool> EdgeHardness = MeshDesc->EdgeAttributes().GetAttributesRef<bool>(MeshAttribute::Edge::IsHard);
			for (FEdgeID EdgeID : EdgeArray.GetElementIDs())
			{
				
			}

			UE_LOG(LogTemp, Warning, TEXT("EdgeArray num = %d"), EdgeArray.Num());

			// loop triangle attribute
			const FTriangleArray& TriangleArray = MeshDesc->Triangles();
			TTriangleAttributesRef<FVector3f> TriangleNormals = MeshDesc->TriangleAttributes().GetAttributesRef<FVector3f>(MeshAttribute::Triangle::Normal);
			for (FTriangleID TriangleID : TriangleArray.GetElementIDs())
			{
				
			}

			UE_LOG(LogTemp, Warning, TEXT("TriangleArray num = %d"), TriangleArray.Num());
			
			// loop polygon
			const FPolygonArray& PolygonArray =  MeshDesc->Polygons();
			TPolygonAttributesRef<int32> PatchGroups = MeshDesc->PolygonAttributes().GetAttributesRef<int32>(MeshAttribute::Polygon::PolygonGroupIndex);

			UE_LOG(LogTemp, Warning, TEXT("PolygonArray num = %d"), PolygonArray.Num());
		}


		if(Mesh->GetRenderData()->LODResources.Num() > Index)
		{
			TArray<FVector3f> Vertexs;
			auto& LodResource = Mesh->GetRenderData()->LODResources[Index];
			int32 VertexNum = LodResource.GetNumVertices();
			for(int32 I = 0; I < VertexNum; I++)
			{
				Vertexs.Add(LodResource.VertexBuffers.PositionVertexBuffer.VertexPosition(I));
			}

			int32 TriangleNum = LodResource.GetNumTriangles();
			TArray<uint32> Indexs;
			for(int32 I = 0; I < TriangleNum; I++)
			{
				Indexs.Add(LodResource.IndexBuffer.GetIndex(I * 3 + 0));
				Indexs.Add(LodResource.IndexBuffer.GetIndex(I * 3 + 1));
				Indexs.Add(LodResource.IndexBuffer.GetIndex(I * 3 + 2));
			}
			
		}
	}
}

 

 

如何填充数据生成一个UStaticMesh

主要是通过填充FMeshDescription的各种图元数据(Vertex, VertexInstance, Polygon, PolygonGroup等等)

void AMyActor::TestCreateStaticMesh()
{
	const FString ObjectName = "TestStaticMesh";
	const FString GameFoldPath = "/Game";
	const FString PackageName = FString::Printf(TEXT("%s/%s"), *GameFoldPath, *ObjectName);

	UPackage* Package = CreatePackage(*PackageName);
	UStaticMesh* MyMesh = NewObject<UStaticMesh>(Package, *ObjectName, RF_Standalone | RF_Public);
	FMeshDescription MeshDescription;
	FStaticMeshAttributes MeshAttribute(MeshDescription);
	MeshAttribute.Register();

	TArray<FDynamicMeshVertex> Vertices;
	Vertices.Add(FDynamicMeshVertex(FVector3f(500.0f, 500.0f, 200)));
	Vertices.Add(FDynamicMeshVertex(FVector3f(-500.0f, 500.0f, 200)));
	Vertices.Add(FDynamicMeshVertex(FVector3f(-500.0f, -500.0f, 200)));
	Vertices.Add(FDynamicMeshVertex(FVector3f(500.0f, -500.0f, 200)));

	TArray<int32> Indexs;
	Indexs.Add(0);
	Indexs.Add(3);
	Indexs.Add(1);

	Indexs.Add(1);
	Indexs.Add(3);
	Indexs.Add(2);
	
	MeshDescription.Empty();
	MeshDescription.ReserveNewVertices(Vertices.Num());
	MeshDescription.ReserveNewTriangles(Indexs.Num() / 3);
	MeshDescription.ReserveNewVertexInstances(Indexs.Num());

	TVertexAttributesRef<FVector3f> VertexPositions = MeshAttribute.GetVertexPositions();
	TVertexInstanceAttributesRef<FVector2f>	VertexInstanceUVs = MeshAttribute.GetVertexInstanceUVs();
	TVertexInstanceAttributesRef<FVector3f>	VertexInstanceNormals = MeshAttribute.GetVertexInstanceNormals();
	TVertexInstanceAttributesRef<FVector3f>	VertexInstanceTangents = MeshAttribute.GetVertexInstanceTangents();
	TPolygonGroupAttributesRef<FName> MaterialSlotNames = MeshAttribute.GetPolygonGroupMaterialSlotNames();
	TArray<UMaterialInterface*> MaterialInterfaces = {UMaterial::GetDefaultMaterial(MD_Surface)};
	for(int32 Index = 0; Index < MaterialInterfaces.Num(); Index++)
	{
		FPolygonGroupID PolygonGroupID = MeshDescription.CreatePolygonGroup();
		FStaticMaterial StaticMaterial = MaterialInterfaces[Index];
		MaterialSlotNames[PolygonGroupID] = StaticMaterial.MaterialSlotName;
	}

	//create vertex
	for(int32 Index = 0; Index < Vertices.Num(); Index++)
	{
		FVertexID VertexId = MeshDescription.CreateVertex();
		VertexPositions.Set(VertexId, Vertices[Index].Position);
	}

	//create vertex instance
	for(int32 Index = 0; Index < Indexs.Num(); Index++)
	{
		FVertexInstanceID VertexInstanceId = FVertexInstanceID(Index);
		FVertexID VertexID = FVertexID(Indexs[Index]);
		MeshDescription.CreateVertexInstanceWithID(VertexInstanceId, VertexID);
	}

	// set vertex instance normal/tangent/uv
	FPolygonGroupID PolygonGroupID(0);
	TArray<FVertexInstanceID> InstanceIds;
	for(int32 Index = 0; Index < Indexs.Num(); Index++)
	{
		FVertexInstanceID VertexInstanceId = FVertexInstanceID(Index);
		InstanceIds.Add(VertexInstanceId);
		const FDynamicMeshVertex& DynamicVertex = Vertices[Indexs[Index]];
		VertexInstanceUVs.Set(VertexInstanceId, DynamicVertex.TextureCoordinate[0]);
		VertexInstanceNormals.Set(VertexInstanceId, DynamicVertex.TangentX.ToFVector3f());
		VertexInstanceTangents.Set(VertexInstanceId, DynamicVertex.TangentZ.ToFVector3f());

		if(InstanceIds.Num() == 3)
		{
			TArray<FEdgeID> EdgeIds;
			MeshDescription.CreatePolygon(PolygonGroupID, InstanceIds, &EdgeIds);
			InstanceIds.Empty();
		}
	}

	// create source model lod0 and commit mesh desc
	const int32 LodIndex = 0;
	if(!MyMesh->IsSourceModelValid(LodIndex))
	{
		FStaticMeshSourceModel& SourceModel = MyMesh->AddSourceModel();
		SourceModel.BuildSettings.bRecomputeNormals = false;
		SourceModel.BuildSettings.bRecomputeTangents = false;
		SourceModel.BuildSettings.bGenerateLightmapUVs = false;
	}

	MyMesh->CreateMeshDescription(LodIndex, MeshDescription);
	MyMesh->CommitMeshDescription(LodIndex);

	MyMesh->ImportVersion = EImportStaticMeshVersion::LastVersion;
	MyMesh->CreateBodySetup();
	MyMesh->GetBodySetup()->CollisionReponse = EBodyCollisionResponse::BodyCollision_Disabled;
	MyMesh->Build(true);
	
	MyMesh->PostEditChange();
	MyMesh->MarkPackageDirty();
	FAssetRegistryModule::AssetCreated(MyMesh);
}

4cf12657eaea4f30b908fbb25d410d6f.png

 

相关推荐

  1. 商城数据库51 52 53 54 55 56 57 58 59 60)

    2024-05-15 15:52:10       13 阅读
  2. UEUEC++ DataTable数据表

    2024-05-15 15:52:10       31 阅读
  3. VTK----VTK数据结构详解(几何篇)

    2024-05-15 15:52:10       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-15 15:52:10       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-15 15:52:10       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-15 15:52:10       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-15 15:52:10       20 阅读

热门阅读

  1. 小米消金引领创新,打造重庆消费金融新生态

    2024-05-15 15:52:10       16 阅读
  2. 算法学习笔记(LCA)

    2024-05-15 15:52:10       14 阅读
  3. SQL中的LAG函数与LEAD函数用法

    2024-05-15 15:52:10       12 阅读
  4. Spring中事务的失效场景

    2024-05-15 15:52:10       14 阅读
  5. Windows下打包项目成Linux版本

    2024-05-15 15:52:10       10 阅读
  6. Scala编程基础7:模式匹配、隐式转换详解

    2024-05-15 15:52:10       10 阅读
  7. 前端下载文件流

    2024-05-15 15:52:10       12 阅读