调arcgisonline瓦片服务,在unity中生成三维地球。
基本原理
构建三维地球网格,将瓦片地图做为材质贴图赋给没有网格面。
瓦片数据获取Services:
-
NatGeo_World_Map
(MapServer) -
USA_Topo_Maps
(MapServer) -
World_Imagery
(MapServer) -
World_Physical_Map
(MapServer) -
World_Shaded_Relief
(MapServer) -
World_Street_Map
(MapServer) -
World_Terrain_Base
(MapServer) -
World_Topo_Map
(MapServer)
支持以上地图读取
高德地图:
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级
到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
注意是否服务还可以使用