How to define stride in Mesh.SetVertexBufferData with raw float[] array

Hey everyone,

I hope this is the right thread for my problem.

I receive (position) sensor data every frame from a C++ backend and want to insert it directly in the vertices property of a Mesh object. The received information is a simple float array, where 3 floats describe a vertex. The index list is just and ascending array of uint’s, that doesn’t change and therefore can be precomputed.

My first idea was to loop over the array, create a Vector3 array and assign this to Mesh.vertices. This introduces a (hopefully) unnecessary step, though, that results in a strong performance hit.

The other idea was to directly write to the vertex buffer of the mesh object with Mesh.SetVertexBufferData. The only problem is that I can’t specify a stride to tell how many entries of this float array build an actual vertex position as I would in plane OpenGL for example.

I already read about the Job system, yet I think that there has to be some way of defining a stride that I was unable to filter out from the documentation.

The code below works only with lines 38/39 but not with 35/36.
I’m working on Unity 2019.4.16f1 with URP 7.3.1.

public class MeshFromRaw : MonoBehaviour
{
  
    [SerializeField]
    private Material MeshMaterial;
    private Mesh _mesh;

    void Start()
    {
        gameObject.AddComponent<MeshFilter>();
        gameObject.AddComponent<MeshRenderer>();
        _mesh = GetComponent<MeshFilter>().mesh;

        FillMeshWFloat();

        MeshRenderer renderer = GetComponent<MeshRenderer>();
        renderer.material = MeshMaterial;
    }
    
    // For simplicity reasons, just builds a triangle and fills vertex and index buffers
    private void FillMeshWFloat()
    {
        _mesh.Clear();
        // simple float array with vertex data. DOES NOT WORK
        float[] vertices = new float[] { 0.0f, 0.0f, 1.0f,
                                        1.0f, 0.0f, 3.0f
                                        2.0f, 0.0f, 1.0f,};

        // The "standard" way that works.
        Vector3[] verticesVec3 = new Vector3[] { new Vector3(0, 0, 1), 
                                                 new Vector3(1, 0, 3), 
                                                 new Vector3(2, 0, 1) };

        uint[] indices = new uint[] { 0, 1, 2 };

        //_mesh.SetVertexBufferParams(vertices.Length/3, new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3));
        //_mesh.SetVertexBufferData<float>(vertices, 0, 0, vertices.Length/3);

        _mesh.SetVertexBufferParams(verticesVec3.Length, new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3));
        _mesh.SetVertexBufferData<Vector3>(verticesVec3, 0, 0, verticesVec3.Length);

        _mesh.SetIndexBufferParams(indices.Length, IndexFormat.UInt32);
        _mesh.SetIndexBufferData<uint>(indices, 0, 0, indices.Length);

        _mesh.SetSubMesh(0, new SubMeshDescriptor(0, indices.Length));
        _mesh.bounds = new Bounds(Vector3.zero, Vector3.one * 1000);
        _mesh.RecalculateNormals();
    }
}
1 Like

It works, if you do not divide by 3 in line 37:

_mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length);

Not that in your example, SetVertexBufferData needs the number of floats to copy, not the number of vertices,

1 Like

Oh my… facepalm. Just tested and it works!

Thank you very much! :slight_smile: