Hi everybody.
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:
Editor with helper scripts:
PuzzleEditor.unitypackage