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 ...
随机推荐
- CTFshow pwn31 wp
PWN31 使用checksec查看保护 发现除了canary剩下保护全开,那么就没有前面几个题目那么简单了,ida打开看见他给了我们main函数地址 虽然开了pie但是在他们之间的偏移是一定的,那么 ...
- #贪心,树#C 平衡的树
分析 处理出子树内剩余删减以及最大的剩余\(a\)和, 如果删了还是超过\(b\)输出无解 代码 #include <cstdio> #include <cctype> #de ...
- Python 潮流周刊第 45 期(摘要)+ 赠书 5 本《Python语言及其应用(第2版)》
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...
- 使用CMake启用RUNPATH特性
使用CMake,启用RUNPATH特性,可以参考官方帖子. 如下源码来自于上述帖子. CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(R ...
- HMS Core机器学习服务身份证识别功能,实现信息高效录入
在各类App都要进行实名制的当下,进行身份认证自然不可避免.平时购买火车票.飞机票,住酒店.打游戏等都需要身份认证,如果每次都要输入那18位的身份证号十分麻烦,手一抖就会出错.因此,使用华为机器服务身 ...
- 数据驱动ddt简单使用
安装 pip install ddt 数据驱动 ddt 可以使用的地方很多 比如: 1. 做接口测试的参数化 2. 读取自动化测试关键字模型的测试用例 等 demo import ddt, unit ...
- mogdb里xlog相关的几个参数
openGauss/MogDB 3.0 闪回恢复测试 本文出处:https://www.modb.pro/db/411368 介绍 闪回恢复功能是数据库恢复技术的一环,可以有选择性的撤销一个已提交事务 ...
- OpenStack实战安装部署
OpenStack安装部署 一.基础准备工作 部署环境:CentOS 7 64 1.关闭本地iptables防火墙并设置开机不自启动 <span style="color:#33333 ...
- 在ashx中如何使用session
前言 都是写陈年往事罢了,如何在ashx 使用session 正文 我们知道在ashx 中使用context.Session 我们即读取不到值,同时设置完也感觉无效. 原因是我们在ashx 中使用的s ...
- 介绍一个气缸控制的FB程序块
关键词: 气缸,双控.单控.电磁阀.感应器.初始位置(简称"始位").末端位置(简称"端位").屏蔽功能.延时功能.报警功能 正文: 1.为什么要做气缸FB功能 ...