Unity新的MeshData API学习
在新版本的Unity中提供了MeshDataArray和MeshData等多个API,使Mesh数据操作支持多线程;以更好的支持DOTS。
API文档:https://docs.unity3d.com/es/2020.2/ScriptReference/Mesh.MeshData.html
1.IJob修改顶点
首先用Mesh.AllocateWritableMeshData分配一个可写的网格数据,然后通过jobs进行顶点操作,
最后通过Mesh.ApplyAndDisposeWritableMeshData接口赋值回Mesh。
用简单的正弦波x轴移动测试:
代码如下:
using System;
using System.Linq;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering; [RequireComponent(typeof(MeshFilter))]
public class MDT1 : MonoBehaviour
{
[BurstCompile]
public struct TestJob : IJobParallelFor
{
[ReadOnly] public float time;
[ReadOnly] public NativeArray<Vector3> sourceVertices;
[WriteOnly] public NativeArray<Vector3> writeVertices; public void Execute(int index)
{
Vector3 vert = sourceVertices[index];
vert.x += math.sin(index + time) * 0.03f;
writeVertices[index] = vert;
}
} public MeshFilter meshFilter;
private NativeArray<Vector3> mCacheVertices;
private NativeArray<Vector3> mCacheNormals; private ushort[] mCacheTriangles;
private Mesh mCacheMesh; private void Awake()
{
Mesh sourceMesh = meshFilter.sharedMesh;
mCacheVertices = new NativeArray<Vector3>(sourceMesh.vertices, Allocator.Persistent);
mCacheNormals = new NativeArray<Vector3>(sourceMesh.normals, Allocator.Persistent);
mCacheTriangles = sourceMesh.triangles
.Select(m => (ushort) m)
.ToArray(); mCacheMesh = new Mesh();
GetComponent<MeshFilter>().mesh = mCacheMesh;
} private void OnDestroy()
{
mCacheVertices.Dispose();
mCacheNormals.Dispose();
} private void Update()
{
Mesh.MeshDataArray dataArray = Mesh.AllocateWritableMeshData(1);
Mesh.MeshData data = dataArray[0]; data.SetVertexBufferParams(mCacheVertices.Length,
new VertexAttributeDescriptor(VertexAttribute.Position),
new VertexAttributeDescriptor(VertexAttribute.Normal, stream: 1));
data.SetIndexBufferParams(mCacheTriangles.Length, IndexFormat.UInt16); NativeArray<Vector3> vertices = data.GetVertexData<Vector3>();
NativeArray<ushort> indices = data.GetIndexData<ushort>(); NativeArray<Vector3> normals = new NativeArray<Vector3>(mCacheNormals.Length, Allocator.TempJob);
data.GetNormals(normals);
for (int i = 0; i < normals.Length; ++i)
normals[i] = mCacheNormals[i];
normals.Dispose(); for (int i = 0; i < mCacheTriangles.Length; ++i)
indices[i] = mCacheTriangles[i]; TestJob job = new TestJob()
{
time = Time.time,
sourceVertices = mCacheVertices,
writeVertices = vertices
}; job
.Schedule(mCacheVertices.Length, 8)
.Complete(); data.subMeshCount = 1;
data.SetSubMesh(0, new SubMeshDescriptor(0, mCacheTriangles.Length)); Mesh.ApplyAndDisposeWritableMeshData(dataArray, mCacheMesh);
mCacheMesh.RecalculateNormals();
mCacheMesh.RecalculateBounds();
}
}
2.直接通过结构获取Mesh对应字段,并修改更新
也可以设置Mesh字段结构一样的结构体,直接GetVertexData获取。这里需要注意,
要在编辑器下检查Mesh的数据,结构体需要与其保持一致。
using System;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering; public class MDT2 : MonoBehaviour
{
struct VertexStruct
{
public float3 pos;
public float3 normal;
public float4 tangent;
public float2 uv0;
public float2 uv1;
} public Mesh srcMesh;
public MeshFilter meshFilter; private Mesh mCacheMesh;
private NativeArray<VertexStruct> mCacheInVertices; private void Start()
{
mCacheMesh = new Mesh();
meshFilter.sharedMesh = mCacheMesh;
} private void Update()
{
Mesh.MeshDataArray inMeshDataArray = Mesh.AcquireReadOnlyMeshData(srcMesh);
Mesh.MeshData inMesh = inMeshDataArray[0];
mCacheInVertices = inMesh.GetVertexData<VertexStruct>(); int vertexCount = srcMesh.vertexCount;
int indexCount = srcMesh.triangles.Length; Mesh.MeshDataArray outMeshDataArray = Mesh.AllocateWritableMeshData(1);
Mesh.MeshData outMesh = outMeshDataArray[0];
outMesh.SetVertexBufferParams(vertexCount,
new VertexAttributeDescriptor(VertexAttribute.Position),
new VertexAttributeDescriptor(VertexAttribute.Normal),
new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, 4),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2),
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float32, 2)); outMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt16); NativeArray<ushort> indices = outMesh.GetIndexData<ushort>();
for (int i = 0; i < srcMesh.triangles.Length; ++i)
indices[i] = (ushort) srcMesh.triangles[i]; NativeArray<VertexStruct> outVertices = outMesh.GetVertexData<VertexStruct>();
for (int i = 0; i < mCacheInVertices.Length; i++)
{
VertexStruct vert = mCacheInVertices[i];
vert.pos.x += math.sin(i + Time.time) * 0.03f;
outVertices[i] = vert;
} outMesh.subMeshCount = 1;
SubMeshDescriptor subMeshDesc = new SubMeshDescriptor
{
indexStart = 0,
indexCount = indexCount,
topology = MeshTopology.Triangles,
firstVertex = 0,
vertexCount = vertexCount,
bounds = new Bounds(Vector3.zero, Vector3.one * 100f)
};
outMesh.SetSubMesh(0, subMeshDesc); Mesh.ApplyAndDisposeWritableMeshData(outMeshDataArray, mCacheMesh);
mCacheMesh.RecalculateNormals();
mCacheMesh.RecalculateBounds(); mCacheInVertices.Dispose();
inMeshDataArray.Dispose();
}
}
3.Graphics Buffer
在unity2021.2版本之后可以拿到Graphics Buffer类型:
mesh.GetVertexBuffer()
该类型可直接作为Buffer参数传入ComputeShader中。具体在github上有示例:
https://github.com/Unity-Technologies/MeshApiExamples
Unity新的MeshData API学习的更多相关文章
- ASP.NET MVC Web API 学习笔记---第一个Web API程序
http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...
- NSData所有API学习
www.MyException.Cn 网友分享于:2015-04-24 浏览:0次 NSData全部API学习. 学习NSData,在网上找资料竟然都是拷贝的纯代码,没人去解释.在这种网上 ...
- 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)
一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...
- TCP协议和socket API 学习笔记
本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类: 原文地址:TCP协议和socket API 学习笔记 作者:gilb ...
- Servlet 常用API学习(三)
Servlet常用API学习 (三) 一.HTTPServletRequest简介 Servlet API 中定义的 ServletRequest 接口类用于封装请求消息. HttpServletRe ...
- Servlet 常用API学习(一)
Servlet常用API学习 一.Servlet体系结构(图片来自百度图片) 二.ServletConfig接口 Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外 ...
- JDBC主要API学习总结
JDBC主要API学习 一.JDBC主要API简介 JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果. 二.Driver 接口 Java.sql.D ...
- JDK1.8新特性——Stream API
JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...
- Windows API 学习
Windows API学习 以下都是我个人一些理解,笔者不太了解windows开发,如有错误请告知,非常感谢,一切以microsoft官方文档为准. https://docs.microsoft.co ...
- odoo ORM API学习总结兼orm学习教程
环境 odoo-14.0.post20221212.tar ORM API学习总结/学习教程 模型(Model) Model字段被定义为model自身的属性 from odoo import mode ...
随机推荐
- #树链剖分,线段树#洛谷 2146 [NOI2015]软件包管理器
题目传送门 分析 安装时1到\(x\)路径上都变为1,删除时\(x\)的子树都变为0, 显然可以用树链剖分+线段树实现 代码 #include <cstdio> #include < ...
- HarmonyOS多音频播放并发政策及音频管理解析
音频打断策略 多音频并发,即多个音频流同时播放.此场景下,如果系统不加管控,会造成多个音频流混音播放,容易让用户感到嘈杂,造成不好的用户体验.为了解决这个问题,系统预设了音频打断策略,对多音频播放 ...
- Blocks—单调栈
思路: 题目意思是求平均数>=k的最长序列先求出a[i]-k的前缀和就是求sum[i]-sum[j]>=0的最大i-j当j<=k<=isum[j]<=sum[k]j< ...
- sass 基本常识
一.什么是SASS SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护. 本文总结了SASS的主要用法.我的目标是,有了这篇文章,日常的一 ...
- c# 前台和后台线程
前台和后台线程 Net的公用语言运行时(Common Language Runtime,CLR)能区分两种不同类型的线程:前台线程和后台线程.这两者的区别就是:应用程序必须运行完所有的前台线程才可以退 ...
- em/px/rem/vh/vw的区别
一.介绍 传统的项目开发中,我们只会用到px.%.em这几个单位,它可以适用于大部分的项目开发,且拥有比较良好的兼容性 从CSS3开始,浏览器对计量单位的支持又提升到了另外一个境界,新增了rem.vh ...
- 力扣1076(MySQL)-员工项目Ⅱ(简单)
题目: 编写一个SQL查询,报告所有雇员最多的项目. 查询结果格式如下所示: 解题思路: 方法一:将两个表联结,以project_id进行分组,统计员工数降序排序,然后筛选出第一条数据. 1 sel ...
- HarmonyOS NEXT应用开发之MpChart图表实现案例
介绍 MpChart是一个包含各种类型图表的图表库,主要用于业务数据汇总,例如销售数据走势图,股价走势图等场景中使用,方便开发者快速实现图表UI.本示例主要介绍如何使用三方库MpChart实现柱状图U ...
- 【SIGIR 2022】面向长代码序列的Transformer模型优化方法,提升长代码场景性能
简介: 论文主导通过引入稀疏自注意力的方式来提高Transformer模型处理长序列的效率和性能 阿里云机器学习平台PAI与华东师范大学高明教授团队合作在SIGIR2022上发表了结构感知的稀疏注意力 ...
- 阿里巴巴开源大规模稀疏模型训练/预测引擎DeepRec
简介:经历6年时间,在各团队的努力下,阿里巴巴集团大规模稀疏模型训练/预测引擎DeepRec正式对外开源,助力开发者提升稀疏模型训练性能和效果. 作者 | 烟秋 来源 | 阿里技术公众号 经历6 ...