using System; using System.Collections.Generic; using UnityEngine; namespace eDriven.Mesh { /// /// Generates a mesh /// public class MeshGenerator { // ReSharper disable FieldCanBeMadeReadOnly.Global public float Width = 1000; public float Height = 1000; public int XSegments = 1; public int YSegments = 1; public UvMode UvMode = UvMode.Normal; // ReSharper restore FieldCanBeMadeReadOnly.Global private readonly List _vertices = new List(); public List Vertices { get { return _vertices; } } private readonly List _triangles = new List(); public List Triangles { get { return _triangles; } } private readonly List _normals = new List(); public List Normals { get { return _normals; } } private readonly List _uv = new List(); public List Uv { get { return _uv; } } public UnityEngine.Mesh Mesh { get { UnityEngine.Mesh m = new UnityEngine.Mesh(); m.vertices = _vertices.ToArray(); m.triangles = _triangles.ToArray(); m.normals = _normals.ToArray(); m.uv = _uv.ToArray(); return m; } } public MeshGenerator() { } public MeshGenerator(float width, float height, int xSegments, int ySegments) { Width = width; Height = height; XSegments = xSegments; YSegments = ySegments; } private int _lastVertexCount; /// /// Creates 2D mesh in a plane /// /// /// public void Tessalate2DMesh(Plane plane, Vector3 cameraUpVector) { int xVertices = XSegments + 1; int yVertices = YSegments + 1; Vector3[] vertices = new Vector3[xVertices * yVertices]; Vector3[] normals = new Vector3[vertices.Length]; Vector3 meshZAxis = plane.normal; Vector3 meshXAxis = Vector3.Cross(cameraUpVector, meshZAxis); // check just in case that cameraUpVector and planeNormal are not parallel if (meshXAxis.magnitude == 0) throw new Exception("The mesh up vector cannot be parallel to the plane normal."); float xSpace = Width / /*(float)*/XSegments; float ySpace = Height / /*(float)*/YSegments; float halfWidth = Width / 2; float halfHeight = Height / 2; int count = 0; /** * GetEaser vertices in local space * */ for (int y = 0; y < yVertices; y++) { for (int x = 0; x < xVertices; x++) { float xCoord = x * xSpace; float yCoord = y * ySpace; vertices[count] = new Vector3(xCoord - halfWidth, yCoord - halfHeight); count++; } } /** * Transform vertices to global space * */ // set transformation matrix Matrix4x4 transform = Matrix4x4.identity; transform.m00 = meshXAxis.x; transform.m01 = meshXAxis.y; transform.m02 = meshXAxis.z; //transform.m03 = 1; transform.m10 = cameraUpVector.x; transform.m11 = cameraUpVector.y; transform.m12 = cameraUpVector.z; //transform.m13 = 1; transform.m20 = meshZAxis.x; transform.m21 = meshZAxis.y; transform.m22 = meshZAxis.z; //transform.m23 = 1; // add translation by plane distance (in the opoposite direction of plane normal) transform = Matrix4x4.TRS(-plane.normal*plane.distance, Quaternion.identity, Vector3.one) * transform; // transform vertices int vertCount = vertices.Length; for (int i = 0; i < vertCount; i++) { vertices[i] = transform.MultiplyPoint(vertices[i]); normals[i] = plane.normal; } //Debug.Log("XSegments: " + XSegments + "; YSegments: " + YSegments); //Debug.Log("vertices.Length: " + vertices.Length); // indices (triangles) int[] triangles = new int[6 * XSegments * YSegments]; //Debug.Log("triangles.Length: " + triangles.Length); int vInc, uInc, v, u; //, iterations; vInc = 1; v = 0; //iterations = doubleSided ? 2 : 1; // make tris in a zigzag pattern (strip compatible) u = 0; uInc = 1; int vCount = YSegments; // reset count count = 0; while (0 < vCount--) { int uCount = XSegments; while (0 < uCount--) { // first triangle in the cell // ----------------- triangles[count++] = (short)(_lastVertexCount + ((v + vInc) * xVertices) + u); triangles[count++] = (short)(_lastVertexCount + (v * xVertices) + u); triangles[count++] = (short)(_lastVertexCount + ((v + vInc) * xVertices) + (u + uInc)); // second triangle in the cell // ------------------ triangles[count++] = (short)(_lastVertexCount + ((v + vInc) * xVertices) + (u + uInc)); triangles[count++] = (short)(_lastVertexCount + (v * xVertices) + u); triangles[count++] = (short)(_lastVertexCount + (v * xVertices) + (u + uInc)); // Next column u += uInc; //Debug.Log("***2. Count: " + count); } // while uCount v += vInc; u = 0; } // while vCount //v = YSegments - 1; //vInc = -vInc; _vertices.AddRange(vertices); _triangles.AddRange(triangles); _normals.AddRange(normals); /** * GetEaser right UV generator * */ IUvGenerator gene; switch (UvMode) { case UvMode.Normal: gene = new NormalUvGenerator(); break; //case UvMode.Curved: default: gene = new CurvedIllusionPlaneUvGenerator(); break; } /** * Calculate UV for each vertex * */ //CurvedIllusionPlaneUvGenerator gene = new CurvedIllusionPlaneUvGenerator(); //NormalUvGenerator gene = new NormalUvGenerator(); _uv.AddRange(gene.CalculateUv(Width, Height, xVertices, yVertices)); //mesh.RecalculateNormals(); _lastVertexCount += vertices.Length; //return mesh; } public void Clear() { _vertices.Clear(); _triangles.Clear(); _lastVertexCount = 0; _normals.Clear(); _uv.Clear(); } } public enum UvMode { Normal, Curved } }