unity三维地球实现方法

  • Post author:
  • Post category:其他


调arcgisonline瓦片服务,在unity中生成三维地球。


基本原理

构建三维地球网格,将瓦片地图做为材质贴图赋给没有网格面。


瓦片数据获取Services:

支持以上地图读取

高德地图:


http://webst04.is.autonavi.com/appmaptile?style=6&x=0&y=0&z=1

tring Url = "http://webst04.is.autonavi.com/appmaptile?style=6&x="+ i + "&y="+ j+ "&z="+ z ;

地球创建

经度分段

    public void getEquator(float radius,float subdivisions)
    {
        Quaternion quaternion = new Quaternion();
        Matrix4x4 matRot = new Matrix4x4();
        Vector3 point = new Vector3();
        Vector3 one = new Vector3(radius, 0, 0);
        float angle = 360 / (subdivisions);
        for (int i = 0; i < subdivisions; i++)
        {
            float newAngle = angle * i;
            quaternion = Quaternion.Euler(new Vector3(0, newAngle, 0));
            matRot.SetTRS(Vector3.zero, quaternion, new Vector3(1, 1, 1));
            point = matRot.MultiplyPoint3x4(one);
            string name = i + "&" +(int)subdivisions*0.5f;
            points.Add(name, writeJosn(point));
            instancePoint(point, name);
            longlatCreat(one, i, newAngle);
        }
    }

纬度分段

 /// <summary>
    /// 墨卡托转经纬度
    /// </summary>
    /// <param name="target">赤道点</param>
    /// <param name="FaName">经度编号</param>
    /// <param name="_angle">经度</param>
    void longlatCreat(Vector3 target, int FaName, float _angle)
    {
  
        double halfSub = (double)((subdivisions) * 0.5f);
        double unit = 20037508.3427 / (halfSub*1.0000);
        Quaternion quaternion = new Quaternion();
        Matrix4x4 matRot = new Matrix4x4();
        Vector3 point = new Vector3();
      
        string name;

        for (int i = 0; i < halfSub; i++)
        {
            double mercatorY = unit * (i+1);
            double angle = webMercator2lonLat(mercatorY);
            Debug.Log(i + "=" + ( - angle)+"&"+ mercatorY);
            quaternion = Quaternion.Euler(new Vector3(0, _angle, float.Parse((-(angle)).ToString())));
            matRot.SetTRS(Vector3.zero, quaternion, new Vector3(1, 1, 1));
            point = matRot.MultiplyPoint3x4(target);
            name = FaName + "&" + (halfSub+(i+1));
            points.Add(name, writeJosn(point));
            instancePoint(point, name);

            quaternion = Quaternion.Euler(new Vector3(0, _angle, float.Parse((angle).ToString())));
            matRot.SetTRS(Vector3.zero, quaternion, new Vector3(1, 1, 1));
            point = matRot.MultiplyPoint3x4(target);
            name = FaName + "&" + (halfSub - (i + 1));
            points.Add(name, writeJosn(point));
            instancePoint(point, name);
        }
        string jsonInfo = JsonMapper.ToJson(points);
        Save("5_32Jmercator", jsonInfo);
    }

    /// <summary>
    /// 求北纬
    /// </summary>
    /// <param name="mercator"></param>
    /// <returns></returns>
    double webMercator2lonLat(double mercatorY)
    {
      
        double lonlat;
        double y = (mercatorY / 20037508.34) * 180.000;
        y = (180.000 / Math.PI) * (2 * Math.Atan(Math.Exp(y * Math.PI / 180.000)) - (Math.PI / 2));
        Debug.Log(Mathf.Exp(Mathf.PI));
        Debug.Log(Math.Exp(Math.PI));
        lonlat = y;
        return lonlat;
    }

瓦片读取

瓦片细分

  void  CreateMeshAll_samll (int x,int y,int z)
    {
      
        string one = x + "&" + y + "&"+ (z-1);
        Debug.Log(one);
        string two = (x+1) + "&" + y + "&" + (z - 1); 
        string three = x + "&" + (y+1) + "&" + (z - 1); 
        string four = (x + 1) + "&" + (y + 1) + "&" + (z - 1); 
        string name_00 = (x * 2) + "&" + (y * 2)+"&"+z;
        string name_01 = (x * 2) + "&" + ((y * 2)+1) + "&" + z;
        string name_02 = (x * 2) + "&" + ((y * 2) + 2) + "&" + z;
        string name_10 = ((x * 2)+1) + "&" + (y * 2) + "&" + z;
        string name_11 = ((x * 2) + 1) + "&" + ((y * 2) + 1) + "&" + z;
        string name_12 = ((x * 2) + 1) + "&" + ((y * 2) + 2) + "&" + z;
        string name_20 = ((x * 2) + 2) + "&" + (y * 2) + "&" + z;
        string name_21 = ((x * 2) + 2) + "&" + ((y * 2) + 1) + "&" + z;
        string name_22 = ((x * 2) + 2) + "&" + ((y * 2) + 2) + "&" + z;

        Vector3 _one = printAll[one];
        Vector3 _two = printAll[two];
        Vector3 _three=printAll[three];
        Vector3 _four = printAll[four];

        addDic(name_00, _one);
        addDic(name_01, (_one+ _three) *0.5f);
        addDic(name_02, _three);
        addDic(name_10, (_one + _two) * 0.5f);
        addDic(name_11, (_one + _two+ _three+ _four) * 0.25f);
        addDic(name_12, (_three + _four) * 0.5f);
        addDic(name_20, _two);
        addDic(name_21, (_two + _four) * 0.5f);
        addDic(name_22, _four);
    }
  public void CreateMeshAll(int beginX, int beginY, int times, Material mat, GameObject Fa, string name)
    {
        int z=5;
        if (!have.ContainsKey(name))
        {
          //  JsonData Points = JsonMapper.ToObject(Json);
            List<Vector3> PosList = new List<Vector3>();
            List<int> Triangles = new List<int>();
            List<Vector2> uvs = new List<Vector2>();
            Mesh mesh = new Mesh();
            int offet = (int)Mathf.Pow(2, (z - times));//z是根据json128定的,2的z次方是128
            if (offet < 1)
            {
                offet = 1;
                z = times;
            }

            Debug.Log(offet);
            string one;
            if ((beginX + 1) * offet < Mathf.Pow(2, z))//2的7次方
            {
                one = (beginX * offet) + "&" + (beginY * offet) + "&" + z;
                string two = ((1 + beginX) * offet) + "&" + (beginY * offet) + "&" + z;
                string three = (beginX * offet) + "&" + ((1 + beginY) * offet) + "&" + z;
                string four = ((1 + beginX) * offet) + "&" + ((1 + beginY) * offet) + "&" + z;
                // Debug.Log(one + "," + two + "," + three + "," + four);
                PosList.Add(printAll[one]);
                PosList.Add(printAll[two]);
                PosList.Add(printAll[three]);
                PosList.Add(printAll[four]);
            }
            else
            {
               
                    one = (beginX * offet) + "&" + (beginY * offet) + "&" + z;
                    string two = 0 + "&" + (beginY * offet) + "&" + z;
                    string three = (beginX * offet) + "&" + ((1 + beginY) * offet) + "&" + z;
                    string four = (0) + "&" + ((1 + beginY) * offet) + "&" + z;
                    PosList.Add(printAll[one]);
                    PosList.Add(printAll[two]);
                    PosList.Add(printAll[three]);
                    PosList.Add(printAll[four]);
            }

            Triangles.Add(0);
            Triangles.Add(2);
            Triangles.Add(1);
            Triangles.Add(1);
            Triangles.Add(2);
            Triangles.Add(3);

            uvs.Add(new Vector2(1, 1));
            uvs.Add(new Vector2(0, 1));
            uvs.Add(new Vector2(1, 0));
            uvs.Add(new Vector2(0, 0));

            GameObject go = new GameObject();
            MeshFilter filter = go.AddComponent<MeshFilter>();
            filter.sharedMesh = mesh;
            mesh.vertices = PosList.ToArray();
            mesh.triangles = Triangles.ToArray();
            mesh.uv = uvs.ToArray();
            mesh.RecalculateNormals();
            mesh.RecalculateBounds();
            MeshRenderer renderer = go.AddComponent<MeshRenderer>();
            renderer.material = mat;
            go.name = name;
            go.AddComponent<MeshCollider>();
            go.transform.parent = Fa.transform;
            have.Add(name, go);
        }
    }

瓦片读取

这里的服务地址可以切换。demo中只到9级

比如


http://server.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer/tile/12/0/0

到12级


http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/10/0/0

到10级

也可以使用其他瓦片服务

 IEnumerator getEartALL(int Count, int x, int y, int z, string date, GameObject Fa, int All)
    {
      
        for (int i = x; i < Count + x; i++)
        {
            for (int j = y; j < Count + y; j++)
            {
                string Url = "http://server.arcgisonline.com/arcgis/rest/services/World_Physical_Map/MapServer/tile/" + z + "/" + j + "/" + i;//影像地图
                Debug.Log(Url);                                                                                         
                using (var webRequest = UnityWebRequestTexture.GetTexture(Url))
                {
                    yield return webRequest.SendWebRequest();

                    if (webRequest.isNetworkError || webRequest.isHttpError)
                    {
                        Debug.LogError(webRequest.error);
               
                    }
                    else
                    {
                        Texture2D texture = DownloadHandlerTexture.GetContent(webRequest);
                        Texture2D texture_h;
                        Material mat = new Material(MAT);
                        string name = i + "&" + j + "&" + z;
                        mat.mainTexture = texture;
                        CreateMeshAll( (All - i), j, z, mat, Fa,name);
                    }
                }
            }
        }

    }

demo下载(本demo只完成框架部分,具体展示方法需要自己完善)



demo下载地址



https://download.csdn.net/download/dxs1990/85011867


改进版本demo(后面会有文章说明)


https://download.csdn.net/download/dxs1990/87707309?spm=1001.2014.3001.5503

注:

本demo读取瓦片

http://server.arcgisonline.com/arcgis/rest/services/USA_Topo_Maps/MapServer/tile/0/0/0

注意是否服务还可以使用



版权声明:本文为dxs1990原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。