Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Question Mesh importer, SetVertexBufferData with dynamic vertex size

Discussion in 'General Graphics' started by Titan8190, Oct 17, 2022.

  1. Titan8190

    Titan8190

    Joined:
    Feb 16, 2013
    Posts:
    29
    Hi,
    for context, I'am working on a mesh importer for a custom format that allows me to pass arbitrary mesh data from blender.

    When creating the mesh in unity I have some difficulties passing my vertex data to the mesh:
    SetVertexBufferData expect an array of struct matching my data size. I first tried to generate a dynamic structure with reflection and TypeBuilder, but that's really complicated and shouldn't be required just to pass some data.

    Then I assumed that a plain bytes array should be enough, so I pushed all my vertices data into a
    MemoryStream and then just passed my memStream.ToArray() to SetVertexBufferData. it works for the first n bytes of my model, where n is the total number of declared vertex. for example my test mesh have 125 vertices declared and a vertex is 20 bytes, so my first 6 vertex are actually correct in the resulting mesh (6x20=120) and I get random garbage from the 7th.

    So what is the proper way to call SetVertexBufferData when you can't actually declare a static struct format like described in the documentation ?
     
  2. Titan8190

    Titan8190

    Joined:
    Feb 16, 2013
    Posts:
    29
    This is the master piece I came up with (to expand to infinity), until I get the courage to dive into dynamicly generated Type again or someone finally explains me the obvious way of doing it that I missed.
    Code (CSharp):
    1.     struct Struct16 { public int _4, _8, _12, _16; }
    2.     struct Struct20 { public int _4, _8, _12, _16, _20; }
    3.  
    4.     T[] ConvertByteToStructArray<T>(byte[] data, int size, int count) where T : struct
    5.     {
    6.         T[] dataStruct = new T[count];
    7.         for (int i = 0; i < count; i++)
    8.         {
    9.             IntPtr ptPoit = Marshal.AllocHGlobal(size);
    10.             Marshal.Copy(data, i * size, ptPoit, size);
    11.             dataStruct[i] = (T) Marshal.PtrToStructure(ptPoit, typeof (T));
    12.             Marshal.FreeHGlobal(ptPoit);
    13.         }
    14.         return dataStruct;
    15.     }
    16.  
    17.     void SetVertexBufferData(Mesh mesh, byte[] verticesData, int size, int count)
    18.     {
    19.         switch (size)
    20.         {
    21.             case 16: mesh.SetVertexBufferData(ConvertByteToStructArray<Struct16>(verticesData, size, count), 0, 0, count); break;
    22.             case 20: mesh.SetVertexBufferData(ConvertByteToStructArray<Struct20>(verticesData, size, count), 0, 0, count); break;
    23.         }
    24.     }
     
  3. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    556
    Maybe you can assign the attributes separately with the old accessor methods (Mesh.vertices, Mesh.normals, Mesh.colors, Mesh.normals, Mesh.tangents, Mesh.uv, Mesh.uv2, ....)?
     
  4. Titan8190

    Titan8190

    Joined:
    Feb 16, 2013
    Posts:
    29
    That would work for position but I can't because these methods are typed and I use my texcoord for everything (byte, float, integers, ....) and not just vector2