GeoJson作为一种模型传输格式, 用的最多的就是地图里面的各种简单模型了, 比如下图中很贴切的俄罗斯方块楼:

  它的格式大概就是下面这样:

{
    "type": "FeatureCollection",
    "crs": {
        "type": "name",
        "properties": {
            "name": "EPSG:3857"
        }
    },
    "features": [{
        "type": "Feature",
        "id": 0,
        "geometry": {
            "type": "Polygon",
            "coordinates": [
                [
                    [-2066.3279353108665, -7427.2858673485389],
                    [-2071.2341353108641, -7436.5054673485392],
                    [-2090.8278353108617, -7426.2554673485392],
                    [-2092.9139353108621, -7430.4644673485382],
                    [-2096.9763353108574, -7438.1128673485382],
                    [-2089.4294353108708, -7441.1304673485392],
                    [-2091.4216353108641, -7448.0708673485387],
                    [-2090.0935353108653, -7448.4624673485378],
                    [-2086.7887353108672, -7449.4635673485391],
                    [-2087.0934353108605, -7450.4654673485384],
                    [-2077.6715353108593, -7453.5912673485382],
                    [-2071.241835310866, -7455.724267348538],
                    [-2070.8513353108574, -7455.8531673485377],
                    [-2070.5388353108574, -7454.7720673485383],
                    [-2066.2340353108593, -7440.1365673485379],
                    [-2064.8513353108574, -7440.5699673485396],
                    [-2064.2340353108593, -7438.5963673485385],
                    [-2064.3123353108676, -7437.5268673485389],
                    [-2068.0935353108653, -7436.5689673485394],
                    [-2064.1636353108624, -7428.1470673485383],
                    [-2066.3279353108665, -7427.2858673485389]
                ]
            ]
        },
        "properties": {
            "FID": 0,
            "CZWCODE": "4403050050110200020",
            "ADDRESS": "湾厦路2号海鲜交易中心",
            "NAME": "海鲜交易中心",
            "LAYERS": 2,
            "floor": 2,
            "height": 6,
            "朝向": -61.9803735785,
            "面积": 540.39058542500004,
            "ID": "4403050050110200020",
            "分类": " ",
            "usage": "商服"
        }
    }]

}

  一般的多边形, 它是给了一个底面的各个顶点, 然后给了一个高度让你去生成简单模型, 这个顶点列表是有序的, 所以这个可能是个凹多边形. 这就关联到前面写的这篇文章了 : 二维空间内的三角剖分 -- (给出边缘顶点的例子)

通过三角剖分我们就能正确生成底面的所有三角面了, 然后底面加上高度就是顶面的所有三角面了, 然后因为底边和顶边是对齐的, 我们就可以按照顺序每个相对应的边组成一个四边形进行三角形划分. 逻辑实在过于简单, 不解释了. 

问题在于三角形面的朝向问题, 这里只计算了三角面, 并没有对朝向进行计算, 如果要进行朝向计算的话就要对每个三角面的朝向是否向外(相对于该多边形来说), 这样逻辑会很复杂, 这里为了简便直接把所有三角形添加一个朝向相反的三角形即可.

  代码 :

        public static Mesh CreateGeoJsonMesh(List<Vector3> basePoints, float height)
        {
            Mesh mesh = new Mesh();
            mesh.name = "GeoJsonMesh";

            List<Vector3> vertices = new List<Vector3>();

            // bottom and top triangles
            var baseVerts = Triangulation.GenericTriangulate(basePoints);
            var topVerts = new List<Vector3>();
            for (int i = 0; i < baseVerts.Count; i++)
            {
                var p = baseVerts[i];
                p.y += height;
                topVerts.Add(p);
            }
            vertices.AddRange(baseVerts);
            vertices.AddRange(topVerts);

            // vertical triangles
            for(int i = 0; i < basePoints.Count; i++)
            {
                bool loop = i + 1 >= basePoints.Count;
                var p0 = basePoints[i];
                var p1 = basePoints[loop ? 0 : i + 1];
                var p2 = p1 + Vector3.up * height;
                var p3 = p0 + Vector3.up * height;

                vertices.Add(p0);
                vertices.Add(p1);
                vertices.Add(p2);

                vertices.Add(p0);
                vertices.Add(p2);
                vertices.Add(p3);
            }

            // add inverse triangles for clip
            for(int i = 0, imax = vertices.Count; i < imax; i += 3)
            {
                vertices.Add(vertices[i + 2]);
                vertices.Add(vertices[i + 1]);
                vertices.Add(vertices[i]);
            }

            // set vertices
            mesh.vertices = vertices.ToArray();

            // set triangles
            int[] triangles = new int[vertices.Count];
            for(int i = 0; i < vertices.Count; i++)
            {
                triangles[i] = i;
            }
            mesh.triangles = triangles;

            // set uvs
            Vector2[] uv = new Vector2[vertices.Count];
            for(int i = 0; i < vertices.Count; i++)
            {
                uv[i] = Vector2.zero;
            }
            mesh.uv = uv;

            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
            mesh.RecalculateTangents();
            return mesh;
        }

  

  测试代码, 还是那个凹字 :

        List<Vector3> points = new List<Vector3>();
        points.Add(new Vector3(0.5f, 1, 0.5f));
        points.Add(new Vector3(0.5f, 1, 1.5f));
        points.Add(new Vector3(1.5f, 1, 1.5f));
        points.Add(new Vector3(1.5f, 1f, -1f));
        points.Add(new Vector3(-1.5f, 1f, -1f));
        points.Add(new Vector3(-1.5f, 1f, 1.5f));
        points.Add(new Vector3(-0.5f, 1f, 1.5f));
        points.Add(new Vector3(-0.5f, 1f, 0.5f));

        var go = GameObject.CreatePrimitive(PrimitiveType.Quad);
        var mesh = WhiteHouseRuntimeMaker.CreateGeoJsonMesh(points, 5.0f);
        go.GetComponent<MeshFilter>().mesh = mesh;
        go.GetComponent<MeshCollider>().sharedMesh = mesh;

  获得的模型

 

 

  PS : 按照这样的逻辑做出来的模型, 有 点-面 数量过多的问题 :

   一. 因为用了正反两面, 直接就多了一倍的面数和三角形数量.

   二. 在三角剖分之后, 每个三角面都使用三个非共享顶点(一般来说在同一个平面上 Normal 相同的所有面都可以使用共享顶点来减少顶点数)

看下图 : 

  左边是生成出来的正方体, 右边是系统自带的正方体.

  它们的差别:

  1. 系统自带的正方体每个面用四个顶点表示, 每个面的两个三角形共享顶点, 所以只有 4*6 = 24个顶点, 然后三角形通过Index描述

  2. 生成的正方体每个面2个三角形, 顶点不共享, 就是6个顶点每个面, 也就是36顶点12个面的原始图形

  3. 生成的正方体因为三角形朝向没有明确所以进行了复制翻转, 多出了一倍的顶点和面, 72顶点24个面. 

  所以虽然生成过程简单高效, 可是运行时额外增加了系统负荷. 后续还是需要进行改进.

 

  一般情况下给出的顶点列表如果都是按照顺时针或逆时针的顺序给出的话, 还是能很简单做出三角面的方向的, 这就直接减少了一半的点面.

 

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!