官方推荐用unity2021.3~版本 (当然2020也可以 我用的2020.3.35f1 打开的)
以URP为例 每个场景对应scripts中的脚本 如果嫌弃可以直接删掉 用处不大
重要的是官方提供的三个示例
导入后
如果用2020版本打开会报没有Newtonsoft这个的错 / 自己加上就好
注意 :
运行后瓦片白色是因为LightingManager 中的HDRP与URP灯光数值太高
在URP中运行LightingManager也会报错 好像是检测HDRP出错 这小问题
1.0版本添加了瓦片碰撞器
主要实现了通过鼠标点击瓦片获取点
在三维地球画线LineRender (只在local 有效 在全局中会飘 )
总结:
public class ArcGis_Tools : MonoBehaviour
{
public GameObject Route;
public GameObject RouteMarker;
private ArcGISMapComponent arcGISMapComponent;
private HPRoot hpRoot;
double3 lastRootPosition;
private LineRenderer lineRenderer;
int a=0;
GameObject[] a_project = new GameObject[2];
// Start is called before the first frame update
void Start()
{
arcGISMapComponent = FindObjectOfType();
lineRenderer = Route.GetComponent();
lastRootPosition = arcGISMapComponent.GetComponent().RootUniversePosition;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(2))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
var routeMarker = Instantiate(RouteMarker, hit.point, Quaternion.identity, arcGISMapComponent.transform);
Debug.Log(hit.point);
var geoPosition = HitToGeoPosition(hit);
Debug.Log(geoPosition.X+“,”+ geoPosition.Y + “,”+geoPosition.Z);
var locationComponent = routeMarker.GetComponent();
locationComponent.enabled = true;
locationComponent.Position = geoPosition;
locationComponent.Rotation = new ArcGISRotation(0, 90, 0);
a_project[a] = routeMarker;
a++;
if (a == 2)
{
var allPoints = new List();
for (int i = 0; i < 2; i++)
{
allPoints.Add(a_project[i].transform.position);
}
lineRenderer.positionCount = 2;
lineRenderer.SetPositions(allPoints.ToArray());
lineRenderer.widthMultiplier = 5;
}
}
}
Game_UpadataRoute();
}
//三维坐标转arcgis坐标 ws84
private ArcGISPoint HitToGeoPosition(RaycastHit hit, float yOffset = 0)
{
var worldPosition = math.inverse(arcGISMapComponent.WorldMatrix).HomogeneousTransformPoint(hit.point.ToDouble3());
var geoPosition = arcGISMapComponent.View.WorldToGeographic(worldPosition);
var offsetPosition = new ArcGISPoint(geoPosition.X, geoPosition.Y, geoPosition.Z + yOffset, geoPosition.SpatialReference);
return GeoUtils.ProjectToSpatialReference(offsetPosition, new ArcGISSpatialReference(4326));
}
//判断相机移动大于1 刷新绳子 通过 平面地球 根据相机变化数值而变
private void RebaseRoute()
{
var rootPosition = arcGISMapComponent.GetComponent().RootUniversePosition;
var delta = (lastRootPosition - rootPosition).ToVector3();
if (delta.magnitude > 1) // 1km
{
if (lineRenderer != null)
{
Vector3[] points = new Vector3[lineRenderer.positionCount];
lineRenderer.GetPositions(points);
for (int i = 0; i < points.Length; i++)
{
points[i] += delta;
}
lineRenderer.SetPositions(points);
}
lastRootPosition = rootPosition;
}
}
//判断相机移动大于1 刷新绳子2 通过已有物体实时更新位置
private void Game_UpadataRoute()
{
var rootPosition = arcGISMapComponent.GetComponent().RootUniversePosition;
var delta = (lastRootPosition - rootPosition).ToVector3();
if (delta.magnitude > 1) // 1km
{
if (lineRenderer != null&& a_project[0])
{
Vector3[] points = new Vector3[lineRenderer.positionCount];
for (int i = 0; i < lineRenderer.positionCount; i++)
{
points[i] = a_project[i].transform.position;
//allPoints.Add(a_project[i].transform.position);
}
lineRenderer.SetPositions(points);
}
lastRootPosition = rootPosition;
}
}
}
注意的是 LineRenderer的刷新
RebaseRoute()方法利用相机的移动来总体移动LineRenderer绑定点的值
Game_UpadataRoute()利用ArcGISLocationComponent 机制 为LineRenderer绑定点赋值
想法:
可以在LineRenderer创建后添加ArcGISLocationComponent 组件 把LineRenderer需要的路径点放在子节点只需要空对象就可以
在ArcGISCameraControllerComponent.cs中添加
改进一下
if (Input.GetMouseButtonDown(2)&& !isMouse_Center)
{
isMouse_Center = true;
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (UnityEngine.Physics.Raycast(ray, out hit))
{
RotationCenter = HitToGeoPosition(hit);
//A_1 = Instantiate(RouteMarker, hit.point, Quaternion.identity, arcGISMapComponent.transform);
var locationComponent = Mouse_Center.GetComponent();
locationComponent.enabled = true;
locationComponent.Position = RotationCenter;
//locationComponent.Rotation = new ArcGISRotation(0,90,0);
}
}
if (Input.GetMouseButton(2))
{
//double3 RotationCenterUP_double3=math.normalize(arcGISMapComponent.View.GeographicToWorld(new ArcGISPoint(0, RotationCenter.Y, 0, RotationCenter.SpatialReference)));//作为Y轴 不得行
double3 RotationCenter_double3= arcGISMapComponent.View.GeographicToWorld(RotationCenter);
MyRotateAround(ref cartesianPosition, ref cartesianRotation, RotationCenter_double3, (double3)Mouse_Center.GetComponent().Up, Input.GetAxis(“Mouse X”) * 5, 0);
//MyRotateAround(ref cartesianPosition, ref cartesianRotation, RotationCenter_double3, RotationCenterUP_double3, Input.GetAxis(“Mouse X”) * 5, 0);//不得行
MyRotateAround(ref cartesianPosition, ref cartesianRotation, RotationCenter_double3, (double3)hpTransform.Right, Input.GetAxis(“Mouse Y”) * 5, 1);
}
if (Input.GetMouseButtonUp(2))
{
Mouse_Center.GetComponent().enabled = false;
isMouse_Center = false;
}
//三维坐标转arcgis坐标 ws84
private ArcGISPoint HitToGeoPosition(RaycastHit hit, float yOffset = 0)
{
var worldPosition = math.inverse(arcGISMapComponent.WorldMatrix).HomogeneousTransformPoint(hit.point.ToDouble3());
var geoPosition = arcGISMapComponent.View.WorldToGeographic(worldPosition);
var offsetPosition = new ArcGISPoint(geoPosition.X, geoPosition.Y, geoPosition.Z + yOffset, geoPosition.SpatialReference);
return GeoUtils.ProjectToSpatialReference(offsetPosition, new ArcGISSpatialReference(4326));
}
//相机绕点旋转 ---------------------------------高度问题
void MyRotateAround(ref double3 cartesianPosition, ref quaternion cartesianRotation, double3 center, double3 axis, double angle, int a)
{
double3 jilu = cartesianPosition;
//Quaternion rot = Quaternion.AngleAxis(angle, axis);
double3 dir = cartesianPosition - center; //计算从圆心指向摄像头的朝向向量
if (a == 0)
{
//dir= TRS(new double3(0,0,0),)
dir = My_Rotate(axis, -angle).HomogeneousTransformPoint(dir);
cartesianPosition = center + dir;
cartesianRotation = My_Rotate(axis, -angle).ToQuaterniond().ToQuaternion() * cartesianRotation;//区别 前后位置乘的原因
}
else
{
dir = My_Rotate(axis, angle).HomogeneousTransformPoint(dir);
cartesianPosition = center + dir;
var right = Matrix4x4.Rotate(cartesianRotation).GetColumn(0);
var rotationX = Quaternion.AngleAxis(-(float)angle, right);
cartesianRotation = rotationX * cartesianRotation;
//cartesianRotation = My_Rotate(axis, angle).ToQuaterniond().ToQuaternion() * cartesianRotation;
}
}
double4x4 My_Rotate(double3 axis, double angle)
{
double radAngle = angle * MathUtils.DegreesToRadians;
double sina = System.Math.Sin(0.5 * radAngle);
double cosa = System.Math.Cos(0.5 * radAngle);
double qx = axis.x * sina, qy = axis.y * sina, qz = axis.z * sina, qw = cosa;
double x = qx * 2.0;
double y = qy * 2.0;
double z = qz * 2.0;
double xx = qx * x;
double yy = qy * y;
double zz = qz * z;
double xy = qx * y;
double xz = qx * z;
double yz = qy * z;
double wx = qw * x;
double wy = qw * y;
double wz = qw * z;
double4x4 m = new double4x4(1.0f - (yy + zz), xy + wz, xz - wy, 0.0,
xy - wz, 1.0f - (xx + zz), yz + wx, 0.0,
xz + wy, yz - wx, 1.0f - (xx + yy), 0.0,
0.0, 0.0, 0.0, 1.0
);
return m;
}
总结:
1 ArcGISPoint与double3转换
arcGISMapComponent.View.WorldToGeographic()
GeographicToWorld
2.hpTransform.UniverseRotation
HpTransform转double3