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;// SourceModelconst 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 postionfor(const FVertexID VertexID : VertexArray.GetElementIDs()){FVector3f& Pos = VertexPositions[VertexID];}UE_LOG(LogTemp, Warning, TEXT("Vertex num = %d"), VertexArray.Num());//loop vertex instance attributeconst 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 attributeconst 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 attributeconst 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 polygonconst 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 vertexfor(int32 Index = 0; Index < Vertices.Num(); Index++){FVertexID VertexId = MeshDescription.CreateVertex();VertexPositions.Set(VertexId, Vertices[Index].Position);}//create vertex instancefor(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/uvFPolygonGroupID 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 descconst 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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/12464.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玩转Matlab-Simscape(初级)- 06 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真(理论部分2)

** 玩转Matlab-Simscape&#xff08;初级&#xff09;- 06 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真&#xff08;理论部分2&#xff09; ** 目录 玩转Matlab-Simscape&#xff08;初级&#xff09;- 06 - 基于Solidworks、Matlab Simulink、COMSOL的协同仿真&am…

风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码)完整代码风电功率预测 | 基于GRU门控循环单元的风电功率预测(附matlab完整源码) 完整代码 clc; clear close allX = xlsread(风电场预测.xlsx)

python数据分析——seaborn绘图2

参考资料&#xff1a;活用pandas库 # 导入库 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns tipspd.read_csv(r"...\seaborn常用数据案例\tips.csv") print(tips.head()) 1、成对关系表示 当数据大部分是数据时&#xff0c;可以使用…

分享一个基于Qt的Ymodem的上位机(GitHub开源)

文章目录 1.项目地址2.Ymodem 协议介绍3.文件传输过程4.使用5.SecureCRT 软件也支持Ymodem6.基于PyQt5的Ymodem界面实现案例 1.项目地址 https://github.com/XinLiGH/SerialPortYmodem 基于VS2019 Qt5.15.2 编译&#xff0c;Linux下编译也可以&#xff0c;这里不做说明。 2.…

Python | Leetcode Python题解之第89题格雷编码

题目&#xff1a; 题解&#xff1a; class Solution:def grayCode(self, n: int) -> List[int]:ans [0] * (1 << n)for i in range(1 << n):ans[i] (i >> 1) ^ ireturn ans

如何在云电脑实现虚拟应用—数据分层(应用分层)技术简介

如何在云电脑实现虚拟应用—数据分层&#xff08;应用分层&#xff09;技术简介 近几年虚拟化市场实现了非常大的发展&#xff0c;桌面虚拟化在企业中应用越来越广泛&#xff0c;其拥有的如下优点得到大量企业的青睐&#xff1a; 数据安全不落地。在虚拟化环境下面数据保存在…

STL库简介

一、STL库的概念 STL&#xff1a;是C标准库的重要追组成部分&#xff0c;不仅是一个可以复用的组件库&#xff0c;而且还是一个包含了数据结构和算法的软件框架。 二、STL的版本 原始版本 Alexander Stepanov、 Meng Lee 在惠普实验室完成的原始版本&#xff0c; 是一个开源…

JVM 双亲委派机制详解

文章目录 1. 双亲委派机制2. 证明3. 优势与劣势 1. 双亲委派机制 类加载器用来把类加载到 Java 虚拟机中。从JDK1.2版本开始&#xff0c;类的加载过程采用双亲委派机制&#xff0c;这种机制能更好地保证 Java 平台的安全。 1.定义 如果一个类加载器在接到加载类的请求时&…

(done) NLP+HMM 协作,还有维特比算法

参考视频&#xff1a;https://www.bilibili.com/video/BV1aP4y147gA/?p2&spm_id_frompageDriver&vd_source7a1a0bc74158c6993c7355c5490fc600 &#xff08;这实际上是 “序列标注任务”&#xff09; HMM 的训练和预测如下图 训练过程&#xff1a;我们首先先给出一个语…

web学习记录--(5.14)

1.Sublime安装与汉化 直接点击windows即可下载&#xff0c;安装即可 Thank You - Sublime Text 汉化 Install Package ChineseLocalzation 2.PHPstorm下载以及激活,汉化 直接下载&#xff0c;然后找激活码激活即可 汉化 plugins&#xff08;插件&#xff09;/chinese&…

SpringBoot接收参数的19种方式

https://juejin.cn/post/7343243744479625267?share_token6D3AD82C-0404-47A7-949C-CA71F9BC9583

未授权访问:ZooKeeper 未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬总结好的文章&#xff1a; 这里附上大…

2025年第十一届北京国际印刷技术展览会

2025年第十一届北京国际印刷技术展览会 展览时间&#xff1a;2025年5月15-19日 展览地点&#xff1a;北京中国国际展览中心&#xff08;顺义馆&#xff09; 主办单位&#xff1a;中国印刷及设备器材工业协会中国国际展览中心集团有限公司 承办单位&#xff1a;北京中印协华港国…

海思Hi3065H 200MHz 高性能 RISCV32 A² MCU

这是一款海思自研的RISCV32内核的高性能实时控制专用MCU&#xff0c; 具有高性能、高集成度、高可靠性、易开发的特点&#xff0c;同时还有嵌入式AI能力。 CPU • RISC-V200MHzFPU 存储 • Up to 152KB Code Flash • 8KB Data Flash • 16KB SRAM 个人认为这是MCU梯队非常…

【PB案例学习笔记】-02 目录浏览器

写在前面 这是PB案例学习笔记系列文章的第二篇&#xff0c;该系列文章适合具有一定PB基础的读者&#xff0c; 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上…

基于Django实现的(bert)深度学习文本相似度检测系统设计

基于Django实现的&#xff08;bert&#xff09;深度学习文本相似度检测系统设计 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 登录页面 注册页面&#xff1a;用户账号&#xff0c;密码…

05-14 周二 PyTorch动态量化和静态量化理解

05-14 周二 PyTorch动态量化和静态量化理解 时间版本修改人描述2024年5月14日10:44:30V0.1宋全恒新建文档2024年5月14日16:28:16V1.0宋全恒填充了PyTorch对于两种量化方式的内容 简介 Pytorch动态量化 设计神经网络时&#xff0c;可以进行许多权衡。在模型开发和训练期间&…

Dilworth定理:最少的下降序列个数就等于整个序列最长上升子序列的长度

概念如下&#xff1a; 狄尔沃斯定理_百度百科 (baidu.com) 本质就是找要求序列中最长的单调的子序列&#xff08;不一定连续&#xff09;的长度。 模板如下&#xff1a; 时间复杂度为O&#xff08;N^2&#xff09; #include<iostream>using namespace std;int dp[100…

RK3568平台开发系列讲解(SPI篇)SPI数据的传输

🚀返回专栏总目录 文章目录 一、数据结构1.1、spi_transfer 结构体1.2、spi_message二、数据发送程序分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 参考资料: spi_transferspi_message一、数据结构 spi 数据传输主要使用了 spi_message 和 spi_transfer 结构…

二叉树的前序遍历(leetcode)

144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 这道题的启发性真的很强 &#xff0c;这里必须传入i的指针进去&#xff0c;下一次栈帧i&#xff0c;但回到了上一层i又变回到了原来的i&#…