Feedback Wanted: Mesh scripting API improvements

Hi! We are thinking of making some improvements to the Mesh C# API (finally, eh). Here’s a google doc with current API outline and status: https://docs.google.com/document/d/1I225X6jAxWN0cheDz_3gnhje3hWNMxTZq3FZQs5KqPc/edit?usp=sharing

Feedback on that is welcome!

TL;DR of the improvements outlined above:

  • Index buffers: ability to manually specify whole index buffer size, set full or partial data from a NativeArray, setup submesh information (topology, index count etc.) manually.
  • Vertex buffers: ability to manually specify vertex buffer layout (attribute data formats, streams split), set full or partial data from a NativeArray.
  • Slice-like (“int start, int length”) overloads added to existing SetFoobar mesh APIs.
  • ushort overloads added to existing mesh index APIs, to avoid 32bit<->16bit conversions for index data.
38 Likes

Do you plan to add utility function like SharedToUnique Vertices, UniqueToShared, Extrude, Quad based Mesh construction, Constructing meshes from parametric curves, stitching meshes together or similar things? Over time I wrote lots of these things myself but having a foundation of a bit more high-level tools to create procedural meshes would be appreciated by a lot of users I think.

4 Likes

To me that that sounds like it should be some “mesh/geometry tools library” above Mesh class or even engine itself, perhaps like a package somewhere etc. Since there’s nothing in the engine itself that it needs, it’s all code that is built on top of the base API.

4 Likes

ya you are right, would make sense to have that as separate package, I think probuilder actually already has some of these things but the documentation there is rather thin.

1 Like

Hi, Do you have a plan to improve Mesh.CombineMeshes() method? In my case, I manually combined meshes into single mesh for UV adjusting, bone index modification and so on. This is commonly need for Texture Atlasing and combining skinned mesh.

It will be very helpful if CombineMeshes have UV offset (+scaling) and bone index remapping features.

3 Likes

The proposed changes all look good. But I can’t help returning to an old bugbear of mine with mesh drawing in Unity. Please add the ability to have meshes with no index buffer and a property for specifying the topology for the draw command. It’s frustrating that you can do everything you want with DrawProcedural, but that it requires binding ComputeBuffers which aren’t available on all targets.

1 Like

This looks like a major step forward.

One thing I’d wonder about is having multiple streams as a replacement for additionalVertexStreams. I used that in my vertex painter, and while it works it has a number of annoying bugs and limitations (always need to set position even if your not overriding it, breaks batching, needs to be reset in some cases). Something that can be serialized in the scene would be ideal, as right now you have to have a component which stores it and copies it to the object at runtime (which prevents the mesh from being read only, breaking batching, and then requiring a separate baking pass). Ideally the data gets intertwined at some point automatically and everything ‘just works’.

There’s also the question of if it makes sense to get away from additional UV sets as a way to say “additional user data”. While every engine seems to use this terminology, it seems a little silly.

6 Likes

It’s should be reposted to DOTS thread :slight_smile:

3 Likes

We also need a way to specify one submesh to render instead of entire mesh with all submeshes.
I thinks it must be part of MeshFilter component in old system and all draw api must support to draw exact submesh instead of entire mesh.

Unity already have this inside static batching but it is not exposed to us.

This is like mesh atlasing that allow to have one mesh and effectively draw different parts of it.

3 Likes

Am I right that I can declare position as byte2 (not 2 bytes per component but 2 bytes for entire position ) with this api?

1 Like

Not quite, since many graphics APIs (e.g. Metal, GLES etc.) require vertex components to be multiple of 4 bytes in size. But you could declare position as two FP16 numbers, or four bytes, etc.

2 Likes

Yay, custom vertex layouts would be great! Right now I have to awkwardly pack everything to UVs.
jbooth also made a good point about additionalVertexStreams.

2 Likes

Another tangential thing is physics; a project I’m working on now uses jobs to generate lots of mesh data, copying the native arrays to arrays via unsafe code. It works well, but the fundamental bottleneck is by far updating physics representations. I can process dozens of times more meshes than I can update physics on, which causes a lot of complexity in amortizing that work.

8 Likes

I’d be happy with properties that accept NativeArray instead of managed array. We’re making procedural meshes using ECS but the problem right now is only managed arrays are allowed. We need to do an extra step of copying the contents of the NativeArray into a managed array.

mesh.nativeVertices = ...;
mesh.nativeUvs = ...;
mesh.nativeColors = ...;
7 Likes

I am personally interested with Mesh Buffers usability over computer shaders. I’d love to use it. I just have a question. Does this changes will require us to use Entities ?

1 Like

VertexAttributeDescriptor[ ] GetVertexAttributes();
Can we get a non-allocating alternative for this? Like a “VertexAttributesCount” and “GetVertexAttribute(int index)”, or something filling a List<>

void SetVertexBufferParams(int vertexCount, params VertexAttributeDescriptor[ ] attributes);
Can this have the slice-like overloads as well?

These may be planned already, but they’re not mentioned in the doc.

P.S: Current use case time: I’m creating mesh data on a dedicated .net thread, writing into a static allochglobal buffer. Then when the size is known, I Marshal.AllocHGlobal() a new buffer that’s used to temp hold the data while sending it to the main thread. There I copy the data to a static List<> as that’s the only one I can reasonably use with the current API. This copying is fun in itself, as I’m pinning the internal array of the List<> gotten with reflection, getting the pointer, and doing a memcpy from said malloc’d buffer into the List<>'s backing array. Then I got to set the List<>'s count as well with reflection. This turned out to be noticably quicker then simply copying data over using List<>.Clear() and List<>Add(). And I pack 2 int16 values into the color channel.

So I may be a happy guy when I can scratch all that for a burst job generating a few NativeArray<>'s and calling this new API :slight_smile:

1 Like

Please add a replacement or fix for Unwrapping.GenerateSecondaryUVSet since this is broken for 32bit indexing. And I may be mistaken but I believe we need serialization of the mesh object to allow for undo/redo functionality. I would also suggest moving towards a format that contains adjacency information like a winged edge data structure or similar.

1 Like

On which version do you see that? I seem to recall someone fixing exactly that, but I forgot how many years or months ago that was.

It does work in 2019.1.0f2 but I get an IndexOutOfRangeException when using Unwrapping.GenerateSecondaryUVSet in the LTS version 2017.4.25f1. This is caused by the triangle indices into the vertex array having been changed to random values like 1048591 for a mesh with only 60 vertices for example.

“It primarily has issues with performance, too much extra memory copying, memory allocation”

I’m running into the exact same problems (copying data for no reason, because the API demands it … and having to jump through hoops to prevent GC allocations that should never have happened in the first place) with the 2D Mesh manipulation APIs (i.e. VertexHelper - which is (correct me if I’m wrong) currently required to create meshes for UnityUI?).

Will this update also fix/replace the VertexHelper class with the same type of improvements? (VH is almost a great class, but the fact it forces you to copy data to/from low-performance List’s on every frame is painful).

2 Likes