Table of Contents

MeshBuilder

Introduction

The MeshBuilder is a utility class allowing dynamic creation of meshes at runtime. Acting as a wrapper around the Mesh class, it provides a simpler API for defining the mesh layout and data.

Once there was a triangle

Like in all rendering examples let's start with a simple triangle.

VertexElement

A vertex element is a value assigned to a specific vertex. In Stride we can use a lot of different types to define our data some of them are Vector3, Vector4, Color, Int, Float, Half and more.

We need to tell Stride how we want layout this data so our shader can read our various values. This is where vertex elements come in. They define a semanticName, semanticIndex, offset and a size.

By default Stride allows you to define structs for your data or to use custom buffers for your data. For most use-cases this is probably fine and the easier approach compared to a mesh builder.

However if you need to define your data dynamically or want a generalized method here we go.

MeshBuilder

The MeshBuilder abstracts away a lot of complexity behind custom buffers, type erasure, memory allocation and instead provides you with a simpler builder API to define your mesh dynamically.

It uses the same concepts as Stride so you still have to define your layout manually but the process is easier and you don't need to worry about the memory layout yourself. To use a MeshBuilder just create a new instance.

using var meshBuilder = new MeshBuilder()
Note

Notice the using at the front. This part is crucial as you should always dispose of your mesh builder when it's no longer needed. The builder utilizes pooling behind the scenes, and failing to dispose of it prevents the return of internal buffers, which can lead to significant performance degradation.

Layout

As we discussed earlier we need to tell the MeshBuilder which data types and fields we want to use. For this we use the various With... methods.

Primitive Type

First we need to select a primitive type in our example we create a bunch of triangles so we use this code:

meshBuilder.WithPrimitiveType(PrimitiveType.TriangleList);

Indexing

The mesh builder supports three types of indexing, None, Int16 or Int32. In our case we definitely don't need more than 32k indices so we can safely use the Int16 version.

meshBuilder.WithIndexType(IndexingType.Int16);

Elements

For our example we will use a vertex with a position and a color element.

var position = meshBuilder.WithPosition<Vector3>();
var color = meshBuilder.WithColor<Color>();

These methods return the element index we need when we set our actual values. We use a Vector3 as our vertex position and a Color for our vertex color. Other types would work as well but these are very common so we will use them as well.

Vertices

Next we define our vertices. For that we use a new method AddVertex(). This will add a new vertex to our builder and allows us to use the Get/SetElement methods.

You can also declare multiple vertices before setting the actual values but this is the simplest way for now.

meshBuilder.AddVertex();

After this we can set our element data. For this we use the SetElement() method. It expects an element index (which we received from WithPosition and WithColor earlier) as well as your desired value.

meshBuilder.SetElement(position, new Vector3(0, 0, 0));
meshBuilder.SetElement(color, Color.Red);

We repeat this for the other two triangle points as well.

meshBuilder.AddVertex();
meshBuilder.SetElement(position, new Vector3(1, 0, 0));
meshBuilder.SetElement(color, Color.Green);

meshBuilder.AddVertex();
meshBuilder.SetElement(position, new Vector3(.5f, 1, 0));
meshBuilder.SetElement(color, Color.Blue);

Indices

Next we need to tell the MeshBuilder how we want to connect the vertices. We configured indexing for our builder so we need to do this explicitly. For a simple example like this you could also completely skip the indexing part and use IndexingType.None instead.

The winding order in Stride is counter-clockwise so we use these indices.

meshBuilder.AddIndex(0);
meshBuilder.AddIndex(2);
meshBuilder.AddIndex(1);

Mesh

The only thing left is building the actual mesh. For this we use this method. It expects a graphics device as an argument. If you call this from a script this is usually available for you using the GraphicsDevice property of your script.

meshBuilder.ToMeshDraw(GraphicsDevice);

Display

To show this MeshDraw on screen we create a ModelComponent and add our MeshDraw as new model. We also need to define a material to use our vertex colors on screen. Else the Triangle would just be white.

var model = new Model
{
    new MaterialInstance {
        Material = Material.New(graphicsDevice, new MaterialDescriptor {
            Attributes = new MaterialAttributes {
                DiffuseModel = new MaterialDiffuseLambertModelFeature(),
                Diffuse = new MaterialDiffuseMapFeature {
                    DiffuseMap = new ComputeVertexStreamColor()
                },
            }
        })
    },
    new Mesh {
        Draw = meshBuilder.ToMeshDraw(graphicsDevice),
        MaterialIndex = 0
    }
}

Congrats 🥳 you got a triangle.

Example

For a more comprehensive usage of MeshBuilder, explore our Procedural Geometry example where you'll find detailed code on creating complex geometries dynamically.