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 ...
随机推荐
- #组合计数,容斥定理#U136346 数星星
题目 天上的繁星一闪一闪的,甚是好看.你和你的小伙伴们一起坐在草地上,欣赏这美丽的夜景. 我们假定天上有\(n\)颗星星,它们排成一排,从左往右以此编号为1到\(n\),但是天上的星星实在太多了,你和 ...
- Apache Maven ToolChains的使用
目录 简介 Toolchains的介绍 Toolchains的例子 Toolchains支持 总结 简介 Maven是java中非常有用和常用的构建工具,基本上现在大型的java项目都是Maven和g ...
- 看你能解锁哪些新身份?OpenHarmony大使、MVP、金码达人在线申报
- OpenHarmony 官网文档有哪些上新?上篇:应用开发文档上新
随着 OpenAtom OpenHarmony(以下简称"OpenHarmony")系统能力持续升级,已具备支撑复杂带屏标准设备和应用开发的基础能力.相较于旧版本,OpenHarm ...
- Numpy数组索引和切片
数组可以通过索引或切片的方式进行访问或修改,数组切片x[start:stop:step],与Ptyhon内置的list标准索引和切片类似,只是数组产生的是一个非副本视图,根据条件索引的值如果修改,直接 ...
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit
1.问题描述 在App中供用户在地图上选择地址,目前在使用Map Kit结合geolocationManager逆地理编码时获取的地址信息描述不准确,希望能提供相应的Demo参考. 解决方案 Demo ...
- Redis和elasticsearch
redis -----------NOSQL的对比和劣和应用场景参考好文http://www.redis.cn/articles/20181020003.html --------- -------- ...
- Bash与shell的区别
Bash 与 shell 的区别 介绍 常见的 shell 解释器有 sh.bash 这两种,其他的 ksh.csh 和 zsh 等是不常见的.Mac OS 中默认安装了以上所有类型,Windows ...
- JDK 19新特性 & JDK 多版本安装切换配置
新的JDK 19包含如下7个新的特性: 转自:JDK19中比较重要的新特性-电子发烧友网 JEP 405: Record Patterns(Record模式) JEP 422: Linux/RISC- ...
- Spring Cloud Bus:消息总线
Spring Cloud Bus:消息总线 SpringCloud学习教程 SpringCloud Spring Cloud Bus 使用轻量级的消息代理来连接微服务架构中的各个服务,可以将其用于广播 ...