[Solved]Problems with creating mesh from script

Hi everybody. :smile:
If you have experience when it comes to generating meshes from script, I need your help.

I am working on an editor that generates a mesh from 3x2D bool arrays. When it comes to creating the mesh, I am making 3 separate vertex-, triangle- and uv-arrays and then combining them before I use them in the mesh. My problem is that I am not able to display the whole mesh.

I have debugged almost everything and I still don’t understand why this is happening. The number of vertices, triangles and uvs is the same before and after I generate the mesh, but only one side is visible. Does anyone know whats wrong?

Here is my code:

public class PuzzleEditorWindow : EditorWindow
{
    private enum View
    {
        Top = 0,
        Side,
        Front,
        Menu
    };

    [MenuItem ("Window/Puzzle Editor")]
    static void Init()
    {
        EditorWindow.GetWindow(typeof(PuzzleEditorWindow));
    }

    /// <summary>
    /// The dimension.
    /// </summary>
    private int dimension;

    public int Dimension
    {
        get{ return dimension;}
        set
        {
            dimension = value;
            dimension = Mathf.Clamp(dimension, 3, 10);
            SetMap(dimension);
        }
    }

    /// <summary>
    /// The map.
    /// </summary>
    private bool[][][] map;

    private void SetMap(int size)
    {
        map = new bool[3][][];

        for(int a = 0; a < map.Length; a++)
        {
            map[a] = new bool[size][];

            for (int i = 0; i < map[a].Length; i++)
            {
                map [a][i] = new bool[size];
                for (int j = 0; j < map[a][i].Length; j++)
                {
                    map[a] [i] [j] = true;
                }
            }
        }
    }

    void OnEnable()
    {
        Dimension = 5;
    }
       
    void OnGUI()
    {
        DoCanvas(View.Top, map[(int)View.Top], new Rect(0, 0, 200, 200));
        DoCanvasName(View.Top, new Rect(0, 0, 200, 200));

        DoCanvas(View.Side, map[(int)View.Side], new Rect(200, 0, 200, 200));
        DoCanvasName(View.Side, new Rect(200, 0, 200, 200));

        DoCanvas(View.Front, map[(int)View.Front], new Rect(0, 200, 200, 200));
        DoCanvasName(View.Front, new Rect(0, 200, 200, 200));
       
        DoMenu(new Rect(200, 200, 200, 200));
    }
    void DoMenu(Rect canvas)
    {
        GUILayout.BeginArea(canvas);
        GUILayout.Label(View.Menu.ToString());
        if(GUILayout.Button("Export Mesh"))
        {
            ExportMesh();
        }

        if(GUILayout.Button("Export Waypoints"))
        {
            Debug.Log("Export Waypoints");
        }

        int tmp = EditorGUILayout.IntField("Dimension", Dimension);
        if(tmp != Dimension)
        {
            Dimension = tmp;
        }

        GUILayout.EndArea();
    }

    void DoCanvas(View view, bool[][] mapSide, Rect canvas)
    {
        GUILayout.BeginArea(canvas);
        //canvas = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
        float delta = canvas.width / dimension;

        DoCanvasInput(delta, mapSide);

        //Canvas
        for (int y = 0; y < mapSide.Length; y++)
        {
            for (int x = 0; x < mapSide[y].Length; x++)
            {
                if (mapSide [y] [x] == true)
                {
                    GUIDraw.SolidRect(new Vector2(x * delta, y * delta), new Vector2(x * delta + delta, y * delta + delta), Color.white);
                } else
                {
                    GUIDraw.SolidRect(new Vector2(x * delta, y * delta), new Vector2(x * delta + delta, y * delta + delta), Color.red);
                }
            }
        }

        //Grid
        for (int y = 0; y < mapSide.Length; y++)
        {
            Handles.color = Color.gray;
            Handles.DrawLine(new Vector3(0f, y * delta, 0f), new Vector3(canvas.width, y * delta, 0f));
            Handles.DrawLine(new Vector3(y * delta, 0f, 0f), new Vector3(y * delta, canvas.height, 0f));
        }

        //Border
        Handles.color = Color.black;
        Handles.DrawLine(new Vector3(0f, 0f, 0f), new Vector3(canvas.width, 0f, 0f));
        Handles.DrawLine(new Vector3(canvas.width, 0f, 0f), new Vector3(canvas.width, canvas.height, 0f));
        Handles.DrawLine(new Vector3(canvas.width, canvas.height, 0f), new Vector3(0f, canvas.height, 0f));
        Handles.DrawLine(new Vector3(0f, canvas.height, 0f), new Vector3(0f, 0f, 0f));

        GUILayout.EndArea();
    }

    void DoCanvasName(View view, Rect canvas)
    {
        GUILayout.BeginArea(canvas);
        GUILayout.Label(view.ToString());
        GUILayout.EndArea();
    }

    void DoCanvasInput(float delta, bool[][] mapSide)
    {
        Event evt = Event.current;
        if (evt.type == EventType.mouseDown)
        {   
            if (evt.button == 0)
            {
                int x = (int)(evt.mousePosition.x / delta);
                int y = (int)(evt.mousePosition.y / delta);

                if (x < 0 || x > dimension - 1)
                {
                    return;
                }
                if (y < 0 || y > dimension - 1)
                {
                    return;
                }

                if (mapSide [y] [x] == true)
                {
                    mapSide [y] [x] = false;
                } else
                {
                    mapSide [y] [x] = true;
                }
            }
            evt.Use();
        }
       
        if (evt.type == EventType.MouseDrag)
        {
//            evt.Use();
        }
       
        if (evt.type == EventType.MouseUp)
        {
//            evt.Use();
        }
    }

    void CreateMeshSide(bool[][] map, View view, ref List<Vector3> masterVert, ref List<int> masterTris, ref List<Vector2> masterUV)
    {
        List<Vector3> vert = new List<Vector3>();
        List<int> tris = new List<int>();
        List<Vector2> uv = new List<Vector2>();

        for (int y = 0; y < map.Length; y++)
        {
            for (int x = 0; x < map[y].Length; x++)
            {
                if (map [y] [x] == true)
                {
                    MeshAddRect(vert, tris, uv, x, y);

                    if (y + 1 < dimension)
                    {
                        if (map [y + 1] [x] == false)
                        {
                            MeshAddRectDown(vert, tris, uv, x, y);
                        }
                    }
                    if (y - 1 >= 0)
                    {
                        if (map [y - 1] [x] == false)
                        {
                            MeshAddRectUp(vert, tris, uv, x, y);
                        }
                    }
                    if (x + 1 < dimension)
                    {
                        if (map [y] [x + 1] == false)
                        {
                            MeshAddRectRight(vert, tris, uv, x, y);
                        }
                    }
                    if (x - 1 >= 0)
                    {
                        if (map [y] [x - 1] == false)
                        {
                            MeshAddRectLeft(vert, tris, uv, x, y);
                        }
                    }
                }
            }
        }

        //center
        Matrix4x4 tm = Matrix4x4.identity;
        tm [0, 3] -= dimension / 2f;
        tm [1, 3] += dimension / 2f;
       
        ApplyMatrix(tm, vert);


        if(view == View.Top)
        {
            //Rotate
            tm = Matrix4x4.identity;
            tm[1,1] = 0;
            tm[1,2] = 1;
            tm[2,1] = -1;
            tm[2,2] = 0;

            ApplyMatrix(tm, vert);

            //Move
            tm = Matrix4x4.identity;
            tm[1, 3] += dimension / 2f;

            ApplyMatrix(tm, vert);
        }

        if(view == View.Front)
        {
            //Move
            tm = Matrix4x4.identity;
            tm[2, 3] += dimension / 2f;
           
            ApplyMatrix(tm, vert);
        }

        if(view == View.Side)
        {
            //Rotate
            tm = Matrix4x4.identity;
            tm[0,0] = 0;
            tm[0,2] = 1;
            tm[2,0] = -1;
            tm[2,2] = 0;
           
            ApplyMatrix(tm, vert);
           
            //Move
            tm = Matrix4x4.identity;
            tm[0, 3] += dimension / 2f;
           
            ApplyMatrix(tm, vert);
        }



        for(int i = 0; i < vert.Count; i++)
        {
            masterVert.Add(vert[i]);
        }

        for(int i = 0; i < tris.Count; i++)
        {
            masterTris.Add(tris[i]);
        }

        for(int i = 0; i < uv.Count; i++)
        {
            masterUV.Add(uv[i]);
        }
    }

    void ExportMesh()
    {
        Mesh mesh = new Mesh();

        List<Vector3> vert = new List<Vector3>();
        List<int> tris = new List<int>();
        List<Vector2> uv = new List<Vector2>();

        //Create mesh sides
        CreateMeshSide(map[(int)View.Top], View.Top, ref vert, ref tris, ref uv);
        CreateMeshSide(map[(int)View.Front], View.Front, ref vert, ref tris, ref uv);
        CreateMeshSide(map[(int)View.Side], View.Side, ref vert, ref tris, ref uv);
       
        UpdateUV(vert, uv);

        mesh.vertices = vert.ToArray();
        mesh.triangles = tris.ToArray();
        mesh.uv = uv.ToArray();

        mesh.RecalculateNormals();

        ObjExporter.MeshToFile(mesh, "Assets/map.obj");
        AssetDatabase.Refresh();
    }

    void MeshAddRect(List<Vector3> v, List<int> t, List<Vector2> uv, int x, int y)
    {
        v.Add(new Vector3(1f * x, -1f * y, 0f));
        v.Add(new Vector3(1f * x + 1f, -1f * y, 0f));
        v.Add(new Vector3(1f * x, -1f * y - 1f, 0f));
        v.Add(new Vector3(1f * x + 1f, -1f * y - 1f, 0f));

        AddTris(v, t);
        AddUV(uv);
    }

    void MeshAddRectDown(List<Vector3> v, List<int> t, List<Vector2> uv, int x, int y)
    {
        v.Add(new Vector3(1f * x, -1f * y - 1f, 0f));
        v.Add(new Vector3(1f * x + 1f, -1f * y - 1f, 0f));
        v.Add(new Vector3(1f * x, -1f * y - 1f, -1f));
        v.Add(new Vector3(1f * x + 1f, -1f * y - 1f, -1f));
       
        AddTris(v, t);
        AddUV(uv);
    }
   
    void MeshAddRectUp(List<Vector3> v, List<int> t, List<Vector2> uv, int x, int y)
    {
        v.Add(new Vector3(1f * x, -1f * y, -1f));
        v.Add(new Vector3(1f * x + 1f, -1f * y, -1f));
        v.Add(new Vector3(1f * x, -1f * y, 0f));
        v.Add(new Vector3(1f * x + 1f, -1f * y, 0f));
       
        AddTris(v, t);
        AddUV(uv);
    }

    void MeshAddRectRight(List<Vector3> v, List<int> t, List<Vector2> uv, int x, int y)
    {
        v.Add(new Vector3(1f * x + 1f, -1f * y, 0f));
        v.Add(new Vector3(1f * x + 1f, -1f * y, -1f));
        v.Add(new Vector3(1f * x + 1f, -1f * y - 1f, 0f));
        v.Add(new Vector3(1f * x + 1f, -1f * y - 1f, -1f));
       
        AddTris(v, t);
        AddUV(uv);
    }

    void MeshAddRectLeft(List<Vector3> v, List<int> t, List<Vector2> uv, int x, int y)
    {
        v.Add(new Vector3(1f * x, -1f * y, -1f));
        v.Add(new Vector3(1f * x, -1f * y, 0f));
        v.Add(new Vector3(1f * x, -1f * y - 1f, -1f));
        v.Add(new Vector3(1f * x, -1f * y - 1f, 0f));
       
        AddTris(v, t);
        AddUV(uv);
    }

    private void AddTris(List<Vector3> v, List<int> t)
    {
        t.Add(v.Count - 2);
        t.Add(v.Count - 3);
        t.Add(v.Count - 4);
       
        t.Add(v.Count - 2);
        t.Add(v.Count - 1);
        t.Add(v.Count - 3);
    }

    private void AddUV(List<Vector2> uv)
    {
        uv.Add(Vector2.zero);
        uv.Add(Vector2.zero);
        uv.Add(Vector2.zero);
        uv.Add(Vector2.zero);
    }

    private void ApplyMatrix(Matrix4x4 m, List<Vector3> v)
    {
        for (int i = 0; i < v.Count; i++)
        {
            v [i] = m.MultiplyPoint(v [i]);
        }
    }

    void UpdateUV(List<Vector3> v, List<Vector2> uv)
    {
        int i = 0;
        while (i < v.Count)
        {
            uv [i] = new Vector2(v [i].x, v [i].z);
            i++;
        }
    }
}

Editor:

Result after exporting Mesh:
1753071--110869--demo1.png 1753071--110870--demo2.png 1753071--110871--demo3.png

Editor with helper scripts:
PuzzleEditor.unitypackage

1753071–110872–PuzzleEditor.unitypackage (4.78 KB)

its been a little while since i did dynamic mesh stuff. But iirc, the faces probably are upside down. If you move the camera below the mesh you’ll probably only see the missing parts. I thiink this is defined by the ordering of the points - but my memory is total garbage.

Thanks for fast reply.

I manage to solve the problem myself by changing this code:

for(int i = 0; i < vert.Count; i++)
{
    masterVert.Add(vert[I]);
}
      
for(int i = 0; i < tris.Count; i++)
{
    masterTris.Add(tris[I]);
}

for(int i = 0; i < uv.Count; i++)
{
    masterUV.Add(uv[I]);
}

To this:

int tmp = masterVert.Count;
for(int i = 0; i < vert.Count; i++)
{
    masterVert.Add(vert[I]);
}
      
for(int i = 0; i < tris.Count; i++)
{
    masterTris.Add(tris[I] + tmp);
}

for(int i = 0; i < uv.Count; i++)
{
    masterUV.Add(uv[I]);
}

I forgot to add the triangle numbers on top of what was already in the lists.