经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
使用类似GeoJson的数据生成物体(建筑等)的功能逻辑
来源:cnblogs  作者:tiancaiKG  时间:2019/6/21 12:39:23  对本文有异议

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

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

  1. {
  2. "type": "FeatureCollection",
  3. "crs": {
  4. "type": "name",
  5. "properties": {
  6. "name": "EPSG:3857"
  7. }
  8. },
  9. "features": [{
  10. "type": "Feature",
  11. "id": 0,
  12. "geometry": {
  13. "type": "Polygon",
  14. "coordinates": [
  15. [
  16. [-2066.3279353108665, -7427.2858673485389],
  17. [-2071.2341353108641, -7436.5054673485392],
  18. [-2090.8278353108617, -7426.2554673485392],
  19. [-2092.9139353108621, -7430.4644673485382],
  20. [-2096.9763353108574, -7438.1128673485382],
  21. [-2089.4294353108708, -7441.1304673485392],
  22. [-2091.4216353108641, -7448.0708673485387],
  23. [-2090.0935353108653, -7448.4624673485378],
  24. [-2086.7887353108672, -7449.4635673485391],
  25. [-2087.0934353108605, -7450.4654673485384],
  26. [-2077.6715353108593, -7453.5912673485382],
  27. [-2071.241835310866, -7455.724267348538],
  28. [-2070.8513353108574, -7455.8531673485377],
  29. [-2070.5388353108574, -7454.7720673485383],
  30. [-2066.2340353108593, -7440.1365673485379],
  31. [-2064.8513353108574, -7440.5699673485396],
  32. [-2064.2340353108593, -7438.5963673485385],
  33. [-2064.3123353108676, -7437.5268673485389],
  34. [-2068.0935353108653, -7436.5689673485394],
  35. [-2064.1636353108624, -7428.1470673485383],
  36. [-2066.3279353108665, -7427.2858673485389]
  37. ]
  38. ]
  39. },
  40. "properties": {
  41. "FID": 0,
  42. "CZWCODE": "4403050050110200020",
  43. "ADDRESS": "湾厦路2号海鲜交易中心",
  44. "NAME": "海鲜交易中心",
  45. "LAYERS": 2,
  46. "floor": 2,
  47. "height": 6,
  48. "朝向": -61.9803735785,
  49. "面积": 540.39058542500004,
  50. "ID": "4403050050110200020",
  51. "分类": " ",
  52. "usage": "商服"
  53. }
  54. }]
  55. }

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

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

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

  代码 :

  1. public static Mesh CreateGeoJsonMesh(List<Vector3> basePoints, float height)
  2. {
  3. Mesh mesh = new Mesh();
  4. mesh.name = "GeoJsonMesh";
  5. List<Vector3> vertices = new List<Vector3>();
  6. // bottom and top triangles
  7. var baseVerts = Triangulation.GenericTriangulate(basePoints);
  8. var topVerts = new List<Vector3>();
  9. for (int i = 0; i < baseVerts.Count; i++)
  10. {
  11. var p = baseVerts[i];
  12. p.y += height;
  13. topVerts.Add(p);
  14. }
  15. vertices.AddRange(baseVerts);
  16. vertices.AddRange(topVerts);
  17. // vertical triangles
  18. for(int i = 0; i < basePoints.Count; i++)
  19. {
  20. bool loop = i + 1 >= basePoints.Count;
  21. var p0 = basePoints[i];
  22. var p1 = basePoints[loop ? 0 : i + 1];
  23. var p2 = p1 + Vector3.up * height;
  24. var p3 = p0 + Vector3.up * height;
  25. vertices.Add(p0);
  26. vertices.Add(p1);
  27. vertices.Add(p2);
  28. vertices.Add(p0);
  29. vertices.Add(p2);
  30. vertices.Add(p3);
  31. }
  32. // add inverse triangles for clip
  33. for(int i = 0, imax = vertices.Count; i < imax; i += 3)
  34. {
  35. vertices.Add(vertices[i + 2]);
  36. vertices.Add(vertices[i + 1]);
  37. vertices.Add(vertices[i]);
  38. }
  39. // set vertices
  40. mesh.vertices = vertices.ToArray();
  41. // set triangles
  42. int[] triangles = new int[vertices.Count];
  43. for(int i = 0; i < vertices.Count; i++)
  44. {
  45. triangles[i] = i;
  46. }
  47. mesh.triangles = triangles;
  48. // set uvs
  49. Vector2[] uv = new Vector2[vertices.Count];
  50. for(int i = 0; i < vertices.Count; i++)
  51. {
  52. uv[i] = Vector2.zero;
  53. }
  54. mesh.uv = uv;
  55. mesh.RecalculateNormals();
  56. mesh.RecalculateBounds();
  57. mesh.RecalculateTangents();
  58. return mesh;
  59. }

  

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

  1. List<Vector3> points = new List<Vector3>();
  2. points.Add(new Vector3(0.5f, 1, 0.5f));
  3. points.Add(new Vector3(0.5f, 1, 1.5f));
  4. points.Add(new Vector3(1.5f, 1, 1.5f));
  5. points.Add(new Vector3(1.5f, 1f, -1f));
  6. points.Add(new Vector3(-1.5f, 1f, -1f));
  7. points.Add(new Vector3(-1.5f, 1f, 1.5f));
  8. points.Add(new Vector3(-0.5f, 1f, 1.5f));
  9. points.Add(new Vector3(-0.5f, 1f, 0.5f));
  10. var go = GameObject.CreatePrimitive(PrimitiveType.Quad);
  11. var mesh = WhiteHouseRuntimeMaker.CreateGeoJsonMesh(points, 5.0f);
  12. go.GetComponent<MeshFilter>().mesh = mesh;
  13. go.GetComponent<MeshCollider>().sharedMesh = mesh;

  获得的模型

 

 

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

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

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

看下图 : 

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

  它们的差别:

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

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

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

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

 

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

 

原文链接:http://www.cnblogs.com/tiancaiwrk/p/11063524.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号