在新版本的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学习的更多相关文章

  1. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  2. NSData所有API学习

      www.MyException.Cn  网友分享于:2015-04-24  浏览:0次   NSData全部API学习. 学习NSData,在网上找资料竟然都是拷贝的纯代码,没人去解释.在这种网上 ...

  3. 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)

    一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...

  4. TCP协议和socket API 学习笔记

    本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类:  原文地址:TCP协议和socket API 学习笔记 作者:gilb ...

  5. Servlet 常用API学习(三)

    Servlet常用API学习 (三) 一.HTTPServletRequest简介 Servlet API 中定义的 ServletRequest 接口类用于封装请求消息. HttpServletRe ...

  6. Servlet 常用API学习(一)

    Servlet常用API学习 一.Servlet体系结构(图片来自百度图片) 二.ServletConfig接口 Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外 ...

  7. JDBC主要API学习总结

    JDBC主要API学习 一.JDBC主要API简介 JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果. 二.Driver 接口 Java.sql.D ...

  8. JDK1.8新特性——Stream API

    JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...

  9. Windows API 学习

    Windows API学习 以下都是我个人一些理解,笔者不太了解windows开发,如有错误请告知,非常感谢,一切以microsoft官方文档为准. https://docs.microsoft.co ...

  10. odoo ORM API学习总结兼orm学习教程

    环境 odoo-14.0.post20221212.tar ORM API学习总结/学习教程 模型(Model) Model字段被定义为model自身的属性 from odoo import mode ...

随机推荐

  1. #组合计数,容斥定理#U136346 数星星

    题目 天上的繁星一闪一闪的,甚是好看.你和你的小伙伴们一起坐在草地上,欣赏这美丽的夜景. 我们假定天上有\(n\)颗星星,它们排成一排,从左往右以此编号为1到\(n\),但是天上的星星实在太多了,你和 ...

  2. Apache Maven ToolChains的使用

    目录 简介 Toolchains的介绍 Toolchains的例子 Toolchains支持 总结 简介 Maven是java中非常有用和常用的构建工具,基本上现在大型的java项目都是Maven和g ...

  3. 看你能解锁哪些新身份?OpenHarmony大使、MVP、金码达人在线申报

  4. OpenHarmony 官网文档有哪些上新?上篇:应用开发文档上新

    随着 OpenAtom OpenHarmony(以下简称"OpenHarmony")系统能力持续升级,已具备支撑复杂带屏标准设备和应用开发的基础能力.相较于旧版本,OpenHarm ...

  5. Numpy数组索引和切片

    数组可以通过索引或切片的方式进行访问或修改,数组切片x[start:stop:step],与Ptyhon内置的list标准索引和切片类似,只是数组产生的是一个非副本视图,根据条件索引的值如果修改,直接 ...

  6. 【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit

    1.问题描述 在App中供用户在地图上选择地址,目前在使用Map Kit结合geolocationManager逆地理编码时获取的地址信息描述不准确,希望能提供相应的Demo参考. 解决方案 Demo ...

  7. Redis和elasticsearch

    redis -----------NOSQL的对比和劣和应用场景参考好文http://www.redis.cn/articles/20181020003.html --------- -------- ...

  8. Bash与shell的区别

    Bash 与 shell 的区别 介绍 常见的 shell 解释器有 sh.bash 这两种,其他的 ksh.csh 和 zsh 等是不常见的.Mac OS 中默认安装了以上所有类型,Windows ...

  9. JDK 19新特性 & JDK 多版本安装切换配置

    新的JDK 19包含如下7个新的特性: 转自:JDK19中比较重要的新特性-电子发烧友网 JEP 405: Record Patterns(Record模式) JEP 422: Linux/RISC- ...

  10. Spring Cloud Bus:消息总线

    Spring Cloud Bus:消息总线 SpringCloud学习教程 SpringCloud Spring Cloud Bus 使用轻量级的消息代理来连接微服务架构中的各个服务,可以将其用于广播 ...