unity GPS坐标为(X,Y,Z),向北旋转
unity GPS coordinates to (X,Y,Z), rotating north
我正在用 Unity3D 制作一个应用程序,它使用 GPS 坐标在 3D 世界中放置一个 "thing",当你在现实世界中走近它时,你会发现它越来越近。有点像 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;
但它确实很奇怪,"right" 位置既在我的右边又在我的左边(为什么?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
}
最简单的方法是将每个地图对象指定为空作为父对象,然后旋转。这样你只需要设置 transform.rotation = Quaternion.Euler (0,Input.compass.trueHeading,0)
on empty as
Input.compass.trueHeading
- The heading in degrees relative to the
geographic North Pole
查看您的代码应该如下所示:
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;
编辑。我不知道为什么在示例中是减号,也许它也应该在我的代码中。
transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading,
0);
我实际上找到了解决我自己问题的方法,那就是:
我取增量(单位北(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的值
我正在用 Unity3D 制作一个应用程序,它使用 GPS 坐标在 3D 世界中放置一个 "thing",当你在现实世界中走近它时,你会发现它越来越近。有点像 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;
但它确实很奇怪,"right" 位置既在我的右边又在我的左边(为什么?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
}
最简单的方法是将每个地图对象指定为空作为父对象,然后旋转。这样你只需要设置 transform.rotation = Quaternion.Euler (0,Input.compass.trueHeading,0)
on empty as
Input.compass.trueHeading
- The heading in degrees relative to the geographic North Pole
查看您的代码应该如下所示:
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;
编辑。我不知道为什么在示例中是减号,也许它也应该在我的代码中。
transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);
我实际上找到了解决我自己问题的方法,那就是:
我取增量(单位北(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的值