Mesh CreateMesh(Vector2[] poly, float height)
    {
        // convert polygon to triangles

        TriangulatorSimple triangulator = new TriangulatorSimple(poly);

        int[] tris = triangulator.Triangulate();
        Mesh  m    = new Mesh();

        Vector3[] vertices = new Vector3[poly.Length * 2];

        for (int i = 0; i < poly.Length; i++)
        {
            vertices[i].x = poly[i].x;
            vertices[i].y = poly[i].y;
            vertices[i].z = 0;// front vertex
            vertices[i + poly.Length].x = poly[i].x;
            vertices[i + poly.Length].y = poly[i].y;
            vertices[i + poly.Length].z = -height;// back vertex
        }
        int[] triangles  = new int[tris.Length * 2 + poly.Length * 6];
        int   count_tris = 0;

        for (int i = 0; i < tris.Length; i += 3)
        {
            triangles[i]     = tris[i] + poly.Length;
            triangles[i + 1] = tris[i + 1] + poly.Length;
            triangles[i + 2] = tris[i + 2] + poly.Length;
        } // front vertices
        count_tris += tris.Length;
        for (int i = 0; i < tris.Length; i += 3)
        {
            triangles[count_tris + i]     = tris[i + 2];
            triangles[count_tris + i + 1] = tris[i + 1];
            triangles[count_tris + i + 2] = tris[i];
        } // back vertices
        count_tris += tris.Length;
        for (int i = 0; i < poly.Length; i++)
        {
            // triangles around the perimeter of the object
            int n = (i + 1) % poly.Length;
            triangles[count_tris]     = i;
            triangles[count_tris + 1] = i + poly.Length;
            triangles[count_tris + 2] = n;
            triangles[count_tris + 3] = i + poly.Length;
            triangles[count_tris + 4] = n + poly.Length;
            triangles[count_tris + 5] = n;
            count_tris += 6;
        }
        m.vertices  = vertices;
        m.triangles = triangles;
        m.RecalculateNormals();
        m.RecalculateBounds();
        m.Optimize();

        return(m);
    }
    void GenerateGeometry(DataTable dataTable)
    {
        GameObject parent = new GameObject("Geodata");

        for (int i = 0; i < dataTable.Rows.Count; i++)
        {
            string polygonText = dataTable.Rows[i].ItemArray[1].ToString().Replace("MULTIPOLYGON(((", "");
            polygonText = polygonText.Replace(")))", "");
            //Debug.Log(polygonText);
            string[] coords = polygonText.Split(',');
            //Debug.Log("Coords " + coords.Length);

            List <Vector3> vertices   = new List <Vector3>();
            List <Vector2> vertices2d = new List <Vector2>();
            for (int j = 0; j < coords.Length - 1; j++)
            {
                coords[j] = coords[j].Replace(".", ",");
                string[] latlonS = coords[j].Split(' ');

                try
                {
                    Vector2d latlon = new Vector2d(double.Parse(latlonS[1]), double.Parse(latlonS[0]));
                    //Debug.Log(latlon.ToString());
                    Vector3 point = map.GeoToWorldPosition(latlon, false);
                    vertices.Add(new Vector3(point.x, point.z, 0));
                    vertices2d.Add(new Vector2(point.x, point.z));
                }
                catch (Exception msg)
                {
                    Debug.Log(msg.ToString());
                }
            }

            float height = 0;
            try
            {
                height = float.Parse(dataTable.Rows[i].ItemArray[2].ToString());
            }
            catch (Exception msg)
            {
                Debug.Log(msg.ToString());
            }

            //------------Generate Mesh------------//
            //vertices2d.Reverse();
            //Mesh mesh = CreateMesh(vertices2d.ToArray(), height);
            TriangulatorSimple triangulator = new TriangulatorSimple(vertices2d.ToArray());
            int[] indices = triangulator.Triangulate();
            //Mesh mesh = new Mesh();
            //mesh.vertices = vertices.ToArray();
            //mesh.triangles = indices;
            //mesh.RecalculateNormals();
            //mesh.RecalculateBounds();
            //mesh.Optimize();

            bool         is3D         = true;
            GameObject   obj          = new GameObject(i.ToString());
            PolyExtruder polyExtruder = obj.AddComponent <PolyExtruder>();
            polyExtruder.createPrism(obj.name, height, vertices2d.ToArray(), Color.white, is3D);
            obj.AddComponent <MeshRenderer>();
            //obj.AddComponent<MeshFilter>();
            //obj.GetComponent<MeshFilter>().mesh = mesh;
            obj.GetComponent <MeshRenderer>().material = mat;
            //obj.transform.localEulerAngles += new Vector3(90, 0, 0);
            obj.transform.parent = parent.transform;
        }
    }
    private void GenerateMeshesFromOutlines(List <List <Vector2> > outlines)
    {
        for (int i = 0; i < transform.childCount; i++)
        {
            DestroyImmediate(transform.GetChild(i).gameObject, true);
        }

        for (int i = 0; i < outlines.Count; i++)
        {
            List <Vector2> outline = outlines [i];

            GameObject   poolObject             = new GameObject("Pool" + i.ToString());
            MeshFilter   poolObjectMeshFilter   = poolObject.AddComponent <MeshFilter> ();
            MeshRenderer poolObjectMeshRenderer = poolObject.AddComponent <MeshRenderer> ();

            GameObject   poolBorderObject             = new GameObject("PoolBorder" + i.ToString());
            MeshFilter   poolBorderObjectMeshFilter   = poolBorderObject.AddComponent <MeshFilter> ();
            MeshRenderer poolBorderObjectMeshRenderer = poolBorderObject.AddComponent <MeshRenderer> ();

            GameObject   poolWallObject             = new GameObject("PoolWall" + i.ToString());
            MeshFilter   poolWallObjectMeshFilter   = poolWallObject.AddComponent <MeshFilter> ();
            MeshRenderer poolWallObjectMeshRenderer = poolWallObject.AddComponent <MeshRenderer> ();

            poolObject.transform.SetParent(transform);
            poolBorderObject.transform.SetParent(transform);
            poolWallObject.transform.SetParent(transform);

            Mesh           poolBorderMesh      = new Mesh();
            List <Vector3> poolBorderVertices  = new List <Vector3> ();
            List <Vector2> poolBorderUvs       = new List <Vector2> ();
            List <int>     poolBorderTriangles = new List <int> ();

            Mesh           poolWallMesh      = new Mesh();
            List <Vector3> poolWallVertices  = new List <Vector3> ();
            List <int>     poolWallTriangles = new List <int> ();

            int li0 = 0;
            int li1 = 0;

            int li2 = 0;
            int li3 = 0;

            for (int j = 0; j < outline.Count; j++)
            {
                int mid = j;
                int fw  = (j + 1) % (outline.Count);
                int bw  = (outline.Count - 1 + j) % (outline.Count);

                Vector3 pMid = outline [mid];
                Vector3 pFw  = outline [fw];
                Vector3 pBw  = outline [bw];

                Vector3 d0 = Vector3.Cross((pFw - pMid).normalized, Vector3.forward);
                Vector3 d1 = Vector3.Cross((pBw - pMid).normalized, Vector3.forward);

                Vector3 p0 = pMid - d0 * borderSize;
                Vector3 p1 = pMid + d1 * borderSize;
                Vector3 pm = p0 + ((p1 - p0) * 0.5f);

                poolBorderVertices.Add(pMid + Vector3.forward * -poolHeight);
                poolBorderVertices.Add(pm + Vector3.forward * -poolHeight);

                poolBorderUvs.Add(new Vector2((float)j / (float)(outline.Count - 1), 0.0f));
                poolBorderUvs.Add(new Vector2((float)j / (float)(outline.Count - 1), 1.0f));

                poolWallVertices.Add(pMid);
                poolWallVertices.Add(pMid + Vector3.forward * -poolHeight);

                if (j > 0)
                {
                    poolBorderTriangles.Add(poolBorderVertices.Count - 2);
                    poolBorderTriangles.Add(li0);
                    poolBorderTriangles.Add(li1);

                    poolBorderTriangles.Add(poolBorderVertices.Count - 2);
                    poolBorderTriangles.Add(li1);
                    poolBorderTriangles.Add(poolBorderVertices.Count - 1);

                    poolWallTriangles.Add(poolWallVertices.Count - 2);
                    poolWallTriangles.Add(li2);
                    poolWallTriangles.Add(li3);

                    poolWallTriangles.Add(poolWallVertices.Count - 2);
                    poolWallTriangles.Add(li3);
                    poolWallTriangles.Add(poolWallVertices.Count - 1);
                }

                li0 = poolBorderVertices.Count - 2;
                li1 = poolBorderVertices.Count - 1;

                li2 = poolWallVertices.Count - 2;
                li3 = poolWallVertices.Count - 1;
            }

            // connect last border triangles of the loop
            poolBorderTriangles.Add(0);
            poolBorderTriangles.Add(poolBorderVertices.Count - 1);
            poolBorderTriangles.Add(1);

            poolBorderTriangles.Add(0);
            poolBorderTriangles.Add(poolBorderVertices.Count - 2);
            poolBorderTriangles.Add(poolBorderVertices.Count - 1);

            // connect last wall triangles of the loop
            poolWallTriangles.Add(0);
            poolWallTriangles.Add(poolWallVertices.Count - 1);
            poolWallTriangles.Add(1);

            poolWallTriangles.Add(0);
            poolWallTriangles.Add(poolWallVertices.Count - 2);
            poolWallTriangles.Add(poolWallVertices.Count - 1);


            poolBorderMesh.SetVertices(poolBorderVertices);
            poolBorderMesh.SetUVs(0, poolBorderUvs);
            poolBorderMesh.SetTriangles(poolBorderTriangles, 0);
            poolBorderMesh.RecalculateBounds();
            poolBorderMesh.RecalculateNormals();

            poolWallMesh.SetVertices(poolWallVertices);
            poolWallMesh.SetTriangles(poolWallTriangles, 0);
            poolWallMesh.RecalculateBounds();
            poolWallMesh.RecalculateNormals();

            poolBorderObjectMeshRenderer.material = poolBorderMaterial;
            poolBorderObjectMeshFilter.mesh       = poolBorderMesh;

            poolWallObjectMeshRenderer.material = poolWallMaterial;
            poolWallObjectMeshFilter.mesh       = poolWallMesh;

            poolObjectMeshRenderer.material = poolMaterial;

            TriangulatorSimple ts = new TriangulatorSimple(outline.ToArray());
            int[] triangles       = ts.Triangulate();

            List <Vector3> vertices = new List <Vector3> ();
            for (int j = 0; j < outline.Count; j++)
            {
                vertices.Add(outline [j]);
            }

            Mesh poolMesh = new Mesh();
            poolMesh.SetVertices(vertices);
            poolMesh.triangles = triangles;
            poolMesh.RecalculateBounds();
            poolMesh.RecalculateNormals();

            poolObjectMeshFilter.mesh = poolMesh;
        }
    }