ArcGISMapsSDK For Unreal Engine插件使用
通过用于虚幻引擎的ArcGIS Maps SDK,可以从ArcGIS平台访问现实世界地图和3D内容,从而为Windows和macO创建交互式3D GIS应用程序。您还可以为Android和iOS构建本机GIS体验,并将Augmented和Virtual Reality应用程序直接部署到您的移动设备。
该插件提供了三个选项来使用场景中的ArcGIS数据和其他地理空间内容:
在详细信息面板UI提供了创建一个场景选项,而无需编写任何代码
蓝图提供了使用虚幻引擎中提供的基于节点的可视脚本界面创建场景的选项
在C ++ API允许访问所述插件的源代码
使用C ++ API
了解如何使用C ++ API在场景中使用ArcGIS数据和其他地理空间内容。
注意
您不需要针对Unreal Engine Beta的ArcGIS Maps SDK的有效API密钥。您应该constexpr auto apiKey = "";为该值设置一个空字符串。
要开始使用API,您可以创建一个新的C ++类:
单击“内容浏览器”中的“添加新按钮” ,然后在“ C ++类”下选择“新建C ++类”。
将显示“选择父类”菜单。您可以选择一个现有的类进行扩展,将其功能添加到自己的类中。选择Actor,这是可以放置在世界上的最基本的对象类型,然后单击Next。
在“命名您的新演员”菜单中,为您的演员命名,然后单击“创建类”
无论您在Content Broswer中选择了哪个文件夹,都将创建新脚本,虚幻引擎会自动打开Visual Studio。默认情况下,虚幻引擎使用Visual Studio,但是您可以选择任何喜欢的编辑器。
通过从内容浏览器中手动选择,拖放Actor,将新创建的Actor添加到关卡中。这会将Actor添加到World Outliner中。单击“ World Outliner”中的Actor,以在“ Details”面板中显示其属性。
您可以在Samples文件夹中找到C ++ API示例级别。要访问该文件夹,请在内容浏览器中单击文件夹图标,然后选择ArcGISMapsSDK内容。如果选项ArcGISMapsSDK Content未出现在列表中,请单击“内容浏览器”右下角的“查看选项”,然后选择“显示插件内容”。
先决条件
查看“入门”页面中的前三个步骤,以确保正确设置了开发环境。
选择全局或本地
使用3D内容时,您可以选择在两个不同的场景环境之一中显示数据:全局或局部。全局或局部场景的最佳环境取决于数据的空间参考,图层类型以及您要在场景中实现的目标。
全球场景
全局场景是一种查看模式,您可以在其中基于WGS84或Web Mercator(辅助球)坐标系在球上显示2D和3D内容。当您想要了解或提供环绕地球球形表面的现象的背景信息时,全局场景非常有用,例如全球天气测量,航空公司的交通路径或航道。
要设置全局场景,请在类中添加以下功能:
复制
auto mapType = Esri::GameEngine::Map::ArcGISMapType::Global; auto arcGISMap = Esri::MakeShared<:gameengine::map::arcgismap>(mapType);
当地景象
局部场景是一种视图模式,可将地形和图层投影到平面而不是球体上,并且仅通过Web Mercator坐标系投影。局部场景可用于表示整个世界,并且可以选择使用固定范围,该范围可裁剪到图层的尺寸。本地场景可用于显示或分析本地或城市规模的数据,当您要查看定义的区域(例如校园设施或建筑开发项目)时,对于城市规划和可视化非常有用。
要设置本地场景,请添加:
复制
auto mapType = Esri::GameEngine::Map::ArcGISMapType::Local; auto arcGISMap = Esri::MakeShared<:gameengine::map::arcgismap>(mapType);
选择底图
底图为场景中的内容提供了地理背景的背景。ArcGIS Maps SDK for Unity包含一个底图库,该库具有多种选择,包括地形,图像和街道。
添加以下代码以设置底图:
复制
auto arcGISBasemapLayer = Esri::GameEngine::Layers::ArcGISBasemapLayer( "https://www.arcgis.com/sharing/rest/content/items/716b600dbbac433faa4bec9220c76b3a/data", apiKey); arcGISMap->SetBasemapLayer(arcGISBasemapLayer);
创建高程
高程图层可以在3D场景中创建浮雕,从而有助于3D可视化。高程表面定义了地图或场景范围内的高度值。高程表面最常见的用途是为栅格化的内容和地面矢量符号定义高程源,但是在编辑要素时也可以使用表面来定义高度。
添加以下代码来设置高程:
复制
auto elevationLayer = Esri::GameEngine::Layers::ArcGISElevationLayer( "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "Elevation", apiKey); arcGISMap->SetElevation(elevationLayer);
新增要素
图层是地图的内容。它们包括关于人,地球,生活等的广泛主题,并且由图像,Web服务和本地数据组成。
您可以添加什么层?
Web服务:栅格图块层,集成网格场景(v1.7),3D对象场景层(v1.7)和高程层
本地服务:集成的网格和3D对象SLPK文件和TPK文件(影像和高程)
添加以下代码来创建图像图层,并将图层名称MyImageLayer和图层不透明度设置为完全不透明:
复制
auto MyImageLayer = Esri::GameEngine::Layers::ArcGISImageLayer( "https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/UrbanObservatory_NYC_TransitFrequency/MapServer", "MyImageLayer", 1.0f, true, apiKey); arcGISMap->GetLayers().Add(MyImageLayer);
添加以下代码以创建3D图层,并将其名称My3DLayer和图层不透明度设置为完全不透明:
复制
auto My3DLayer = Esri::GameEngine::Layers::ArcGIS3DModelLayer( "https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_NewYork_17/SceneServer", "My3DLayer, 1.0f, true, apiKey); arcGISMap->GetLayers().Add(My3DLayer);
添加以下代码以从本地文件创建3D图层,并将名称MyLocal3DLayer和图层不透明度设置为完全不透明:
复制
auto MyLocal3DLayer = Esri::GameEngine::Layers::ArcGIS3DModelLayer( " C:/Users/my_username/Downloads/example.slpk", "MyLocal3DLayer", 1.0f, true, apiKey); arcGISMap->GetLayers().Add(MyLocal3DLayer);
更改图层的不透明度:
复制
MyImageLayer.SetOpacity(0.9f);
删除图层:
复制
auto index = arcGISMap->GetLayers().IndexOf(MyImageLayer); arcGISMap->GetLayers().Remove(index);
相机
为了在关卡中移动,可以使用ArcGIS Default Pawn。
Pawn类是可以由玩家或AI控制的所有Actor的基类。兵是世界上玩家或AI实体的物理表示。这意味着Pawn可以确定玩家或AI实体的视觉外观,还可以通过物理原理和碰撞检测来确定其与世界的交互方式。
默认情况下,控制器和兵之间存在一对一的关系。换句话说,每个控制器在任何给定时间仅拥有一个Pawn。同样,在游戏过程中生成的棋子不会被控制器自动拥有。
有关如何管理pawn和照相机的更多信息,请参见Pawn和照相机。
设置摄像机的初始视角:
复制
String name("Camera_1"); Esri::GameEngine::Location::ArcGISRotation orientation(68, 0, 65); Esri::GameEngine::Location::ArcGISGlobalCoordinatesPosition position(40.691242, -74.054921, 3000); // Create a camera auto arcGISCamera = Esri::MakeShared<:gameengine::camera::arcgiscamera>(name, position, orientation); // Create the renderer view and set it the camera and the map auto rendererView = Esri::MakeShared<:gameengine::view::arcgisrendererview>(); rendererView->SetMap(arcGISMap); rendererView->SetCamera(arcGISCamera); // Set the renderer view to the renderer component ArcGISRendererComponent->RendererView = rendererView; // Create our sample pawn ASampleDefaultPawn* arcGISPawn = GetWorld()->SpawnActor(); // ASSIGN RENDERERVIEW TO THE CURRENT MAIN CAMERA COMPONENT auto cameraComponent = arcGISPawn->FindComponentByClass(); cameraComponent->RendererView = rendererView; arcGISPawn->SetActorLocationAndRotation(Convert::ToFVector(rendererView->GetCameraLocalPosition()), Convert::ToFQuat(rendererView->GetCameraLocalRotation()));
可以通过以下属性使用自己的坐标来定位摄像机:
复制
cameraGE.Latitude = 40.691242; cameraGE.Longitude = -74.054921; cameraGE.Height = 3000; cameraGE.Heading = 65; cameraGE.Pitch =68 cameraGE.Roll = 0;
创建范围
在本地场景中,可以将底图和图层裁剪到视图的自定义范围。这对于提高性能,关注项目的关键元素以及与地下层进行交互非常有用。
地图范围由一系列边界坐标定义,这些边界坐标描绘了您要使用的地图或场景的区域。
设置矩形范围
复制
auto extentCenter = Esri::GameEngine::Location::ArcGISGlobalCoordinatesPosition(40.691242, -74.054921, 3000); auto extent = Esri::GameEngine::Map::Extent::ArcGISMapExtentRectangle(extentCenter, 2000, 4000); arcGISMap->SetExtent(extent);
注意
这些是此代码中使用的值。他们将初始视角设置为纽约市上方的位置:
纬度:40.691242
经度:-74.054921
海拔:3000 m
宽度:2000 m
高度:4000 m
重新定位直射的天空和天空
必须重新定位定向光(太阳)和天空,以便它们可以随地图一起移动:
复制
auto directionalLightActor = UGameplayStatics::GetActorOfClass(GetWorld(), ADirectionalLight::StaticClass()); auto skyLightActor = UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass()); if (directionalLightActor) { auto directionalLightReposition = NewObject( directionalLightActor, UArcGISDirectionalLightRepositionComponent::StaticClass(), NAME_None, RF_Transient); directionalLightReposition->RendererView = rendererView; directionalLightReposition->RegisterComponent(); } if (skyLightActor) { auto lightReposition = NewObject(skyLightActor, UArcGISSkyLightRepositionComponent::StaticClass(), NAME_None, RF_Transient); lightReposition->RendererView = rendererView;