What is great reading material on `MultiMeshInstance2D` (videos ok too)

Godot Version

4.4 up to most recent

Background

The past year I’ve been developing Scalable Vector Shapes 2D; an in-editor vector drawing plugin using Bézier curves including a pretty feature complete SVG importer, animated curves, polygon clipping and sprite sheet exporter (among other things)

Recently I’ve been really active on this forum, learning a lot of new stuff, including about better ways to draw directly to the viewport.

Question

I have quite some experience with the CanvasItem draw functions by now, but I want to take it to the next level by adding a scene export to MultiMeshInstance2D, converting all Line2D and Polygon2D to Meshes. In gdscript of course.

To add extra complexity I want (gradient) textures and albedo material to keep working as well.

However.

Just looking at the documentation alone opens up to a very wide topic. Links seem to refer to 3D demo’s, which may be good enough, but may add a layer of complexity I am not really interested in (at the moment).

So: what is the best reading material for this?

I can digest a couple of videos too, as long as someone I trust to know what they’re talking about advises them.

The issue I opened on Github

TBH I didn’t know MultiMeshInstance2D existed until you made this post. I’ve never heard anyone talk about it on here.

Well, I may have to rephrase my question, because in the end I get the impression it’s just a wrapper to trigger a fast and optimized render for meshes with.

What I really would like to learn about is how to programmatically draw a flat mesh. The underlying implementation appears to be exactly the same as 3D, which may force me to learn more about materials and shaders… I don’t want to open a Pandora’s box. But a step by step guide on how to draw a flat mesh with an albedo and a texture would be good too.

Both ArrayMesh and ImmediateMesh can be used for this. Their examples in the docs are for 3D meshes, but can easily be adjusted to 2D.

ArrayMesh

Just use a PackedVector2Array with Vector2s:

var vertices = PackedVector2Array()
vertices.push_back(Vector2(  0, 100))
vertices.push_back(Vector2(100,   0))
vertices.push_back(Vector2(  0,   0))

# Initialize the ArrayMesh.
var arr_mesh = ArrayMesh.new()
var arrays = []
arrays.resize(Mesh.ARRAY_MAX)
arrays[Mesh.ARRAY_VERTEX] = vertices

# Create the Mesh.
arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)

ImmediateMesh

Use the surface_add_vertex_2d() function to add the vertices.

var mesh = ImmediateMesh.new()
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
mesh.surface_add_vertex_2d(Vector2(  0, 100))
mesh.surface_add_vertex_2d(Vector2(100,   0))
mesh.surface_add_vertex_2d(Vector2(  0,   0))
mesh.surface_end()

In both cases, use the mesh on a MeshInstance2D instead of 3D.


Things like vertex colors or UVs should be the same as for 3D meshes:

For ArrayMesh, you can put all kinds of data into the arrays argument. It’s an array of arrays, and its structure is defined by the the Mesh.ArrayType enum. E. g. arrays[Mesh.ARRAY_VERTEX] is supposed to have the vertex positions, arrays[Mesh.ARRAY_NORMAL] the vertex normals, and so on…

ImmediateMesh has specific functions like surface_set_color() which you can call during mesh construction.

It’s exactly the same as the 3D counterpart. Majority of work is done by MultiMesh resource anyway and the same resource class is used in both cases.

That said, I’m not sure multi instancing can help you much. It’s good for optimizing when you need to render many of the same thing. There’s really no use case with your bezier plugin as shapes will typically be different from each other.

If you just want to convert lines and polygons to mesh resources, the main question is - for what purpose. The engine already does that under the hood. Otherwise it wouldn’t be able to draw them.

Creating meshes programatically is rather straightforward. Again, it’s exactly the same regardless if the mesh is 2D or 3D. The engine really doesn’t make that distinction in any significant ways. A 2D mesh is just a “flattened” 3D mesh. You just supply vertex arrays and pass them to the API. I’m not big on tutorials so I can’t recommend any but there are plenty of decent ones that describe the basics of mesh generation. If you have anything specific - ask away.

In this case it would be useful to cover scenes with large amounts of nodes representing the image (like the weird case of trying to rotate pixel art with seamless like edges :grin:)

Oh, like a vector pattern fill? I guess that is a valid use case.

In a nutshell, meshes are just buffers filled with vertex data. When drawing them, GPU runs shader code that processes that vertex data and rasterizes it to the display. Everything is done this way in game engines, from full blown animated 3D characters to gui text.

Whatever you’re trying to pull off, your best entry point is looking at how mesh data is created using ArrayMesh. Understanding this will help you with everything else. There’s a decent tutorial in the docs: Using the ArrayMesh — Godot Engine (stable) documentation in English

Yeah sure. I was really thinking of our Jagged Edges friend the perfectionist, but now you’ve given me an even better excuse, cus my SVG Importer can only be feature complete when it supports pattern fills too! :rofl:

If your main motivation is to aid perfectionists be more perfect - I’ll have to think twice about helping with that :rofl: