ArcGIS Maps SDK for Unreal Engine demo
插件主要分为两部分:ArcGIS
数据API
接口和UE4
渲染部分。
UArcGISRendererComponent
继承自AActor
,包含以下对象:
ArcGISRendererView
负责组织数据源map,更新位置camera,坐标转换coords。
SceneComponentProvider
:有地图数据动态生成Mesh组件,并挂载到UArcGISRendererComponent
下。
GPUResourcesProvider
: 材质资源的生成。
NormalMapGenerator
:法向量。
TextureComposer
:纹理混合。
Matrix
:CoordinateSystem
FArcGISRenderer
: 实际渲染的实现。
void UArcGISRendererComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (RendererView)
{
//准备相关渲染处理函数
if (!ArcGISRenderer)
{
//GPU资源相关处理
GPUResourcesProvider = std::make_shared<FGPUResourcesProvider>();
//Mesh资源相关处理
SceneComponentProvider = std::make_shared<FSceneComponentProvider>(this);
//纹理资源相关处理
TextureComposer = std::make_shared<FTextureComposer>(this, GPUResourcesProvider);
//法线向量相关处理
NormalMapGenerator = std::make_shared<FNormalMapGenerator>(this, GPUResourcesProvider);
//生成渲染对象
ArcGISRenderer =
Esri::MakeShared<Esri::ArcGISMapsSDKLib::FArcGISRenderer>(RendererView, GPUResourcesProvider->GetFunctions(), SceneComponentProvider->GetFunctions(),
TextureComposer->GetFunctions(), NormalMapGenerator->GetFunctions());
CoordinateSystem = RendererView->GetCoordinateSystem();
RepositionAllActors(CoordinateSystem);
}
//每一帧渲染,开始渲染
ArcGISRenderer->Tick(DeltaTime);
UpdateCoordinateSystem();
}
}
示例
- Create the map document
- Add a basemap
- Set the basemap
- Set the elevation
- Create other layers
- Create extent
- Create a camera
- Create the renderer view and set it the camera and the map
- Set the renderer view to the renderer component
- Create our sample pawn
- Assign renderview to the current main camera component
- Add reposition components to the directional and sky lights
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/ArcGISRendererComponent.h"
#include "SampleAPIMapCreator.generated.h"
// The declaration of our Actor class
UCLASS()
class ARCGISSAMPLES_API ASampleAPIMapCreator : public AActor
{
GENERATED_BODY()
public:
ASampleAPIMapCreator();
protected:
virtual void BeginPlay() override;
private:
UArcGISRendererComponent* ArcGISRendererComponent;
void CreateArcGISMap();
};
#include "SampleAPIMapCreator.h"
#include "Components/DirectionalLightComponent.h"
#include "Components/SkyLightComponent.h"
#include "Engine/DirectionalLight.h"
#include "Engine/SkyLight.h"
#include "Engine/World.h"
#include "Kismet/GameplayStatics.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Camera/ArcGISCamera.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Layers/ArcGIS3DModelLayer.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Layers/ArcGISBasemapLayer.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Layers/ArcGISElevationLayer.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Layers/ArcGISImageLayer.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Map/ArcGISMap.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Map/ArcGISMapElevation.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Map/ArcGISMapType.h"
#include "ArcGISMapsSDKLib/API/GameEngine/Map/Extent/ArcGISMapExtentRectangle.h"
#include "ArcGISMapsSDKLib/API/Unreal/Collection.h"
#include "Components/ArcGISDirectionalLightRepositionComponent.h"
#include "Components/ArcGISSkyLightRepositionComponent.h"
#include "Math/Convert.h"
#include "SampleDefaultPawn.h"
ASampleAPIMapCreator::ASampleAPIMapCreator()
{
PrimaryActorTick.bCanEverTick = false;
//生成渲染组件
ArcGISRendererComponent = CreateDefaultSubobject<UArcGISRendererComponent>(TEXT("ArcGISRendererComponent"));
AddOwnedComponent(ArcGISRendererComponent);
}
void ASampleAPIMapCreator::BeginPlay()
{
Super::BeginPlay();
CreateArcGISMap();
}
// We create our map with this method
void ASampleAPIMapCreator::CreateArcGISMap()
{
// API Key
constexpr auto apiKey = ""; // 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b";
// Create the map document
auto mapType = Esri::GameEngine::Map::ArcGISMapType::Global;
auto arcGISMap = Esri::MakeShared<Esri::GameEngine::Map::ArcGISMap>(mapType);
// Add a basemap
auto arcGISBasemapLayer = Esri::GameEngine::Layers::ArcGISBasemapLayer(
"https://www.arcgis.com/sharing/rest/content/items/716b600dbbac433faa4bec9220c76b3a/data", apiKey);
// Set the basemap
arcGISMap->SetBasemapLayer(arcGISBasemapLayer);
// Set the elevation
auto elevationLayer = Esri::GameEngine::Layers::ArcGISElevationLayer(
"https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "Elevation", apiKey);
arcGISMap->SetElevation(elevationLayer);
// Create layers
auto layer_1 = Esri::GameEngine::Layers::ArcGISImageLayer(
"https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/UrbanObservatory_NYC_TransitFrequency/MapServer", "MyLayer_1", 1.0f,
true, apiKey);
arcGISMap->GetLayers().Add(layer_1);
auto layer_2 = Esri::GameEngine::Layers::ArcGISImageLayer(
"https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/New_York_Industrial/MapServer", "MyLayer_2", 1.0f, true, apiKey);
arcGISMap->GetLayers().Add(layer_2);
auto layer_3 = Esri::GameEngine::Layers::ArcGISImageLayer(
"https://tiles.arcgis.com/tiles/4yjifSiIG17X0gW4/arcgis/rest/services/NewYorkCity_PopDensity/MapServer", "MyLayer_3", 1.0f, true, apiKey);
arcGISMap->GetLayers().Add(layer_3);
auto layer_4 = Esri::GameEngine::Layers::ArcGIS3DModelLayer(
"https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_NewYork_17/SceneServer", "MyLayer_4", 1.0f, true, apiKey);
arcGISMap->GetLayers().Add(layer_4);
// Remove a layer
auto index = arcGISMap->GetLayers().IndexOf(layer_3);
arcGISMap->GetLayers().Remove(index);
// Update properties
layer_1.SetOpacity(0.9f);
layer_2.SetOpacity(0.6f);
layer_4.SetOpacity(1.0f);
// Create extent
if (mapType == Esri::GameEngine::Map::ArcGISMapType::Local)
{
auto extentCenter = Esri::GameEngine::Location::ArcGISGlobalCoordinatesPosition(40.691242, -74.054921, 3000);
auto extent = Esri::GameEngine::Map::Extent::ArcGISMapExtentRectangle(extentCenter, 10000, 10000);
arcGISMap->SetExtent(extent);
}
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<Esri::GameEngine::Camera::ArcGISCamera>(name, position, orientation);
// Create the renderer view and set it the camera and the map
auto rendererView = Esri::MakeShared<Esri::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<ASampleDefaultPawn>();
// ASSIGN RENDERERVIEW TO THE CURRENT MAIN CAMERA COMPONENT
auto cameraComponent = arcGISPawn->FindComponentByClass<UArcGISCameraComponent>();
cameraComponent->RendererView = rendererView;
arcGISPawn->SetActorLocationAndRotation(Convert::ToFVector(rendererView->GetCameraLocalPosition()),
Convert::ToFQuat(rendererView->GetCameraLocalRotation()));
// Add reposition components to the directional and sky lights
auto directionalLightActor = UGameplayStatics::GetActorOfClass(GetWorld(), ADirectionalLight::StaticClass());
auto skyLightActor = UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass());
if (directionalLightActor)
{
auto directionalLightReposition = NewObject<UArcGISDirectionalLightRepositionComponent>(
directionalLightActor, UArcGISDirectionalLightRepositionComponent::StaticClass(), NAME_None, RF_Transient);
directionalLightReposition->RendererView = rendererView;
directionalLightReposition->RegisterComponent();
}
if (skyLightActor)
{
auto lightReposition =
NewObject<UArcGISSkyLightRepositionComponent>(skyLightActor, UArcGISSkyLightRepositionComponent::StaticClass(), NAME_None, RF_Transient);
lightReposition->RendererView = rendererView;
lightReposition->RegisterComponent();
}
}