统一GPS坐标到(X,Y,Z),向北旋转

时间:2016-09-12 16:38:49

标签: unity3d gps compass-geolocation

我正在使用Unity3D创建一个应用程序,它使用GPS坐标在3D世界中放置一个“东西”,当你走近它的真实世界时,你会发现它越来越近了。有点像PokemonGO

所以问题是: 我设法将对象放置在正确的位置和距离,使用函数dist(lat1,lon1,lat2,lon2),它给出了2坐标之间的距离(见下文)。

我接下来要做的是让场景围绕Y轴转动以向北(Z轴+应指向北)。我该怎么做?

我做的是这个:

float xx = dist (0, Tlon, 0, lon), zz = dist (Tlat, 0, lat, 0);
Vector3 position = new Vector3 (xx, 0, zz);
position.Normalize ();
float beta = Mathf.Acos(position.z) * Mathf.Rad2Deg;
position = Quaternion.Euler (0,beta-Input.compass.trueHeading,0)*position;
transform.position = position;

但它确实很奇怪,“正确”的位置在我右边和左边(为什么?idk)

{dist函数,用于计算2个坐标之间的距离:}

float dist(float lat1, float lon1, float lat2, float lon2){  // generally used geo measurement function
    var R = 6378.137; // Radius of earth in KM
    var dLat = (lat2 - lat1) * Mathf.PI / 180;
    var dLon = (lon2 - lon1) * Mathf.PI / 180;
    var a = Mathf.Sin(dLat/2) * Mathf.Sin(dLat/2) +
        Mathf.Cos(lat1 * Mathf.PI / 180) * Mathf.Cos(lat2 * Mathf.PI / 180) *
        Mathf.Sin(dLon/2) * Mathf.Sin(dLon/2);
    var c = 2 * Mathf.Atan2(Mathf.Sqrt(a), Mathf.Sqrt(1-a));
    var d = R * c;
    return (float)(d * 1000); // meters
}

2 个答案:

答案 0 :(得分:1)

最简单的方法是,如果您将每个地图对象指定为空作为父项,然后旋转。这样,您只需将transform.rotation = Quaternion.Euler (0,Input.compass.trueHeading,0)设置为空

  

Input.compass.trueHeading - 以度为单位的标题   地理北极

查看您的代码,它应该如下所示:

float xx = dist (0, Tlon, 0, lon), zz = dist (Tlat, 0, lat, 0);
Vector3 position = new Vector3 (xx, 0, zz);
position.Normalize ();
position = Quaternion.AngleAxis(Input.compass.trueHeading, Vector3.up) * position;
transform.position = position;

EDIT。我不知道为什么在例子中是减号,也许它应该在我的代码中。

  

transform.rotation = Quaternion.Euler(0,-Input.compass.trueHeading,   0);

答案 1 :(得分:1)

我实际上找到了我自己的问题的解决方案,那就是:

我取三角洲(统一北(z =轴)和实际地理北极之间的差异)

if (delta == 0 && (gcb.activeSelf||head.transform.eulerAngles.y!=0)) {
    Vector3 fwd = new Vector3 (0, 0, 1);
    Vector3 north = Quaternion.Euler (0, Input.compass.trueHeading, 0) * fwd;
    delta = SignedAngle(fwd,north) + (360-head.transform.eulerAngles.y);
}

然后我计算unityNorth和元素放置位置之间的角度:

float xx = dist (0, Tlon, 0, lon), zz = dist (Tlat, 0, lat, 0);
Vector3 position = new Vector3 (xx, 0, zz); //the position of the target if unityNorth and actual geoNorth were the same
position.Normalize ();
Vector3 unityN = new Vector3 (0,0,1); // unity north
angoloTrgt = Vector3.Angle (unityN, position);
position *= MIN_CUBE_DIST;
target.transform.position = new Vector3 (0,0,MIN_CUBE_DIST);

然后将对象放置在正确的角度

bollettino.transform.RotateAround (Vector3.zero, Vector3.up,  angoloTrgt - old_compass-delta);

其中old_compass是场景加载时Input.compass.trueHeading的值